From eb52c118d072c485cfbe16ee3a3f3cff8343ecca Mon Sep 17 00:00:00 2001 From: Feotov Daniil Date: Thu, 5 Feb 2015 18:44:08 +0300 Subject: [PATCH 001/695] Migration of scram passwords with piefxis (riak and internal only) --- src/ejabberd_auth_internal.erl | 5 ++- src/ejabberd_auth_riak.erl | 5 ++- src/ejabberd_piefxis.erl | 61 +++++++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index 415c217139e..fc128ac5a54 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -151,7 +151,10 @@ set_password(User, Server, Password) -> try_register(User, Server, PasswordList) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), - Password = iolist_to_binary(PasswordList), + Password = if is_list(PasswordList); is_binary(PasswordList) -> + iolist_to_binary(PasswordList); + true -> PasswordList + end, US = {LUser, LServer}, if (LUser == error) or (LServer == error) -> {error, invalid_jid}; diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 081ee6bb809..5d631f49750 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -125,7 +125,10 @@ set_password(User, Server, Password) -> try_register(User, Server, PasswordList) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), - Password = iolist_to_binary(PasswordList), + Password = if is_list(PasswordList); is_binary(PasswordList) -> + iolist_to_binary(PasswordList); + true -> PasswordList + end, US = {LUser, LServer}, if (LUser == error) or (LServer == error) -> {error, invalid_jid}; diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 9a965927069..641db497b6f 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -238,7 +238,17 @@ export_users([], _Server, _Fd) -> %%%================================== %%%% Utilities export_user(User, Server, Fd) -> - Pass = ejabberd_auth:get_password_s(User, Server), + Password = ejabberd_auth:get_password_s(User, Server), + LServer = jlib:nameprep(Server), + PasswordFormat = ejabberd_config:get_option({auth_password_format, LServer}, fun(X) -> X end, plain), + Pass = case Password of + {_,_,_,_} -> + case PasswordFormat of + scram -> format_scram_password(Password); + _ -> <<"">> + end; + _ -> Password + end, Els = get_offline(User, Server) ++ get_vcard(User, Server) ++ get_privacy(User, Server) ++ @@ -250,6 +260,23 @@ export_user(User, Server, Fd) -> {<<"password">>, Pass}], children = Els})). +format_scram_password({StoredKey, ServerKey, Salt, IterationCount}) -> + StoredKeyB64 = base64:encode(StoredKey), + ServerKeyB64 = base64:encode(ServerKey), + SaltB64 = base64:encode(Salt), + IterationCountBin = list_to_binary(integer_to_list(IterationCount)), + <<"scram:", StoredKeyB64/binary, ",", ServerKeyB64/binary, ",", SaltB64/binary, ",", IterationCountBin/binary>>. + +parse_scram_password(PassData) -> + Split = binary:split(PassData, <<",">>, [global]), + [StoredKeyB64, ServerKeyB64, SaltB64, IterationCountBin] = Split, + #scram{ + storedkey = StoredKeyB64, + serverkey = ServerKeyB64, + salt = SaltB64, + iterationcount = list_to_integer(binary_to_list(IterationCountBin)) + }. + get_vcard(User, Server) -> JID = jlib:make_jid(User, Server, <<>>), case mod_vcard:process_sm_iq(JID, JID, #iq{type = get}) of @@ -457,7 +484,18 @@ process_users([], State) -> process_user(#xmlel{name = <<"user">>, attrs = Attrs, children = Els}, #state{server = LServer} = State) -> Name = xml:get_attr_s(<<"name">>, Attrs), - Pass = xml:get_attr_s(<<"password">>, Attrs), + Password = xml:get_attr_s(<<"password">>, Attrs), + PasswordFormat = ejabberd_config:get_option({auth_password_format, LServer}, fun(X) -> X end, plain), + Pass = case PasswordFormat of + scram -> + case Password of + <<"scram:", PassData/binary>> -> + parse_scram_password(PassData); + P -> P + end; + _ -> Password + end, + case jlib:nodeprep(Name) of error -> stop("Invalid 'user': ~s", [Name]); @@ -541,8 +579,23 @@ process_privacy(El, State = #state{user = U, server = S}) -> JID = jlib:make_jid(U, S, <<"">>), case mod_privacy:process_iq_set( [], JID, JID, #iq{type = set, sub_el = El}) of - {error, _} = Err -> - stop("Failed to write privacy: ~p", [Err]); + {error, Error} = Err -> + #xmlel{children = Els} = El, + Name = case xml:remove_cdata(Els) of + [#xmlel{name = N}] -> N; + _ -> undefined + end, + #xmlel{attrs = Attrs} = Error, + ErrorCode = case lists:keysearch(<<"code">>, 1, Attrs) of + {value, {_, V}} -> V; + false -> undefined + end, + if + ErrorCode == <<"404">>, Name == <<"default">> -> + {ok, State}; + true -> + stop("Failed to write privacy: ~p", [Err]) + end; _ -> {ok, State} end. From b81250d667c846d30499b5284585597a35c96631 Mon Sep 17 00:00:00 2001 From: Feotov Daniil Date: Mon, 16 Feb 2015 16:23:29 +0300 Subject: [PATCH 002/695] Hook on group message --- src/mod_muc_room.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 58ac2610b92..e9092d4f8c2 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2454,6 +2454,8 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, calendar:now_to_universal_time(TimeStamp), Size}, StateData#state.history), + ejabberd_hooks:run(offline_group_message_hook, StateData#state.server_host, + [FromJID, FromNick, StateData#state.jid, Packet]), add_to_log(text, {FromNick, Packet}, StateData), StateData#state{history = Q1}. From 2a15453d98425c72ae24e9da4d56ad295a57be1d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 24 Feb 2015 23:59:39 +0100 Subject: [PATCH 003/695] Fix EJABBERD_OPTS quoting for Elixir --- ejabberdctl.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 2025fd22d8f..32a6cdf15ba 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -136,17 +136,17 @@ if [ "$EJABBERD_CONFIG_PATH" != "${EJABBERD_CONFIG_PATH%.yml}" ] ; then rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) count=$(sed '/^[ ]*log_rotate_count/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) - date=$(sed '/^[ ]*log_rotate_date/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) + date=$(sed '/^[ ]*log_rotate_date/!d;s/.*://;s/ *//;s/""/[]/' $EJABBERD_CONFIG_PATH) else rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) count=$(sed '/^[ ]*log_rotate_count/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) - date=$(sed '/^[ ]*log_rotate_date/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) + date=$(sed '/^[ ]*log_rotate_date/!d;s/.*,//;s/ *//;s/""/[]/;s/}\.//' $EJABBERD_CONFIG_PATH) fi [ -z "$rate" ] || EJABBERD_OPTS="log_rate_limit $rate" [ -z "$rotate" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_size $rotate" [ -z "$count" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_count $count" -[ -z "$date" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_date '$date'" +[ -z "$date" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_date $date" [ -z "$EJABBERD_OPTS" ] || EJABBERD_OPTS="-ejabberd ${EJABBERD_OPTS}" [ -d $SPOOL_DIR ] || $EXEC_CMD "mkdir -p $SPOOL_DIR" From 8732817c3cb770f948404a4a481667d286541c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 9 Apr 2015 13:35:37 +0200 Subject: [PATCH 004/695] Fix problem with pushing bufferend #xmlel-s to receiver in websocket code --- src/ejabberd_http_ws.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index 0808ffd9768..a0cc31e2a00 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -138,8 +138,10 @@ handle_event({activate, From}, StateName, StateData) -> StateData#state{waiting_input = From}}; Input -> Receiver = From, - lists:foreach(fun(I) -> - Receiver ! {tcp, StateData#state.socket, I} + lists:foreach(fun(I) when is_binary(I)-> + Receiver ! {tcp, StateData#state.socket, I}; + (I2) -> + Receiver ! {tcp, StateData#state.socket, [I2]} end, Input), {next_state, StateName, StateData#state{input = [], waiting_input = false, From 2797fa16a6fb58dc1ca111f633cd4838c1895a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 4 Feb 2015 14:42:03 +0100 Subject: [PATCH 005/695] Show received input and expected input in ?recv* macros in case of failure Throwing catch clause error is not that good for finding out what happened --- test/suite.erl | 3 +++ test/suite.hrl | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/test/suite.erl b/test/suite.erl index a50bb64dfc1..75fb15a7b8d 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -175,6 +175,9 @@ re_register(Config) -> {atomic, ok} = ejabberd_auth:try_register(User, Server, Pass), ok. +match_failure(Received, Matches) -> + ct:fail("Received input:~n~n~p~n~ndon't match expected patterns:~n~n~p", [Received, Matches]). + recv() -> receive {'$gen_event', {xmlstreamelement, El}} -> diff --git a/test/suite.hrl b/test/suite.hrl index 26962017984..31e21ee5f66 100644 --- a/test/suite.hrl +++ b/test/suite.hrl @@ -21,7 +21,10 @@ (fun() -> case {R1 = recv(), R2 = recv()} of {P1, P2} -> {R1, R2}; - {P2, P1} -> {R2, R1} + {P2, P1} -> {R2, R1}; + {P1, V1} -> suite:match_failure([V1], [P2]); + {P2, V2} -> suite:match_failure([V2], [P1]); + {V3, V4} -> suite:match_failure([V3, V4], [P1, P2]) end end)()). @@ -30,7 +33,8 @@ case R3 = recv() of P1 -> insert(R3, 1, ?recv2(P2, P3)); P2 -> insert(R3, 2, ?recv2(P1, P3)); - P3 -> insert(R3, 3, ?recv2(P1, P2)) + P3 -> insert(R3, 3, ?recv2(P1, P2)); + V -> suite:match_failure([V], [P1, P2, P3]) end end)()). @@ -40,7 +44,8 @@ P1 -> insert(R4, 1, ?recv3(P2, P3, P4)); P2 -> insert(R4, 2, ?recv3(P1, P3, P4)); P3 -> insert(R4, 3, ?recv3(P1, P2, P4)); - P4 -> insert(R4, 4, ?recv3(P1, P2, P3)) + P4 -> insert(R4, 4, ?recv3(P1, P2, P3)); + V -> suite:match_failure([V], [P1, P2, P3, P4]) end end)()). @@ -51,7 +56,8 @@ P2 -> insert(R5, 2, ?recv4(P1, P3, P4, P5)); P3 -> insert(R5, 3, ?recv4(P1, P2, P4, P5)); P4 -> insert(R5, 4, ?recv4(P1, P2, P3, P5)); - P5 -> insert(R5, 5, ?recv4(P1, P2, P3, P4)) + P5 -> insert(R5, 5, ?recv4(P1, P2, P3, P4)); + V -> suite:match_failure([V], [P1, P2, P3, P4, P5]) end end)()). From e8701802ee28cd8c8dfd4c182b93b60aca3eb22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 9 Apr 2015 16:39:52 +0200 Subject: [PATCH 006/695] Give better error messages for tests failing on #...{} = recv() lines --- test/ejabberd_SUITE.erl | 180 ++++++++++++++++++++-------------------- test/suite.erl | 2 + test/suite.hrl | 13 ++- 3 files changed, 104 insertions(+), 91 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index a90ebdb6984..bc938b82df5 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -326,8 +326,8 @@ all() -> stop_ejabberd(Config) -> ok = application:stop(ejabberd), - #stream_error{reason = 'system-shutdown'} = recv(), - {xmlstreamend, <<"stream:stream">>} = recv(), + ?recv1(#stream_error{reason = 'system-shutdown'}), + ?recv1({xmlstreamend, <<"stream:stream">>}), Config. test_connect(Config) -> @@ -391,7 +391,7 @@ try_unregister(Config) -> Config, #iq{type = set, sub_els = [#register{remove = true}]}), - #stream_error{reason = conflict} = recv(), + ?recv1(#stream_error{reason = conflict}), Config. auth_md5(Config) -> @@ -440,7 +440,7 @@ roster_ver(Config) -> %% Attempting to subscribe to server's JID send(Config, #presence{type = subscribe, to = server_jid(Config)}), %% Receive a single roster push with the new "ver" - #iq{type = set, sub_els = [#roster{ver = Ver2}]} = recv(), + ?recv1(#iq{type = set, sub_els = [#roster{ver = Ver2}]}), %% Requesting roster with the previous "ver". Should receive Ver2 again #iq{type = result, sub_els = [#roster{ver = Ver2}]} = send_recv(Config, #iq{type = get, @@ -454,7 +454,7 @@ roster_ver(Config) -> presence(Config) -> send(Config, #presence{}), JID = my_jid(Config), - #presence{from = JID, to = JID} = recv(), + ?recv1(#presence{from = JID, to = JID}), disconnect(Config). presence_broadcast(Config) -> @@ -546,16 +546,16 @@ sm(Config) -> true = ?config(sm, Config), %% Enable the session management with resumption enabled send(Config, #sm_enable{resume = true, xmlns = ?NS_STREAM_MGMT_3}), - #sm_enabled{id = ID, resume = true} = recv(), + ?recv1(#sm_enabled{id = ID, resume = true}), %% Initial request; 'h' should be 0. send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}), - #sm_a{h = 0} = recv(), + ?recv1(#sm_a{h = 0}), %% sending two messages and requesting again; 'h' should be 3. send(Config, Msg), send(Config, Msg), send(Config, Msg), send(Config, #sm_r{xmlns = ?NS_STREAM_MGMT_3}), - #sm_a{h = 3} = recv(), + ?recv1(#sm_a{h = 3}), close_socket(Config), {save_config, set_opt(sm_previd, ID, Config)}. @@ -570,9 +570,9 @@ sm_resume(Config) -> %% Route message. The message should be queued by the C2S process. ejabberd_router:route(ServerJID, MyJID, xmpp_codec:encode(Msg)), send(Config, #sm_resume{previd = ID, h = 0, xmlns = ?NS_STREAM_MGMT_3}), - #sm_resumed{previd = ID, h = 3} = recv(), - #message{from = ServerJID, to = MyJID, body = [Txt]} = recv(), - #sm_r{} = recv(), + ?recv1(#sm_resumed{previd = ID, h = 3}), + ?recv1(#message{from = ServerJID, to = MyJID, body = [Txt]}), + ?recv1(#sm_r{}), send(Config, #sm_a{h = 1, xmlns = ?NS_STREAM_MGMT_3}), disconnect(Config). @@ -767,13 +767,13 @@ vcard_xupdate_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), send(Config, #presence{}), - #presence{from = MyJID, type = undefined} = recv(), + ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), - #presence{from = Peer, type = undefined} = recv(), - #presence{from = Peer, type = undefined, - sub_els = [#vcard_xupdate{photo = ImgHash}]} = recv(), - #presence{from = Peer, type = undefined, - sub_els = [#vcard_xupdate{photo = undefined}]} = recv(), + ?recv1(#presence{from = Peer, type = undefined}), + ?recv1(#presence{from = Peer, type = undefined, + sub_els = [#vcard_xupdate{photo = ImgHash}]}), + ?recv1(#presence{from = Peer, type = undefined, + sub_els = [#vcard_xupdate{photo = undefined}]}), disconnect(Config). stats(Config) -> @@ -873,16 +873,16 @@ pubsub(Config) -> roster_subscribe_master(Config) -> send(Config, #presence{}), - #presence{} = recv(), + ?recv1(#presence{}), wait_for_slave(Config), Peer = ?config(slave, Config), LPeer = jlib:jid_remove_resource(Peer), send(Config, #presence{type = subscribe, to = LPeer}), - Push1 = #iq{type = set, + Push1 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ ask = subscribe, subscription = none, - jid = LPeer}]}]} = recv(), + jid = LPeer}]}]}), send(Config, make_iq_result(Push1)), {Push2, _} = ?recv2( #iq{type = set, @@ -891,19 +891,19 @@ roster_subscribe_master(Config) -> jid = LPeer}]}]}, #presence{type = subscribed, from = LPeer}), send(Config, make_iq_result(Push2)), - #presence{type = undefined, from = Peer} = recv(), + ?recv1(#presence{type = undefined, from = Peer}), %% BUG: ejabberd sends previous push again. Is it ok? - Push3 = #iq{type = set, + Push3 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = to, - jid = LPeer}]}]} = recv(), + jid = LPeer}]}]}), send(Config, make_iq_result(Push3)), - #presence{type = subscribe, from = LPeer} = recv(), + ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), - Push4 = #iq{type = set, + Push4 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = both, - jid = LPeer}]}]} = recv(), + jid = LPeer}]}]}), send(Config, make_iq_result(Push4)), %% Move into a group Groups = [<<"A">>, <<"B">>], @@ -920,28 +920,28 @@ roster_subscribe_master(Config) -> #iq{sub_els = [#roster{items = [#roster_item{groups = G1}]}]} = Push5, Groups = lists:sort(G1), wait_for_slave(Config), - #presence{type = unavailable, from = Peer} = recv(), + ?recv1(#presence{type = unavailable, from = Peer}), disconnect(Config). roster_subscribe_slave(Config) -> send(Config, #presence{}), - #presence{} = recv(), + ?recv1(#presence{}), wait_for_master(Config), Peer = ?config(master, Config), LPeer = jlib:jid_remove_resource(Peer), - #presence{type = subscribe, from = LPeer} = recv(), + ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), - Push1 = #iq{type = set, + Push1 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ subscription = from, - jid = LPeer}]}]} = recv(), + jid = LPeer}]}]}), send(Config, make_iq_result(Push1)), send(Config, #presence{type = subscribe, to = LPeer}), - Push2 = #iq{type = set, + Push2 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ ask = subscribe, subscription = from, - jid = LPeer}]}]} = recv(), + jid = LPeer}]}]}), send(Config, make_iq_result(Push2)), {Push3, _} = ?recv2( #iq{type = set, @@ -950,7 +950,7 @@ roster_subscribe_slave(Config) -> jid = LPeer}]}]}, #presence{type = subscribed, from = LPeer}), send(Config, make_iq_result(Push3)), - #presence{type = undefined, from = Peer} = recv(), + ?recv1(#presence{type = undefined, from = Peer}), wait_for_master(Config), disconnect(Config). @@ -993,9 +993,9 @@ roster_remove_slave(Config) -> Peer = ?config(master, Config), LPeer = jlib:jid_remove_resource(Peer), send(Config, #presence{}), - #presence{from = MyJID, type = undefined} = recv(), + ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), - #presence{from = Peer, type = undefined} = recv(), + ?recv1(#presence{from = Peer, type = undefined}), %% Remove the peer from roster. Item = #roster_item{jid = LPeer, subscription = remove}, I = send(Config, #iq{type = set, sub_els = [#roster{items = [Item]}]}), @@ -1016,7 +1016,7 @@ proxy65_master(Config) -> Peer = ?config(slave, Config), wait_for_slave(Config), send(Config, #presence{}), - #presence{from = MyJID, type = undefined} = recv(), + ?recv1(#presence{from = MyJID, type = undefined}), true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy), #iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} = send_recv( @@ -1032,14 +1032,14 @@ proxy65_master(Config) -> #iq{type = set, to = Proxy, sub_els = [#bytestreams{activate = Peer, sid = SID}]}), socks5_send(Socks5, Data), - %%#presence{type = unavailable, from = Peer} = recv(), + %%?recv1(#presence{type = unavailable, from = Peer}), disconnect(Config). proxy65_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), send(Config, #presence{}), - #presence{from = MyJID, type = undefined} = recv(), + ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), {StreamHost, SID, Data} = get_event(Config), Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}), @@ -1070,14 +1070,14 @@ muc_master(Config) -> %% 4. The room subject %% 5. Live messages, presence updates, new user joins, etc. %% As this is the newly created room, we receive only the 2nd stanza. - #presence{ + ?recv1(#presence{ from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ status_codes = Codes, items = [#muc_item{role = moderator, jid = MyJID, - affiliation = owner}]}]} = recv(), + affiliation = owner}]}]}), %% 110 -> Inform user that presence refers to itself %% 201 -> Inform user that a new room has been created [110, 201] = lists:sort(Codes), @@ -1122,17 +1122,17 @@ muc_master(Config) -> %% Set subject send(Config, #message{to = Room, type = groupchat, body = [#text{data = Subject}]}), - #message{from = MyNickJID, type = groupchat, - body = [#text{data = Subject}]} = recv(), + ?recv1(#message{from = MyNickJID, type = groupchat, + body = [#text{data = Subject}]}), %% Sending messages (and thus, populating history for our peer) lists:foreach( fun(N) -> Text = #text{data = jlib:integer_to_binary(N)}, I = send(Config, #message{to = Room, body = [Text], type = groupchat}), - #message{from = MyNickJID, id = I, + ?recv1(#message{from = MyNickJID, id = I, type = groupchat, - body = [Text]} = recv() + body = [Text]}) end, lists:seq(1, 5)), %% Inviting the peer send(Config, #message{to = Room, type = normal, @@ -1141,17 +1141,17 @@ muc_master(Config) -> invites = [#muc_invite{to = PeerJID}]}]}), %% Peer is joining - #presence{from = PeerNickJID, + ?recv1(#presence{from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = visitor, jid = PeerJID, - affiliation = none}]}]} = recv(), + affiliation = none}]}]}), %% Receiving a voice request - #message{from = Room, + ?recv1(#message{from = Room, sub_els = [#xdata{type = form, instructions = [_], - fields = VoiceReqFs}]} = recv(), + fields = VoiceReqFs}]}), %% Approving the voice request ReplyVoiceReqFs = lists:map( @@ -1175,14 +1175,14 @@ muc_master(Config) -> sub_els = [#xdata{type = submit, fields = ReplyVoiceReqFs}]}), %% Peer is becoming a participant - #presence{from = PeerNickJID, + ?recv1(#presence{from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = participant, jid = PeerJID, - affiliation = none}]}]} = recv(), + affiliation = none}]}]}), %% Receive private message from the peer - #message{from = PeerNickJID, body = [#text{data = Subject}]} = recv(), + ?recv1(#message{from = PeerNickJID, body = [#text{data = Subject}]}), %% Granting membership to the peer and localhost server I1 = send(Config, #iq{type = set, to = Room, @@ -1194,17 +1194,17 @@ muc_master(Config) -> jid = PeerBareJID, affiliation = member}]}]}), %% Peer became a member - #presence{from = PeerNickJID, + ?recv1(#presence{from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{affiliation = member, jid = PeerJID, - role = participant}]}]} = recv(), + role = participant}]}]}), %% BUG: We should not receive any sub_els! - #iq{type = result, id = I1, sub_els = [_|_]} = recv(), + ?recv1(#iq{type = result, id = I1, sub_els = [_|_]}), %% Receive groupchat message from the peer - #message{type = groupchat, from = PeerNickJID, - body = [#text{data = Subject}]} = recv(), + ?recv1(#message{type = groupchat, from = PeerNickJID, + body = [#text{data = Subject}]}), %% Kick the peer I2 = send(Config, #iq{type = set, to = Room, @@ -1213,14 +1213,14 @@ muc_master(Config) -> role = none}]}]}), %% Got notification the peer is kicked %% 307 -> Inform user that he or she has been kicked from the room - #presence{from = PeerNickJID, type = unavailable, + ?recv1(#presence{from = PeerNickJID, type = unavailable, sub_els = [#muc_user{ status_codes = [307], items = [#muc_item{affiliation = member, jid = PeerJID, - role = none}]}]} = recv(), + role = none}]}]}), %% BUG: We should not receive any sub_els! - #iq{type = result, id = I2, sub_els = [_|_]} = recv(), + ?recv1(#iq{type = result, id = I2, sub_els = [_|_]}), %% Destroying the room I3 = send(Config, #iq{type = set, to = Room, @@ -1228,13 +1228,13 @@ muc_master(Config) -> destroy = #muc_owner_destroy{ reason = Subject}}]}), %% Kicked off - #presence{from = MyNickJID, type = unavailable, + ?recv1(#presence{from = MyNickJID, type = unavailable, sub_els = [#muc_user{items = [#muc_item{role = none, affiliation = none}], destroy = #muc_user_destroy{ - reason = Subject}}]} = recv(), + reason = Subject}}]}), %% BUG: We should not receive any sub_els! - #iq{type = result, id = I3, sub_els = [_|_]} = recv(), + ?recv1(#iq{type = result, id = I3, sub_els = [_|_]}), disconnect(Config). muc_slave(Config) -> @@ -1250,10 +1250,10 @@ muc_slave(Config) -> Subject = ?config(room_subject, Config), Localhost = jlib:make_jid(<<"">>, <<"localhost">>, <<"">>), %% Receive an invite from the peer - #message{from = Room, type = normal, + ?recv1(#message{from = Room, type = normal, sub_els = [#muc_user{invites = - [#muc_invite{from = PeerJID}]}]} = recv(), + [#muc_invite{from = PeerJID}]}]}), %% But before joining we discover the MUC service first %% to check if the room is in the disco list #iq{type = result, @@ -1269,33 +1269,33 @@ muc_slave(Config) -> %% Now joining send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}), %% First presence is from the participant, i.e. from the peer - #presence{ + ?recv1(#presence{ from = PeerNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ status_codes = [], items = [#muc_item{role = moderator, - affiliation = owner}]}]} = recv(), + affiliation = owner}]}]}), %% The next is the self-presence (code 110 means it) - #presence{ + ?recv1(#presence{ from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ status_codes = [110], items = [#muc_item{role = visitor, - affiliation = none}]}]} = recv(), + affiliation = none}]}]}), %% Receive the room subject - #message{from = PeerNickJID, type = groupchat, + ?recv1(#message{from = PeerNickJID, type = groupchat, body = [#text{data = Subject}], - sub_els = [#delay{}, #legacy_delay{}]} = recv(), + sub_els = [#delay{}, #legacy_delay{}]}), %% Receive MUC history lists:foreach( fun(N) -> Text = #text{data = jlib:integer_to_binary(N)}, - #message{from = PeerNickJID, + ?recv1(#message{from = PeerNickJID, type = groupchat, body = [Text], - sub_els = [#delay{}, #legacy_delay{}]} = recv() + sub_els = [#delay{}, #legacy_delay{}]}) end, lists:seq(1, 5)), %% Sending a voice request VoiceReq = #xdata{ @@ -1310,20 +1310,20 @@ muc_slave(Config) -> values = [<<"participant">>]}]}, send(Config, #message{to = Room, sub_els = [VoiceReq]}), %% Becoming a participant - #presence{from = MyNickJID, + ?recv1(#presence{from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = participant, - affiliation = none}]}]} = recv(), + affiliation = none}]}]}), %% Sending private message to the peer send(Config, #message{to = PeerNickJID, body = [#text{data = Subject}]}), %% Becoming a member - #presence{from = MyNickJID, + ?recv1(#presence{from = MyNickJID, sub_els = [#vcard_xupdate{}, #muc_user{ items = [#muc_item{role = participant, - affiliation = member}]}]} = recv(), + affiliation = member}]}]}), %% Retrieving a member list #iq{type = result, sub_els = [#muc_admin{items = MemberList}]} = send_recv(Config, @@ -1338,15 +1338,15 @@ muc_slave(Config) -> send(Config, #message{to = Room, type = groupchat, body = [#text{data = Subject}]}), %% Receive this message back - #message{type = groupchat, from = MyNickJID, - body = [#text{data = Subject}]} = recv(), + ?recv1(#message{type = groupchat, from = MyNickJID, + body = [#text{data = Subject}]}), %% We're kicked off %% 307 -> Inform user that he or she has been kicked from the room - #presence{from = MyNickJID, type = unavailable, + ?recv1(#presence{from = MyNickJID, type = unavailable, sub_els = [#muc_user{ status_codes = [307], items = [#muc_item{affiliation = member, - role = none}]}]} = recv(), + role = none}]}]}), disconnect(Config). muc_register_nick(Config, MUC, PrevNick, Nick) -> @@ -1381,7 +1381,7 @@ muc_register_nick(Config, MUC, PrevNick, Nick) -> send_recv(Config, #iq{type = get, to = MUC, sub_els = [#register{}]}), #xdata_field{type = 'text-single', var = <<"nick">>, - values = [Nick]} = + values = [Nick]} = lists:keyfind(<<"nick">>, #xdata_field.var, FsWithNick). muc_register_master(Config) -> @@ -1415,11 +1415,11 @@ announce_master(Config) -> MotdJID = jlib:jid_replace_resource(ServerJID, <<"announce/motd">>), MotdText = #text{data = <<"motd">>}, send(Config, #presence{}), - #presence{from = MyJID} = recv(), + ?recv1(#presence{from = MyJID}), %% Set message of the day send(Config, #message{to = MotdJID, body = [MotdText]}), %% Receive this message back - #message{from = ServerJID, body = [MotdText]} = recv(), + ?recv1(#message{from = ServerJID, body = [MotdText]}), disconnect(Config). announce_slave(Config) -> @@ -1461,9 +1461,9 @@ carbons_master(Config) -> Txt = #text{data = <<"body">>}, true = is_feature_advertised(Config, ?NS_CARBONS_2), send(Config, #presence{priority = 10}), - #presence{from = MyJID} = recv(), + ?recv1(#presence{from = MyJID}), wait_for_slave(Config), - #presence{from = Peer} = recv(), + ?recv1(#presence{from = Peer}), %% Enable carbons #iq{type = result, sub_els = []} = send_recv(Config, @@ -1566,7 +1566,7 @@ carbons_slave(Config) -> sub_els = [#carbons_disable{}]}), wait_for_master(Config), %% Now we should receive nothing but presence unavailable from the peer - #presence{from = Peer, type = unavailable} = recv(), + ?recv1(#presence{from = Peer, type = unavailable}), disconnect(Config). client_state_master(Config) -> @@ -1595,9 +1595,9 @@ client_state_slave(Config) -> Peer = ?config(master, Config), send(Config, #csi{type = inactive}), wait_for_master(Config), - #presence{from = Peer, sub_els = [#vcard_xupdate{}|_]} = recv(), - #message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}], - body = [#text{data = <<"body">>}]} = recv(), + ?recv1(#presence{from = Peer, sub_els = [#vcard_xupdate{}|_]}), + ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}], + body = [#text{data = <<"body">>}]}), wait_for_master(Config), send(Config, #csi{type = active}), ?recv2(#presence{from = Peer, type = unavailable, diff --git a/test/suite.erl b/test/suite.erl index 75fb15a7b8d..69bfbecefc6 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -175,6 +175,8 @@ re_register(Config) -> {atomic, ok} = ejabberd_auth:try_register(User, Server, Pass), ok. +match_failure(Received, [Match]) when is_list(Match)-> + ct:fail("Received input:~n~n~p~n~ndon't match expected patterns:~n~n~s", [Received, Match]); match_failure(Received, Matches) -> ct:fail("Received input:~n~n~p~n~ndon't match expected patterns:~n~n~p", [Received, Matches]). diff --git a/test/suite.hrl b/test/suite.hrl index 31e21ee5f66..5463575a829 100644 --- a/test/suite.hrl +++ b/test/suite.hrl @@ -17,6 +17,15 @@ -define(EJABBERD_CT_URI, <<"http://www.process-one.net/en/ejabberd_ct/">>). +-define(recv1(P1), + P1 = (fun() -> + V = recv(), + case V of + P1 -> V; + _ -> suite:match_failure([V], [??P1]) + end + end)()). + -define(recv2(P1, P2), (fun() -> case {R1 = recv(), R2 = recv()} of @@ -24,7 +33,9 @@ {P2, P1} -> {R2, R1}; {P1, V1} -> suite:match_failure([V1], [P2]); {P2, V2} -> suite:match_failure([V2], [P1]); - {V3, V4} -> suite:match_failure([V3, V4], [P1, P2]) + {V3, P1} -> suite:match_failure([V3], [P2]); + {V4, P2} -> suite:match_failure([V4], [P1]); + {V5, V6} -> suite:match_failure([V5, V6], [P1, P2]) end end)()). From b9fdcc3985278b3ea108786c04c532b38b754bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 9 Apr 2015 17:14:30 +0200 Subject: [PATCH 007/695] Add ability to configure parameters used by "make test" with test/config.ctc --- rebar.config.script | 13 ++++++++-- test/ejabberd_SUITE_data/ejabberd.yml | 24 +++++++++--------- test/suite.erl | 36 +++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index 37ee5acbb7f..2c42c961d32 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -164,12 +164,21 @@ ElixirConfig = case lists:keysearch(elixir, 1, Cfg) of {ok, Cwd} = file:get_cwd(), +TestConfigFile = filename:join([Cwd, "test", "config.ctc"]), +TestConfig = case file:read_file_info(TestConfigFile) of + {ok, _} -> + "-userconfig ct_config_plain " ++ TestConfigFile ++ " "; + _ -> + "" + end, + Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++ [{src_dirs, [asn1, src | SrcDirs]}]}, {sub_dirs, ["rel"]}, {keep_build_info, true}, - {ct_extra_params, "-include " - ++ filename:join([Cwd, "tools"])}, + {ct_extra_params, "-ct_hooks cth_surefire " + ++ TestConfig + ++ "-include " ++ filename:join([Cwd, "tools"])}, {xref_warnings, false}, {xref_checks, []}, {xref_queries, diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index b23c6927101..58f90c80265 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -1,12 +1,12 @@ host_config: "pgsql.localhost": - odbc_username: "ejabberd_test" + odbc_username: "@@pgsql_user@@" odbc_type: pgsql - odbc_server: "localhost" - odbc_port: 5432 + odbc_server: "@@pgsql_server@@" + odbc_port: @@pgsql_port@@ odbc_pool_size: 1 - odbc_password: "ejabberd_test" - odbc_database: "ejabberd_test" + odbc_password: "@@pgsql_pass@@" + odbc_database: "@@pgsql_db@@" auth_method: odbc modules: mod_announce: @@ -106,13 +106,13 @@ Welcome to this XMPP server." mod_time: [] mod_version: [] "mysql.localhost": - odbc_username: "ejabberd_test" + odbc_username: "@@mysql_user@@" odbc_type: mysql - odbc_server: "localhost" - odbc_port: 3306 + odbc_server: "@@mysql_server@@" + odbc_port: @@mysql_port@@ odbc_pool_size: 1 - odbc_password: "ejabberd_test" - odbc_database: "ejabberd_test" + odbc_password: "@@mysql_pass@@" + odbc_database: "@@mysql_db@@" auth_method: odbc modules: mod_announce: @@ -331,7 +331,7 @@ define_macro: language: "en" listen: - - port: 5222 + port: @@c2s_port@@ module: ejabberd_c2s max_stanza_size: 65536 certfile: CERTFILE @@ -343,7 +343,7 @@ listen: port: 5269 module: ejabberd_s2s_in - - port: 5280 + port: @@web_port@@ module: ejabberd_http captcha: true loglevel: 4 diff --git a/test/suite.erl b/test/suite.erl index 69bfbecefc6..3b5d402c83b 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -21,13 +21,30 @@ init_config(Config) -> PrivDir = proplists:get_value(priv_dir, Config), [_, _|Tail] = lists:reverse(filename:split(DataDir)), BaseDir = filename:join(lists:reverse(Tail)), - ConfigPath = filename:join([DataDir, "ejabberd.yml"]), + ConfigPathTpl = filename:join([DataDir, "ejabberd.yml"]), LogPath = filename:join([PrivDir, "ejabberd.log"]), SASLPath = filename:join([PrivDir, "sasl.log"]), MnesiaDir = filename:join([PrivDir, "mnesia"]), CertFile = filename:join([DataDir, "cert.pem"]), {ok, CWD} = file:get_cwd(), {ok, _} = file:copy(CertFile, filename:join([CWD, "cert.pem"])), + {ok, CfgContentTpl} = file:read_file(ConfigPathTpl), + CfgContent = process_config_tpl(CfgContentTpl, [ + {c2s_port, 5222}, + {web_port, 5280}, + {mysql_server, <<"localhost">>}, + {mysql_port, 3306}, + {mysql_db, <<"ejabberd_test">>}, + {mysql_user, <<"ejabberd_test">>}, + {mysql_pass, <<"ejabberd_test">>}, + {pgsql_server, <<"localhost">>}, + {pgsql_port, 5432}, + {pgsql_db, <<"ejabberd_test">>}, + {pgsql_user, <<"ejabberd_test">>}, + {pgsql_pass, <<"ejabberd_test">>} + ]), + ConfigPath = filename:join([CWD, "ejabberd.yml"]), + ok = file:write_file(ConfigPath, CfgContent), ok = application:load(sasl), ok = application:load(mnesia), ok = application:load(ejabberd), @@ -35,7 +52,7 @@ init_config(Config) -> application:set_env(ejabberd, log_path, LogPath), application:set_env(sasl, sasl_error_logger, {file, SASLPath}), application:set_env(mnesia, dir, MnesiaDir), - [{server_port, 5222}, + [{server_port, ct:get_config(c2s_port, 5222)}, {server_host, "localhost"}, {server, ?COMMON_VHOST}, {user, <<"test_single">>}, @@ -50,6 +67,21 @@ init_config(Config) -> {password, <<"password">>} |Config]. +process_config_tpl(Content, []) -> + Content; +process_config_tpl(Content, [{Name, DefaultValue} | Rest]) -> + Val = case ct:get_config(Name, DefaultValue) of + V1 when is_integer(V1) -> + integer_to_binary(V1); + V2 when is_atom(V2) -> + atom_to_binary(V2, latin1); + V3 -> + V3 + end, + NewContent = binary:replace(Content, <<"@@",(atom_to_binary(Name, latin1))/binary, "@@">>, Val), + process_config_tpl(NewContent, Rest). + + connect(Config) -> {ok, Sock} = ejabberd_socket:connect( ?config(server_host, Config), From 25449a076fa2c338f243ee9532820d9aa1eed7ad Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 10 Apr 2015 16:02:45 +0200 Subject: [PATCH 008/695] Clean multicast routing code detected by xref --- src/ejabberd_router_multicast.erl | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index e438fefdb99..9cd7dd3dd67 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -196,42 +196,18 @@ do_route(From, Domain, Destinations, Packet) -> [jlib:jid_to_string(To) || To <- Destinations], Packet]), - {Groups, Rest} = lists:foldr( - fun(Dest, {Groups1, Rest1}) -> - case ejabberd_sm:get_session_pid(Dest#jid.luser, Dest#jid.lserver, Dest#jid.lresource) of - none -> - {Groups1, [Dest|Rest1]}; - Pid -> - Node = node(Pid), - if Node /= node() -> - {dict:append(Node, Dest, Groups1), Rest1}; - true -> - {Groups1, [Dest|Rest1]} - end - end - end, {dict:new(), []}, Destinations), - - dict:map( - fun(Node, [Single]) -> - ejabberd_cluster:send({ejabberd_sm, Node}, - {route, From, Single, Packet}); - (Node, Dests) -> - ejabberd_cluster:send({ejabberd_sm, Node}, - {route_multiple, From, Dests, Packet}) - end, Groups), - %% Try to find an appropriate multicast service case mnesia:dirty_read(route_multicast, Domain) of %% If no multicast service is available in this server, send manually - [] -> do_route_normal(From, Rest, Packet); + [] -> do_route_normal(From, Destinations, Packet); %% If available, send the packet using multicast service [R] -> case R#route_multicast.pid of Pid when is_pid(Pid) -> - Pid ! {route_trusted, From, Rest, Packet}; - _ -> do_route_normal(From, Rest, Packet) + Pid ! {route_trusted, From, Destinations, Packet}; + _ -> do_route_normal(From, Destinations, Packet) end end. From b67af5e036e359f6cfc877c2617d9b3c3d877c89 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 14 Apr 2015 15:46:43 +0200 Subject: [PATCH 009/695] Fix nick logging in mod_muc_log plaintext (#522) --- src/mod_muc_log.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 47b21a7006e..d94151418db 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -381,6 +381,11 @@ set_filemode(Fn, {FileMode, FileGroup}) -> ok = file:change_mode(Fn, list_to_integer(integer_to_list(FileMode), 8)), ok = file:change_group(Fn, FileGroup). +htmlize_nick(Nick1, html) -> + htmlize(<<"<", Nick1/binary, ">">>, html); +htmlize_nick(Nick1, plaintext) -> + htmlize(<>, plaintext). + add_message_to_log(Nick1, Message, RoomJID, Opts, State) -> #logstate{out_dir = OutDir, dir_type = DirType, @@ -391,7 +396,7 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, State, Room = get_room_info(RoomJID, Opts), Nick = htmlize(Nick1, FileFormat), - Nick2 = htmlize(<<"<", Nick1/binary, ">">>, FileFormat), + Nick2 = htmlize_nick(Nick1, FileFormat), Now = now(), TimeStamp = case Timezone of local -> calendar:now_to_local_time(Now); From e408276283038e15d009a2b4a6a08c1092d0b799 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 14 Apr 2015 20:22:34 +0200 Subject: [PATCH 010/695] Don't forget gen_tcp:listen/2 options Fixes #530. --- src/ejabberd_listener.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index a4ccbe84ebb..0cfca0aa0b2 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -202,7 +202,8 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) -> {nodelay, true}, {send_timeout, ?TCP_SEND_TIMEOUT}, {send_timeout_close, true}, - {keepalive, true}]), + {keepalive, true} | + SockOpts]), case Res of {ok, ListenSocket} -> ListenSocket; From a1f81057cac8d3cccd24e48c43f131704f9461a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 15 Apr 2015 10:33:25 +0200 Subject: [PATCH 011/695] Enable websocket connection in default config file --- ejabberd.yml.example | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 0d4cbb1a244..4bf2dcffd57 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -161,8 +161,9 @@ listen: - port: 5280 module: ejabberd_http - ## request_handlers: - ## "/pub/archive": mod_http_fileserver + request_handlers: + "/websocket": ejabberd_http_ws + ## "/pub/archive": mod_http_fileserver web_admin: true http_poll: true http_bind: true From ba69c469b551e77929bd1a6eb3fd16a82ef13687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 15 Apr 2015 10:47:10 +0200 Subject: [PATCH 012/695] Remove http_poll module For couple years browsers did limit ability to change cookies from js for different domains, this made http_poll connections practically not usuable. I don't think this module is used at all so it's time to put it to rest. --- ejabberd.yml.example | 1 - src/ejabberd_c2s.erl | 5 +- src/ejabberd_http.erl | 10 +- src/ejabberd_http_poll.erl | 425 ------------------------------------- src/ejabberd_socket.erl | 8 +- src/ejabberd_sup.erl | 11 - src/ejabberd_web_admin.erl | 5 +- 7 files changed, 9 insertions(+), 456 deletions(-) delete mode 100644 src/ejabberd_http_poll.erl diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 4bf2dcffd57..5f577d1ad5b 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -165,7 +165,6 @@ listen: "/websocket": ejabberd_http_ws ## "/pub/archive": mod_http_fileserver web_admin: true - http_poll: true http_bind: true ## register: true captcha: true diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 7e83fb8c153..4603af9985b 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1798,7 +1798,7 @@ print_state(State = #state{pres_t = T, pres_f = F, pres_a = A}) -> pres_f = {pres_f, ?SETS:size(F)}, pres_a = {pres_a, ?SETS:size(A)} }. - + %%---------------------------------------------------------------------- %% Func: terminate/3 %% Purpose: Shutdown the fsm @@ -1881,7 +1881,7 @@ send_text(StateData, Text) when StateData#state.mgmt_state == pending -> ?DEBUG("Cannot send text while waiting for resumption: ~p", [Text]); send_text(StateData, Text) when StateData#state.xml_socket -> ?DEBUG("Send Text on stream = ~p", [Text]), - (StateData#state.sockmod):send_xml(StateData#state.socket, + (StateData#state.sockmod):send_xml(StateData#state.socket, {xmlstreamraw, Text}); send_text(StateData, Text) when StateData#state.mgmt_state == active -> ?DEBUG("Send XML on stream = ~p", [Text]), @@ -2024,7 +2024,6 @@ get_conn_type(StateData) -> gen_tcp -> c2s_compressed; p1_tls -> c2s_compressed_tls end; - ejabberd_http_poll -> http_poll; ejabberd_http_bind -> http_bind; _ -> unknown end. diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index a06d3f99bf4..4e7f4b554eb 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -56,7 +56,7 @@ %% to have the module test_web handle requests with %% paths starting with "/test/module": %% - %% {5280, ejabberd_http, [http_poll, web_admin, + %% {5280, ejabberd_http, [http_bind, web_admin, %% {request_handlers, [{["test", "module"], mod_test_web}]}]} %% request_handlers = [], @@ -135,10 +135,6 @@ init({SockMod, Socket}, Opts) -> true -> [{[<<"http-bind">>], mod_http_bind}]; false -> [] end, - Poll = case proplists:get_bool(http_poll, Opts) of - true -> [{[<<"http-poll">>], ejabberd_http_poll}]; - false -> [] - end, XMLRPC = case proplists:get_bool(xmlrpc, Opts) of true -> [{[], ejabberd_xmlrpc}]; false -> [] @@ -151,7 +147,7 @@ init({SockMod, Socket}, Opts) -> Mod} || {Path, Mod} <- Hs] end, []), RequestHandlers = DefinedHandlers ++ Captcha ++ Register ++ - Admin ++ Bind ++ Poll ++ XMLRPC, + Admin ++ Bind ++ XMLRPC, ?DEBUG("S: ~p~n", [RequestHandlers]), DefaultHost = gen_mod:get_opt(default_host, Opts, fun(A) -> A end, undefined), @@ -862,7 +858,7 @@ transform_listen_option(web_admin, Opts) -> transform_listen_option(http_bind, Opts) -> [{http_bind, true}|Opts]; transform_listen_option(http_poll, Opts) -> - [{http_poll, true}|Opts]; + Opts; transform_listen_option({request_handlers, Hs}, Opts) -> Hs1 = lists:map( fun({PList, Mod}) when is_list(PList) -> diff --git a/src/ejabberd_http_poll.erl b/src/ejabberd_http_poll.erl deleted file mode 100644 index 174c7821169..00000000000 --- a/src/ejabberd_http_poll.erl +++ /dev/null @@ -1,425 +0,0 @@ -%%%---------------------------------------------------------------------- -%%% File : ejabberd_http_poll.erl -%%% Author : Alexey Shchepin -%%% Purpose : HTTP Polling support (XEP-0025) -%%% Created : 4 Mar 2004 by Alexey Shchepin -%%% -%%% -%%% ejabberd, Copyright (C) 2002-2015 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., -%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -%%% -%%%---------------------------------------------------------------------- - --module(ejabberd_http_poll). - --author('alexey@process-one.net'). - --behaviour(gen_fsm). - -%% External exports --export([start_link/3, init/1, handle_event/3, - handle_sync_event/4, code_change/4, handle_info/3, - terminate/3, send/2, setopts/2, sockname/1, peername/1, - controlling_process/2, close/1, process/2]). - --include("ejabberd.hrl"). --include("logger.hrl"). - --include("jlib.hrl"). - --include("ejabberd_http.hrl"). - --record(http_poll, {id :: pid() | binary(), pid :: pid()}). - --type poll_socket() :: #http_poll{}. --export_type([poll_socket/0]). - --record(state, - {id, key, socket, output = [], input = <<"">>, - waiting_input = false, last_receiver, http_poll_timeout, - timer}). - -%-define(DBGFSM, true). - --ifdef(DBGFSM). - --define(FSMOPTS, [{debug, [trace]}]). - --else. - --define(FSMOPTS, []). - --endif. - --define(HTTP_POLL_TIMEOUT, 300). - --define(CT, - {<<"Content-Type">>, <<"text/xml; charset=utf-8">>}). - --define(BAD_REQUEST, - [?CT, {<<"Set-Cookie">>, <<"ID=-3:0; expires=-1">>}]). - -%%%---------------------------------------------------------------------- -%%% API -%%%---------------------------------------------------------------------- -start(ID, Key, IP) -> - mnesia:create_table(http_poll, - [{ram_copies, [node()]}, - {attributes, record_info(fields, http_poll)}]), - supervisor:start_child(ejabberd_http_poll_sup, [ID, Key, IP]). - -start_link(ID, Key, IP) -> - gen_fsm:start_link(?MODULE, [ID, Key, IP], ?FSMOPTS). - -send({http_poll, FsmRef, _IP}, Packet) -> - gen_fsm:sync_send_all_state_event(FsmRef, - {send, Packet}). - -setopts({http_poll, FsmRef, _IP}, Opts) -> - case lists:member({active, once}, Opts) of - true -> - gen_fsm:send_all_state_event(FsmRef, - {activate, self()}); - _ -> ok - end. - -sockname(_Socket) -> {ok, {{0, 0, 0, 0}, 0}}. - -peername({http_poll, _FsmRef, IP}) -> {ok, IP}. - -controlling_process(_Socket, _Pid) -> ok. - -close({http_poll, FsmRef, _IP}) -> - catch gen_fsm:sync_send_all_state_event(FsmRef, close). - -process([], - #request{data = Data, ip = IP} = _Request) -> - case catch parse_request(Data) of - {ok, ID1, Key, NewKey, Packet} -> - ID = if - (ID1 == <<"0">>) or (ID1 == <<"mobile">>) -> - NewID = p1_sha:sha(term_to_binary({now(), make_ref()})), - {ok, Pid} = start(NewID, <<"">>, IP), - mnesia:transaction( - fun() -> - mnesia:write(#http_poll{id = NewID, pid = Pid}) - end), - NewID; - true -> - ID1 - end, - case http_put(ID, Key, NewKey, Packet) of - {error, not_exists} -> - {200, ?BAD_REQUEST, <<"">>}; - {error, bad_key} -> - {200, ?BAD_REQUEST, <<"">>}; - ok -> - receive - after 100 -> ok - end, - case http_get(ID) of - {error, not_exists} -> - {200, ?BAD_REQUEST, <<"">>}; - {ok, OutPacket} -> - if - ID == ID1 -> - Cookie = <<"ID=", ID/binary, "; expires=-1">>, - {200, [?CT, {<<"Set-Cookie">>, Cookie}], - OutPacket}; - ID1 == <<"mobile">> -> - {200, [?CT], [ID, $\n, OutPacket]}; - true -> - Cookie = <<"ID=", ID/binary, "; expires=-1">>, - {200, [?CT, {<<"Set-Cookie">>, Cookie}], - OutPacket} - end - end - end; - _ -> - HumanHTMLxmlel = get_human_html_xmlel(), - {200, [?CT, {<<"Set-Cookie">>, <<"ID=-2:0; expires=-1">>}], HumanHTMLxmlel} - end; -process(_, _Request) -> - {400, [], - #xmlel{name = <<"h1">>, attrs = [], - children = [{xmlcdata, <<"400 Bad Request">>}]}}. - -%% Code copied from mod_http_bind.erl and customized -get_human_html_xmlel() -> - Heading = <<"ejabberd ", - (iolist_to_binary(atom_to_list(?MODULE)))/binary>>, - #xmlel{name = <<"html">>, - attrs = - [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}], - children = - [#xmlel{name = <<"head">>, attrs = [], - children = - [#xmlel{name = <<"title">>, attrs = [], - children = [{xmlcdata, Heading}]}]}, - #xmlel{name = <<"body">>, attrs = [], - children = - [#xmlel{name = <<"h1">>, attrs = [], - children = [{xmlcdata, Heading}]}, - #xmlel{name = <<"p">>, attrs = [], - children = - [{xmlcdata, <<"An implementation of ">>}, - #xmlel{name = <<"a">>, - attrs = - [{<<"href">>, - <<"http://xmpp.org/extensions/xep-0025.html">>}], - children = - [{xmlcdata, - <<"Jabber HTTP Polling (XEP-0025)">>}]}]}, - #xmlel{name = <<"p">>, attrs = [], - children = - [{xmlcdata, - <<"This web page is only informative. To " - "use HTTP-Poll you need a Jabber/XMPP " - "client that supports it.">>}]}]}]}. - -%%%---------------------------------------------------------------------- -%%% Callback functions from gen_fsm -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, StateName, StateData} | -%% {ok, StateName, StateData, Timeout} | -%% ignore | -%% {stop, StopReason} -%%---------------------------------------------------------------------- -init([ID, Key, IP]) -> - ?INFO_MSG("started: ~p", [{ID, Key, IP}]), - Opts = ejabberd_c2s_config:get_c2s_limits(), - HTTPPollTimeout = ejabberd_config:get_option( - {http_poll_timeout, ?MYNAME}, - fun(I) when is_integer(I), I>0 -> I end, - ?HTTP_POLL_TIMEOUT) * 1000, - Socket = {http_poll, self(), IP}, - ejabberd_socket:start(ejabberd_c2s, ?MODULE, Socket, - Opts), - Timer = erlang:start_timer(HTTPPollTimeout, self(), []), - {ok, loop, - #state{id = ID, key = Key, socket = Socket, - http_poll_timeout = HTTPPollTimeout, timer = Timer}}. - -%%---------------------------------------------------------------------- -%% Func: StateName/2 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: StateName/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- -%state_name(Event, From, StateData) -> -% Reply = ok, -% {reply, Reply, state_name, StateData}. - -%%---------------------------------------------------------------------- -%% Func: handle_event/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- -handle_event({activate, From}, StateName, StateData) -> - case StateData#state.input of - <<"">> -> - {next_state, StateName, - StateData#state{waiting_input = {From, ok}}}; - Input -> - Receiver = From, - Receiver ! - {tcp, StateData#state.socket, Input}, - {next_state, StateName, - StateData#state{input = <<"">>, waiting_input = false, - last_receiver = Receiver}} - end; -handle_event(_Event, StateName, StateData) -> - {next_state, StateName, StateData}. - -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- -handle_sync_event({send, Packet}, _From, StateName, - StateData) -> - Packet2 = iolist_to_binary(Packet), - Output = StateData#state.output ++ [Packet2], - Reply = ok, - {reply, Reply, StateName, - StateData#state{output = Output}}; -handle_sync_event(stop, _From, _StateName, StateData) -> - Reply = ok, {stop, normal, Reply, StateData}; -handle_sync_event({http_put, Key, NewKey, Packet}, - _From, StateName, StateData) -> - Allow = case StateData#state.key of - <<"">> -> true; - OldKey -> - NextKey = jlib:encode_base64((p1_sha:sha1(Key))), - if OldKey == NextKey -> true; - true -> false - end - end, - if Allow -> - case StateData#state.waiting_input of - false -> - Input = <<(StateData#state.input)/binary, Packet/binary>>, - Reply = ok, - {reply, Reply, StateName, - StateData#state{input = Input, key = NewKey}}; - {Receiver, _Tag} -> - Receiver ! - {tcp, StateData#state.socket, iolist_to_binary(Packet)}, - cancel_timer(StateData#state.timer), - Timer = - erlang:start_timer(StateData#state.http_poll_timeout, - self(), []), - Reply = ok, - {reply, Reply, StateName, - StateData#state{waiting_input = false, - last_receiver = Receiver, key = NewKey, - timer = Timer}} - end; - true -> - Reply = {error, bad_key}, - {reply, Reply, StateName, StateData} - end; -handle_sync_event(http_get, _From, StateName, - StateData) -> - Reply = {ok, StateData#state.output}, - {reply, Reply, StateName, - StateData#state{output = []}}; -handle_sync_event(_Event, _From, StateName, - StateData) -> - Reply = ok, {reply, Reply, StateName, StateData}. - -code_change(_OldVsn, StateName, StateData, _Extra) -> - {ok, StateName, StateData}. - -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- -handle_info({timeout, Timer, _}, _StateName, - #state{timer = Timer} = StateData) -> - {stop, normal, StateData}; -handle_info(_, StateName, StateData) -> - {next_state, StateName, StateData}. - -%%---------------------------------------------------------------------- -%% Func: terminate/3 -%% Purpose: Shutdown the fsm -%% Returns: any -%%---------------------------------------------------------------------- -terminate(_Reason, _StateName, StateData) -> - mnesia:transaction( - fun() -> - mnesia:delete({http_poll, StateData#state.id}) - end), - case StateData#state.waiting_input of - false -> - case StateData#state.last_receiver of - undefined -> ok; - Receiver -> - Receiver ! {tcp_closed, StateData#state.socket} - end; - {Receiver, _Tag} -> - Receiver ! {tcp_closed, StateData#state.socket} - end, - catch resend_messages(StateData#state.output), - ok. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- - -http_put(ID, Key, NewKey, Packet) -> - case mnesia:dirty_read({http_poll, ID}) of - [] -> - {error, not_exists}; - [#http_poll{pid = FsmRef}] -> - gen_fsm:sync_send_all_state_event( - FsmRef, {http_put, Key, NewKey, Packet}) - end. - -http_get(ID) -> - case mnesia:dirty_read({http_poll, ID}) of - [] -> - {error, not_exists}; - [#http_poll{pid = FsmRef}] -> - gen_fsm:sync_send_all_state_event(FsmRef, http_get) - end. - -parse_request(Data) -> - Comma = str:chr(Data, $,), - Header = str:substr(Data, 1, Comma - 1), - Packet = str:substr(Data, Comma + 1, byte_size(Data)), - {ID, Key, NewKey} = case str:tokens(Header, <<";">>) of - [ID1] -> {ID1, <<"">>, <<"">>}; - [ID1, Key1] -> {ID1, Key1, Key1}; - [ID1, Key1, NewKey1] -> {ID1, Key1, NewKey1} - end, - {ok, ID, Key, NewKey, Packet}. - -cancel_timer(Timer) -> - erlang:cancel_timer(Timer), - receive {timeout, Timer, _} -> ok after 0 -> ok end. - -%% Resend the polled messages -resend_messages(Messages) -> -%% This function is used to resend messages that have been polled but not -%% delivered. - lists:foreach(fun (Packet) -> resend_message(Packet) - end, - Messages). - -resend_message(Packet) -> - #xmlel{name = Name} = ParsedPacket = - xml_stream:parse_element(Packet), - if Name == <<"iq">>; - Name == <<"message">>; - Name == <<"presence">> -> - From = get_jid(<<"from">>, ParsedPacket), - To = get_jid(<<"to">>, ParsedPacket), - ?DEBUG("Resend ~p ~p ~p~n", [From, To, ParsedPacket]), - ejabberd_router:route(From, To, ParsedPacket); - true -> ok - end. - -%% Type can be "from" or "to" -%% Parsed packet is a parsed Jabber packet. -get_jid(Type, ParsedPacket) -> - case xml:get_tag_attr(Type, ParsedPacket) of - {value, StringJid} -> jlib:string_to_jid(StringJid); - false -> jlib:make_jid(<<"">>, <<"">>, <<"">>) - end. diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index 86f6971b688..29c7774e4a2 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -50,16 +50,14 @@ -include("logger.hrl"). -include("jlib.hrl"). --type sockmod() :: ejabberd_http_poll | - ejabberd_http_bind | +-type sockmod() :: ejabberd_http_bind | ejabberd_http_ws | gen_tcp | p1_tls | ezlib. -type receiver() :: pid () | atom(). -type socket() :: pid() | inet:socket() | p1_tls:tls_socket() | ezlib:zlib_socket() | - ejabberd_http_bind:bind_socket() | - ejabberd_http_poll:poll_socket(). + ejabberd_http_bind:bind_socket(). -record(socket_state, {sockmod = gen_tcp :: sockmod(), socket = self() :: socket(), @@ -192,7 +190,7 @@ send(SocketData, Data) -> %% Can only be called when in c2s StateData#state.xml_socket is true %% This function is used for HTTP bind -%% sockmod=ejabberd_http_poll|ejabberd_http_bind or any custom module +%% sockmod=ejabberd_http_ws|ejabberd_http_bind or any custom module -spec send_xml(socket_state(), xmlel()) -> any(). send_xml(SocketData, Data) -> diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index 423f84ab954..da25af2c787 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -144,14 +144,6 @@ init([]) -> infinity, supervisor, [ejabberd_tmp_sup]}, - HTTPPollSupervisor = - {ejabberd_http_poll_sup, - {ejabberd_tmp_sup, start_link, - [ejabberd_http_poll_sup, ejabberd_http_poll]}, - permanent, - infinity, - supervisor, - [ejabberd_tmp_sup]}, FrontendSocketSupervisor = {ejabberd_frontend_socket_sup, {ejabberd_tmp_sup, start_link, @@ -183,9 +175,6 @@ init([]) -> S2SOutSupervisor, ServiceSupervisor, HTTPSupervisor, - HTTPPollSupervisor, IQSupervisor, FrontendSocketSupervisor, Listener]}}. - - diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 65bac357f49..29ecb7346ea 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1549,9 +1549,7 @@ user_info(User, Server, Query, Lang) -> c2s_compressed_tls -> <<"tls+zlib">>; http_bind -> - <<"http-bind">>; - http_poll -> - <<"http-poll">> + <<"http-bind">> end, <<" (", ConnS/binary, "://", @@ -2879,4 +2877,3 @@ make_menu_item(item, 3, URI, Name, Lang) -> %%%================================== %%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: - From 63d6d68979249afd794197f388d2b9c1bb1e29ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 19 Feb 2015 12:28:31 +0100 Subject: [PATCH 013/695] Make sure that server processed our inactive request before processing further in testing --- test/ejabberd_SUITE.erl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index bc938b82df5..1c247694cf4 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1594,6 +1594,9 @@ client_state_slave(Config) -> true = ?config(csi, Config), Peer = ?config(master, Config), send(Config, #csi{type = inactive}), + send_recv( + Config, + #iq{type = get, sub_els = [#ping{}], to = server_jid(Config)}), wait_for_master(Config), ?recv1(#presence{from = Peer, sub_els = [#vcard_xupdate{}|_]}), ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}], From a5adaf57982c44c4e226abfd4a7657be682a63c0 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Apr 2015 11:49:49 +0200 Subject: [PATCH 014/695] Revert "Hook on group message" This reverts commit b81250d667c846d30499b5284585597a35c96631. --- src/mod_muc_room.erl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index ad77ae66177..f381e845823 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2456,8 +2456,6 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> Q1 = lqueue_in({FromNick, TSPacket, HaveSubject, calendar:now_to_universal_time(TimeStamp), Size}, StateData#state.history), - ejabberd_hooks:run(offline_group_message_hook, StateData#state.server_host, - [FromJID, FromNick, StateData#state.jid, Packet]), add_to_log(text, {FromNick, Packet}, StateData), StateData#state{history = Q1}. From d6247534106c0f668ec7a5abe29a641a3064036d Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Apr 2015 11:50:10 +0200 Subject: [PATCH 015/695] Update get_password_s description with SCRAM return values --- src/ejabberd_auth.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 9985dd3de1a..991cb664b91 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -72,7 +72,7 @@ -callback get_vh_registered_users_number(binary()) -> number(). -callback get_vh_registered_users_number(binary(), opts()) -> number(). -callback get_password(binary(), binary()) -> false | binary() | {binary(), binary(), binary(), integer()}. --callback get_password_s(binary(), binary()) -> binary(). +-callback get_password_s(binary(), binary()) -> binary() | {binary(), binary(), binary(), integer()}. start() -> %% This is only executed by ejabberd_c2s for non-SASL auth client @@ -276,7 +276,7 @@ get_password(User, Server) -> end, false, auth_modules(Server)). --spec get_password_s(binary(), binary()) -> binary(). +-spec get_password_s(binary(), binary()) -> binary() | {binary(), binary(), binary(), integer()}. get_password_s(User, Server) -> case get_password(User, Server) of From 01b3defb8656ec783367096b4248855c1129b226 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 16 Apr 2015 08:45:17 +0200 Subject: [PATCH 016/695] CSI test: Fix race when slave becomes active again Make sure the server processed the slave's active request after the previous test stanzas were received by the slave and before the final Chat State notification is sent by the master. --- test/ejabberd_SUITE.erl | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 1c247694cf4..1577513ff7d 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1575,16 +1575,17 @@ client_state_master(Config) -> Message = #message{to = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}]}, wait_for_slave(Config), - %% Should be queued (but see below): - send(Config, Presence), - %% Should be sent immediately, together with the previous presence: - send(Config, Message#message{body = [#text{data = <<"body">>}]}), %% Should be dropped: send(Config, Message), %% Should be queued (but see below): - send(Config, Presence), + send(Config, Presence#presence{type = unavailable}), %% Should replace the previous presence in the queue: + send(Config, Presence), + %% Should be sent immediately, together with the previous presence: + send(Config, Message#message{body = [#text{data = <<"body">>}]}), + %% Should be queued: send(Config, Presence#presence{type = unavailable}), + %% Wait for the slave to become active. wait_for_slave(Config), %% Should be sent immediately, as the client is active again. send(Config, Message), @@ -1601,11 +1602,12 @@ client_state_slave(Config) -> ?recv1(#presence{from = Peer, sub_els = [#vcard_xupdate{}|_]}), ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}], body = [#text{data = <<"body">>}]}), - wait_for_master(Config), send(Config, #csi{type = active}), - ?recv2(#presence{from = Peer, type = unavailable, - sub_els = [#delay{}, #legacy_delay{}]}, - #message{from = Peer, thread = <<"1">>, + %% The server now flushes the queue, so we receive the following presence. + ?recv1(#presence{from = Peer, type = unavailable, + sub_els = [#delay{}, #legacy_delay{}]}), + wait_for_master(Config), + ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}]}), disconnect(Config). From b447839592703ea7238f23c2f54f098cea161422 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 16 Apr 2015 23:20:14 +0200 Subject: [PATCH 017/695] CSI test: Simplify and improve readability --- test/ejabberd_SUITE.erl | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 1577513ff7d..4606ae0fd79 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1570,42 +1570,38 @@ carbons_slave(Config) -> disconnect(Config). client_state_master(Config) -> + true = ?config(csi, Config), Peer = ?config(slave, Config), Presence = #presence{to = Peer}, - Message = #message{to = Peer, thread = <<"1">>, - sub_els = [#chatstate{type = active}]}, + ChatState = #message{to = Peer, thread = <<"1">>, + sub_els = [#chatstate{type = active}]}, + Message = ChatState#message{body = [#text{data = <<"body">>}]}, + %% Wait for the slave to become inactive. wait_for_slave(Config), %% Should be dropped: - send(Config, Message), + send(Config, ChatState), %% Should be queued (but see below): - send(Config, Presence#presence{type = unavailable}), - %% Should replace the previous presence in the queue: send(Config, Presence), - %% Should be sent immediately, together with the previous presence: - send(Config, Message#message{body = [#text{data = <<"body">>}]}), - %% Should be queued: + %% Should replace the previous presence in the queue: send(Config, Presence#presence{type = unavailable}), + %% Should be sent immediately, together with the previous presence: + send(Config, Message), %% Wait for the slave to become active. wait_for_slave(Config), - %% Should be sent immediately, as the client is active again. - send(Config, Message), + %% Should be delivered, as the client is active again: + send(Config, ChatState), disconnect(Config). client_state_slave(Config) -> - true = ?config(csi, Config), Peer = ?config(master, Config), - send(Config, #csi{type = inactive}), - send_recv( - Config, - #iq{type = get, sub_els = [#ping{}], to = server_jid(Config)}), + change_client_state(Config, inactive), wait_for_master(Config), - ?recv1(#presence{from = Peer, sub_els = [#vcard_xupdate{}|_]}), - ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}], - body = [#text{data = <<"body">>}]}), - send(Config, #csi{type = active}), - %% The server now flushes the queue, so we receive the following presence. ?recv1(#presence{from = Peer, type = unavailable, sub_els = [#delay{}, #legacy_delay{}]}), + ?recv1(#message{from = Peer, thread = <<"1">>, + body = [#text{data = <<"body">>}], + sub_els = [#chatstate{type = active}]}), + change_client_state(Config, active), wait_for_master(Config), ?recv1(#message{from = Peer, thread = <<"1">>, sub_els = [#chatstate{type = active}]}), @@ -1614,6 +1610,11 @@ client_state_slave(Config) -> %%%=================================================================== %%% Aux functions %%%=================================================================== +change_client_state(Config, NewState) -> + send(Config, #csi{type = NewState}), + send_recv(Config, #iq{type = get, to = server_jid(Config), + sub_els = [#ping{}]}). + bookmark_conference() -> #bookmark_conference{name = <<"Some name">>, autojoin = true, From afdc269825382687db46e04c5778a161ff96a9f1 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 16 Apr 2015 23:51:16 +0200 Subject: [PATCH 018/695] ejabberd_s2s_out: Remove Erlang/OTP version check The version check won't work for Erlang/OTP >= 17; and it's no longer needed, as we don't support versions older than R16 anyway. --- src/ejabberd_s2s_out.erl | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 97164326dbd..6196f136f2d 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -319,18 +319,11 @@ open_socket1(Host, Port) -> open_socket2(Type, Addr, Port) -> ?DEBUG("s2s_out: connecting to ~p:~p~n", [Addr, Port]), Timeout = outgoing_s2s_timeout(), - SockOpts = try erlang:system_info(otp_release) >= "R13B" - of - true -> [{send_timeout_close, true}]; - false -> [] - catch - _:_ -> [] - end, case catch ejabberd_socket:connect(Addr, Port, [binary, {packet, 0}, {send_timeout, ?TCP_SEND_TIMEOUT}, - {active, false}, Type - | SockOpts], + {send_timeout_close, true}, + {active, false}, Type], Timeout) of {ok, _Socket} = R -> R; From c01940f33c1b94b8ed629e1e39ef98561e705a10 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 17 Apr 2015 20:21:11 +0200 Subject: [PATCH 019/695] cyrsasl_scram: Return user name with error message Let ejabberd_c2s run the 'c2s_auth_result' hook (which needs the user name) on SCRAM authentication failure. --- src/cyrsasl_scram.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl index 1fd7c1be5f6..deef51c5760 100644 --- a/src/cyrsasl_scram.erl +++ b/src/cyrsasl_scram.erl @@ -160,7 +160,7 @@ mech_step(#state{step = 4} = State, ClientIn) -> {ok, [{username, State#state.username}], <<"v=", (jlib:encode_base64(ServerSignature))/binary>>}; - true -> {error, <<"bad-auth">>} + true -> {error, <<"bad-auth">>, State#state.username} end; _Else -> {error, <<"bad-protocol">>} end; From aa36742a406e11124eb79554f8b31eaa14e7a856 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 18 Apr 2015 11:08:05 +0200 Subject: [PATCH 020/695] mod_fail2ban: Add 'access' option for whitelisting Closes #535. --- src/mod_fail2ban.erl | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 7c9eba88a18..63c09db26f5 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -53,20 +53,25 @@ start_link(Host, Opts) -> gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). c2s_auth_result(false, _User, LServer, {Addr, _Port}) -> - BanLifetime = gen_mod:get_module_opt( - LServer, ?MODULE, c2s_auth_ban_lifetime, - fun(T) when is_integer(T), T > 0 -> T end, - ?C2S_AUTH_BAN_LIFETIME), - MaxFailures = gen_mod:get_module_opt( - LServer, ?MODULE, c2s_max_auth_failures, - fun(I) when is_integer(I), I > 0 -> I end, - ?C2S_MAX_AUTH_FAILURES), - UnbanTS = unban_timestamp(BanLifetime), - case ets:lookup(failed_auth, Addr) of - [{Addr, N, _, _}] -> - ets:insert(failed_auth, {Addr, N+1, UnbanTS, MaxFailures}); - [] -> - ets:insert(failed_auth, {Addr, 1, UnbanTS, MaxFailures}) + case is_whitelisted(LServer, Addr) of + true -> + ok; + false -> + BanLifetime = gen_mod:get_module_opt( + LServer, ?MODULE, c2s_auth_ban_lifetime, + fun(T) when is_integer(T), T > 0 -> T end, + ?C2S_AUTH_BAN_LIFETIME), + MaxFailures = gen_mod:get_module_opt( + LServer, ?MODULE, c2s_max_auth_failures, + fun(I) when is_integer(I), I > 0 -> I end, + ?C2S_MAX_AUTH_FAILURES), + UnbanTS = unban_timestamp(BanLifetime), + case ets:lookup(failed_auth, Addr) of + [{Addr, N, _, _}] -> + ets:insert(failed_auth, {Addr, N+1, UnbanTS, MaxFailures}); + [] -> + ets:insert(failed_auth, {Addr, 1, UnbanTS, MaxFailures}) + end end; c2s_auth_result(true, _User, _Server, _AddrPort) -> ok. @@ -160,6 +165,12 @@ code_change(_OldVsn, State, _Extra) -> %%%=================================================================== %%% Internal functions %%%=================================================================== +is_whitelisted(Host, Addr) -> + Access = gen_mod:get_module_opt(Host, ?MODULE, access, + fun(A) when is_atom(A) -> A end, + none), + acl:match_rule(Host, Access, Addr) == allow. + unban_timestamp(BanLifetime) -> {MegaSecs, MSecs, USecs} = now(), UnbanSecs = MegaSecs * 1000000 + MSecs + BanLifetime, From c2e6ce0f0467965e645def11e714120f01a28002 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 20 Apr 2015 15:56:37 +0200 Subject: [PATCH 021/695] Remove load_config command because is superseded by reload_config (#532) --- src/mod_admin_extra.erl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 0162a40c34c..49e6a986978 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -33,7 +33,6 @@ -export([start/2, stop/1, %% Node compile/1, - load_config/1, get_cookie/0, remove_node/1, export2odbc/2, @@ -146,11 +145,6 @@ commands() -> module = ?MODULE, function = compile, args = [{file, string}], result = {res, rescode}}, - #ejabberd_commands{name = load_config, tags = [server], - desc = "Load ejabberd configuration file", - module = ?MODULE, function = load_config, - args = [{file, string}], - result = {res, rescode}}, #ejabberd_commands{name = get_cookie, tags = [erlang], desc = "Get the Erlang cookie of this node", module = ?MODULE, function = get_cookie, @@ -547,9 +541,6 @@ commands() -> compile(File) -> compile:file(File). -load_config(Path) -> - ok = ejabberd_config:load_file(Path). - get_cookie() -> atom_to_list(erlang:get_cookie()). From e8576c23c53337af9a5fde8f66866da0923af9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 20 Apr 2015 16:16:30 +0200 Subject: [PATCH 022/695] Make s2s port configurable in test runner --- test/ejabberd_SUITE_data/ejabberd.yml | 2 +- test/suite.erl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 58f90c80265..c19e2244177 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -340,7 +340,7 @@ listen: shaper: c2s_shaper access: c2s - - port: 5269 + port: @@s2s_port@@ module: ejabberd_s2s_in - port: @@web_port@@ diff --git a/test/suite.erl b/test/suite.erl index 3b5d402c83b..fd5e175eae1 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -31,6 +31,7 @@ init_config(Config) -> {ok, CfgContentTpl} = file:read_file(ConfigPathTpl), CfgContent = process_config_tpl(CfgContentTpl, [ {c2s_port, 5222}, + {s2s_port, 5269}, {web_port, 5280}, {mysql_server, <<"localhost">>}, {mysql_port, 3306}, From fd54181435f17a2aa54306b62bac83d551ead477 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 20 Apr 2015 17:01:56 +0300 Subject: [PATCH 023/695] Fixed error replying on blocked messages --- src/ejabberd_c2s.erl | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 4603af9985b..863ce83ceab 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1680,12 +1680,17 @@ handle_info({route, From, To, of allow -> {true, Attrs, StateData}; deny -> - Err = - jlib:make_error_reply(Packet, - ?ERR_SERVICE_UNAVAILABLE), - ejabberd_router:route(To, From, - Err), - {false, Attrs, StateData} + case xml:get_attr_s(<<"type">>, Attrs) of + <<"error">> -> ok; + <<"result">> -> ok; + _ -> + Err = + jlib:make_error_reply(Packet, + ?ERR_SERVICE_UNAVAILABLE), + ejabberd_router:route(To, From, + Err) + end, + {false, Attrs, StateData} end; _ -> {true, Attrs, StateData} end, @@ -2171,15 +2176,16 @@ check_privacy_route(From, StateData, FromRoute, To, case privacy_check_packet(StateData, From, To, Packet, out) of - deny -> - Lang = StateData#state.lang, - ErrText = <<"Your active privacy list has denied " - "the routing of this stanza.">>, - Err = jlib:make_error_reply(Packet, - ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), - ejabberd_router:route(To, From, Err), - ok; - allow -> ejabberd_router:route(FromRoute, To, Packet) + deny -> + Lang = StateData#state.lang, + ErrText = <<"Your active privacy list has denied " + "the routing of this stanza.">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), + Err2 = jlib:replace_from_to(To, From, Err), + send_element(StateData, Err2), + ok; + allow -> ejabberd_router:route(FromRoute, To, Packet) end. %% Check if privacy rules allow this delivery From 94936b261e6a50a8a0581e8172301bd27d52f001 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 20 Apr 2015 22:03:18 +0200 Subject: [PATCH 024/695] Add privacy error stanza to XEP-0198 queue --- src/ejabberd_c2s.erl | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 863ce83ceab..f2d16e878ba 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1292,15 +1292,13 @@ session_established2(El, StateData) -> ejabberd_hooks:run(user_send_packet, Server, [FromJID, ToJID, NewEl]), check_privacy_route(FromJID, NewStateData, - FromJID, ToJID, NewEl), - NewStateData + FromJID, ToJID, NewEl) end; <<"message">> -> ejabberd_hooks:run(user_send_packet, Server, [FromJID, ToJID, NewEl]), check_privacy_route(FromJID, NewStateData, FromJID, - ToJID, NewEl), - NewStateData; + ToJID, NewEl); _ -> NewStateData end end, @@ -2138,37 +2136,29 @@ presence_track(From, To, Packet, StateData) -> Server = StateData#state.server, case xml:get_attr_s(<<"type">>, Attrs) of <<"unavailable">> -> - check_privacy_route(From, StateData, From, To, Packet), A = remove_element(LTo, StateData#state.pres_a), - StateData#state{pres_a = A}; + check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet); <<"subscribe">> -> - try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData), - StateData; + try_roster_subscribe(subscribe, User, Server, From, To, Packet, StateData); <<"subscribed">> -> ejabberd_hooks:run(roster_out_subscription, Server, [User, Server, To, subscribed]), check_privacy_route(From, StateData, - jlib:jid_remove_resource(From), To, Packet), - StateData; + jlib:jid_remove_resource(From), To, Packet); <<"unsubscribe">> -> - try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData), - StateData; + try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData); <<"unsubscribed">> -> ejabberd_hooks:run(roster_out_subscription, Server, [User, Server, To, unsubscribed]), check_privacy_route(From, StateData, - jlib:jid_remove_resource(From), To, Packet), - StateData; + jlib:jid_remove_resource(From), To, Packet); <<"error">> -> - check_privacy_route(From, StateData, From, To, Packet), - StateData; + check_privacy_route(From, StateData, From, To, Packet); <<"probe">> -> - check_privacy_route(From, StateData, From, To, Packet), - StateData; + check_privacy_route(From, StateData, From, To, Packet); _ -> - check_privacy_route(From, StateData, From, To, Packet), A = (?SETS):add_element(LTo, StateData#state.pres_a), - StateData#state{pres_a = A} + check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet) end. check_privacy_route(From, StateData, FromRoute, To, @@ -2183,9 +2173,10 @@ check_privacy_route(From, StateData, FromRoute, To, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), Err2 = jlib:replace_from_to(To, From, Err), - send_element(StateData, Err2), - ok; - allow -> ejabberd_router:route(FromRoute, To, Packet) + send_stanza(StateData, Err2); + allow -> + ejabberd_router:route(FromRoute, To, Packet), + StateData end. %% Check if privacy rules allow this delivery @@ -2208,7 +2199,7 @@ try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) -> case acl:match_rule(Server, Access, JID1) of deny -> %% Silently drop this (un)subscription request - ok; + StateData; allow -> ejabberd_hooks:run(roster_out_subscription, Server, From ed79a61752dc137f83c8bbd8963924baea53ddc9 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 21 Apr 2015 11:49:41 +0300 Subject: [PATCH 025/695] Fix LDAP substrings filter (EJAB-1715) --- src/eldap.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/eldap.erl b/src/eldap.erl index 5e084b01b54..a9edebdf03c 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -507,16 +507,14 @@ present(Attribute) -> -type substr() :: [{initial | any | final, binary()}]. -type 'SubstringFilter'() :: #'SubstringFilter'{type :: binary(), - substrings :: {'SubstringFilter_substrings', - substr()}}. + substrings :: substr()}. -type substrings() :: {substrings, 'SubstringFilter'()}. -spec substrings(binary(), substr()) -> substrings(). substrings(Type, SubStr) -> - Ss = {'SubstringFilter_substrings', SubStr}, {substrings, - #'SubstringFilter'{type = Type, substrings = Ss}}. + #'SubstringFilter'{type = Type, substrings = SubStr}}. -type match_opts() :: [{matchingRule | type, binary()} | {dnAttributes, boolean()}]. From 63926efd204c093b3125f789d5114e85ae4ff988 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 21 Apr 2015 13:32:14 +0200 Subject: [PATCH 026/695] Improve join/leave cluster scripts --- tools/joincluster | 56 +++++++++++++++++++++++----------------------- tools/leavecluster | 50 ++++++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 48 deletions(-) diff --git a/tools/joincluster b/tools/joincluster index e4351d799df..de36e437c31 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -1,18 +1,17 @@ -#!/bin/bash +#!/bin/sh # Add the current ejabberd node in a cluster # copyright (c) 2010-2015 ProcessOne -# -# This script is proprietary software and cannot be published or redistribute. # Return Code: # 0 : groovy baby +# 10 : ejabberdctl not found # 11 : erl not found # 12 : erlc not found -# 20 : database dir doesn't exist +# 20 : database dir can not be created # 21 : database dir not writable -# 21 : database dir variable not set +# 22 : temporary dir can not be created # 30 : network issue # 31 : node names incompatibility @@ -53,23 +52,28 @@ echo "" REMOTE=$1 } -cont=Y -ping -q -c 1 ${REMOTE#*@} 2>/dev/null >/dev/null -[ $? -eq 0 ] || { - echo "Cannot ping ${REMOTE#*@}. Are you sure network setup is correct ?" - echo -n "Should we continue anyway ? (Y/n) " - read cont +PA=/tmp/clustersetup_$$ +CTL=$(which ejabberdctl) +[ "$CTL" == "" ] && { + HERE=`which "$0"` + BASE=`dirname $HERE`/.. + ROOTDIR=`cd $BASE; pwd` + PATH=$ROOTDIR/bin:$PATH + PA=$ROOTDIR/clustersetup_$$ + CTL=$(which ejabberdctl) } -cont=`echo $cont | tr a-z A-Z` -[ "$cont" == "Y" ] || error "Check your network configuration (dns, firewall, etc...)" 30 +echo "Using commands:" +[ -x $CTL ] && echo $CTL || error "can't find ejabberdctl" 10 + +. $CTL stop 2>/dev/null >/dev/null +ERLC=${ERL}c + +[ -x $ERL ] && echo $ERL || error "can't find erl" 11 +[ -x $ERLC ] && echo $ERLC || error "can't find erlc" 12 +echo "" -HERE=`which "$0"` -BASE=`dirname $HERE`/.. -ROOTDIR=`cd $BASE; pwd` -. $ROOTDIR/bin/ejabberdctl stop 2>/dev/null >/dev/null NAME=-name [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname -PA=/tmp/clustersetup_$$ CLUSTERSETUP=clustersetup CLUSTERSETUP_ERL=$PA/$CLUSTERSETUP.erl @@ -89,17 +93,11 @@ REMOTENAME=-name set -o errexit set -o nounset -echo "Using commands:" -which erl || error "can't find erl" 11 -which erlc || error "can't find erlc" 12 -echo "" - [ -d $SPOOL_DIR ] && rm -Rf $SPOOL_DIR mkdir $SPOOL_DIR || error "$SPOOL_DIR cannot be created" 20 [ -w $SPOOL_DIR ] || error "$SPOOL_DIR directory is not writable" 21 - -cd $ROOTDIR -mkdir -p $PA +mkdir -p $PA || error "$PA cannot be created" 22 +cd $PA cat < $CLUSTERSETUP_ERL -module($CLUSTERSETUP). @@ -144,8 +142,10 @@ start() -> end, halt(R). EOF -erlc -o $PA $CLUSTERSETUP_ERL -sh -c "erl $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia extra_db_nodes \"['$REMOTE']\" dir \"\\\"$SPOOL_DIR\\\"\" -s mnesia -s $CLUSTERSETUP start" + +$ERLC -o $PA $CLUSTERSETUP_ERL +sh -c "$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia extra_db_nodes \"['$REMOTE']\" dir \"\\\"$SPOOL_DIR\\\"\" -s mnesia -s $CLUSTERSETUP start" +cd - rm -Rf $PA echo "End." diff --git a/tools/leavecluster b/tools/leavecluster index ec21621bc89..cb4737adb5d 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -1,18 +1,15 @@ -#!/bin/bash +#!/bin/sh # Remove the current ejabberd node in a cluster # copyright (c) 2010-2015 ProcessOne -# -# This script is proprietary software and cannot be published or redistribute. # Return Code: # 0 : groovy baby +# 10 : ejabberdctl not found # 11 : erl not found # 12 : erlc not found -# 20 : database dir doesn't exist -# 21 : database dir not writable -# 21 : database dir variable not set +# 22 : temporary dir can not be created function error { @@ -33,25 +30,36 @@ echo "Press any key to continue, or Ctrl+C to stop now" read foo echo "" -HERE=`which "$0"` -BASE=`dirname $HERE`/.. -ROOTDIR=`cd $BASE; pwd` -. $ROOTDIR/bin/ejabberdctl stop 2>/dev/null >/dev/null -$ROOTDIR/bin/ejabberdctl stopped PA=/tmp/clustersetup_$$ +CTL=$(which ejabberdctl) +[ "$CTL" == "" ] && { + HERE=`which "$0"` + BASE=`dirname $HERE`/.. + ROOTDIR=`cd $BASE; pwd` + PATH=$ROOTDIR/bin:$PATH + PA=$ROOTDIR/clustersetup_$$ + CTL=$(which ejabberdctl) +} +echo "Using commands:" +[ -x $CTL ] && echo $CTL || error "can't find ejabberdctl" 10 + +. $CTL stop 2>/dev/null >/dev/null +ERLC=${ERL}c + +[ -x $ERL ] && echo $ERL || error "can't find erl" 11 +[ -x $ERLC ] && echo $ERLC || error "can't find erlc" 12 +echo "" + +$CTL stopped + CLUSTERSETUP=clustersetup CLUSTERSETUP_ERL=$PA/$CLUSTERSETUP.erl set -o errexit set -o nounset -echo "Using commands:" -which erl || error "can't find erl" 11 -which erlc || error "can't find erlc" 12 -echo "" - -cd $ROOTDIR -mkdir -p $PA +mkdir -p $PA || error "$PA cannot be created" 22 +cd $PA cat < $CLUSTERSETUP_ERL -module($CLUSTERSETUP). @@ -89,8 +97,10 @@ start() -> end, halt(0). EOF -erlc -o $PA $CLUSTERSETUP_ERL -sh -c "erl $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia dir "\"$SPOOL_DIR\"" -s mnesia -s $CLUSTERSETUP start" + +$ERLC -o $PA $CLUSTERSETUP_ERL +sh -c "$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia dir \"\\\"$SPOOL_DIR\\\"\" -s mnesia -s $CLUSTERSETUP start" +cd - rm -Rf $PA echo "End." From e0563e3918984d151fbea45a5f6fc8255913726d Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 8 Apr 2015 17:12:05 +0200 Subject: [PATCH 027/695] PubSub improvements This commit contains - code cleanup - use of db_type instead of old mod_pubsub_odbc - some minor optimizations - some minor bugfixes --- include/pubsub.hrl | 148 +- src/gen_pubsub_node.erl | 213 +- src/gen_pubsub_nodetree.erl | 73 +- src/mod_pubsub.erl | 7361 +++++++++++-------------- src/mod_pubsub_odbc.erl | 5103 ----------------- src/node.template | 194 - src/node_buddy.erl | 207 +- src/node_club.erl | 208 +- src/node_dag.erl | 165 +- src/node_dispatch.erl | 197 +- src/node_flat.erl | 198 +- src/node_flat_odbc.erl | 209 +- src/node_hometree.erl | 1508 ++--- src/node_hometree_odbc.erl | 2049 +++---- src/node_mb.erl | 239 +- src/node_pep.erl | 593 +- src/node_pep_odbc.erl | 502 +- src/node_private.erl | 206 +- src/node_public.erl | 208 +- src/nodetree_dag.erl | 368 +- src/nodetree_tree.erl | 336 +- src/nodetree_tree_odbc.erl | 589 +- src/nodetree_virtual.erl | 177 +- src/pubsub_db_odbc.erl | 112 +- src/pubsub_index.erl | 39 +- src/pubsub_migrate.erl | 422 ++ src/pubsub_subscription.erl | 431 +- src/pubsub_subscription_odbc.erl | 344 +- test/ejabberd_SUITE.erl | 5 +- test/ejabberd_SUITE_data/ejabberd.cfg | 9 +- test/ejabberd_SUITE_data/ejabberd.yml | 9 +- 31 files changed, 7066 insertions(+), 15356 deletions(-) delete mode 100644 src/mod_pubsub_odbc.erl delete mode 100644 src/node.template create mode 100644 src/pubsub_migrate.erl diff --git a/include/pubsub.hrl b/include/pubsub.hrl index 3be41e3fdfa..2f85bdbfab6 100644 --- a/include/pubsub.hrl +++ b/include/pubsub.hrl @@ -27,8 +27,7 @@ %% ------------------------------- %% Pubsub constants --define(ERR_EXTENDED(E, C), - mod_pubsub:extended_error(E, C)). +-define(ERR_EXTENDED(E, C), mod_pubsub:extended_error(E, C)). %% The actual limit can be configured with mod_pubsub's option max_items_node -define(MAXITEMS, 10). @@ -40,7 +39,6 @@ %% ------------------------------- %% Pubsub types -%% @type hostPubsub() = string(). -type(hostPubsub() :: binary()). %%

hostPubsub is the name of the PubSub service. For example, it can be %% "pubsub.localhost".

@@ -59,12 +57,15 @@ -type(nodeId() :: binary()). %% @type nodeId() = binary(). %%

A node is defined by a list of its ancestors. The last element is the name -%% of the current node. For example: %% of the current node. For example: %% ```<<"/home/localhost/user">>'''

--type(nodeIdx() :: pos_integer()). -%% @type nodeIdx() = integer(). +-type(nodeIdx() :: pos_integer() | binary()). +%% @type nodeIdx() = integer() | binary(). +%% note: pos_integer() should always be used, but we allow anything else coded +%% as binary, so one can have a custom implementation of nodetree with custom +%% indexing (see nodetree_virtual). this also allows to use any kind of key for +%% indexing nodes, as this can be usefull with external backends such as odbc. -type(itemId() :: binary()). %% @type itemId() = string(). @@ -72,28 +73,12 @@ -type(subId() :: binary()). %% @type subId() = string(). - -%% @type payload() = [#xmlelement{} | #xmlcdata{}]. - -%% @type stanzaError() = #xmlelement{}. -%% Example: -%% Example: -%% ```{xmlelement, "error", -%% [{"code", Code}, {"type", Type}], -%% [{xmlelement, Condition, [{"xmlns", ?NS_STANZAS}], []}]}''' -%% @type pubsubIQResponse() = #xmlelement{}. -%% Example: -%% ```{xmlelement, "pubsub", -%% [{"xmlns", ?NS_PUBSUB_EVENT}], -%% [{xmlelement, "affiliations", [], -%% []}]}''' - -type(nodeOption() :: {Option::atom(), - Value::binary() | [binary()] | boolean() | non_neg_integer() + Value::atom() | [binary()] | boolean() | non_neg_integer() }). --type(nodeOptions() :: [NodeOption::mod_pubsub:nodeOption(),...]). +-type(nodeOptions() :: [mod_pubsub:nodeOption(),...]). %% @type nodeOption() = {Option, Value} %% Option = atom() @@ -106,26 +91,9 @@ Value::binary() | [binary()] | boolean() }). --type(subOptions() :: [SubOption::mod_pubsub:subOption(),...]). - -%% @type nodeType() = string(). -%%

The nodeType is a string containing the name of the PubSub -%% plugin to use to manage a given node. For example, it can be -%% "flat", "hometree" or "blog".

+-type(subOptions() :: [mod_pubsub:subOption(),...]). -%% @type jid() = {jid, User, Server, Resource, LUser, LServer, LResource} -%% User = string() -%% Server = string() -%% Resource = string() -%% LUser = string() -%% LServer = string() -%% LResource = string(). -%-type(ljid() :: {binary(), binary(), binary()}). -%% @type ljid() = {User, Server, Resource} -%% User = string() -%% Server = string() -%% Resource = string(). -type(affiliation() :: 'none' | 'owner' @@ -151,16 +119,11 @@ ). %% @type accessModel() = 'open' | 'presence' | 'roster' | 'authorize' | 'whitelist'. -%% @type pubsubIndex() = {pubsub_index, Index, Last, Free} -%% Index = atom() -%% Last = integer() -%% Free = [integer()]. -%% internal pubsub index table -type(publishModel() :: 'publishers' | 'subscribers' | 'open' ). - +%% @type publishModel() = 'publishers' | 'subscribers' | 'open' -record(pubsub_index, { @@ -169,91 +132,42 @@ free :: [mod_pubsub:nodeIdx()] }). -%% @type pubsubNode() = {pubsub_node, NodeId, Id, Parents, Type, Owners, Options} -%% NodeId = {host() | ljid(), nodeId()} -%% Id = nodeIdx() -%% Parents = [nodeId()] -%% Type = nodeType() -%% Owners = [ljid()] -%% Options = [nodeOption()]. -%%

This is the format of the nodes table. The type of the table -%% is: set,ram/disc.

-%%

The Parents and type fields are indexed.

-%% id can be anything you want. -record(pubsub_node, { - nodeid ,%:: {Host::mod_pubsub:host(), NodeId::mod_pubsub:nodeId()}, - id ,%:: mod_pubsub:nodeIdx(), - parents = [] ,%:: [Parent_NodeId::mod_pubsub:nodeId()], - type = <<"flat">> ,%:: binary(), - owners = [] ,%:: [Owner::ljid(),...], - options = [] %:: mod_pubsub:nodeOptions() + nodeid ,% :: {mod_pubsub:host(), mod_pubsub:nodeId()}, + id ,% :: mod_pubsub:nodeIdx(), + parents = [] ,% :: [mod_pubsub:nodeId(),...], + type = <<"flat">>,% :: binary(), + owners = [] ,% :: [jlib:ljid(),...], + options = [] % :: mod_pubsub:nodeOptions() }). -%% @type pubsubState() = {pubsub_state, StateId, Items, Affiliation, Subscriptions} -%% StateId = {ljid(), nodeIdx()} -%% Items = [itemId()] -%% Affiliation = affiliation() -%% Subscriptions = [{subscription(), subId()}]. -%%

This is the format of the affiliations table. The type of the -%% table is: set,ram/disc.

- -%-record(pubsub_state, -% {stateid, items = [], affiliation = none, -% subscriptions = []}). -record(pubsub_state, { - stateid ,%:: {Entity::ljid(), NodeIdx::mod_pubsub:nodeIdx()}, - items = [] ,%:: [ItemId::mod_pubsub:itemId()], - affiliation = 'none' ,%:: mod_pubsub:affiliation(), - subscriptions = [] %:: [{mod_pubsub:subscription(), mod_pubsub:subId()}] + stateid ,% :: {jlib:ljid(), mod_pubsub:nodeIdx()}, + items = [] ,% :: [mod_pubsub:itemId(),...], + affiliation = 'none',% :: mod_pubsub:affiliation(), + subscriptions = [] % :: [{mod_pubsub:subscription(), mod_pubsub:subId()}] }). -%% @type pubsubItem() = {pubsub_item, ItemId, Creation, Modification, Payload} -%% ItemId = {itemId(), nodeIdx()} -%% Creation = {now(), ljid()} -%% Modification = {now(), ljid()} -%% Payload = payload(). -%%

This is the format of the published items table. The type of the -%% table is: set,disc,fragmented.

-%-record(pubsub_item, -% {itemid, creation = {unknown, unknown}, -% modification = {unknown, unknown}, payload = []}). - -record(pubsub_item, { - itemid ,%:: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()}, - creation = {unknown, unknown} ,%:: {erlang:timestamp(), ljid()}, - modification = {unknown, unknown} ,%:: {erlang:timestamp(), ljid()}, - payload = [] %:: mod_pubsub:payload() + itemid ,% :: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()}, + creation = {unknown, unknown},% :: {erlang:timestamp(), jlib:ljid()}, + modification = {unknown, unknown},% :: {erlang:timestamp(), jlib:ljid()}, + payload = [] % :: mod_pubsub:payload() }). -%% @type pubsubSubscription() = {pubsub_subscription, SubId, Options} -%% SubId = subId() -%% Options = [nodeOption()]. -%%

This is the format of the subscriptions table. The type of the -%% table is: set,ram/disc.

-%-record(pubsub_subscription, {subid, options}). -record(pubsub_subscription, { - subid ,%:: mod_pubsub:subId(), - options %:: [] | mod_pubsub:subOptions() + subid ,% :: mod_pubsub:subId(), + options = [] % :: mod_pubsub:subOptions() }). -%% @type pubsubLastItem() = {pubsub_last_item, NodeId, ItemId, Creation, Payload} -%% NodeId = nodeIdx() -%% ItemId = itemId() -%% Creation = {now(),ljid()} -%% Payload = payload(). -%%

This is the format of the last items table. it stores last item payload -%% for every node

-%-record(pubsub_last_item, -% {nodeid, itemid, creation, payload}). - -record(pubsub_last_item, { - nodeid ,%:: mod_pubsub:nodeIdx(), - itemid ,%:: mod_pubsub:itemId(), - creation ,%:: {erlang:timestamp(), ljid()}, - payload %:: mod_pubsub:payload() + nodeid ,% :: mod_pubsub:nodeIdx(), + itemid ,% :: mod_pubsub:itemId(), + creation ,% :: {erlang:timestamp(), jlib:ljid()}, + payload % :: mod_pubsub:payload() }). diff --git a/src/gen_pubsub_node.erl b/src/gen_pubsub_node.erl index da8cd6a0e58..c608dad8124 100644 --- a/src/gen_pubsub_node.erl +++ b/src/gen_pubsub_node.erl @@ -32,191 +32,146 @@ -include("jlib.hrl"). --type(host() :: mod_pubsub:host() - | mod_pubsub_odbc:host() -). - --type(nodeId() :: mod_pubsub:nodeId() - | mod_pubsub_odbc:nodeId() -). - --type(nodeIdx() :: mod_pubsub:nodeIdx() - | mod_pubsub_odbc:nodeIdx() -). - --type(itemId() :: mod_pubsub:itemId() - | mod_pubsub_odbc:itemId() -). - --type(pubsubNode() :: mod_pubsub:pubsubNode() - | mod_pubsub_odbc:pubsubNode() -). - --type(pubsubState() :: mod_pubsub:pubsubState() - | mod_pubsub_odbc:pubsubState() -). - --type(pubsubItem() :: mod_pubsub:pubsubItem() - | mod_pubsub_odbc:pubsubItem() -). - --type(nodeOptions() :: mod_pubsub:nodeOptions() - | mod_pubsub_odbc:nodeOptions() -). - --type(subOptions() :: mod_pubsub:subOptions() - | mod_pubsub_odbc:subOptions() -). - --type(affiliation() :: mod_pubsub:affiliation() - | mod_pubsub_odbc:affiliation() -). - --type(subscription() :: mod_pubsub:subscription() - | mod_pubsub_odbc:subscription() -). - --type(subId() :: mod_pubsub:subId() - | mod_pubsub_odbc:subId() -). - --type(accessModel() :: mod_pubsub:accessModel() - | mod_pubsub_odbc:accessModel() -). - --type(publishModel() :: mod_pubsub:publishModel() - | mod_pubsub_odbc:publishModel() -). - --type(payload() :: mod_pubsub:payload() - | mod_pubsub_odbc:payload() -). +-type(host() :: mod_pubsub:host()). +-type(nodeId() :: mod_pubsub:nodeId()). +-type(nodeIdx() :: mod_pubsub:nodeIdx()). +-type(itemId() :: mod_pubsub:itemId()). +-type(pubsubNode() :: mod_pubsub:pubsubNode()). +-type(pubsubState() :: mod_pubsub:pubsubState()). +-type(pubsubItem() :: mod_pubsub:pubsubItem()). +-type(subOptions() :: mod_pubsub:subOptions()). +-type(affiliation() :: mod_pubsub:affiliation()). +-type(subscription() :: mod_pubsub:subscription()). +-type(subId() :: mod_pubsub:subId()). +-type(accessModel() :: mod_pubsub:accessModel()). +-type(publishModel() :: mod_pubsub:publishModel()). +-type(payload() :: mod_pubsub:payload()). -callback init(Host :: binary(), - ServerHost :: binary(), - Opts :: [any()]) -> atom(). + ServerHost :: binary(), + Opts :: [any()]) -> atom(). -callback terminate(Host :: host(), - ServerHost :: binary()) -> atom(). + ServerHost :: binary()) -> atom(). -callback options() -> [{atom(), any()}]. -callback features() -> [binary()]. -callback create_node_permission(Host :: host(), - ServerHost :: binary(), - Node :: nodeId(), - ParentNode :: nodeId(), - Owner :: jid(), Access :: atom()) -> + ServerHost :: binary(), + Node :: nodeId(), + ParentNode :: nodeId(), + Owner :: jid(), Access :: atom()) -> {result, boolean()}. -callback create_node(NodeIdx :: nodeIdx(), - Owner :: jid()) -> + Owner :: jid()) -> {result, {default, broadcast}}. -callback delete_node(Nodes :: [pubsubNode(),...]) -> {result, - {default, broadcast, - [{pubsubNode(), - [{ljid(), [{subscription(), subId()}]},...]},...] - } - } + {default, broadcast, + [{pubsubNode(), + [{ljid(), [{subscription(), subId()}]},...]},...] + } + } | {result, - {[], - [{pubsubNode(), - [{ljid(), [{subscription(), subId()}]},...]},...] - } - }. + {[], + [{pubsubNode(), + [{ljid(), [{subscription(), subId()}]},...]},...] + } + }. -callback purge_node(NodeIdx :: nodeIdx(), - Owner :: jid()) -> + Owner :: jid()) -> {result, {default, broadcast}} | {error, xmlel()}. -callback subscribe_node(NodeIdx :: nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - AccessModel :: accessModel(), - SendLast :: 'never' | 'on_sub' | 'on_sub_and_presence', - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - Options :: subOptions()) -> + Sender :: jid(), + Subscriber :: jid(), + AccessModel :: accessModel(), + SendLast :: 'never' | 'on_sub' | 'on_sub_and_presence', + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + Options :: subOptions()) -> {result, {default, subscribed, subId()}} | {result, {default, subscribed, subId(), send_last}} | {result, {default, pending, subId()}} | {error, xmlel()}. -callback unsubscribe_node(NodeIdx :: nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - SubId :: subId()) -> + Sender :: jid(), + Subscriber :: jid(), + SubId :: subId()) -> {result, default} | {error, xmlel()}. -callback publish_item(NodeId :: nodeIdx(), - Publisher :: jid(), - PublishModel :: publishModel(), - Max_Items :: non_neg_integer(), - ItemId :: <<>> | itemId(), - Payload :: payload()) -> + Publisher :: jid(), + PublishModel :: publishModel(), + Max_Items :: non_neg_integer(), + ItemId :: <<>> | itemId(), + Payload :: payload()) -> {result, {default, broadcast, [itemId()]}} | {error, xmlel()}. -callback delete_item(NodeIdx :: nodeIdx(), - Publisher :: jid(), - PublishModel :: publishModel(), - ItemId :: <<>> | itemId()) -> + Publisher :: jid(), + PublishModel :: publishModel(), + ItemId :: <<>> | itemId()) -> {result, {default, broadcast}} | {error, xmlel()}. -callback remove_extra_items(NodeIdx :: nodeIdx(), - Max_Items :: unlimited | non_neg_integer(), - ItemIds :: [itemId()]) -> + Max_Items :: unlimited | non_neg_integer(), + ItemIds :: [itemId()]) -> {result, {[itemId()], [itemId()]} - }. + }. -callback get_node_affiliations(NodeIdx :: nodeIdx()) -> {result, [{ljid(), affiliation()}]}. -callback get_entity_affiliations(Host :: host(), - Owner :: jid()) -> + Owner :: jid()) -> {result, [{pubsubNode(), affiliation()}]}. -callback get_affiliation(NodeIdx :: nodeIdx(), - Owner :: jid()) -> + Owner :: jid()) -> {result, affiliation()}. -callback set_affiliation(NodeIdx :: nodeIdx(), - Owner :: ljid(), - Affiliation :: affiliation()) -> + Owner :: jid(), + Affiliation :: affiliation()) -> ok | {error, xmlel()}. -callback get_node_subscriptions(NodeIdx :: nodeIdx()) -> {result, - [{ljid(), subscription(), subId()}] | - [{ljid(), none},...] - }. + [{ljid(), subscription(), subId()}] | + [{ljid(), none},...] + }. -callback get_entity_subscriptions(Host :: host(), - Owner :: jid()) -> + Key :: jid()) -> {result, [{pubsubNode(), subscription(), subId(), ljid()}] - }. + }. -callback get_subscriptions(NodeIdx :: nodeIdx(), - Owner :: ljid()) -> + Owner :: jid()) -> {result, [{subscription(), subId()}]}. -callback get_pending_nodes(Host :: host(), - Owner :: jid()) -> + Owner :: jid()) -> {result, [nodeId()]}. -callback get_states(NodeIdx::nodeIdx()) -> {result, [pubsubState()]}. -callback get_state(NodeIdx :: nodeIdx(), - JID :: ljid()) -> + Key :: ljid()) -> pubsubState(). -callback set_state(State::pubsubState()) -> @@ -224,30 +179,32 @@ {error, xmlel()}. -callback get_items(NodeIdx :: nodeIdx(), - JID :: jid(), - AccessModel :: accessModel(), - Presence_Subscription :: boolean(), - RosterGroup :: boolean(), - SubId :: subId()) -> - {result, [pubsubItem()]} | + JID :: jid(), + AccessModel :: accessModel(), + Presence_Subscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId(), + RSM :: none | rsm_in()) -> + {result, {[pubsubItem()], none | rsm_out()}} | {error, xmlel()}. -callback get_items(NodeIdx :: nodeIdx(), - From :: jid()) -> - {result, [pubsubItem()]}. + From :: jid(), + RSM :: none | rsm_in()) -> + {result, {[pubsubItem()], none | rsm_out()}}. -callback get_item(NodeIdx :: nodeIdx(), - ItemId :: itemId(), - JID :: jid(), - AccessModel :: accessModel(), - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - SubId :: subId()) -> + ItemId :: itemId(), + JID :: jid(), + AccessModel :: accessModel(), + PresenceSubscription :: boolean(), + RosterGroup :: boolean(), + SubId :: subId()) -> {result, pubsubItem()} | {error, xmlel()}. -callback get_item(NodeIdx :: nodeIdx(), - ItemId :: itemId()) -> + ItemId :: itemId()) -> {result, pubsubItem()} | {error, xmlel()}. @@ -256,8 +213,8 @@ % | {error, _}. -callback get_item_name(Host :: host(), - ServerHost :: binary(), - Node :: nodeId()) -> + ServerHost :: binary(), + Node :: nodeId()) -> itemId(). -callback node_to_path(Node :: nodeId()) -> diff --git a/src/gen_pubsub_nodetree.erl b/src/gen_pubsub_nodetree.erl index 8cbe1d3dfb2..ce6750dbac8 100644 --- a/src/gen_pubsub_nodetree.erl +++ b/src/gen_pubsub_nodetree.erl @@ -32,49 +32,31 @@ -include("jlib.hrl"). --type(host() :: mod_pubsub:host() - | mod_pubsub_odbc:host() -). - --type(nodeId() :: mod_pubsub:nodeId() - | mod_pubsub_odbc:nodeId() -). - --type(nodeIdx() :: mod_pubsub:nodeIdx() - | mod_pubsub_odbc:nodeIdx() -). - --type(itemId() :: mod_pubsub:itemId() - | mod_pubsub_odbc:itemId() -). - --type(pubsubNode() :: mod_pubsub:pubsubNode() - | mod_pubsub_odbc:pubsubNode() -). - --type(nodeOptions() :: mod_pubsub:nodeOptions() - | mod_pubsub_odbc:nodeOptions() -). +-type(host() :: mod_pubsub:host()). +-type(nodeId() :: mod_pubsub:nodeId()). +-type(nodeIdx() :: mod_pubsub:nodeIdx()). +-type(pubsubNode() :: mod_pubsub:pubsubNode()). +-type(nodeOptions() :: mod_pubsub:nodeOptions()). -callback init(Host :: host(), - ServerHost :: binary(), - Opts :: [any()]) -> atom(). + ServerHost :: binary(), + Opts :: [any()]) -> atom(). -callback terminate(Host :: host(), ServerHost :: binary()) -> atom(). -callback options() -> nodeOptions(). -callback set_node(PubsubNode :: pubsubNode()) -> - ok | {result, NodeIdx::mod_pubsub_odbc:nodeIdx()} | {error, xmlel()}. + ok | {result, NodeIdx::nodeIdx()} | {error, xmlel()}. -callback get_node(Host :: host(), - NodeId :: nodeId(), - From :: jid()) -> + NodeId :: nodeId(), + From :: jid()) -> pubsubNode() | {error, xmlel()}. -callback get_node(Host :: host(), - NodeId :: nodeId()) -> + NodeId :: nodeId()) -> pubsubNode() | {error, xmlel()}. @@ -83,42 +65,43 @@ {error, xmlel()}. -callback get_nodes(Host :: host(), - From :: jid())-> + From :: jid())-> [pubsubNode()]. -callback get_nodes(Host :: host())-> [pubsubNode()]. -callback get_parentnodes(Host :: host(), - NodeId :: nodeId(), - From :: jid()) -> + NodeId :: nodeId(), + From :: jid()) -> [pubsubNode()] | {error, xmlel()}. -callback get_parentnodes_tree(Host :: host(), - NodeId :: nodeId(), - From :: jid()) -> + NodeId :: nodeId(), + From :: jid()) -> [{0, [pubsubNode(),...]}]. -callback get_subnodes(Host :: host(), - NodeId :: nodeId(), - From :: ljid()) -> + NodeId :: nodeId(), + From :: jid()) -> [pubsubNode()]. -callback get_subnodes_tree(Host :: host(), - NodeId :: nodeId(), - From :: ljid()) -> + NodeId :: nodeId(), + From :: jid()) -> [pubsubNode()]. -callback create_node(Host :: host(), - NodeId :: nodeId(), - Type :: binary(), - Owner :: jid(), - Options :: nodeOptions(), - Parents :: [nodeId()]) -> + NodeId :: nodeId(), + Type :: binary(), + Owner :: jid(), + Options :: nodeOptions(), + Parents :: [nodeId()]) -> {ok, NodeIdx::nodeIdx()} | - {error, xmlel()}. + {error, xmlel()} | + {error, {virtual, {host(), nodeId()}}}. -callback delete_node(Host :: host(), - NodeId :: nodeId()) -> + NodeId :: nodeId()) -> [pubsubNode()]. diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 579c4775714..8fbdfbb6fd7 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -4,13 +4,13 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne @@ -44,77 +44,54 @@ %%% XEP-0060 section 12.18. -module(mod_pubsub). - --author('christophe.romain@process-one.net'). - --version('1.13-0'). - --behaviour(gen_server). - -behaviour(gen_mod). +-behaviour(gen_server). +-author('christophe.romain@process-one.net'). +-version('1.13-1'). -include("ejabberd.hrl"). -include("logger.hrl"). - -include("adhoc.hrl"). - -include("jlib.hrl"). - -include("pubsub.hrl"). -define(STDTREE, <<"tree">>). - -define(STDNODE, <<"flat">>). - -define(PEPNODE, <<"pep">>). %% exports for hooks -export([presence_probe/3, caps_update/3, - in_subscription/6, out_subscription/4, - on_user_offline/3, remove_user/2, - disco_local_identity/5, disco_local_features/5, - disco_local_items/5, disco_sm_identity/5, - disco_sm_features/5, disco_sm_items/5]). + in_subscription/6, out_subscription/4, + on_user_offline/3, remove_user/2, + disco_local_identity/5, disco_local_features/5, + disco_local_items/5, disco_sm_identity/5, + disco_sm_features/5, disco_sm_items/5]). %% exported iq handlers -export([iq_sm/3]). %% exports for console debug manual use --export([create_node/5, - delete_node/3, - subscribe_node/5, - unsubscribe_node/5, - publish_item/6, - delete_item/4, - send_items/7, - get_items/2, - get_item/3, - get_cached_item/2, - broadcast_stanza/9, - get_configure/5, - set_configure/5, - tree_action/3, - node_action/4 - ]). +-export([create_node/5, create_node/7, delete_node/3, + subscribe_node/5, unsubscribe_node/5, publish_item/6, + delete_item/4, send_items/7, get_items/2, get_item/3, + get_cached_item/2, get_configure/5, set_configure/5, + tree_action/3, node_action/4, node_call/4]). %% general helpers for plugins -export([subscription_to_string/1, affiliation_to_string/1, - string_to_subscription/1, string_to_affiliation/1, - extended_error/2, extended_error/3, - rename_default_nodeplugin/0]). + string_to_subscription/1, string_to_affiliation/1, + extended_error/2, extended_error/3, service_jid/1, + tree/1, tree/2, plugin/2, config/3, host/1, serverhost/1]). %% API and gen_server callbacks -export([start_link/2, start/2, stop/1, init/1, - handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). + handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). %% calls for parallel sending of last items -export([send_loop/1]). --export([export/1]). - -define(PROCNAME, ejabberd_mod_pubsub). - -define(LOOPNAME, ejabberd_mod_pubsub_loop). %%==================================================================== @@ -124,128 +101,125 @@ %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- --define(PLUGIN_PREFIX, <<"node_">>). --define(TREE_PREFIX, <<"nodetree_">>). - -% -export_type([ - host/0, - hostPubsub/0, - hostPEP/0, - %% - nodeIdx/0, - nodeId/0, - itemId/0, - subId/0, - payload/0, - %% - nodeOption/0, - nodeOptions/0, - subOption/0, - subOptions/0, - %% - affiliation/0, - subscription/0, - accessModel/0, - publishModel/0 -]). + host/0, + hostPubsub/0, + hostPEP/0, + %% + nodeIdx/0, + nodeId/0, + itemId/0, + subId/0, + payload/0, + %% + nodeOption/0, + nodeOptions/0, + subOption/0, + subOptions/0, + %% + affiliation/0, + subscription/0, + accessModel/0, + publishModel/0 + ]). %% -type payload() defined here because the -type xmlel() is not accessible %% from pubsub.hrl -type(payload() :: [] | [xmlel(),...]). -export_type([ - pubsubNode/0, - pubsubState/0, - pubsubItem/0, - pubsubSubscription/0, - pubsubLastItem/0 -]). + pubsubNode/0, + pubsubState/0, + pubsubItem/0, + pubsubSubscription/0, + pubsubLastItem/0 + ]). -type(pubsubNode() :: #pubsub_node{ - nodeid :: {Host::mod_pubsub:host(), NodeId::mod_pubsub:nodeId()}, - id :: mod_pubsub:nodeIdx(), - parents :: [Parent_NodeId::mod_pubsub:nodeId()], - type :: binary(), - owners :: [Owner::ljid(),...], - options :: mod_pubsub:nodeOptions() - } -). + nodeid :: {Host::mod_pubsub:host(), Node::mod_pubsub:nodeId()}, + id :: Nidx::mod_pubsub:nodeIdx(), + parents :: [Node::mod_pubsub:nodeId()], + type :: Type::binary(), + owners :: [Owner::ljid(),...], + options :: Opts::mod_pubsub:nodeOptions() + } + ). -type(pubsubState() :: #pubsub_state{ - stateid :: {Entity::ljid(), NodeIdx::mod_pubsub:nodeIdx()}, - items :: [ItemId::mod_pubsub:itemId()], - affiliation :: mod_pubsub:affiliation(), - subscriptions :: [{mod_pubsub:subscription(), mod_pubsub:subId()}] - } -). + stateid :: {Entity::ljid(), Nidx::mod_pubsub:nodeIdx()}, + items :: [ItemId::mod_pubsub:itemId()], + affiliation :: Affs::mod_pubsub:affiliation(), + subscriptions :: [{Sub::mod_pubsub:subscription(), SubId::mod_pubsub:subId()}] + } + ). -type(pubsubItem() :: #pubsub_item{ - itemid :: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()}, - creation :: {erlang:timestamp(), ljid()}, - modification :: {erlang:timestamp(), ljid()}, - payload :: mod_pubsub:payload() - } -). + itemid :: {ItemId::mod_pubsub:itemId(), Nidx::mod_pubsub:nodeIdx()}, + creation :: {erlang:timestamp(), ljid()}, + modification :: {erlang:timestamp(), ljid()}, + payload :: mod_pubsub:payload() + } + ). -type(pubsubSubscription() :: #pubsub_subscription{ - subid :: mod_pubsub:subId(), - options :: [] | mod_pubsub:subOptions() - } -). + subid :: SubId::mod_pubsub:subId(), + options :: [] | mod_pubsub:subOptions() + } + ). -type(pubsubLastItem() :: #pubsub_last_item{ - nodeid :: mod_pubsub:nodeIdx(), - itemid :: mod_pubsub:itemId(), - creation :: {erlang:timestamp(), ljid()}, - payload :: mod_pubsub:payload() - } -). + nodeid :: mod_pubsub:nodeIdx(), + itemid :: mod_pubsub:itemId(), + creation :: {erlang:timestamp(), ljid()}, + payload :: mod_pubsub:payload() + } + ). -record(state, -{ - server_host, - host, - access, - pep_mapping = [], - ignore_pep_from_offline = true, - last_item_cache = false, - max_items_node = ?MAXITEMS, - nodetree = ?STDTREE, - plugins = [?STDNODE] -}). + { + server_host, + host, + access, + pep_mapping = [], + ignore_pep_from_offline = true, + last_item_cache = false, + max_items_node = ?MAXITEMS, + nodetree = <<"nodetree_", (?STDTREE)/binary>>, + plugins = [?STDNODE], + db_type + }). -type(state() :: #state{ - server_host :: binary(), - host :: mod_pubsub:hostPubsub(), - access :: atom(), - pep_mapping :: [{binary(), binary()}], - ignore_pep_from_offline :: boolean(), - last_item_cache :: boolean(), - max_items_node :: non_neg_integer(), - nodetree :: binary(), - plugins :: [binary(),...] - } + server_host :: binary(), + host :: mod_pubsub:hostPubsub(), + access :: atom(), + pep_mapping :: [{binary(), binary()}], + ignore_pep_from_offline :: boolean(), + last_item_cache :: boolean(), + max_items_node :: non_neg_integer(), + nodetree :: binary(), + plugins :: [binary(),...], + db_type :: atom() + } -). + ). start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - gen_server:start_link({local, Proc}, ?MODULE, - [Host, Opts], []). + gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). start(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, - transient, 1000, worker, [?MODULE]}, + transient, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> @@ -259,125 +233,115 @@ stop(Host) -> %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- -spec(init/1 :: -( - _:: _) - -> {ok, state()} -). + ( + [binary() | [{_,_}],...]) + -> {'ok',state()} + ). init([ServerHost, Opts]) -> ?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]), Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>), Access = gen_mod:get_opt(access_createnode, Opts, - fun(A) when is_atom(A) -> A end, all), + fun(A) when is_atom(A) -> A end, all), PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, - fun(A) when is_boolean(A) -> A end, true), + fun(A) when is_boolean(A) -> A end, true), IQDisc = gen_mod:get_opt(iqdisc, Opts, - fun(A) when is_atom(A) -> A end, one_queue), + fun(A) when is_atom(A) -> A end, one_queue), LastItemCache = gen_mod:get_opt(last_item_cache, Opts, - fun(A) when is_boolean(A) -> A end, false), + fun(A) when is_boolean(A) -> A end, false), MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, - fun(A) when is_integer(A) andalso A >= 0 -> A end, ?MAXITEMS), + fun(A) when is_integer(A) andalso A >= 0 -> A end, ?MAXITEMS), pubsub_index:init(Host, ServerHost, Opts), - ets:new(gen_mod:get_module_proc(Host, config), - [set, named_table]), - ets:new(gen_mod:get_module_proc(ServerHost, config), - [set, named_table]), - {Plugins, NodeTree, PepMapping} = init_plugins(Host, - ServerHost, Opts), + ets:new(gen_mod:get_module_proc(ServerHost, config), [set, named_table]), + {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts), mnesia:create_table(pubsub_last_item, - [{ram_copies, [node()]}, - {attributes, record_info(fields, pubsub_last_item)}]), + [{ram_copies, [node()]}, + {attributes, record_info(fields, pubsub_last_item)}]), mod_disco:register_feature(ServerHost, ?NS_PUBSUB), - ets:insert(gen_mod:get_module_proc(Host, config), - {nodetree, NodeTree}), - ets:insert(gen_mod:get_module_proc(Host, config), - {plugins, Plugins}), - ets:insert(gen_mod:get_module_proc(Host, config), - {last_item_cache, LastItemCache}), - ets:insert(gen_mod:get_module_proc(Host, config), - {max_items_node, MaxItemsNode}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {nodetree, NodeTree}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {plugins, Plugins}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {last_item_cache, LastItemCache}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {max_items_node, MaxItemsNode}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {pep_mapping, PepMapping}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {ignore_pep_from_offline, PepOffline}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {host, Host}), - ejabberd_hooks:add(sm_remove_connection_hook, - ServerHost, ?MODULE, on_user_offline, 75), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {nodetree, NodeTree}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {plugins, Plugins}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, LastItemCache}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, MaxItemsNode}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {pep_mapping, PepMapping}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {ignore_pep_from_offline, PepOffline}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {host, Host}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {access, Access}), + ejabberd_hooks:add(sm_remove_connection_hook, ServerHost, + ?MODULE, on_user_offline, 75), ejabberd_hooks:add(disco_local_identity, ServerHost, - ?MODULE, disco_local_identity, 75), + ?MODULE, disco_local_identity, 75), ejabberd_hooks:add(disco_local_features, ServerHost, - ?MODULE, disco_local_features, 75), + ?MODULE, disco_local_features, 75), ejabberd_hooks:add(disco_local_items, ServerHost, - ?MODULE, disco_local_items, 75), + ?MODULE, disco_local_items, 75), ejabberd_hooks:add(presence_probe_hook, ServerHost, - ?MODULE, presence_probe, 80), + ?MODULE, presence_probe, 80), ejabberd_hooks:add(roster_in_subscription, ServerHost, - ?MODULE, in_subscription, 50), + ?MODULE, in_subscription, 50), ejabberd_hooks:add(roster_out_subscription, ServerHost, - ?MODULE, out_subscription, 50), - ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, - remove_user, 50), + ?MODULE, out_subscription, 50), + ejabberd_hooks:add(remove_user, ServerHost, + ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, ServerHost, - ?MODULE, remove_user, 50), + ?MODULE, remove_user, 50), case lists:member(?PEPNODE, Plugins) of - true -> - ejabberd_hooks:add(caps_update, ServerHost, ?MODULE, - caps_update, 80), - ejabberd_hooks:add(disco_sm_identity, ServerHost, - ?MODULE, disco_sm_identity, 75), - ejabberd_hooks:add(disco_sm_features, ServerHost, - ?MODULE, disco_sm_features, 75), - ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, - disco_sm_items, 75), - gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, - ?NS_PUBSUB, ?MODULE, iq_sm, IQDisc), - gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, - ?NS_PUBSUB_OWNER, ?MODULE, iq_sm, - IQDisc); - false -> ok + true -> + ejabberd_hooks:add(caps_update, ServerHost, + ?MODULE, caps_update, 80), + ejabberd_hooks:add(disco_sm_identity, ServerHost, + ?MODULE, disco_sm_identity, 75), + ejabberd_hooks:add(disco_sm_features, ServerHost, + ?MODULE, disco_sm_features, 75), + ejabberd_hooks:add(disco_sm_items, ServerHost, + ?MODULE, disco_sm_items, 75), + gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, + ?NS_PUBSUB, ?MODULE, iq_sm, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, + ?NS_PUBSUB_OWNER, ?MODULE, iq_sm, IQDisc); + false -> + ok end, ejabberd_router:register_route(Host), - update_node_database(Host, ServerHost), - update_state_database(Host, ServerHost), - update_item_database_binary(), - put(server_host, ServerHost), + pubsub_migrate:update_node_database(Host, ServerHost), + pubsub_migrate:update_state_database(Host, ServerHost), + pubsub_migrate:update_lastitem_database(Host, ServerHost), init_nodes(Host, ServerHost, NodeTree, Plugins), - State = #state{host = Host, server_host = ServerHost, - access = Access, pep_mapping = PepMapping, - ignore_pep_from_offline = PepOffline, - last_item_cache = LastItemCache, - max_items_node = MaxItemsNode, nodetree = NodeTree, - plugins = Plugins}, - init_send_loop(ServerHost, State), + {_, State} = init_send_loop(ServerHost), {ok, State}. -init_send_loop(ServerHost, State) -> +init_send_loop(ServerHost) -> + NodeTree = config(ServerHost, nodetree), + Plugins = config(ServerHost, plugins), + LastItemCache = config(ServerHost, last_item_cache), + MaxItemsNode = config(ServerHost, max_items_node), + PepMapping = config(ServerHost, pep_mapping), + PepOffline = config(ServerHost, ignore_pep_from_offline), + Host = config(ServerHost, host), + Access = config(ServerHost, access), + DBType = gen_mod:db_type(ServerHost, ?MODULE), + State = #state{host = Host, server_host = ServerHost, + access = Access, pep_mapping = PepMapping, + ignore_pep_from_offline = PepOffline, + last_item_cache = LastItemCache, + max_items_node = MaxItemsNode, nodetree = NodeTree, + plugins = Plugins, db_type = DBType}, Proc = gen_mod:get_module_proc(ServerHost, ?LOOPNAME), - SendLoop = spawn(?MODULE, send_loop, [State]), - register(Proc, SendLoop), - SendLoop. - -%% @spec (Host, ServerHost, Opts) -> Plugins -%% Host = mod_pubsub:host() Opts = [{Key,Value}] -%% ServerHost = host() -%% Key = atom() -%% Value = term() -%% Plugins = [Plugin::string()] + Pid = case whereis(Proc) of + undefined -> + SendLoop = spawn(?MODULE, send_loop, [State]), + register(Proc, SendLoop), + SendLoop; + Loop -> + Loop + end, + {Pid, State}. + %% @doc Call the init/1 function for each plugin declared in the config file. %% The default plugin module is implicit. %%

The Erlang code for the plugin is located in a module called @@ -386,594 +350,129 @@ init_send_loop(ServerHost, State) -> %% and sorted to ensure that each module is initialized only once.

%%

See {@link node_hometree:init/1} for an example implementation.

init_plugins(Host, ServerHost, Opts) -> - TreePlugin = - jlib:binary_to_atom(<<(?TREE_PREFIX)/binary, - (gen_mod:get_opt(nodetree, Opts, fun(A) when is_binary(A) -> A end, - ?STDTREE))/binary>>), + TreePlugin = tree(Host, gen_mod:get_opt(nodetree, Opts, + fun(A) when is_binary(A) -> A end, + ?STDTREE)), ?DEBUG("** tree plugin is ~p", [TreePlugin]), TreePlugin:init(Host, ServerHost, Opts), Plugins = gen_mod:get_opt(plugins, Opts, - fun(A) when is_list(A) -> A end, [?STDNODE]), + fun(A) when is_list(A) -> A end, [?STDNODE]), PepMapping = gen_mod:get_opt(pep_mapping, Opts, - fun(A) when is_list(A) -> A end, []), + fun(A) when is_list(A) -> A end, []), ?DEBUG("** PEP Mapping : ~p~n", [PepMapping]), - PluginsOK = lists:foldl(fun (Name, Acc) -> - Plugin = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Name/binary>>), - case catch apply(Plugin, init, - [Host, ServerHost, Opts]) - of - {'EXIT', _Error} -> Acc; - _ -> - ?DEBUG("** init ~s plugin", [Name]), - [Name | Acc] - end - end, - [], Plugins), + PluginsOK = lists:foldl( + fun (Name, Acc) -> + Plugin = plugin(Host, Name), + case catch apply(Plugin, init, [Host, ServerHost, Opts]) of + {'EXIT', _Error} -> + Acc; + _ -> + ?DEBUG("** init ~s plugin", [Name]), + [Name | Acc] + end + end, + [], Plugins), {lists:reverse(PluginsOK), TreePlugin, PepMapping}. -terminate_plugins(Host, ServerHost, Plugins, - TreePlugin) -> - lists:foreach(fun (Name) -> - ?DEBUG("** terminate ~s plugin", [Name]), - Plugin = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Name/binary>>), - Plugin:terminate(Host, ServerHost) - end, - Plugins), +terminate_plugins(Host, ServerHost, Plugins, TreePlugin) -> + lists:foreach( + fun (Name) -> + ?DEBUG("** terminate ~s plugin", [Name]), + Plugin = plugin(Host, Name), + Plugin:terminate(Host, ServerHost) + end, + Plugins), TreePlugin:terminate(Host, ServerHost), ok. init_nodes(Host, ServerHost, _NodeTree, Plugins) -> case lists:member(<<"hometree">>, Plugins) of - true -> + true -> create_node(Host, ServerHost, <<"/home">>, service_jid(Host), <<"hometree">>), - create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, service_jid(Host), - <<"hometree">>); - false -> ok - end. - - -update_item_database_binary() -> - F = fun () -> - case catch mnesia:read({pubsub_last_item, mnesia:first(pubsub_last_item)}) of - [First] when is_list(First#pubsub_last_item.itemid) -> - ?INFO_MSG("Binarization of pubsub items table...", []), - lists:foreach(fun (Id) -> - [Node] = mnesia:read({pubsub_last_item, Id}), - - ItemId = iolist_to_binary(Node#pubsub_last_item.itemid), - - ok = mnesia:delete({pubsub_last_item, Id}), - ok = mnesia:write(Node#pubsub_last_item{itemid=ItemId}) - end, - mnesia:all_keys(pubsub_last_item)); - _-> no_need - end - end, - case mnesia:transaction(F) of - {aborted, Reason} -> - ?ERROR_MSG("Failed to binarize pubsub items table: ~p", [Reason]); - {atomic, no_need} -> - ok; - {atomic, Result} -> - ?INFO_MSG("Pubsub items table has been binarized: ~p", [Result]) - end. - - -update_node_database_binary() -> - F = fun () -> - case catch mnesia:read({pubsub_node, mnesia:first(pubsub_node)}) of - [First] when is_list(First#pubsub_node.type) -> - ?INFO_MSG("Binarization of pubsub nodes table...", []), - lists:foreach(fun ({H, N}) -> - [Node] = mnesia:read({pubsub_node, {H, N}}), - - Type = iolist_to_binary(Node#pubsub_node.type), - BN = case N of - Binary when is_binary(Binary) -> - N; - _ -> - {result, BN1} = node_call(Type, path_to_node, [N]), - BN1 - end, - BP = case [case P of - Binary2 when is_binary(Binary2) -> P; - _ -> element(2, node_call(Type, path_to_node, [P])) - end - || P <- Node#pubsub_node.parents] of - [<<>>] -> []; - Parents -> Parents - end, - - BH = case H of - {U, S, R} -> {iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)}; - String -> iolist_to_binary(String) - end, - - Owners = [{iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)} || - {U, S, R} <- Node#pubsub_node.owners], - - ok = mnesia:delete({pubsub_node, {H, N}}), - ok = mnesia:write(Node#pubsub_node{nodeid = {BH, BN}, - parents = BP, - type = Type, - owners = Owners}); - (_) -> ok - end, - mnesia:all_keys(pubsub_node)); - _-> no_need - end - end, - case mnesia:transaction(F) of - {aborted, Reason} -> - ?ERROR_MSG("Failed to binarize pubsub node table: ~p", [Reason]); - {atomic, no_need} -> - ok; - {atomic, Result} -> - ?INFO_MSG("Pubsub nodes table has been binarized: ~p", [Result]) - end. - -update_node_database(Host, ServerHost) -> - mnesia:del_table_index(pubsub_node, type), - mnesia:del_table_index(pubsub_node, parentid), - case catch mnesia:table_info(pubsub_node, attributes) of - [host_node, host_parent, info] -> - ?INFO_MSG("Upgrading pubsub nodes table...", []), - F = fun () -> - {Result, LastIdx} = lists:foldl(fun ({pubsub_node, - NodeId, ParentId, - {nodeinfo, Items, - Options, - Entities}}, - {RecList, - NodeIdx}) -> - ItemsList = - lists:foldl(fun - ({item, - IID, - Publisher, - Payload}, - Acc) -> - C = - {unknown, - Publisher}, - M = - {now(), - Publisher}, - mnesia:write(#pubsub_item{itemid - = - {IID, - NodeIdx}, - creation - = - C, - modification - = - M, - payload - = - Payload}), - [{Publisher, - IID} - | Acc] - end, - [], - Items), - Owners = - dict:fold(fun - (JID, - {entity, - Aff, - Sub}, - Acc) -> - UsrItems = - lists:foldl(fun - ({P, - I}, - IAcc) -> - case - P - of - JID -> - [I - | IAcc]; - _ -> - IAcc - end - end, - [], - ItemsList), - mnesia:write({pubsub_state, - {JID, - NodeIdx}, - UsrItems, - Aff, - Sub}), - case - Aff - of - owner -> - [JID - | Acc]; - _ -> - Acc - end - end, - [], - Entities), - mnesia:delete({pubsub_node, - NodeId}), - {[#pubsub_node{nodeid - = - NodeId, - id - = - NodeIdx, - parents - = - [element(2, - ParentId)], - owners - = - Owners, - options - = - Options} - | RecList], - NodeIdx + 1} - end, - {[], 1}, - mnesia:match_object({pubsub_node, - {Host, - '_'}, - '_', - '_'})), - mnesia:write(#pubsub_index{index = node, last = LastIdx, - free = []}), - Result - end, - {atomic, NewRecords} = mnesia:transaction(F), - {atomic, ok} = mnesia:delete_table(pubsub_node), - {atomic, ok} = mnesia:create_table(pubsub_node, - [{disc_copies, [node()]}, - {attributes, - record_info(fields, - pubsub_node)}]), - FNew = fun () -> - lists:foreach(fun (Record) -> mnesia:write(Record) end, - NewRecords) - end, - case mnesia:transaction(FNew) of - {atomic, Result} -> - ?INFO_MSG("Pubsub nodes table upgraded: ~p", - [Result]); - {aborted, Reason} -> - ?ERROR_MSG("Problem upgrading Pubsub nodes table:~n~p", - [Reason]) - end; - [nodeid, parentid, type, owners, options] -> - F = fun ({pubsub_node, NodeId, {_, Parent}, Type, - Owners, Options}) -> - #pubsub_node{nodeid = NodeId, id = 0, - parents = [Parent], type = Type, - owners = Owners, options = Options} - end, - mnesia:transform_table(pubsub_node, F, - [nodeid, id, parents, type, owners, options]), - FNew = fun () -> - LastIdx = lists:foldl(fun (#pubsub_node{nodeid = - NodeId} = - PubsubNode, - NodeIdx) -> - mnesia:write(PubsubNode#pubsub_node{id - = - NodeIdx}), - lists:foreach(fun - (#pubsub_state{stateid - = - StateId} = - State) -> - {JID, - _} = - StateId, - mnesia:delete({pubsub_state, - StateId}), - mnesia:write(State#pubsub_state{stateid - = - {JID, - NodeIdx}}) - end, - mnesia:match_object(#pubsub_state{stateid - = - {'_', - NodeId}, - _ - = - '_'})), - lists:foreach(fun - (#pubsub_item{itemid - = - ItemId} = - Item) -> - {IID, - _} = - ItemId, - {M1, - M2} = - Item#pubsub_item.modification, - {C1, - C2} = - Item#pubsub_item.creation, - mnesia:delete({pubsub_item, - ItemId}), - mnesia:write(Item#pubsub_item{itemid - = - {IID, - NodeIdx}, - modification - = - {M2, - M1}, - creation - = - {C2, - C1}}) - end, - mnesia:match_object(#pubsub_item{itemid - = - {'_', - NodeId}, - _ - = - '_'})), - NodeIdx + 1 - end, - 1, - mnesia:match_object({pubsub_node, - {Host, '_'}, - '_', '_', - '_', '_', - '_'}) - ++ - mnesia:match_object({pubsub_node, - {{'_', - ServerHost, - '_'}, - '_'}, - '_', '_', - '_', '_', - '_'})), - mnesia:write(#pubsub_index{index = node, - last = LastIdx, free = []}) - end, - case mnesia:transaction(FNew) of - {atomic, Result} -> - rename_default_nodeplugin(), - ?INFO_MSG("Pubsub nodes table upgraded: ~p", - [Result]); - {aborted, Reason} -> - ?ERROR_MSG("Problem upgrading Pubsub nodes table:~n~p", - [Reason]) - end; - [nodeid, id, parent, type, owners, options] -> - F = fun ({pubsub_node, NodeId, Id, Parent, Type, Owners, - Options}) -> - #pubsub_node{nodeid = NodeId, id = Id, - parents = [Parent], type = Type, - owners = Owners, options = Options} - end, - mnesia:transform_table(pubsub_node, F, - [nodeid, id, parents, type, owners, options]), - rename_default_nodeplugin(); - _ -> ok - end, - update_node_database_binary(). - -rename_default_nodeplugin() -> - lists:foreach(fun (Node) -> - mnesia:dirty_write(Node#pubsub_node{type = - <<"hometree">>}) - end, - mnesia:dirty_match_object(#pubsub_node{type = - <<"default">>, - _ = '_'})). - -update_state_database(_Host, _ServerHost) -> - case catch mnesia:table_info(pubsub_state, attributes) of - [stateid, nodeidx, items, affiliation, subscriptions] -> - ?INFO_MSG("Upgrading pubsub states table...", []), - F = fun ({pubsub_state, {{U,S,R}, NodeID}, _NodeIdx, Items, Aff, Sub}, Acc) -> - JID = {iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)}, - Subs = case Sub of - none -> - []; - [] -> - []; - _ -> - {result, SubID} = pubsub_subscription:subscribe_node(JID, NodeID, []), - [{Sub, SubID}] - end, - NewState = #pubsub_state{stateid = {JID, NodeID}, - items = Items, - affiliation = Aff, - subscriptions = Subs}, - [NewState | Acc] - end, - {atomic, NewRecs} = mnesia:transaction(fun mnesia:foldl/3, - [F, [], pubsub_state]), - {atomic, ok} = mnesia:delete_table(pubsub_state), - {atomic, ok} = mnesia:create_table(pubsub_state, - [{disc_copies, [node()]}, - {attributes, record_info(fields, pubsub_state)}]), - FNew = fun () -> - lists:foreach(fun mnesia:write/1, NewRecs) - end, - case mnesia:transaction(FNew) of - {atomic, Result} -> - ?INFO_MSG("Pubsub states table upgraded: ~p", - [Result]); - {aborted, Reason} -> - ?ERROR_MSG("Problem upgrading Pubsub states table:~n~p", - [Reason]) - end; - _ -> - ok + create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, service_jid(Host), <<"hometree">>); + false -> ok end. send_loop(State) -> receive - {presence, JID, Pid} -> - Host = State#state.host, - ServerHost = State#state.server_host, - LJID = jlib:jid_tolower(JID), - BJID = jlib:jid_remove_resource(LJID), - lists:foreach(fun (PType) -> - {result, Subscriptions} = node_action(Host, - PType, - get_entity_subscriptions, - [Host, - JID]), - lists:foreach(fun ({Node, subscribed, _, - SubJID}) -> - if (SubJID == LJID) or - (SubJID == BJID) -> - #pubsub_node{nodeid - = - {H, - N}, - type = - Type, - id = - NodeId, - options - = - Options} = - Node, - case - get_option(Options, - send_last_published_item) - of - on_sub_and_presence -> - send_items(H, - N, - NodeId, - Type, - Options, - LJID, - last); - _ -> ok - end; - true -> - % resource not concerned about that subscription - ok - end; - (_) -> ok - end, - lists:usort(Subscriptions)) - end, - State#state.plugins), - if not State#state.ignore_pep_from_offline -> - {User, Server, Resource} = jlib:jid_tolower(JID), - case catch ejabberd_c2s:get_subscribed(Pid) of - Contacts when is_list(Contacts) -> - lists:foreach(fun ({U, S, R}) -> - case S of - ServerHost -> %% local contacts - case user_resources(U, S) of - [] -> %% offline - PeerJID = - jlib:make_jid(U, S, - R), - self() ! - {presence, User, - Server, [Resource], - PeerJID}; - _ -> %% online - % this is already handled by presence probe - ok - end; - _ -> %% remote contacts - % we can not do anything in any cases - ok - end - end, - Contacts); - _ -> ok - end; - true -> ok - end, - send_loop(State); - {presence, User, Server, Resources, JID} -> - spawn(fun () -> + {presence, JID, Pid} -> + Host = State#state.host, + ServerHost = State#state.server_host, + DBType = State#state.db_type, + LJID = jlib:jid_tolower(JID), + BJID = jlib:jid_remove_resource(LJID), + lists:foreach( + fun(PType) -> + Subs = get_subscriptions_for_send_last(Host, PType, DBType, JID, LJID, BJID), + lists:foreach( + fun({NodeRec, _, _, SubJID}) -> + {_, Node} = NodeRec#pubsub_node.nodeid, + Nidx = NodeRec#pubsub_node.id, + Options = NodeRec#pubsub_node.options, + send_items(Host, Node, Nidx, PType, Options, SubJID, last) + end, + lists:usort(Subs)) + end, + State#state.plugins), + if not State#state.ignore_pep_from_offline -> + {User, Server, Resource} = LJID, + case catch ejabberd_c2s:get_subscribed(Pid) of + Contacts when is_list(Contacts) -> + lists:foreach( + fun({U, S, R}) when S == ServerHost -> + case user_resources(U, S) of + [] -> %% offline + PeerJID = jlib:make_jid(U, S, R), + self() ! {presence, User, Server, [Resource], PeerJID}; + _ -> %% online + % this is already handled by presence probe + ok + end; + (_) -> + % we can not do anything in any cases + ok + end, + Contacts); + _ -> + ok + end; + true -> + ok + end, + send_loop(State); + {presence, User, Server, Resources, JID} -> + spawn(fun() -> Host = State#state.host, Owner = jlib:jid_remove_resource(jlib:jid_tolower(JID)), - lists:foreach(fun (#pubsub_node{nodeid = {_, Node}, - type = Type, - id = NodeId, - options = Options}) -> - case get_option(Options, - send_last_published_item) - of - on_sub_and_presence -> - lists:foreach(fun - (Resource) -> - LJID = - {User, - Server, - Resource}, - Subscribed = - case - get_option(Options, - access_model) - of - open -> - true; - presence -> - true; - whitelist -> - false; % subscribers are added manually - authorize -> - false; % likewise - roster -> - Grps = - get_option(Options, - roster_groups_allowed, - []), - {OU, - OS, - _} = - Owner, - element(2, - get_roster_info(OU, - OS, - LJID, - Grps)) - end, - if - Subscribed -> - send_items(Owner, - Node, - NodeId, - Type, - Options, - LJID, - last); - true -> - ok - end - end, - Resources); - _ -> ok - end - end, - tree_action(Host, get_nodes, - [Owner, JID])) + lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, type = Type, id = Nidx, options = Options}) -> + case match_option(Options, send_last_published_item, on_sub_and_presence) of + true -> + lists:foreach(fun(Resource) -> + LJID = {User, Server, Resource}, + Subscribed = case get_option(Options, access_model) of + open -> true; + presence -> true; + whitelist -> false; % subscribers are added manually + authorize -> false; % likewise + roster -> + Grps = get_option(Options, roster_groups_allowed, []), + {OU, OS, _} = Owner, + element(2, get_roster_info(OU, OS, LJID, Grps)) + end, + if Subscribed -> send_items(Owner, Node, Nidx, Type, Options, LJID, last); + true -> ok + end + end, + Resources); + _ -> + ok + end + end, + tree_action(Host, get_nodes, [Owner, JID])) end), - send_loop(State); - stop -> ok + send_loop(State); + stop -> + ok end. %% ------- @@ -981,49 +480,43 @@ send_loop(State) -> %% -spec(disco_local_identity/5 :: -( - Acc :: [xmlel()], - _From :: jid(), - To :: jid(), - NodeId :: <<>> | mod_pubsub:nodeId(), - Lang :: binary()) + ( + Acc :: [xmlel()], + _From :: jid(), + To :: jid(), + Node :: <<>> | mod_pubsub:nodeId(), + Lang :: binary()) -> [xmlel()] -). + ). disco_local_identity(Acc, _From, To, <<>>, _Lang) -> case lists:member(?PEPNODE, plugins(To#jid.lserver)) of - true -> - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}], - children = []} - | Acc]; - false -> Acc + true -> + [#xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"pubsub">>}, + {<<"type">>, <<"pep">>}]} + | Acc]; + false -> + Acc end; disco_local_identity(Acc, _From, _To, _Node, _Lang) -> Acc. -spec(disco_local_features/5 :: -( - Acc :: [xmlel()], - _From :: jid(), - To :: jid(), - NodeId :: <<>> | mod_pubsub:nodeId(), - Lang :: binary()) + ( + Acc :: [xmlel()], + _From :: jid(), + To :: jid(), + Node :: <<>> | mod_pubsub:nodeId(), + Lang :: binary()) -> [binary(),...] -). + ). disco_local_features(Acc, _From, To, <<>>, _Lang) -> Host = To#jid.lserver, Feats = case Acc of - {result, I} -> I; - _ -> [] - end, - {result, - Feats ++ - lists:map(fun (Feature) -> - <<(?NS_PUBSUB)/binary, "#", Feature/binary>> - end, - features(Host, <<>>))}; + {result, I} -> I; + _ -> [] + end, + {result, Feats ++ [feature(F) || F <- features(Host, <<>>)]}; disco_local_features(Acc, _From, _To, _Node, _Lang) -> Acc. @@ -1033,179 +526,156 @@ disco_local_items(Acc, _From, _To, _Node, _Lang) -> Acc. %disco_sm_identity(Acc, From, To, Node, Lang) % when is_binary(Node) -> % disco_sm_identity(Acc, From, To, iolist_to_binary(Node), -% Lang); +% Lang); -spec(disco_sm_identity/5 :: -( - Acc :: empty | [xmlel()], - From :: jid(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Lang :: binary()) + ( + Acc :: empty | [xmlel()], + From :: jid(), + To :: jid(), + Node :: mod_pubsub:nodeId(), + Lang :: binary()) -> [xmlel()] -). + ). disco_sm_identity(empty, From, To, Node, Lang) -> disco_sm_identity([], From, To, Node, Lang); disco_sm_identity(Acc, From, To, Node, _Lang) -> disco_identity(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From) - ++ Acc. + ++ Acc. disco_identity(_Host, <<>>, _From) -> [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}], - children = []}]; + attrs = [{<<"category">>, <<"pubsub">>}, + {<<"type">>, <<"pep">>}]}]; disco_identity(Host, Node, From) -> - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options, owners = Owners}) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - {result, _} -> - {result, - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}], - children = []}, - #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"leaf">>} - | case get_option(Options, title) of - false -> []; - [Title] -> [{<<"name">>, Title}] - end], - children = []}]}; - _ -> {result, []} - end - end, + Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of + {result, _} -> + {result, [#xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"pubsub">>}, + {<<"type">>, <<"pep">>}]}, + #xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"pubsub">>}, + {<<"type">>, <<"leaf">>} + | case get_option(Options, title) of + false -> []; + [Title] -> [{<<"name">>, Title}] + end]}]}; + _ -> + {result, []} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> Result; - _ -> [] + {result, {_, Result}} -> Result; + _ -> [] end. -spec(disco_sm_features/5 :: -( - Acc :: empty | {result, Features::[Feature::binary()]}, - From :: jid(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Lang :: binary()) + ( + Acc :: empty | {result, Features::[Feature::binary()]}, + From :: jid(), + To :: jid(), + Node :: mod_pubsub:nodeId(), + Lang :: binary()) -> {result, Features::[Feature::binary()]} -). + ). %disco_sm_features(Acc, From, To, Node, Lang) % when is_binary(Node) -> % disco_sm_features(Acc, From, To, iolist_to_binary(Node), -% Lang); +% Lang); disco_sm_features(empty, From, To, Node, Lang) -> disco_sm_features({result, []}, From, To, Node, Lang); disco_sm_features({result, OtherFeatures} = _Acc, From, To, Node, _Lang) -> {result, - OtherFeatures ++ - disco_features(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From)}; + OtherFeatures ++ + disco_features(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From)}; disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. -disco_features(_Host, <<>>, _From) -> - [?NS_PUBSUB | [<<(?NS_PUBSUB)/binary, "#", Feature/binary>> - || Feature <- features(<<"pep">>)]]; +disco_features(Host, <<>>, _From) -> + [?NS_PUBSUB | [feature(F) || F <- plugin_features(Host, <<"pep">>)]]; disco_features(Host, Node, From) -> - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options, owners = Owners}) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - {result, _} -> - {result, - [?NS_PUBSUB | [<<(?NS_PUBSUB)/binary, "#", - Feature/binary>> - || Feature <- features(<<"pep">>)]]}; - _ -> {result, []} - end - end, + Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of + {result, _} -> {result, [?NS_PUBSUB | [feature(F) || F <- plugin_features(Host, <<"pep">>)]]}; + _ -> {result, []} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> Result; - _ -> [] + {result, {_, Result}} -> Result; + _ -> [] end. -spec(disco_sm_items/5 :: -( - Acc :: empty | {result, [xmlel()]}, - From :: jid(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Lang :: binary()) + ( + Acc :: empty | {result, [xmlel()]}, + From :: jid(), + To :: jid(), + Node :: mod_pubsub:nodeId(), + Lang :: binary()) -> {result, [xmlel()]} -). + ). %disco_sm_items(Acc, From, To, Node, Lang) % when is_binary(Node) -> % disco_sm_items(Acc, From, To, iolist_to_binary(Node), -% Lang); +% Lang); disco_sm_items(empty, From, To, Node, Lang) -> disco_sm_items({result, []}, From, To, Node, Lang); disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> - {result, - lists:usort(OtherItems ++ - disco_items(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From))}; + {result, lists:usort(OtherItems ++ + disco_items(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From))}; disco_sm_items(Acc, _From, _To, _Node, _Lang) -> Acc. -spec(disco_items/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid()) + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + From :: jid()) -> [xmlel()] -). + ). disco_items(Host, <<>>, From) -> - Action = fun (#pubsub_node{nodeid = {_, NodeID}, - options = Options, type = Type, id = Idx, - owners = Owners}, - Acc) -> - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - {result, _} -> - [#xmlel{name = <<"item">>, - attrs = - [{<<"node">>, (NodeID)}, - {<<"jid">>, - case Host of - {_, _, _} -> - jlib:jid_to_string(Host); - _Host -> Host - end} - | case get_option(Options, title) of - false -> []; - [Title] -> [{<<"name">>, Title}] - end], - children = []} - | Acc]; - _ -> Acc - end - end, - case transaction(Host, Action, sync_dirty) of - {result, Items} -> Items; - _ -> [] + Action = fun (#pubsub_node{nodeid = {_, Node}, + options = Options, type = Type, id = Nidx, owners = O}, + Acc) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of + {result, _} -> + [#xmlel{name = <<"item">>, + attrs = [{<<"node">>, (Node)}, + {<<"jid">>, jlib:jid_to_string(Host)} + | case get_option(Options, title) of + false -> []; + [Title] -> [{<<"name">>, Title}] + end]} + | Acc]; + _ -> + Acc + end + end, + NodeBloc = fun() -> + {result, + lists:foldl(Action, [], tree_call(Host, get_nodes, [Host]))} + end, + case transaction(Host, NodeBloc, sync_dirty) of + {result, Items} -> Items; + _ -> [] end; disco_items(Host, Node, From) -> - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options, owners = Owners}) -> - case get_allowed_items_call(Host, Idx, From, Type, - Options, Owners) - of - {result, Items} -> - {result, - [#xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, - case Host of - {_, _, _} -> - jlib:jid_to_string(Host); - _Host -> Host - end}, - {<<"name">>, ItemID}], - children = []} - || #pubsub_item{itemid = {ItemID, _}} <- Items]}; - _ -> {result, []} - end - end, + Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of + {result, Items} -> + {result, [#xmlel{name = <<"item">>, + attrs = [{<<"jid">>, jlib:jid_to_string(Host)}, + {<<"name">>, ItemId}]} + || #pubsub_item{itemid = {ItemId, _}} <- Items]}; + _ -> + {result, []} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> Result; - _ -> [] + {result, {_, Result}} -> Result; + _ -> [] end. %% ------- @@ -1233,26 +703,10 @@ presence_probe(_Host, _JID, _Pid) -> ok. presence(ServerHost, Presence) -> - SendLoop = case - whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) - of - undefined -> - Host = host(ServerHost), - Plugins = plugins(Host), - PepOffline = case catch - ets:lookup(gen_mod:get_module_proc(ServerHost, - config), - ignore_pep_from_offline) - of - [{ignore_pep_from_offline, PO}] -> PO; - _ -> true - end, - State = #state{host = Host, server_host = ServerHost, - ignore_pep_from_offline = PepOffline, - plugins = Plugins}, - init_send_loop(ServerHost, State); - Pid -> Pid - end, + {SendLoop, _} = case whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) of + undefined -> init_send_loop(ServerHost); + Pid -> {Pid, undefined} + end, SendLoop ! Presence. %% ------- @@ -1260,73 +714,57 @@ presence(ServerHost, Presence) -> %% out_subscription(User, Server, JID, subscribed) -> - Owner = jlib:make_jid(User, Server, <<"">>), + Owner = jlib:make_jid(User, Server, <<>>), {PUser, PServer, PResource} = jlib:jid_tolower(JID), PResources = case PResource of - <<>> -> user_resources(PUser, PServer); - _ -> [PResource] - end, - presence(Server, - {presence, PUser, PServer, PResources, Owner}), + <<>> -> user_resources(PUser, PServer); + _ -> [PResource] + end, + presence(Server, {presence, PUser, PServer, PResources, Owner}), true; -out_subscription(_, _, _, _) -> true. +out_subscription(_, _, _, _) -> + true. -in_subscription(_, User, Server, Owner, unsubscribed, - _) -> - unsubscribe_user(jlib:make_jid(User, Server, <<"">>), - Owner), +in_subscription(_, User, Server, Owner, unsubscribed, _) -> + unsubscribe_user(jlib:make_jid(User, Server, <<>>), Owner), true; -in_subscription(_, _, _, _, _, _) -> true. +in_subscription(_, _, _, _, _, _) -> + true. unsubscribe_user(Entity, Owner) -> BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), Host = host(element(2, BJID)), spawn(fun () -> - lists:foreach(fun (PType) -> - {result, Subscriptions} = - node_action(Host, PType, - get_entity_subscriptions, - [Host, Entity]), - lists:foreach(fun ({#pubsub_node{options - = - Options, - owners - = - Owners, - id = - NodeId}, - subscribed, _, - JID}) -> - case - get_option(Options, - access_model) - of - presence -> - case - lists:member(BJID, - Owners) - of - true -> - node_action(Host, - PType, - unsubscribe_node, - [NodeId, - Entity, - JID, - all]); - false -> - {result, - ok} - end; - _ -> - {result, ok} - end; - (_) -> ok - end, - Subscriptions) + lists:foreach(fun (PType) -> + {result, Subs} = node_action(Host, PType, + get_entity_subscriptions, + [Host, Entity]), + lists:foreach(fun + ({#pubsub_node{options = Options, + owners = O, + id = Nidx}, + subscribed, _, JID}) -> + case match_option(Options, access_model, presence) of + true -> + Owners = node_owners_action(Host, PType, Nidx, O), + case lists:member(BJID, Owners) of + true -> + node_action(Host, PType, + unsubscribe_node, + [Nidx, Entity, JID, all]); + false -> + {result, ok} + end; + _ -> + {result, ok} + end; + (_) -> + ok end, - plugins(Host)) - end). + Subs) + end, + plugins(Host)) + end). %% ------- %% user remove hook handling function @@ -1335,68 +773,43 @@ unsubscribe_user(Entity, Owner) -> remove_user(User, Server) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), - Entity = jlib:make_jid(LUser, LServer, <<"">>), + Entity = jlib:make_jid(LUser, LServer, <<>>), Host = host(LServer), HomeTreeBase = <<"/home/", LServer/binary, "/", LUser/binary>>, spawn(fun () -> - lists:foreach(fun (PType) -> - {result, Subscriptions} = - node_action(Host, PType, - get_entity_subscriptions, - [Host, Entity]), - lists:foreach(fun ({#pubsub_node{id = - NodeId}, - _, _, JID}) -> - node_action(Host, - PType, - unsubscribe_node, - [NodeId, - Entity, - JID, - all]); - (_) -> ok - end, - Subscriptions), - {result, Affiliations} = - node_action(Host, PType, - get_entity_affiliations, - [Host, Entity]), - lists:foreach(fun ({#pubsub_node{nodeid - = - {H, - N}, - parents - = - []}, - owner}) -> - delete_node(H, N, - Entity); - ({#pubsub_node{nodeid - = - {H, - N}, - type = - <<"hometree">>}, - owner}) - when N == - HomeTreeBase -> - delete_node(H, N, - Entity); - ({#pubsub_node{id = - NodeId}, - publisher}) -> - node_action(Host, - PType, - set_affiliation, - [NodeId, - Entity, - none]); - (_) -> ok - end, - Affiliations) + lists:foreach(fun (PType) -> + {result, Subs} = node_action(Host, PType, + get_entity_subscriptions, + [Host, Entity]), + lists:foreach(fun + ({#pubsub_node{id = Nidx}, _, _, JID}) -> + node_action(Host, PType, + unsubscribe_node, + [Nidx, Entity, JID, all]); + (_) -> + ok + end, + Subs), + {result, Affs} = node_action(Host, PType, + get_entity_affiliations, + [Host, Entity]), + lists:foreach(fun + ({#pubsub_node{nodeid = {H, N}, parents = []}, owner}) -> + delete_node(H, N, Entity); + ({#pubsub_node{nodeid = {H, N}, type = Type}, owner}) + when N == HomeTreeBase, Type == <<"hometree">> -> + delete_node(H, N, Entity); + ({#pubsub_node{id = Nidx}, publisher}) -> + node_action(Host, PType, + set_affiliation, + [Nidx, Entity, none]); + (_) -> + ok end, - plugins(Host)) - end). + Affs) + end, + plugins(Host)) + end). handle_call(server_host, _From, State) -> {reply, State#state.server_host, State}; @@ -1411,36 +824,32 @@ handle_call(stop, _From, State) -> %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} +%% {noreply, State, Timeout} | +%% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- %% @private handle_cast(_Msg, State) -> {noreply, State}. -spec(handle_info/2 :: -( - _ :: {route, From::jid(), To::jid(), Packet::xmlel()}, - State :: state()) + ( + _ :: {route, From::jid(), To::jid(), Packet::xmlel()}, + State :: state()) -> {noreply, state()} -). + ). %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} +%% {noreply, State, Timeout} | +%% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- %% @private handle_info({route, From, To, Packet}, - #state{server_host = ServerHost, access = Access, - plugins = Plugins} = - State) -> - case catch do_route(ServerHost, Access, Plugins, - To#jid.lserver, From, To, Packet) - of - {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); - _ -> ok + #state{server_host = ServerHost, access = Access, plugins = Plugins} = State) -> + case catch do_route(ServerHost, Access, Plugins, To#jid.lserver, From, To, Packet) of + {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); + _ -> ok end, {noreply, State}; handle_info(_Info, State) -> @@ -1455,47 +864,51 @@ handle_info(_Info, State) -> %%-------------------------------------------------------------------- %% @private terminate(_Reason, - #state{host = Host, server_host = ServerHost, - nodetree = TreePlugin, plugins = Plugins}) -> + #state{host = Host, server_host = ServerHost, nodetree = TreePlugin, plugins = Plugins}) -> ejabberd_router:unregister_route(Host), case lists:member(?PEPNODE, Plugins) of - true -> - ejabberd_hooks:delete(caps_update, ServerHost, ?MODULE, - caps_update, 80), - ejabberd_hooks:delete(disco_sm_identity, ServerHost, - ?MODULE, disco_sm_identity, 75), - ejabberd_hooks:delete(disco_sm_features, ServerHost, - ?MODULE, disco_sm_features, 75), - ejabberd_hooks:delete(disco_sm_items, ServerHost, - ?MODULE, disco_sm_items, 75), - gen_iq_handler:remove_iq_handler(ejabberd_sm, - ServerHost, ?NS_PUBSUB), - gen_iq_handler:remove_iq_handler(ejabberd_sm, - ServerHost, ?NS_PUBSUB_OWNER); - false -> ok + true -> + ejabberd_hooks:delete(caps_update, ServerHost, + ?MODULE, caps_update, 80), + ejabberd_hooks:delete(disco_sm_identity, ServerHost, + ?MODULE, disco_sm_identity, 75), + ejabberd_hooks:delete(disco_sm_features, ServerHost, + ?MODULE, disco_sm_features, 75), + ejabberd_hooks:delete(disco_sm_items, ServerHost, + ?MODULE, disco_sm_items, 75), + gen_iq_handler:remove_iq_handler(ejabberd_sm, + ServerHost, ?NS_PUBSUB), + gen_iq_handler:remove_iq_handler(ejabberd_sm, + ServerHost, ?NS_PUBSUB_OWNER); + false -> + ok end, - ejabberd_hooks:delete(sm_remove_connection_hook, - ServerHost, ?MODULE, on_user_offline, 75), + ejabberd_hooks:delete(sm_remove_connection_hook, ServerHost, + ?MODULE, on_user_offline, 75), ejabberd_hooks:delete(disco_local_identity, ServerHost, - ?MODULE, disco_local_identity, 75), + ?MODULE, disco_local_identity, 75), ejabberd_hooks:delete(disco_local_features, ServerHost, - ?MODULE, disco_local_features, 75), + ?MODULE, disco_local_features, 75), ejabberd_hooks:delete(disco_local_items, ServerHost, - ?MODULE, disco_local_items, 75), + ?MODULE, disco_local_items, 75), ejabberd_hooks:delete(presence_probe_hook, ServerHost, - ?MODULE, presence_probe, 80), - ejabberd_hooks:delete(roster_in_subscription, - ServerHost, ?MODULE, in_subscription, 50), - ejabberd_hooks:delete(roster_out_subscription, - ServerHost, ?MODULE, out_subscription, 50), - ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, - remove_user, 50), + ?MODULE, presence_probe, 80), + ejabberd_hooks:delete(roster_in_subscription, ServerHost, + ?MODULE, in_subscription, 50), + ejabberd_hooks:delete(roster_out_subscription, ServerHost, + ?MODULE, out_subscription, 50), + ejabberd_hooks:delete(remove_user, ServerHost, + ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, - ?MODULE, remove_user, 50), + ?MODULE, remove_user, 50), mod_disco:unregister_feature(ServerHost, ?NS_PUBSUB), - gen_mod:get_module_proc(ServerHost, ?LOOPNAME) ! stop, - terminate_plugins(Host, ServerHost, Plugins, - TreePlugin). + case whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) of + undefined -> + ?ERROR_MSG("~s process is dead, pubsub was broken", [?LOOPNAME]); + Pid -> + Pid ! stop + end, + terminate_plugins(Host, ServerHost, Plugins, TreePlugin). %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} @@ -1505,16 +918,16 @@ terminate(_Reason, code_change(_OldVsn, State, _Extra) -> {ok, State}. -spec(do_route/7 :: -( - ServerHost :: binary(), - Access :: atom(), - Plugins :: [binary(),...], - Host :: mod_pubsub:hostPubsub(), - From :: jid(), - To :: jid(), - Packet :: xmlel()) + ( + ServerHost :: binary(), + Access :: atom(), + Plugins :: [binary(),...], + Host :: mod_pubsub:hostPubsub(), + From :: jid(), + To :: jid(), + Packet :: xmlel()) -> ok -). + ). %%-------------------------------------------------------------------- %%% Internal functions @@ -1522,1029 +935,833 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> #xmlel{name = Name, attrs = Attrs} = Packet, case To of - #jid{luser = <<"">>, lresource = <<"">>} -> - case Name of - <<"iq">> -> - case jlib:iq_query_info(Packet) of - #iq{type = get, xmlns = ?NS_DISCO_INFO, sub_el = SubEl, - lang = Lang} = - IQ -> - #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), - Info = ejabberd_hooks:run_fold(disco_info, ServerHost, - [], - [ServerHost, ?MODULE, - <<"">>, <<"">>]), - Res = case iq_disco_info(Host, Node, From, Lang) of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = - [#xmlel{name = - <<"query">>, - attrs = - QAttrs, - children = - IQRes ++ - Info}]}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) + #jid{luser = <<>>, lresource = <<>>} -> + case Name of + <<"iq">> -> + case jlib:iq_query_info(Packet) of + #iq{type = get, xmlns = ?NS_DISCO_INFO, sub_el = SubEl, lang = Lang} = IQ -> + #xmlel{attrs = QAttrs} = SubEl, + Node = xml:get_attr_s(<<"node">>, QAttrs), + Info = ejabberd_hooks:run_fold(disco_info, ServerHost, + [], + [ServerHost, ?MODULE, <<>>, <<>>]), + Res = case iq_disco_info(Host, Node, From, Lang) of + {result, IQRes} -> + jlib:iq_to_xml(IQ#iq{type = result, + sub_el = + [#xmlel{name = <<"query">>, + attrs = QAttrs, + children = IQRes ++ Info}]}); + {error, Error} -> + jlib:make_error_reply(Packet, Error) end, - ejabberd_router:route(To, From, Res); - #iq{type = get, xmlns = ?NS_DISCO_ITEMS, - sub_el = SubEl} = - IQ -> - #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), - Res = case iq_disco_items(Host, Node, From) of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = - [#xmlel{name = - <<"query">>, - attrs = - QAttrs, - children = - IQRes}]}) -% {error, Error} -> -% jlib:make_error_reply(Packet, Error) + ejabberd_router:route(To, From, Res); + #iq{type = get, xmlns = ?NS_DISCO_ITEMS, sub_el = SubEl} = IQ -> + #xmlel{attrs = QAttrs} = SubEl, + Node = xml:get_attr_s(<<"node">>, QAttrs), + Res = case iq_disco_items(Host, Node, From, jlib:rsm_decode(IQ)) of + {result, IQRes} -> + jlib:iq_to_xml(IQ#iq{type = result, + sub_el = + [#xmlel{name = <<"query">>, + attrs = QAttrs, + children = IQRes}]}) + %{error, Error} -> + % jlib:make_error_reply(Packet, Error) end, - ejabberd_router:route(To, From, Res); - #iq{type = IQType, xmlns = ?NS_PUBSUB, lang = Lang, - sub_el = SubEl} = - IQ -> - Res = case iq_pubsub(Host, ServerHost, From, IQType, - SubEl, Lang, Access, Plugins) - of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = IQRes}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) + ejabberd_router:route(To, From, Res); + #iq{type = IQType, xmlns = ?NS_PUBSUB, lang = Lang, sub_el = SubEl} = IQ -> + Res = case iq_pubsub(Host, ServerHost, From, IQType, + SubEl, Lang, Access, Plugins) + of + {result, IQRes} -> + jlib:iq_to_xml(IQ#iq{type = result, sub_el = IQRes}); + {error, Error} -> + jlib:make_error_reply(Packet, Error) end, - ejabberd_router:route(To, From, Res); - #iq{type = IQType, xmlns = ?NS_PUBSUB_OWNER, - lang = Lang, sub_el = SubEl} = - IQ -> - Res = case iq_pubsub_owner(Host, ServerHost, From, - IQType, SubEl, Lang) - of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = IQRes}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) + ejabberd_router:route(To, From, Res); + #iq{type = IQType, xmlns = ?NS_PUBSUB_OWNER, lang = Lang, sub_el = SubEl} = IQ -> + Res = case iq_pubsub_owner(Host, ServerHost, From, + IQType, SubEl, Lang) + of + {result, IQRes} -> + jlib:iq_to_xml(IQ#iq{type = result, sub_el = IQRes}); + {error, Error} -> + jlib:make_error_reply(Packet, Error) end, - ejabberd_router:route(To, From, Res); - #iq{type = get, xmlns = (?NS_VCARD) = XMLNS, - lang = Lang, sub_el = _SubEl} = - IQ -> - Res = IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"vCard">>, - attrs = [{<<"xmlns">>, XMLNS}], - children = iq_get_vcard(Lang)}]}, - ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); - #iq{type = set, xmlns = ?NS_COMMANDS} = IQ -> - Res = case iq_command(Host, ServerHost, From, IQ, - Access, Plugins) - of - {error, Error} -> - jlib:make_error_reply(Packet, Error); - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = IQRes}) + ejabberd_router:route(To, From, Res); + #iq{type = get, xmlns = (?NS_VCARD) = XMLNS, lang = Lang, sub_el = _SubEl} = IQ -> + Res = IQ#iq{type = result, + sub_el = + [#xmlel{name = <<"vCard">>, + attrs = [{<<"xmlns">>, XMLNS}], + children = iq_get_vcard(Lang)}]}, + ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); + #iq{type = set, xmlns = ?NS_COMMANDS} = IQ -> + Res = case iq_command(Host, ServerHost, From, IQ, Access, Plugins) of + {error, Error} -> + jlib:make_error_reply(Packet, Error); + {result, IQRes} -> + jlib:iq_to_xml(IQ#iq{type = result, sub_el = IQRes}) end, - ejabberd_router:route(To, From, Res); - #iq{} -> - Err = jlib:make_error_reply(Packet, - ?ERR_FEATURE_NOT_IMPLEMENTED), - ejabberd_router:route(To, From, Err); - _ -> ok - end; - <<"message">> -> - case xml:get_attr_s(<<"type">>, Attrs) of - <<"error">> -> ok; - _ -> - case find_authorization_response(Packet) of - none -> ok; - invalid -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, - ?ERR_BAD_REQUEST)); - XFields -> - handle_authorization_response(Host, From, To, - Packet, XFields) - end - end; - _ -> ok - end; - _ -> - case xml:get_attr_s(<<"type">>, Attrs) of - <<"error">> -> ok; - <<"result">> -> ok; - _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_ITEM_NOT_FOUND), - ejabberd_router:route(To, From, Err) - end + ejabberd_router:route(To, From, Res); + #iq{} -> + Err = jlib:make_error_reply(Packet, ?ERR_FEATURE_NOT_IMPLEMENTED), + ejabberd_router:route(To, From, Err); + _ -> + ok + end; + <<"message">> -> + case xml:get_attr_s(<<"type">>, Attrs) of + <<"error">> -> + ok; + _ -> + case find_authorization_response(Packet) of + none -> + ok; + invalid -> + Err = jlib:make_error_reply(Packet, ?ERR_BAD_REQUEST), + ejabberd_router:route(To, From, Err); + XFields -> + handle_authorization_response(Host, From, To, Packet, XFields) + end + end; + _ -> + ok + end; + _ -> + case xml:get_attr_s(<<"type">>, Attrs) of + <<"error">> -> + ok; + <<"result">> -> + ok; + _ -> + Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND), + ejabberd_router:route(To, From, Err) + end end. command_disco_info(_Host, ?NS_COMMANDS, _From) -> IdentityEl = #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"automation">>}, - {<<"type">>, <<"command-list">>}], - children = []}, + attrs = [{<<"category">>, <<"automation">>}, + {<<"type">>, <<"command-list">>}]}, {result, [IdentityEl]}; -command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, - _From) -> +command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> IdentityEl = #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"automation">>}, - {<<"type">>, <<"command-node">>}], - children = []}, + attrs = [{<<"category">>, <<"automation">>}, + {<<"type">>, <<"command-node">>}]}, FeaturesEl = #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_COMMANDS}], children = []}, + attrs = [{<<"var">>, ?NS_COMMANDS}]}, {result, [IdentityEl, FeaturesEl]}. node_disco_info(Host, Node, From) -> node_disco_info(Host, Node, From, true, true). node_disco_info(Host, Node, From, _Identity, _Features) -> -% Action = -% fun(#pubsub_node{type = Type, id = NodeId}) -> -% I = case Identity of -% false -> -% []; -% true -> -% Types = -% case tree_call(Host, get_subnodes, [Host, Node, From]) of -% [] -> -% [<<"leaf">>]; %% No sub-nodes: it's a leaf node -% _ -> -% case node_call(Type, get_items, [NodeId, From]) of -% {result, []} -> [<<"collection">>]; -% {result, _} -> [<<"leaf">>, <<"collection">>]; -% _ -> [] -% end -% end, -% lists:map(fun(T) -> -% #xmlel{name = <<"identity">>, -% attrs = -% [{<<"category">>, -% <<"pubsub">>}, -% {<<"type">>, T}], -% children = []} -% end, Types) -% end, -% F = case Features of -% false -> -% []; -% true -> -% [#xmlel{name = <<"feature">>, -% attrs = [{<<"var">>, ?NS_PUBSUB}], -% children = []} -% | lists:map(fun (T) -> -% #xmlel{name = <<"feature">>, -% attrs = -% [{<<"var">>, -% <<(?NS_PUBSUB)/binary, -% "#", -% T/binary>>}], -% children = []} -% end, -% features(Type))] -% end, -% %% TODO: add meta-data info (spec section 5.4) -% {result, I ++ F} -% end, -% case transaction(Host, Node, Action, sync_dirty) of -% {result, {_, Result}} -> {result, Result}; -% Other -> Other -% end. - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - Types = case tree_call(Host, get_subnodes, - [Host, Node, From]) - of - [] -> [<<"leaf">>]; - _ -> - case node_call(Type, get_items, - [NodeId, From]) - of - {result, []} -> - [<<"collection">>]; - {result, _} -> - [<<"leaf">>, - <<"collection">>]; - _ -> [] - end - end, - I = lists:map(fun (T) -> - #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, - <<"pubsub">>}, - {<<"type">>, T}], - children = []} - end, - Types), - F = [#xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_PUBSUB}], - children = []} - | lists:map(fun (T) -> - #xmlel{name = <<"feature">>, - attrs = - [{<<"var">>, - <<(?NS_PUBSUB)/binary, - "#", - T/binary>>}], - children = []} - end, - features(Type))], - {result, I ++ F} - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + Types = case tree_call(Host, get_subnodes, [Host, Node, From]) of + [] -> + [<<"leaf">>]; + _ -> + case node_call(Host, Type, get_items, [Nidx, From, none]) of + {result, {[], _}} -> [<<"collection">>]; + {result, _} -> [<<"leaf">>, <<"collection">>]; + _ -> [] + end + end, + I = [#xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"pubsub">>}, {<<"type">>, T}]} + || T <- Types], + F = [#xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_PUBSUB}]} + | [#xmlel{name = <<"feature">>, + attrs = [{<<"var">>, feature(F)}]} + || F <- plugin_features(Host, Type)]], + {result, I ++ F} + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other + {result, {_, Result}} -> {result, Result}; + Other -> Other end. iq_disco_info(Host, SNode, From, Lang) -> [Node | _] = case SNode of - <<>> -> [<<>>]; - _ -> str:tokens(SNode, <<"!">>) - end, - % Node = string_to_node(RealSNode), + <<>> -> [<<>>]; + _ -> str:tokens(SNode, <<"!">>) + end, + % Node = string_to_node(RealSNode), case Node of - <<>> -> - {result, - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"service">>}, - {<<"name">>, - translate:translate(Lang, <<"Publish-Subscribe">>)}], - children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_DISCO_INFO}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_DISCO_ITEMS}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_PUBSUB}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_COMMANDS}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_VCARD}], children = []}] - ++ - lists:map(fun (Feature) -> - #xmlel{name = <<"feature">>, - attrs = - [{<<"var">>, <<(?NS_PUBSUB)/binary, "#", Feature/binary>>}], - children = []} - end, - features(Host, Node))}; - ?NS_COMMANDS -> command_disco_info(Host, Node, From); - ?NS_PUBSUB_GET_PENDING -> - command_disco_info(Host, Node, From); - _ -> node_disco_info(Host, Node, From) + <<>> -> + {result, [#xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"pubsub">>}, + {<<"type">>, <<"service">>}, + {<<"name">>, translate:translate(Lang, <<"Publish-Subscribe">>)}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_DISCO_INFO}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_DISCO_ITEMS}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_PUBSUB}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_COMMANDS}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_VCARD}]}] + ++ [#xmlel{name = <<"feature">>, + attrs = [{<<"var">>, feature(F)}]} + || F <- features(Host, Node)]}; + ?NS_COMMANDS -> + command_disco_info(Host, Node, From); + ?NS_PUBSUB_GET_PENDING -> + command_disco_info(Host, Node, From); + _ -> + node_disco_info(Host, Node, From) end. --spec(iq_disco_items/3 :: -( - Host :: mod_pubsub:host(), - NodeId :: <<>> | mod_pubsub:nodeId(), - From :: jid()) +-spec(iq_disco_items/4 :: + ( + Host :: mod_pubsub:host(), + Node :: <<>> | mod_pubsub:nodeId(), + From :: jid(), + Rsm :: none | rsm_in()) -> {result, [xmlel()]} -). -iq_disco_items(Host, <<>>, From) -> - {result, - lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, - options = Options}) -> - Attrs = case get_option(Options, title) of - false -> - [{<<"jid">>, Host} - | nodeAttr(SubNode)]; - Title -> - [{<<"jid">>, Host}, - {<<"name">>, Title} - | nodeAttr(SubNode)] - end, - #xmlel{name = <<"item">>, attrs = Attrs, - children = []} - end, - tree_action(Host, get_subnodes, [Host, <<>>, From]))}; -% case tree_action(Host, get_subnodes, [Host, <<>>, From]) of -% Nodes when is_list(Nodes) -> -% {result, -% lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, -% options = Options}) -> -% Attrs = case get_option(Options, title) of -% false -> -% [{<<"jid">>, Host} -% | nodeAttr(SubNode)]; -% Title -> -% [{<<"jid">>, Host}, -% {<<"name">>, Title} -% | nodeAttr(SubNode)] -% end, -% #xmlel{name = <<"item">>, attrs = Attrs, -% children = []} -% end, -% Nodes)}; -% Other -> Other -% end; -iq_disco_items(Host, ?NS_COMMANDS, _From) -> - CommandItems = [#xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, Host}, - {<<"node">>, ?NS_PUBSUB_GET_PENDING}, - {<<"name">>, <<"Get Pending">>}], - children = []}], - {result, CommandItems}; -iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> - CommandItems = [], {result, CommandItems}; -iq_disco_items(Host, Item, From) -> + ). +iq_disco_items(Host, <<>>, From, _RSM) -> + {result, + lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, options = Options}) -> + Attrs = case get_option(Options, title) of + false -> + [{<<"jid">>, Host} + | nodeAttr(SubNode)]; + Title -> + [{<<"jid">>, Host}, + {<<"name">>, Title} + | nodeAttr(SubNode)] + end, + #xmlel{name = <<"item">>, attrs = Attrs} + end, + tree_action(Host, get_subnodes, [Host, <<>>, From]))}; +iq_disco_items(Host, ?NS_COMMANDS, _From, _RSM) -> + {result, [#xmlel{name = <<"item">>, + attrs = [{<<"jid">>, Host}, + {<<"node">>, ?NS_PUBSUB_GET_PENDING}, + {<<"name">>, <<"Get Pending">>}]}]}; +iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From, _RSM) -> + {result, []}; +iq_disco_items(Host, Item, From, RSM) -> case str:tokens(Item, <<"!">>) of - [_Node, _ItemID] -> {result, []}; - [Node] -> -% Node = string_to_node(SNode), - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options, owners = Owners}) -> - NodeItems = case get_allowed_items_call(Host, Idx, - From, Type, - Options, - Owners) - of - {result, R} -> R; - _ -> [] - end, - Nodes = lists:map(fun (#pubsub_node{nodeid = - {_, SubNode}, - options = - SubOptions}) -> - Attrs = case - get_option(SubOptions, - title) - of - false -> - [{<<"jid">>, - Host} - | nodeAttr(SubNode)]; - Title -> - [{<<"jid">>, - Host}, - {<<"name">>, - Title} - | nodeAttr(SubNode)] - end, - #xmlel{name = <<"item">>, - attrs = Attrs, - children = []} - end, - tree_call(Host, get_subnodes, - [Host, Node, From])), - Items = lists:map(fun (#pubsub_item{itemid = - {RN, _}}) -> - {result, Name} = - node_call(Type, - get_item_name, - [Host, Node, - RN]), - #xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, - Host}, - {<<"name">>, - Name}], - children = []} - end, - NodeItems), - {result, Nodes ++ Items} - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end + [_Node, _ItemId] -> + {result, []}; + [Node] -> + Action = fun (#pubsub_node{id = Nidx, type = Type, options = Options, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + {NodeItems, RsmOut} = case get_allowed_items_call(Host, Nidx, + From, Type, Options, Owners, RSM) + of + {result, R} -> R; + _ -> {[], none} + end, + Nodes = lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, options = SubOptions}) -> + Attrs = case get_option(SubOptions, title) of + false -> + [{<<"jid">>, Host} + | nodeAttr(SubNode)]; + Title -> + [{<<"jid">>, Host}, + {<<"name">>, Title} + | nodeAttr(SubNode)] + end, + #xmlel{name = <<"item">>, attrs = Attrs} + end, + tree_call(Host, get_subnodes, [Host, Node, From])), + Items = lists:map(fun (#pubsub_item{itemid = {RN, _}}) -> + {result, Name} = node_call(Host, Type, get_item_name, [Host, Node, RN]), + #xmlel{name = <<"item">>, + attrs = [{<<"jid">>, Host}, {<<"name">>, Name}]} + end, + NodeItems), + {result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)} + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end end. -spec(iq_sm/3 :: -( - From :: jid(), - To :: jid(), - IQ :: iq_request()) + ( + From :: jid(), + To :: jid(), + IQ :: iq_request()) -> iq_result() | iq_error() -). + ). iq_sm(From, To, #iq{type = Type, sub_el = SubEl, xmlns = XMLNS, lang = Lang} = IQ) -> ServerHost = To#jid.lserver, LOwner = jlib:jid_tolower(jlib:jid_remove_resource(To)), Res = case XMLNS of - ?NS_PUBSUB -> - iq_pubsub(LOwner, ServerHost, From, Type, SubEl, Lang); - ?NS_PUBSUB_OWNER -> - iq_pubsub_owner(LOwner, ServerHost, From, Type, SubEl, - Lang) - end, + ?NS_PUBSUB -> + iq_pubsub(LOwner, ServerHost, From, Type, SubEl, Lang); + ?NS_PUBSUB_OWNER -> + iq_pubsub_owner(LOwner, ServerHost, From, Type, SubEl, Lang) + end, case Res of - {result, IQRes} -> IQ#iq{type = result, sub_el = IQRes}; - {error, Error} -> - IQ#iq{type = error, sub_el = [Error, SubEl]} + {result, IQRes} -> IQ#iq{type = result, sub_el = IQRes}; + {error, Error} -> IQ#iq{type = error, sub_el = [Error, SubEl]} end. iq_get_vcard(Lang) -> [#xmlel{name = <<"FN">>, attrs = [], children = [{xmlcdata, <<"ejabberd/mod_pubsub">>}]}, - #xmlel{name = <<"URL">>, attrs = [], + #xmlel{name = <<"URL">>, attrs = [], children = [{xmlcdata, ?EJABBERD_URI}]}, - #xmlel{name = <<"DESC">>, attrs = [], - children = - [{xmlcdata, - <<(translate:translate(Lang, - <<"ejabberd Publish-Subscribe module">>))/binary, - "\nCopyright (c) 2004-2015 ProcessOne">>}]}]. + #xmlel{name = <<"DESC">>, attrs = [], + children = [{xmlcdata, + <<(translate:translate(Lang, <<"ejabberd Publish-Subscribe module">>))/binary, + "\nCopyright (c) 2004-2015 ProcessOne">>}]}]. -spec(iq_pubsub/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - From :: jid(), - IQType :: 'get' | 'set', - SubEl :: xmlel(), - Lang :: binary()) + ( + Host :: mod_pubsub:host(), + ServerHost :: binary(), + From :: jid(), + IQType :: 'get' | 'set', + SubEl :: xmlel(), + Lang :: binary()) -> {result, [xmlel()]} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) -> iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(ServerHost)). -spec(iq_pubsub/8 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - From :: jid(), - IQType :: 'get' | 'set', - SubEl :: xmlel(), - Lang :: binary(), - Access :: atom(), - Plugins :: [binary(),...]) + ( + Host :: mod_pubsub:host(), + ServerHost :: binary(), + From :: jid(), + IQType :: 'get' | 'set', + SubEl :: xmlel(), + Lang :: binary(), + Access :: atom(), + Plugins :: [binary(),...]) -> {result, [xmlel()]} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> #xmlel{children = SubEls} = SubEl, case xml:remove_cdata(SubEls) of - [#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] -> - Node = xml:get_attr_s(<<"node">>, Attrs), - case {IQType, Name} of - {set, <<"create">>} -> - Config = case Rest of - [#xmlel{name = <<"configure">>, children = C}] -> C; - _ -> [] - end, - Type = case xml:get_attr_s(<<"type">>, Attrs) of - <<>> -> hd(Plugins); - T -> T - end, - case lists:member(Type, Plugins) of - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"create-nodes">>)}; - true -> - create_node(Host, ServerHost, Node, From, Type, Access, Config) - end; - {set, <<"publish">>} -> - case xml:remove_cdata(Els) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs, - children = Payload}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), - publish_item(Host, ServerHost, Node, From, ItemId, Payload, Access); - [] -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; - _ -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)} - end; - {set, <<"retract">>} -> - ForceNotify = case xml:get_attr_s(<<"notify">>, Attrs) - of - <<"1">> -> true; - <<"true">> -> true; - _ -> false - end, - case xml:remove_cdata(Els) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), - delete_item(Host, Node, From, ItemId, ForceNotify); - _ -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)} - end; - {set, <<"subscribe">>} -> - Config = case Rest of - [#xmlel{name = <<"options">>, children = C}] -> C; - _ -> [] - end, - JID = xml:get_attr_s(<<"jid">>, Attrs), - subscribe_node(Host, Node, From, JID, Config); - {set, <<"unsubscribe">>} -> - JID = xml:get_attr_s(<<"jid">>, Attrs), - SubId = xml:get_attr_s(<<"subid">>, Attrs), - unsubscribe_node(Host, Node, From, JID, SubId); - {get, <<"items">>} -> - MaxItems = xml:get_attr_s(<<"max_items">>, Attrs), - SubId = xml:get_attr_s(<<"subid">>, Attrs), - ItemIDs = lists:foldl(fun (#xmlel{name = <<"item">>, - attrs = ItemAttrs}, - Acc) -> - case xml:get_attr_s(<<"id">>, - ItemAttrs) - of - <<"">> -> Acc; - ItemID -> [ItemID | Acc] - end; - (_, Acc) -> Acc - end, - [], xml:remove_cdata(Els)), - get_items(Host, Node, From, SubId, MaxItems, ItemIDs); - {get, <<"subscriptions">>} -> - get_subscriptions(Host, Node, From, Plugins); - {get, <<"affiliations">>} -> - get_affiliations(Host, Node, From, Plugins); - {get, <<"options">>} -> - SubID = xml:get_attr_s(<<"subid">>, Attrs), - JID = xml:get_attr_s(<<"jid">>, Attrs), - get_options(Host, Node, JID, SubID, Lang); - {set, <<"options">>} -> - SubID = xml:get_attr_s(<<"subid">>, Attrs), - JID = xml:get_attr_s(<<"jid">>, Attrs), - set_options(Host, Node, JID, SubID, Els); - _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} - end; - Other -> - ?INFO_MSG("Too many actions: ~p", [Other]), - {error, ?ERR_BAD_REQUEST} + [#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] -> + Node = xml:get_attr_s(<<"node">>, Attrs), + case {IQType, Name} of + {set, <<"create">>} -> + Config = case Rest of + [#xmlel{name = <<"configure">>, children = C}] -> C; + _ -> [] + end, + Type = case xml:get_attr_s(<<"type">>, Attrs) of + <<>> -> hd(Plugins); + T -> T + end, + case lists:member(Type, Plugins) of + false -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"create-nodes">>)}; + true -> + create_node(Host, ServerHost, Node, From, Type, Access, Config) + end; + {set, <<"publish">>} -> + case xml:remove_cdata(Els) of + [#xmlel{name = <<"item">>, attrs = ItemAttrs, + children = Payload}] -> + ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), + publish_item(Host, ServerHost, Node, From, ItemId, Payload, Access); + [] -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; + _ -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)} + end; + {set, <<"retract">>} -> + ForceNotify = case xml:get_attr_s(<<"notify">>, Attrs) of + <<"1">> -> true; + <<"true">> -> true; + _ -> false + end, + case xml:remove_cdata(Els) of + [#xmlel{name = <<"item">>, attrs = ItemAttrs}] -> + ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), + delete_item(Host, Node, From, ItemId, ForceNotify); + _ -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"item-required">>)} + end; + {set, <<"subscribe">>} -> + Config = case Rest of + [#xmlel{name = <<"options">>, children = C}] -> C; + _ -> [] + end, + JID = xml:get_attr_s(<<"jid">>, Attrs), + subscribe_node(Host, Node, From, JID, Config); + {set, <<"unsubscribe">>} -> + JID = xml:get_attr_s(<<"jid">>, Attrs), + SubId = xml:get_attr_s(<<"subid">>, Attrs), + unsubscribe_node(Host, Node, From, JID, SubId); + {get, <<"items">>} -> + MaxItems = xml:get_attr_s(<<"max_items">>, Attrs), + SubId = xml:get_attr_s(<<"subid">>, Attrs), + ItemIds = lists:foldl(fun + (#xmlel{name = <<"item">>, attrs = ItemAttrs}, Acc) -> + case xml:get_attr_s(<<"id">>, ItemAttrs) of + <<>> -> Acc; + ItemId -> [ItemId | Acc] + end; + (_, Acc) -> + Acc + end, + [], xml:remove_cdata(Els)), + get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(SubEl)); + {get, <<"subscriptions">>} -> + get_subscriptions(Host, Node, From, Plugins); + {get, <<"affiliations">>} -> + get_affiliations(Host, Node, From, Plugins); + {get, <<"options">>} -> + SubId = xml:get_attr_s(<<"subid">>, Attrs), + JID = xml:get_attr_s(<<"jid">>, Attrs), + get_options(Host, Node, JID, SubId, Lang); + {set, <<"options">>} -> + SubId = xml:get_attr_s(<<"subid">>, Attrs), + JID = xml:get_attr_s(<<"jid">>, Attrs), + set_options(Host, Node, JID, SubId, Els); + _ -> + {error, ?ERR_FEATURE_NOT_IMPLEMENTED} + end; + Other -> + ?INFO_MSG("Too many actions: ~p", [Other]), + {error, ?ERR_BAD_REQUEST} end. -spec(iq_pubsub_owner/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - From :: jid(), - IQType :: 'get' | 'set', - SubEl :: xmlel(), - Lang :: binary()) + ( + Host :: mod_pubsub:host(), + ServerHost :: binary(), + From :: jid(), + IQType :: 'get' | 'set', + SubEl :: xmlel(), + Lang :: binary()) -> {result, [xmlel()]} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> #xmlel{children = SubEls} = SubEl, Action = xml:remove_cdata(SubEls), case Action of - [#xmlel{name = Name, attrs = Attrs, children = Els}] -> - Node = xml:get_attr_s(<<"node">>, Attrs), - case {IQType, Name} of - {get, <<"configure">>} -> - get_configure(Host, ServerHost, Node, From, Lang); - {set, <<"configure">>} -> - set_configure(Host, Node, From, Els, Lang); - {get, <<"default">>} -> - get_default(Host, Node, From, Lang); - {set, <<"delete">>} -> delete_node(Host, Node, From); - {set, <<"purge">>} -> purge_node(Host, Node, From); - {get, <<"subscriptions">>} -> - get_subscriptions(Host, Node, From); - {set, <<"subscriptions">>} -> - set_subscriptions(Host, Node, From, - xml:remove_cdata(Els)); - {get, <<"affiliations">>} -> - get_affiliations(Host, Node, From); - {set, <<"affiliations">>} -> - set_affiliations(Host, Node, From, xml:remove_cdata(Els)); - _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} - end; - _ -> - ?INFO_MSG("Too many actions: ~p", [Action]), - {error, ?ERR_BAD_REQUEST} + [#xmlel{name = Name, attrs = Attrs, children = Els}] -> + Node = xml:get_attr_s(<<"node">>, Attrs), + case {IQType, Name} of + {get, <<"configure">>} -> + get_configure(Host, ServerHost, Node, From, Lang); + {set, <<"configure">>} -> + set_configure(Host, Node, From, Els, Lang); + {get, <<"default">>} -> + get_default(Host, Node, From, Lang); + {set, <<"delete">>} -> + delete_node(Host, Node, From); + {set, <<"purge">>} -> + purge_node(Host, Node, From); + {get, <<"subscriptions">>} -> + get_subscriptions(Host, Node, From); + {set, <<"subscriptions">>} -> + set_subscriptions(Host, Node, From, xml:remove_cdata(Els)); + {get, <<"affiliations">>} -> + get_affiliations(Host, Node, From); + {set, <<"affiliations">>} -> + set_affiliations(Host, Node, From, xml:remove_cdata(Els)); + _ -> + {error, ?ERR_FEATURE_NOT_IMPLEMENTED} + end; + _ -> + ?INFO_MSG("Too many actions: ~p", [Action]), + {error, ?ERR_BAD_REQUEST} end. iq_command(Host, ServerHost, From, IQ, Access, Plugins) -> case adhoc:parse_request(IQ) of - Req when is_record(Req, adhoc_request) -> - case adhoc_request(Host, ServerHost, From, Req, Access, - Plugins) - of - Resp when is_record(Resp, adhoc_response) -> - {result, [adhoc:produce_response(Req, Resp)]}; - Error -> Error - end; - Err -> Err + Req when is_record(Req, adhoc_request) -> + case adhoc_request(Host, ServerHost, From, Req, Access, Plugins) of + Resp when is_record(Resp, adhoc_response) -> + {result, [adhoc:produce_response(Req, Resp)]}; + Error -> + Error + end; + Err -> Err end. %% @doc

Processes an Ad Hoc Command.

adhoc_request(Host, _ServerHost, Owner, - #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - lang = Lang, action = <<"execute">>, - xdata = false}, - _Access, Plugins) -> + #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, + lang = Lang, action = <<"execute">>, + xdata = false}, + _Access, Plugins) -> send_pending_node_form(Host, Owner, Lang, Plugins); adhoc_request(Host, _ServerHost, Owner, - #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - action = <<"execute">>, xdata = XData}, - _Access, _Plugins) -> + #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, + action = <<"execute">>, xdata = XData}, + _Access, _Plugins) -> ParseOptions = case XData of - #xmlel{name = <<"x">>} = XEl -> - case jlib:parse_xdata_submit(XEl) of - invalid -> {error, ?ERR_BAD_REQUEST}; - XData2 -> - case set_xoption(Host, XData2, []) of - NewOpts when is_list(NewOpts) -> - {result, NewOpts}; - Err -> Err - end - end; - _ -> - ?INFO_MSG("Bad XForm: ~p", [XData]), - {error, ?ERR_BAD_REQUEST} - end, + #xmlel{name = <<"x">>} = XEl -> + case jlib:parse_xdata_submit(XEl) of + invalid -> + {error, ?ERR_BAD_REQUEST}; + XData2 -> + case set_xoption(Host, XData2, []) of + NewOpts when is_list(NewOpts) -> {result, NewOpts}; + Err -> Err + end + end; + _ -> + ?INFO_MSG("Bad XForm: ~p", [XData]), + {error, ?ERR_BAD_REQUEST} + end, case ParseOptions of - {result, XForm} -> - case lists:keysearch(node, 1, XForm) of - {value, {_, Node}} -> - send_pending_auth_events(Host, Node, Owner); - false -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"bad-payload">>)} - end; - Error -> Error + {result, XForm} -> + case lists:keysearch(node, 1, XForm) of + {value, {_, Node}} -> send_pending_auth_events(Host, Node, Owner); + false -> {error, extended_error(?ERR_BAD_REQUEST, <<"bad-payload">>)} + end; + Error -> Error end; adhoc_request(_Host, _ServerHost, _Owner, - #adhoc_request{action = <<"cancel">>}, _Access, - _Plugins) -> + #adhoc_request{action = <<"cancel">>}, _Access, + _Plugins) -> #adhoc_response{status = canceled}; adhoc_request(Host, ServerHost, Owner, - #adhoc_request{action = <<>>} = R, Access, Plugins) -> + #adhoc_request{action = <<>>} = R, Access, Plugins) -> adhoc_request(Host, ServerHost, Owner, - R#adhoc_request{action = <<"execute">>}, Access, - Plugins); -adhoc_request(_Host, _ServerHost, _Owner, Other, - _Access, _Plugins) -> + R#adhoc_request{action = <<"execute">>}, Access, + Plugins); +adhoc_request(_Host, _ServerHost, _Owner, Other, _Access, _Plugins) -> ?DEBUG("Couldn't process ad hoc command:~n~p", [Other]), {error, ?ERR_ITEM_NOT_FOUND}. -%% @spec (Host, Owner, Lang, Plugins) -> iqRes() -%% @doc

Sends the process pending subscriptions XForm for Host to -%% Owner.

+%% @doc

Sends the process pending subscriptions XForm for Host to Owner.

send_pending_node_form(Host, Owner, _Lang, Plugins) -> - Filter = fun (Plugin) -> - lists:member(<<"get-pending">>, features(Plugin)) - end, + Filter = fun (Type) -> + lists:member(<<"get-pending">>, plugin_features(Host, Type)) + end, case lists:filter(Filter, Plugins) of - [] -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED}; - Ps -> - XOpts = lists:map(fun (Node) -> - #xmlel{name = <<"option">>, attrs = [], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Node}]}]} - end, - get_pending_nodes(Host, Owner, Ps)), - XForm = #xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [#xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"list-single">>}, - {<<"var">>, <<"pubsub#node">>}], - children = lists:usort(XOpts)}]}, - #adhoc_response{status = executing, - defaultaction = <<"execute">>, elements = [XForm]} + [] -> + {error, ?ERR_FEATURE_NOT_IMPLEMENTED}; + Ps -> + XOpts = [#xmlel{name = <<"option">>, attrs = [], + children = [#xmlel{name = <<"value">>, + attrs = [], + children = [{xmlcdata, Node}]}]} + || Node <- get_pending_nodes(Host, Owner, Ps)], + XForm = #xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"form">>}], + children = [#xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"list-single">>}, + {<<"var">>, <<"pubsub#node">>}], + children = lists:usort(XOpts)}]}, + #adhoc_response{status = executing, + defaultaction = <<"execute">>, elements = [XForm]} end. get_pending_nodes(Host, Owner, Plugins) -> Tr = fun (Type) -> - case node_call(Type, get_pending_nodes, [Host, Owner]) - of - {result, Nodes} -> Nodes; - _ -> [] - end - end, - case transaction(fun () -> - {result, lists:flatmap(Tr, Plugins)} - end, - sync_dirty) - of - {result, Res} -> Res; - Err -> Err + case node_call(Host, Type, get_pending_nodes, [Host, Owner]) of + {result, Nodes} -> Nodes; + _ -> [] + end + end, + Action = fun() -> {result, lists:flatmap(Tr, Plugins)} end, + case transaction(Host, Action, sync_dirty) of + {result, Res} -> Res; + Err -> Err end. -%% @spec (Host, Node, Owner) -> iqRes() %% @doc

Send a subscription approval form to Owner for all pending %% subscriptions on Host and Node.

send_pending_auth_events(Host, Node, Owner) -> - ?DEBUG("Sending pending auth events for ~s on " - "~s:~s", - [jlib:jid_to_string(Owner), Host, Node]), - Action = fun (#pubsub_node{id = NodeID, type = Type}) -> - case lists:member(<<"get-pending">>, features(Type)) of - true -> - case node_call(Type, get_affiliation, - [NodeID, Owner]) - of - {result, owner} -> - node_call(Type, get_node_subscriptions, - [NodeID]); - _ -> {error, ?ERR_FORBIDDEN} - end; - false -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} - end - end, + ?DEBUG("Sending pending auth events for ~s on ~s:~s", + [jlib:jid_to_string(Owner), Host, Node]), + Action = fun (#pubsub_node{id = Nidx, type = Type}) -> + case lists:member(<<"get-pending">>, plugin_features(Host, Type)) of + true -> + case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of + {result, owner} -> node_call(Host, Type, get_node_subscriptions, [Nidx]); + _ -> {error, ?ERR_FORBIDDEN} + end; + false -> + {error, ?ERR_FEATURE_NOT_IMPLEMENTED} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {N, Subscriptions}} -> - lists:foreach(fun ({J, pending, _SubID}) -> - send_authorization_request(N, jlib:make_jid(J)); - ({J, pending}) -> - send_authorization_request(N, jlib:make_jid(J)); - (_) -> ok - end, - Subscriptions), - #adhoc_response{}; - Err -> Err + {result, {N, Subs}} -> + lists:foreach(fun + ({J, pending, _SubId}) -> send_authorization_request(N, jlib:make_jid(J)); + ({J, pending}) -> send_authorization_request(N, jlib:make_jid(J)); + (_) -> ok + end, + Subs), + #adhoc_response{}; + Err -> + Err end. %%% authorization handling -send_authorization_request(#pubsub_node{owners = Owners, nodeid = {Host, Node}}, - Subscriber) -> +send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = Nidx, owners = O}, + Subscriber) -> Lang = <<"en">>, Stanza = #xmlel{name = <<"message">>, attrs = [], + children = + [#xmlel{name = <<"x">>, + attrs = + [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"form">>}], children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [#xmlel{name = <<"title">>, attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, - <<"PubSub subscriber request">>)}]}, - #xmlel{name = <<"instructions">>, - attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, - <<"Choose whether to approve this entity's " - "subscription.">>)}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"FORM_TYPE">>}, - {<<"type">>, <<"hidden">>}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - ?NS_PUBSUB_SUB_AUTH}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"pubsub#node">>}, - {<<"type">>, - <<"text-single">>}, - {<<"label">>, - translate:translate(Lang, - <<"Node ID">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Node}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, - <<"pubsub#subscriber_jid">>}, - {<<"type">>, <<"jid-single">>}, - {<<"label">>, - translate:translate(Lang, - <<"Subscriber Address">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - jlib:jid_to_string(Subscriber)}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, - <<"pubsub#allow">>}, - {<<"type">>, <<"boolean">>}, - {<<"label">>, - translate:translate(Lang, - <<"Allow this Jabber ID to subscribe to " - "this pubsub node?">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - <<"false">>}]}]}]}]}, + [#xmlel{name = <<"title">>, attrs = [], + children = + [{xmlcdata, + translate:translate(Lang, <<"PubSub subscriber request">>)}]}, + #xmlel{name = <<"instructions">>, + attrs = [], + children = + [{xmlcdata, + translate:translate(Lang, + <<"Choose whether to approve this entity's " + "subscription.">>)}]}, + #xmlel{name = <<"field">>, + attrs = + [{<<"var">>, <<"FORM_TYPE">>}, + {<<"type">>, <<"hidden">>}], + children = + [#xmlel{name = <<"value">>, + attrs = [], + children = + [{xmlcdata, ?NS_PUBSUB_SUB_AUTH}]}]}, + #xmlel{name = <<"field">>, + attrs = + [{<<"var">>, <<"pubsub#node">>}, + {<<"type">>, + <<"text-single">>}, + {<<"label">>, translate:translate(Lang, <<"Node ID">>)}], + children = + [#xmlel{name = <<"value">>, + attrs = [], + children = + [{xmlcdata, Node}]}]}, + #xmlel{name = <<"field">>, + attrs = + [{<<"var">>, + <<"pubsub#subscriber_jid">>}, + {<<"type">>, <<"jid-single">>}, + {<<"label">>, + translate:translate(Lang, <<"Subscriber Address">>)}], + children = + [#xmlel{name = <<"value">>, + attrs = [], + children = + [{xmlcdata, jlib:jid_to_string(Subscriber)}]}]}, + #xmlel{name = <<"field">>, + attrs = + [{<<"var">>, + <<"pubsub#allow">>}, + {<<"type">>, <<"boolean">>}, + {<<"label">>, + translate:translate(Lang, + <<"Allow this Jabber ID to subscribe to " + "this pubsub node?">>)}], + children = + [#xmlel{name = <<"value">>, + attrs = [], + children = + [{xmlcdata, <<"false">>}]}]}]}]}, lists:foreach(fun (Owner) -> - ejabberd_router:route(service_jid(Host), - jlib:make_jid(Owner), Stanza) - end, - Owners). + ejabberd_router:route(service_jid(Host), jlib:make_jid(Owner), Stanza) + end, + node_owners_action(Host, Type, Nidx, O)). find_authorization_response(Packet) -> #xmlel{children = Els} = Packet, - XData1 = lists:map(fun (#xmlel{name = <<"x">>, - attrs = XAttrs} = - XEl) -> - case xml:get_attr_s(<<"xmlns">>, XAttrs) of - ?NS_XDATA -> - case xml:get_attr_s(<<"type">>, XAttrs) of - <<"cancel">> -> none; - _ -> jlib:parse_xdata_submit(XEl) - end; - _ -> none - end; - (_) -> none - end, - xml:remove_cdata(Els)), + XData1 = lists:map(fun + (#xmlel{name = <<"x">>, attrs = XAttrs} = XEl) -> + case xml:get_attr_s(<<"xmlns">>, XAttrs) of + ?NS_XDATA -> + case xml:get_attr_s(<<"type">>, XAttrs) of + <<"cancel">> -> none; + _ -> jlib:parse_xdata_submit(XEl) + end; + _ -> + none + end; + (_) -> + none + end, + xml:remove_cdata(Els)), XData = lists:filter(fun (E) -> E /= none end, XData1), case XData of - [invalid] -> invalid; - [] -> none; - [XFields] when is_list(XFields) -> - ?DEBUG("XFields: ~p", [XFields]), - case lists:keysearch(<<"FORM_TYPE">>, 1, XFields) of - {value, {_, [?NS_PUBSUB_SUB_AUTH]}} -> XFields; - _ -> invalid - end + [invalid] -> + invalid; + [] -> + none; + [XFields] when is_list(XFields) -> + ?DEBUG("XFields: ~p", [XFields]), + case lists:keysearch(<<"FORM_TYPE">>, 1, XFields) of + {value, {_, [?NS_PUBSUB_SUB_AUTH]}} -> XFields; + _ -> invalid + end end. -%% @spec (Host, JID, Node, Subscription) -> void -%% Host = mod_pubsub:host() -%% JID = jlib:jid() -%% SNode = string() -%% Subscription = atom() | {atom(), mod_pubsub:subid()} + %% @doc Send a message to JID with the supplied Subscription -%% TODO : ask Christophe's opinion send_authorization_approval(Host, JID, SNode, Subscription) -> SubAttrs = case Subscription of -% {S, SID} -> -% [{<<"subscription">>, subscription_to_string(S)}, -% {<<"subid">>, SID}]; - S -> [{<<"subscription">>, subscription_to_string(S)}] - end, - Stanza = event_stanza([#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jlib:jid_to_string(JID)} - | nodeAttr(SNode)] - ++ SubAttrs, - children = []}]), + %{S, SID} -> + % [{<<"subscription">>, subscription_to_string(S)}, + % {<<"subid">>, SID}]; + S -> + [{<<"subscription">>, subscription_to_string(S)}] + end, + Stanza = event_stanza(<<"subscription">>, + [{<<"jid">>, jlib:jid_to_string(JID)} + | nodeAttr(SNode)] + ++ SubAttrs), ejabberd_router:route(service_jid(Host), JID, Stanza). handle_authorization_response(Host, From, To, Packet, XFields) -> case {lists:keysearch(<<"pubsub#node">>, 1, XFields), - lists:keysearch(<<"pubsub#subscriber_jid">>, 1, XFields), - lists:keysearch(<<"pubsub#allow">>, 1, XFields)} - of - {{value, {_, [Node]}}, {value, {_, [SSubscriber]}}, - {value, {_, [SAllow]}}} -> -% Node = string_to_node(SNode), - Subscriber = jlib:string_to_jid(SSubscriber), - Allow = case SAllow of - <<"1">> -> true; - <<"true">> -> true; - _ -> false - end, - Action = fun (#pubsub_node{type = Type, owners = Owners, - id = NodeId}) -> - IsApprover = - lists:member(jlib:jid_tolower(jlib:jid_remove_resource(From)), - Owners), - {result, Subscriptions} = node_call(Type, - get_subscriptions, - [NodeId, - Subscriber]), - if not IsApprover -> {error, ?ERR_FORBIDDEN}; - true -> - update_auth(Host, Node, Type, NodeId, - Subscriber, Allow, Subscriptions) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {error, Error} -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, Error)); - {result, {_, _NewSubscription}} -> - %% XXX: notify about subscription state change, section 12.11 - ok; - _ -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, - ?ERR_INTERNAL_SERVER_ERROR)) - end; - _ -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, - ?ERR_NOT_ACCEPTABLE)) + lists:keysearch(<<"pubsub#subscriber_jid">>, 1, XFields), + lists:keysearch(<<"pubsub#allow">>, 1, XFields)} + of + {{value, {_, [Node]}}, + {value, {_, [SSubscriber]}}, + {value, {_, [SAllow]}}} -> + FromLJID = jlib:jid_tolower(jlib:jid_remove_resource(From)), + Subscriber = jlib:string_to_jid(SSubscriber), + Allow = case SAllow of + <<"1">> -> true; + <<"true">> -> true; + _ -> false + end, + Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case lists:member(FromLJID, Owners) of + true -> + {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), + update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs); + false -> + {error, ?ERR_FORBIDDEN} + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {error, Error} -> + Err = jlib:make_error_reply(Packet, Error), + ejabberd_router:route(To, From, Err); + {result, {_, _NewSubscription}} -> + %% XXX: notify about subscription state change, section 12.11 + ok; + _ -> + Err = jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR), + ejabberd_router:route(To, From, Err) + end; + _ -> + Err = jlib:make_error_reply(Packet, ?ERR_NOT_ACCEPTABLE), + ejabberd_router:route(To, From, Err) end. -update_auth(Host, Node, Type, NodeId, Subscriber, Allow, - Subscriptions) -> - Subscription = lists:filter(fun ({pending, _}) -> true; - (_) -> false - end, - Subscriptions), - case Subscription of - [{pending, SubID}] -> - NewSubscription = case Allow of - true -> subscribed; - false -> none - end, - node_call(Type, set_subscriptions, - [NodeId, Subscriber, NewSubscription, SubID]), - send_authorization_approval(Host, Subscriber, Node, - NewSubscription), - {result, ok}; - _ -> {error, ?ERR_UNEXPECTED_REQUEST} +update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> + Sub= lists:filter(fun + ({pending, _}) -> true; + (_) -> false + end, + Subs), + case Sub of + [{pending, SubId}] -> + NewSub = case Allow of + true -> subscribed; + false -> none + end, + node_call(Host, Type, set_subscriptions, [Nidx, Subscriber, NewSub, SubId]), + send_authorization_approval(Host, Subscriber, Node, NewSub), + {result, ok}; + _ -> + {error, ?ERR_UNEXPECTED_REQUEST} end. -define(XFIELD(Type, Label, Var, Val), - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]}]}). + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, Type}, + {<<"label">>, translate:translate(Lang, Label)}, + {<<"var">>, Var}], + children = [#xmlel{name = <<"value">>, attrs = [], + children = [{xmlcdata, Val}]}]}). -define(BOOLXFIELD(Label, Var, Val), - ?XFIELD(<<"boolean">>, Label, Var, - case Val of - true -> <<"1">>; - _ -> <<"0">> - end)). + ?XFIELD(<<"boolean">>, Label, Var, + case Val of + true -> <<"1">>; + _ -> <<"0">> + end)). -define(STRINGXFIELD(Label, Var, Val), - ?XFIELD(<<"text-single">>, Label, Var, Val)). + ?XFIELD(<<"text-single">>, Label, Var, Val)). -define(STRINGMXFIELD(Label, Var, Vals), - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"text-multi">>}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, V}]} - || V <- Vals]}). + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"text-multi">>}, + {<<"label">>, translate:translate(Lang, Label)}, + {<<"var">>, Var}], + children = [#xmlel{name = <<"value">>, attrs = [], + children = [{xmlcdata, V}]} + || V <- Vals]}). -define(XFIELDOPT(Type, Label, Var, Val, Opts), - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - lists:map(fun (Opt) -> - #xmlel{name = <<"option">>, attrs = [], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Opt}]}]} - end, - Opts) - ++ - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]}]}). + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, Type}, + {<<"label">>, translate:translate(Lang, Label)}, + {<<"var">>, Var}], + children = [#xmlel{name = <<"option">>, attrs = [], + children = [#xmlel{name = <<"value">>, + attrs = [], + children = [{xmlcdata, Opt}]}]} + || Opt <- Opts] + ++ + [#xmlel{name = <<"value">>, attrs = [], + children = [{xmlcdata, Val}]}]}). -define(LISTXFIELD(Label, Var, Val, Opts), - ?XFIELDOPT(<<"list-single">>, Label, Var, Val, Opts)). + ?XFIELDOPT(<<"list-single">>, Label, Var, Val, Opts)). -define(LISTMXFIELD(Label, Var, Vals, Opts), -%% @spec (Host::host(), ServerHost::host(), Node::pubsubNode(), Owner::jid(), NodeType::nodeType()) -> -%% {error, Reason::stanzaError()} | -%% {result, []} + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"list-multi">>}, + {<<"label">>, translate:translate(Lang, Label)}, + {<<"var">>, Var}], + children = [#xmlel{name = <<"option">>, attrs = [], + children = [#xmlel{name = <<"value">>, + attrs = [], + children = [{xmlcdata, Opt}]}]} + || Opt <- Opts] + ++ + [#xmlel{name = <<"value">>, attrs = [], + children = [{xmlcdata, Val}]} + || Val <- Vals]}). + %% @doc

Create new pubsub nodes

%%

In addition to method-specific error conditions, there are several general reasons why the node creation request might fail:

%%
    %%
  • The service does not support node creation.
  • %%
  • Only entities that are registered with the service are allowed to create nodes but the requesting entity is not registered.
  • %%
  • The requesting entity does not have sufficient privileges to create nodes.
  • -%%
  • The requested NodeID already exists.
  • -%%
  • The request did not include a NodeID and "instant nodes" are not supported.
  • +%%
  • The requested Node already exists.
  • +%%
  • The request did not include a Node and "instant nodes" are not supported.
  • %%
%%

ote: node creation is a particular case, error return code is evaluated at many places:

%%
    @@ -2554,176 +1771,124 @@ update_auth(Host, Node, Type, NodeId, Subscriber, Allow, %%
  • nodetree create_node checks if nodeid already exists
  • %%
  • node plugin create_node just sets default affiliation/subscription
  • %%
- #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"list-multi">>}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - lists:map(fun (Opt) -> - #xmlel{name = <<"option">>, attrs = [], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Opt}]}]} - end, - Opts) - ++ - lists:map(fun (Val) -> - #xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]} - end, - Vals)}). - --spec(create_node/5 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: <<>> | mod_pubsub:nodeId(), - Owner :: jid(), - Type :: binary()) +-spec(create_node/7 :: + ( + Host :: mod_pubsub:host(), + ServerHost :: binary(), + Node :: <<>> | mod_pubsub:nodeId(), + Owner :: jid(), + Type :: binary(), + Access :: atom(), + Configuration :: [xmlel()]) -> {result, [xmlel(),...]} %%% - | {error, xmlel()} -). - + | {error, xmlel()} + ). create_node(Host, ServerHost, Node, Owner, Type) -> create_node(Host, ServerHost, Node, Owner, Type, all, []). - --spec(create_node/7 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: <<>> | mod_pubsub:nodeId(), - Owner :: jid(), - Type :: binary(), - Access :: atom(), - Configuration :: [xmlel()]) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) -> - case lists:member(<<"instant-nodes">>, features(Type)) of - true -> - NewNode = randoms:get_string(), - case create_node(Host, ServerHost, NewNode, Owner, Type, - Access, Configuration) - of - {result, _} -> - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"create">>, - attrs = nodeAttr(NewNode), - children = []}]}]}; - Error -> Error - end; - false -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, - <<"nodeid-required">>)} + case lists:member(<<"instant-nodes">>, plugin_features(Host, Type)) of + true -> + Node = randoms:get_string(), + case create_node(Host, ServerHost, Node, Owner, Type, Access, Configuration) of + {result, _} -> + {result, [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"create">>, + attrs = nodeAttr(Node)}]}]}; + Error -> + Error + end; + false -> + {error, extended_error(?ERR_NOT_ACCEPTABLE, <<"nodeid-required">>)} end; create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> Type = select_type(ServerHost, Host, Node, GivenType), ParseOptions = case xml:remove_cdata(Configuration) of - [] -> {result, node_options(Type)}; - [#xmlel{name = <<"x">>} = XEl] -> - case jlib:parse_xdata_submit(XEl) of - invalid -> {error, ?ERR_BAD_REQUEST}; - XData -> - case set_xoption(Host, XData, node_options(Type)) - of - NewOpts when is_list(NewOpts) -> - {result, NewOpts}; - Err -> Err - end - end; - _ -> - ?INFO_MSG("Node ~p; bad configuration: ~p", - [Node, Configuration]), - {error, ?ERR_BAD_REQUEST} - end, + [] -> + {result, node_options(Host, Type)}; + [#xmlel{name = <<"x">>} = XEl] -> + case jlib:parse_xdata_submit(XEl) of + invalid -> + {error, ?ERR_BAD_REQUEST}; + XData -> + case set_xoption(Host, XData, node_options(Host, Type)) of + NewOpts when is_list(NewOpts) -> {result, NewOpts}; + Err -> Err + end + end; + _ -> + ?INFO_MSG("Node ~p; bad configuration: ~p", [Node, Configuration]), + {error, ?ERR_BAD_REQUEST} + end, case ParseOptions of {result, NodeOptions} -> - CreateNode = - fun() -> - Parent = case node_call(Type, node_to_path, [Node]) of - {result, [Node]} -> <<>>; - {result, Path} -> element(2, node_call(Type, path_to_node, [lists:sublist(Path, length(Path)-1)])) - end, - Parents = case Parent of - <<>> -> []; - _ -> [Parent] - end, - case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of - {result, true} -> - case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions, Parents]) of - {ok, NodeId} -> - ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, Owner]), - SubsByDepth = [{Depth, [{N, get_node_subs(N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree], - case node_call(Type, create_node, [NodeId, Owner]) of - {result, Result} -> {result, {NodeId, SubsByDepth, Result}}; - Error -> Error - end; - {error, {virtual, NodeId}} -> - case node_call(Type, create_node, [NodeId, Owner]) of - {result, Result} -> {result, {NodeId, [], Result}}; - Error -> Error - end; - Error -> - Error - end; - _ -> - {error, ?ERR_FORBIDDEN} - end - end, + CreateNode = fun () -> + Parent = case node_call(Host, Type, node_to_path, [Node]) of + {result, [Node]} -> + <<>>; + {result, Path} -> + element(2, node_call(Host, Type, path_to_node, [lists:sublist(Path, length(Path)-1)])) + end, + Parents = case Parent of + <<>> -> []; + _ -> [Parent] + end, + case node_call(Host, Type, create_node_permission, + [Host, ServerHost, Node, Parent, Owner, Access]) + of + {result, true} -> + case tree_call(Host, create_node, + [Host, Node, Type, Owner, NodeOptions, Parents]) + of + {ok, Nidx} -> + SubsByDepth = get_node_subs_by_depth(Host, Node, Owner), + case node_call(Host, Type, create_node, [Nidx, Owner]) of + {result, Result} -> {result, {Nidx, SubsByDepth, Result}}; + Error -> Error + end; + {error, {virtual, Nidx}} -> + case node_call(Host, Type, create_node, [Nidx, Owner]) of + {result, Result} -> {result, {Nidx, [], Result}}; + Error -> Error + end; + Error -> + Error + end; + _ -> + {error, ?ERR_FORBIDDEN} + end + end, Reply = [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"create">>, - attrs = nodeAttr(Node), - children = []}]}], - case transaction(CreateNode, transaction) of - {result, {NodeId, SubsByDepth, {Result, broadcast}}} -> - broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth), - ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]), + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"create">>, + attrs = nodeAttr(Node)}]}], + case transaction(Host, CreateNode, transaction) of + {result, {Nidx, SubsByDepth, {Result, broadcast}}} -> + broadcast_created_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth), + ejabberd_hooks:run(pubsub_create_node, ServerHost, + [ServerHost, Host, Node, Nidx, NodeOptions]), case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, {NodeId, _SubsByDepth, default}} -> - ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]), - {result, Reply}; - {result, {NodeId, _SubsByDepth, Result}} -> - ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]), - {result, Result}; - Error -> - %% in case we change transaction to sync_dirty... - %% node_call(Type, delete_node, [Host, Node]), - %% tree_call(Host, delete_node, [Host, Node]), + {result, {Nidx, _SubsByDepth, Result}} -> + ejabberd_hooks:run(pubsub_create_node, ServerHost, + [ServerHost, Host, Node, Nidx, NodeOptions]), + case Result of + default -> {result, Reply}; + _ -> {result, Result} + end; + Error -> + %% in case we change transaction to sync_dirty... + %% node_call(Host, Type, delete_node, [Host, Node]), + %% tree_call(Host, delete_node, [Host, Node]), Error end; Error -> Error end. -%% @spec (Host, Node, Owner) -> -%% {error, Reason} | {result, []} -%% Host = host() -%% Node = pubsubNode() -%% Owner = jid() -%% Reason = stanzaError() --spec(delete_node/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - Owner :: jid()) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). %% @doc

Delete specified node and all childs.

%%

There are several reasons why the node deletion request might fail:

%%
    @@ -2731,80 +1896,75 @@ create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> %%
  • The node is the root collection node, which cannot be deleted.
  • %%
  • The specified node does not exist.
  • %%
+-spec(delete_node/3 :: + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + Owner :: jid()) + -> {result, [xmlel(),...]} + %%% + | {error, xmlel()} + ). delete_node(_Host, <<>>, _Owner) -> {error, ?ERR_NOT_ALLOWED}; delete_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, Owner]) of - {result, owner} -> - ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]), - SubsByDepth = [{Depth, [{N, get_node_subs(N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree], - Removed = tree_call(Host, delete_node, [Host, Node]), - case node_call(Type, delete_node, [Removed]) of - {result, Res} -> {result, {SubsByDepth, Res}}; - Error -> Error - end; - _ -> - %% Entity is not an owner - {error, ?ERR_FORBIDDEN} - end - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + case node_call(Host, Type, get_affiliation, [Nidx, Owner]) of + {result, owner} -> + SubsByDepth = get_node_subs_by_depth(Host, Node, service_jid(Host)), + Removed = tree_call(Host, delete_node, [Host, Node]), + case node_call(Host, Type, delete_node, [Removed]) of + {result, Res} -> {result, {SubsByDepth, Res}}; + Error -> Error + end; + _ -> + {error, ?ERR_FORBIDDEN} + end + end, Reply = [], - ServerHost = get(server_host), + ServerHost = serverhost(Host), case transaction(Host, Node, Action, transaction) of - {result, {_TNode, {SubsByDepth, {Result, broadcast, Removed}}}} -> - lists:foreach(fun({RNode, _RSubscriptions}) -> - {RH, RN} = RNode#pubsub_node.nodeid, - NodeId = RNode#pubsub_node.id, - Type = RNode#pubsub_node.type, - Options = RNode#pubsub_node.options, - broadcast_removed_node(RH, RN, NodeId, Type, Options, SubsByDepth), - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId]) - end, Removed), + {result, {_, {SubsByDepth, {Result, broadcast, Removed}}}} -> + lists:foreach(fun ({RNode, _RSubs}) -> + {RH, RN} = RNode#pubsub_node.nodeid, + RNidx = RNode#pubsub_node.id, + RType = RNode#pubsub_node.type, + ROptions = RNode#pubsub_node.options, + broadcast_removed_node(RH, RN, RNidx, RType, ROptions, SubsByDepth), + ejabberd_hooks:run(pubsub_delete_node, + ServerHost, + [ServerHost, RH, RN, RNidx]) + end, + Removed), case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, {_TNode, {_, {Result, Removed}}}} -> - lists:foreach(fun({RNode, _RSubscriptions}) -> - {RH, RN} = RNode#pubsub_node.nodeid, - NodeId = RNode#pubsub_node.id, - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId]) - end, Removed), + {result, {_, {_, {Result, Removed}}}} -> + lists:foreach(fun ({RNode, _RSubs}) -> + {RH, RN} = RNode#pubsub_node.nodeid, + RNidx = RNode#pubsub_node.id, + ejabberd_hooks:run(pubsub_delete_node, + ServerHost, + [ServerHost, RH, RN, RNidx]) + end, + Removed), case Result of default -> {result, Reply}; _ -> {result, Result} end; - {result, {TNode, {_, default}}} -> - NodeId = TNode#pubsub_node.id, - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]), - {result, Reply}; {result, {TNode, {_, Result}}} -> - NodeId = TNode#pubsub_node.id, - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]), - {result, Result}; + Nidx = TNode#pubsub_node.id, + ejabberd_hooks:run(pubsub_delete_node, ServerHost, + [ServerHost, Host, Node, Nidx]), + case Result of + default -> {result, Reply}; + _ -> {result, Result} + end; Error -> Error end. -%% @spec (Host, Node, From, JID, Configuration) -> -%% {error, Reason::stanzaError()} | -%% {result, []} -%% Host = host() -%% Node = pubsubNode() -%% From = jid() -%% JID = jid() --spec(subscribe_node/5 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - JID :: binary(), - Configuration :: [xmlel()]) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). %% @see node_hometree:subscribe_node/5 %% @doc

Accepts or rejects subcription requests on a PubSub node.

%%

There are several reasons why the subscription request might fail:

@@ -2820,109 +1980,94 @@ delete_node(Host, Node, Owner) -> %%
  • The node does not support subscriptions.
  • %%
  • The node does not exist.
  • %% +-spec(subscribe_node/5 :: + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + From :: jid(), + JID :: binary(), + Configuration :: [xmlel()]) + -> {result, [xmlel(),...]} + %%% + | {error, xmlel()} + ). subscribe_node(Host, Node, From, JID, Configuration) -> - SubOpts = case - pubsub_subscription:parse_options_xform(Configuration) - of - {result, GoodSubOpts} -> GoodSubOpts; - _ -> invalid - end, - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> - case jlib:jid_tolower(J) of - error -> {<<"">>, <<"">>, <<"">>}; - J1 -> J1 - end - end, - Action = fun (#pubsub_node{options = Options, - owners = Owners, type = Type, id = NodeId}) -> - Features = features(Type), - SubscribeFeature = lists:member(<<"subscribe">>, Features), - OptionsFeature = lists:member(<<"subscription-options">>, Features), - HasOptions = not (SubOpts == []), - SubscribeConfig = get_option(Options, subscribe), - AccessModel = get_option(Options, access_model), - SendLast = get_option(Options, send_last_published_item), - AllowedGroups = get_option(Options, roster_groups_allowed, []), - {PresenceSubscription, RosterGroup} = - get_presence_and_roster_permissions(Host, Subscriber, - Owners, AccessModel, AllowedGroups), - if not SubscribeFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"subscribe">>)}; - not SubscribeConfig -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"subscribe">>)}; - HasOptions andalso not OptionsFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"subscription-options">>)}; - SubOpts == invalid -> - {error, - extended_error(?ERR_BAD_REQUEST, - <<"invalid-options">>)}; - true -> - node_call(Type, subscribe_node, - [NodeId, From, Subscriber, AccessModel, - SendLast, PresenceSubscription, - RosterGroup, SubOpts]) - end - end, + SubModule = subscription_plugin(Host), + SubOpts = case SubModule:parse_options_xform(Configuration) of + {result, GoodSubOpts} -> GoodSubOpts; + _ -> invalid + end, + Subscriber = string_to_ljid(JID), + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx, owners = O}) -> + Features = plugin_features(Host, Type), + SubscribeFeature = lists:member(<<"subscribe">>, Features), + OptionsFeature = lists:member(<<"subscription-options">>, Features), + HasOptions = not (SubOpts == []), + SubscribeConfig = get_option(Options, subscribe), + AccessModel = get_option(Options, access_model), + SendLast = get_option(Options, send_last_published_item), + AllowedGroups = get_option(Options, roster_groups_allowed, []), + if not SubscribeFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscribe">>)}; + not SubscribeConfig -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscribe">>)}; + HasOptions andalso not OptionsFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscription-options">>)}; + SubOpts == invalid -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; + true -> + Owners = node_owners_call(Host, Type, Nidx, O), + {PS, RG} = get_presence_and_roster_permissions(Host, Subscriber, + Owners, AccessModel, AllowedGroups), + node_call(Host, Type, subscribe_node, + [Nidx, From, Subscriber, AccessModel, + SendLast, PS, RG, SubOpts]) + end + end, Reply = fun (Subscription) -> - SubAttrs = case Subscription of - {subscribed, SubId} -> - [{<<"subscription">>, - subscription_to_string(subscribed)}, - {<<"subid">>, SubId}, {<<"node">>, Node}]; - Other -> - [{<<"subscription">>, - subscription_to_string(Other)}, - {<<"node">>, Node}] - end, - Fields = [{<<"jid">>, jlib:jid_to_string(Subscriber)} - | SubAttrs], - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"subscription">>, - attrs = Fields, children = []}]}] + SubAttrs = case Subscription of + {subscribed, SubId} -> + [{<<"subscription">>, subscription_to_string(subscribed)}, + {<<"subid">>, SubId}, {<<"node">>, Node}]; + Other -> + [{<<"subscription">>, subscription_to_string(Other)}, + {<<"node">>, Node}] end, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"subscription">>, + attrs = [{<<"jid">>, jlib:jid_to_string(Subscriber)} + | SubAttrs]}]}] + end, case transaction(Host, Node, Action, sync_dirty) of - {result, - {TNode, {Result, subscribed, SubId, send_last}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - send_items(Host, Node, NodeId, Type, Options, Subscriber, last), - case Result of - default -> {result, Reply({subscribed, SubId})}; - _ -> {result, Result} - end; - {result, {_TNode, {default, subscribed, SubId}}} -> - {result, Reply({subscribed, SubId})}; - {result, {_TNode, {Result, subscribed, _SubId}}} -> - {result, Result}; - {result, {TNode, {default, pending, _SubId}}} -> - send_authorization_request(TNode, Subscriber), - {result, Reply(pending)}; - {result, {TNode, {Result, pending}}} -> - send_authorization_request(TNode, Subscriber), - {result, Result}; - {result, {_, Result}} -> {result, Result}; - Error -> Error + {result, {TNode, {Result, subscribed, SubId, send_last}}} -> + Nidx = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + send_items(Host, Node, Nidx, Type, Options, Subscriber, last), + case Result of + default -> {result, Reply({subscribed, SubId})}; + _ -> {result, Result} + end; + {result, {_TNode, {default, subscribed, SubId}}} -> + {result, Reply({subscribed, SubId})}; + {result, {_TNode, {Result, subscribed, _SubId}}} -> + {result, Result}; + {result, {TNode, {default, pending, _SubId}}} -> + send_authorization_request(TNode, Subscriber), + {result, Reply(pending)}; + {result, {TNode, {Result, pending}}} -> + send_authorization_request(TNode, Subscriber), + {result, Result}; + {result, {_, Result}} -> + {result, Result}; + Error -> Error end. -%% @spec (Host, Noce, From, JID, SubId) -> {error, Reason} | {result, []} -%% Host = host() -%% Node = pubsubNode() -%% From = jid() -%% JID = string() -%% SubId = string() -%% Reason = stanzaError() %% @doc

    Unsubscribe JID from the Node.

    %%

    There are several reasons why the unsubscribe request might fail:

    %%
      @@ -2933,41 +2078,28 @@ subscribe_node(Host, Node, From, JID, Configuration) -> %%
    • The request specifies a subscription ID that is not valid or current.
    • %%
    -spec(unsubscribe_node/5 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - JID :: binary() | ljid(), - SubId :: mod_pubsub:subId()) + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + From :: jid(), + JID :: binary() | ljid(), + SubId :: mod_pubsub:subId()) -> {result, []} %%% - | {error, xmlel()} -). -unsubscribe_node(Host, Node, From, JID, SubId) - when is_binary(JID) -> - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> - case jlib:jid_tolower(J) of - error -> {<<"">>, <<"">>, <<"">>}; - J1 -> J1 - end - end, - unsubscribe_node(Host, Node, From, Subscriber, SubId); + | {error, xmlel()} + ). +unsubscribe_node(Host, Node, From, JID, SubId) when is_binary(JID) -> + unsubscribe_node(Host, Node, From, string_to_ljid(JID), SubId); unsubscribe_node(Host, Node, From, Subscriber, SubId) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, unsubscribe_node, - [NodeId, From, Subscriber, SubId]) - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + node_call(Host, Type, unsubscribe_node, [Nidx, From, Subscriber, SubId]) + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, default}} -> {result, []}; -% {result, {_, Result}} -> {result, Result}; - Error -> Error + {result, {_, default}} -> {result, []}; + % {result, {_, Result}} -> {result, Result}; + Error -> Error end. -%% @spec (Host::host(), ServerHost::host(), JID::jid(), Node::pubsubNode(), ItemId::string(), Payload::term()) -> -%% {error, Reason::stanzaError()} | -%% {result, []} %% @doc

    Publish item to a PubSub node.

    %%

    The permission to publish an item must be verified by the plugin implementation.

    %%

    There are several reasons why the publish request might fail:

    @@ -2980,123 +2112,113 @@ unsubscribe_node(Host, Node, From, Subscriber, SubId) -> %%
  • The request does not match the node configuration.
  • %% -spec(publish_item/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: mod_pubsub:nodeId(), - Publisher :: jid(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) + ( + Host :: mod_pubsub:host(), + ServerHost :: binary(), + Node :: mod_pubsub:nodeId(), + Publisher :: jid(), + ItemId :: <<>> | mod_pubsub:itemId(), + Payload :: mod_pubsub:payload()) -> {result, [xmlel(),...]} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> - publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, all). + publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, all). publish_item(Host, ServerHost, Node, Publisher, <<>>, Payload, Access) -> publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload, Access); publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, Access) -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - PublishFeature = lists:member(<<"publish">>, Features), - PublishModel = get_option(Options, publish_model), - DeliverPayloads = get_option(Options, deliver_payloads), - PersistItems = get_option(Options, persist_items), - MaxItems = max_items(Host, Options), - PayloadCount = payload_xmlelements(Payload), - PayloadSize = byte_size(term_to_binary(Payload)) - 2, - PayloadMaxSize = get_option(Options, max_payload_size), - if not PublishFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"publish">>)}; - PayloadSize > PayloadMaxSize -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"payload-too-big">>)}; - (PayloadCount == 0) and (Payload == []) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"payload-required">>)}; - (PayloadCount > 1) or (PayloadCount == 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)}; - (DeliverPayloads == false) and (PersistItems == false) and - (PayloadSize > 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-forbidden">>)}; - ((DeliverPayloads == true) or (PersistItems == true)) and - (PayloadSize == 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; - true -> - node_call(Type, publish_item, [NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload]) - end - end, - ejabberd_hooks:run(pubsub_publish_item, ServerHost, [ServerHost, Node, Publisher, service_jid(Host), ItemId, Payload]), + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) -> + Features = plugin_features(Host, Type), + PublishFeature = lists:member(<<"publish">>, Features), + PublishModel = get_option(Options, publish_model), + DeliverPayloads = get_option(Options, deliver_payloads), + PersistItems = get_option(Options, persist_items), + MaxItems = max_items(Host, Options), + PayloadCount = payload_xmlelements(Payload), + PayloadSize = byte_size(term_to_binary(Payload)) - 2, + PayloadMaxSize = get_option(Options, max_payload_size), + if not PublishFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"publish">>)}; + PayloadSize > PayloadMaxSize -> + {error, + extended_error(?ERR_NOT_ACCEPTABLE, <<"payload-too-big">>)}; + (PayloadCount == 0) and (Payload == []) -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"payload-required">>)}; + (PayloadCount > 1) or (PayloadCount == 0) -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)}; + (DeliverPayloads == false) and (PersistItems == false) and + (PayloadSize > 0) -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"item-forbidden">>)}; + ((DeliverPayloads == true) or (PersistItems == true)) and (PayloadSize == 0) -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; + true -> + node_call(Host, Type, publish_item, + [Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload]) + end + end, Reply = [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"publish">>, attrs = nodeAttr(Node), - children = - [#xmlel{name = <<"item">>, - attrs = itemAttr(ItemId), - children = []}]}]}], + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"publish">>, attrs = nodeAttr(Node), + children = [#xmlel{name = <<"item">>, + attrs = itemAttr(ItemId)}]}]}], case transaction(Host, Node, Action, sync_dirty) of {result, {TNode, {Result, Broadcast, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, + BrPayload = case Broadcast of + broadcast -> Payload; + PluginPayload -> PluginPayload + end, + ejabberd_hooks:run(pubsub_publish_item, ServerHost, + [ServerHost, Node, Publisher, service_jid(Host), ItemId, BrPayload]), + set_cached_item(Host, Nidx, ItemId, Publisher, BrPayload), case get_option(Options, deliver_notifications) of - true -> - BroadcastPayload = case Broadcast of - default -> Payload; - broadcast -> Payload; - PluginPayload -> PluginPayload - end, - broadcast_publish_item(Host, Node, NodeId, Type, Options, - Removed, ItemId, jlib:jid_tolower(Publisher), - BroadcastPayload); - false -> - ok - end, - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + true -> + broadcast_publish_item(Host, Node, Nidx, Type, Options, ItemId, + Publisher, BrPayload, Removed); + false -> + ok + end, case Result of default -> {result, Reply}; _ -> {result, Result} end; {result, {TNode, {default, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Reply}; {result, {TNode, {Result, Removed}}} -> - NodeId = TNode#pubsub_node.id, + Nidx = TNode#pubsub_node.id, Type = TNode#pubsub_node.type, Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), + broadcast_retract_items(Host, Node, Nidx, Type, Options, Removed), + set_cached_item(Host, Nidx, ItemId, Publisher, Payload), {result, Result}; {result, {_, default}} -> {result, Reply}; {result, {_, Result}} -> {result, Result}; {error, ?ERR_ITEM_NOT_FOUND} -> - %% handles auto-create feature - %% for automatic node creation. we'll take the default node type: - %% first listed into the plugins configuration option, or pep Type = select_type(ServerHost, Host, Node), - case lists:member(<<"auto-create">>, features(Type)) of + case lists:member(<<"auto-create">>, plugin_features(Host, Type)) of true -> case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of - {result, [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"create">>, - attrs = [{<<"node">>, NewNode}], - children = []}]}]} -> - publish_item(Host, ServerHost, NewNode, - Publisher, ItemId, Payload); + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"create">>, + attrs = [{<<"node">>, NewNode}]}]}]} -> + publish_item(Host, ServerHost, NewNode, Publisher, ItemId, Payload); _ -> {error, ?ERR_ITEM_NOT_FOUND} end; @@ -3107,19 +2229,6 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, Access) -> Error end. -%% @spec (Host::host(), JID::jid(), Node::pubsubNode(), ItemId::string()) -> -%% {error, Reason::stanzaError()} | -%% {result, []} --spec(delete_item/4 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - Publisher :: jid(), - ItemId :: mod_pubsub:itemId()) - -> {result, []} - %%% - | {error, xmlel()} -). %% @doc

    Delete item from a PubSub node.

    %%

    The permission to delete an item must be verified by the plugin implementation.

    %%

    There are several reasons why the item retraction request might fail:

    @@ -3131,64 +2240,62 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, Access) -> %%
  • The node does not support persistent items.
  • %%
  • The service does not support the deletion of items.
  • %% +-spec(delete_item/4 :: + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + Publisher :: jid(), + ItemId :: mod_pubsub:itemId()) + -> {result, []} + %%% + | {error, xmlel()} + ). delete_item(Host, Node, Publisher, ItemId) -> delete_item(Host, Node, Publisher, ItemId, false). - - -delete_item(_, <<"">>, _, _, _) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"node-required">>)}; +delete_item(_, <<>>, _, _, _) -> + {error, extended_error(?ERR_BAD_REQUEST, <<"node-required">>)}; delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - PersistentFeature = lists:member(<<"persistent-items">>, Features), - DeleteFeature = lists:member(<<"delete-items">>, Features), - PublishModel = get_option(Options, publish_model), - if %%-> iq_pubsub just does that matchs - %% %% Request does not specify an item - %% {error, extended_error(?ERR_BAD_REQUEST, "item-required")}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - not DeleteFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"delete-items">>)}; - true -> - node_call(Type, delete_item, - [NodeId, Publisher, PublishModel, ItemId]) - end - end, + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) -> + Features = plugin_features(Host, Type), + PersistentFeature = lists:member(<<"persistent-items">>, Features), + DeleteFeature = lists:member(<<"delete-items">>, Features), + PublishModel = get_option(Options, publish_model), + if %%-> iq_pubsub just does that matchs + %% %% Request does not specify an item + %% {error, extended_error(?ERR_BAD_REQUEST, "item-required")}; + not PersistentFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + not DeleteFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"delete-items">>)}; + true -> + node_call(Host, Type, delete_item, [Nidx, Publisher, PublishModel, ItemId]) + end + end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, - Options, [ItemId], ForceNotify), - case get_cached_item(Host, NodeId) of - #pubsub_item{itemid = {ItemId, NodeId}} -> - unset_cached_item(Host, NodeId); - _ -> ok - end, - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {_, default}} -> {result, Reply}; - {result, {_, Result}} -> {result, Result}; - Error -> Error + {result, {TNode, {Result, broadcast}}} -> + Nidx = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_retract_items(Host, Node, Nidx, Type, Options, [ItemId], ForceNotify), + case get_cached_item(Host, Nidx) of + #pubsub_item{itemid = {ItemId, Nidx}} -> unset_cached_item(Host, Nidx); + _ -> ok + end, + case Result of + default -> {result, Reply}; + _ -> {result, Result} + end; + {result, {_, default}} -> + {result, Reply}; + {result, {_, Result}} -> + {result, Result}; + Error -> + Error end. -%% @spec (Host, JID, Node) -> -%% {error, Reason} | {result, []} -%% Host = host() -%% Node = pubsubNode() -%% JID = jid() -%% Reason = stanzaError() %% @doc

    Delete all items of specified node owned by JID.

    %%

    There are several reasons why the node purge request might fail:

    %%
      @@ -3198,52 +2305,50 @@ delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> %%
    • The specified node does not exist.
    • %%
    -spec(purge_node/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - Owner :: jid()) + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + Owner :: jid()) -> {result, []} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). purge_node(Host, Node, Owner) -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - PurgeFeature = lists:member(<<"purge-nodes">>, Features), - PersistentFeature = lists:member(<<"persistent-items">>, Features), - PersistentConfig = get_option(Options, persist_items), - if not PurgeFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"purge-nodes">>)}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - not PersistentConfig -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - true -> node_call(Type, purge_node, [NodeId, Owner]) - end - end, + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) -> + Features = plugin_features(Host, Type), + PurgeFeature = lists:member(<<"purge-nodes">>, Features), + PersistentFeature = lists:member(<<"persistent-items">>, Features), + PersistentConfig = get_option(Options, persist_items), + if not PurgeFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"purge-nodes">>)}; + not PersistentFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + not PersistentConfig -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + true -> node_call(Host, Type, purge_node, [Nidx, Owner]) + end + end, Reply = [], case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_purge_node(Host, Node, NodeId, Type, Options), - unset_cached_item(Host, NodeId), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {_, default}} -> {result, Reply}; - {result, {_, Result}} -> {result, Result}; - Error -> Error + {result, {TNode, {Result, broadcast}}} -> + Nidx = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_purge_node(Host, Node, Nidx, Type, Options), + unset_cached_item(Host, Nidx), + case Result of + default -> {result, Reply}; + _ -> {result, Result} + end; + {result, {_, default}} -> + {result, Reply}; + {result, {_, Result}} -> + {result, Result}; + Error -> + Error end. %% @doc

    Return the items of a given node.

    @@ -3251,886 +2356,722 @@ purge_node(Host, Node, Owner) -> %%

    The permission are not checked in this function.

    %% @todo We probably need to check that the user doing the query has the right %% to read the items. --spec(get_items/6 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - SubId :: mod_pubsub:subId(), - SMaxItems :: binary(), - ItemIDs :: [mod_pubsub:itemId()]) +-spec(get_items/7 :: + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + From :: jid(), + SubId :: mod_pubsub:subId(), + SMaxItems :: binary(), + ItemIds :: [mod_pubsub:itemId()], + Rsm :: none | rsm_in()) -> {result, [xmlel(),...]} %%% - | {error, xmlel()} -). -get_items(Host, Node, From, SubId, SMaxItems, ItemIDs) -> - MaxItems = if SMaxItems == <<"">> -> - get_max_items_node(Host); - true -> - case catch jlib:binary_to_integer(SMaxItems) of - {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; - Val -> Val - end - end, + | {error, xmlel()} + ). +get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> + MaxItems = if SMaxItems == <<>> -> + get_max_items_node(Host); + true -> + case catch jlib:binary_to_integer(SMaxItems) of + {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; + Val -> Val + end + end, case MaxItems of - {error, Error} -> {error, Error}; - _ -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId, - owners = Owners}) -> - Features = features(Type), - RetreiveFeature = lists:member(<<"retrieve-items">>, Features), - PersistentFeature = lists:member(<<"persistent-items">>, Features), - AccessModel = get_option(Options, access_model), - AllowedGroups = get_option(Options, roster_groups_allowed, []), - {PresenceSubscription, RosterGroup} = - get_presence_and_roster_permissions(Host, From, Owners, - AccessModel, AllowedGroups), - if not RetreiveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-items">>)}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - true -> - node_call(Type, get_items, - [NodeId, From, AccessModel, - PresenceSubscription, RosterGroup, - SubId]) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Items}} -> - SendItems = case ItemIDs of - [] -> Items; - _ -> - lists:filter(fun (#pubsub_item{itemid = - {ItemId, - _}}) -> - lists:member(ItemId, - ItemIDs) - end, - Items) - end, - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = - itemsEls(lists:sublist(SendItems, - MaxItems))}]}]}; - Error -> Error - end + {error, Error} -> + {error, Error}; + _ -> + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx, owners = O}) -> + Features = plugin_features(Host, Type), + RetreiveFeature = lists:member(<<"retrieve-items">>, Features), + PersistentFeature = lists:member(<<"persistent-items">>, Features), + AccessModel = get_option(Options, access_model), + AllowedGroups = get_option(Options, roster_groups_allowed, []), + if not RetreiveFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"retrieve-items">>)}; + not PersistentFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"persistent-items">>)}; + true -> + Owners = node_owners_call(Host, Type, Nidx, O), + {PS, RG} = get_presence_and_roster_permissions(Host, From, Owners, + AccessModel, AllowedGroups), + node_call(Host, Type, get_items, + [Nidx, From, AccessModel, PS, RG, SubId, RSM]) + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, {Items, RsmOut}}} -> + SendItems = case ItemIds of + [] -> + Items; + _ -> + lists:filter(fun (#pubsub_item{itemid = {ItemId, _}}) -> + lists:member(ItemId, ItemIds) + end, + Items) + end, + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = + [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), + children = itemsEls(lists:sublist(SendItems, MaxItems))} + | jlib:rsm_encode(RsmOut)]}]}; + Error -> + Error + end end. get_items(Host, Node) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_items, [NodeId, service_jid(Host)]) - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + node_call(Host, Type, get_items, [Nidx, service_jid(Host), none]) + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Items}} -> Items; - Error -> Error + {result, {_, {Items, _}}} -> Items; + Error -> Error end. get_item(Host, Node, ItemId) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_item, [NodeId, ItemId]) - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + node_call(Host, Type, get_item, [Nidx, ItemId]) + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Items}} -> Items; - Error -> Error + {result, {_, Items}} -> Items; + Error -> Error end. -get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) -> +get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> + case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, none) of + {result, {I, none}} -> {result, I}; + Error -> Error + end. +get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, RSM) -> AccessModel = get_option(Options, access_model), AllowedGroups = get_option(Options, roster_groups_allowed, []), - {PresenceSubscription, RosterGroup} = - get_presence_and_roster_permissions(Host, From, Owners, AccessModel, - AllowedGroups), - node_call(Type, get_items, - [NodeIdx, From, AccessModel, PresenceSubscription, RosterGroup, undefined]). - -%% @spec (Host, Node, NodeId, Type, LJID, Number) -> any() -%% Host = pubsubHost() -%% Node = pubsubNode() -%% NodeId = pubsubNodeId() -%% Type = pubsubNodeType() -%% Options = mod_pubsub:nodeOptions() -%% LJID = {U, S, []} -%% Number = last | integer() + {PS, RG} = get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups), + node_call(Host, Type, get_items, [Nidx, From, AccessModel, PS, RG, undefined, RSM]). + +get_last_item(Host, Type, Nidx, LJID) -> + case get_cached_item(Host, Nidx) of + undefined -> get_last_item(Host, Type, Nidx, LJID, gen_mod:db_type(serverhost(Host), ?MODULE)); + LastItem -> LastItem + end. +get_last_item(Host, Type, Nidx, LJID, mnesia) -> + case node_action(Host, Type, get_items, [Nidx, LJID, none]) of + {result, {[LastItem|_], _}} -> LastItem; + _ -> undefined + end; +get_last_item(Host, Type, Nidx, LJID, odbc) -> + case node_action(Host, Type, get_last_items, [Nidx, LJID, 1]) of + {result, [LastItem]} -> LastItem; + _ -> undefined + end; +get_last_item(_Host, _Type, _Nidx, _LJID, _) -> + undefined. + +get_last_items(Host, Type, Nidx, LJID, Number) -> + get_last_items(Host, Type, Nidx, LJID, Number, gen_mod:db_type(serverhost(Host), ?MODULE)). +get_last_items(Host, Type, Nidx, LJID, Number, mnesia) -> + case node_action(Host, Type, get_items, [Nidx, LJID, none]) of + {result, {Items, _}} -> lists:sublist(Items, Number); + _ -> [] + end; +get_last_items(Host, Type, Nidx, LJID, Number, odbc) -> + case node_action(Host, Type, get_last_items, [Nidx, LJID, Number]) of + {result, Items} -> Items; + _ -> [] + end; +get_last_items(_Host, _Type, _Nidx, _LJID, _Number, _) -> + []. + %% @doc

    Resend the items of a node to the user.

    %% @todo use cache-last-item feature -send_items(Host, Node, NodeId, Type, Options, LJID, last) -> - case get_cached_item(Host, NodeId) of - undefined -> - send_items(Host, Node, NodeId, Type, Options, LJID, 1); - LastItem -> - {ModifNow, ModifUSR} = - LastItem#pubsub_item.modification, - Stanza = event_stanza_with_delay([#xmlel{name = - <<"items">>, - attrs = nodeAttr(Node), - children = - itemsEls([LastItem])}], - ModifNow, ModifUSR), - dispatch_items(Host, LJID, Node, Options, Stanza) +send_items(Host, Node, Nidx, Type, Options, LJID, last) -> + case get_last_item(Host, Type, Nidx, LJID) of + undefined -> + ok; + LastItem -> + Stanza = items_event_stanza(Node, [LastItem]), + dispatch_items(Host, LJID, Node, Options, Stanza) end; -send_items(Host, Node, NodeId, Type, Options, LJID, Number) -> - ToSend = case node_action(Host, Type, get_items, - [NodeId, LJID]) - of - {result, []} -> []; - {result, Items} -> - case Number of - N when N > 0 -> lists:sublist(Items, N); - _ -> Items - end; - _ -> [] - end, - Stanza = case ToSend of - [] -> - undefined; - [LastItem] -> - {ModifNow, ModifUSR} = - LastItem#pubsub_item.modification, - event_stanza_with_delay([#xmlel{name = <<"items">>, - attrs = nodeAttr(Node), - children = - itemsEls(ToSend)}], - ModifNow, ModifUSR); - _ -> - event_stanza([#xmlel{name = <<"items">>, - attrs = nodeAttr(Node), - children = itemsEls(ToSend)}]) - end, +send_items(Host, Node, Nidx, Type, Options, LJID, Number) when Number > 0 -> + Stanza = items_event_stanza(Node, get_last_items(Host, Type, Nidx, Number, LJID)), + dispatch_items(Host, LJID, Node, Options, Stanza); +send_items(Host, Node, _Nidx, _Type, Options, LJID, _) -> + Stanza = items_event_stanza(Node, []), dispatch_items(Host, LJID, Node, Options, Stanza). --spec(dispatch_items/5 :: -( - From :: mod_pubsub:host(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Options :: mod_pubsub:nodeOptions(), - Stanza :: xmlel() | undefined) - -> any() -). - -dispatch_items(_From, _To, _Node, _Options, _Stanza = undefined) -> ok; dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To, Node, - Options, BaseStanza) -> - NotificationType = get_option(Options, notification_type, headline), - Stanza = add_message_type(BaseStanza, NotificationType), + Options, Stanza) -> C2SPid = case ejabberd_sm:get_session_pid(ToU, ToS, ToR) of - ToPid when is_pid(ToPid) -> ToPid; - _ -> - R = user_resource(FromU, FromS, FromR), - case ejabberd_sm:get_session_pid(FromU, FromS, R) of - FromPid when is_pid(FromPid) -> FromPid; - _ -> undefined - end - end, + ToPid when is_pid(ToPid) -> ToPid; + _ -> + R = user_resource(FromU, FromS, FromR), + case ejabberd_sm:get_session_pid(FromU, FromS, R) of + FromPid when is_pid(FromPid) -> FromPid; + _ -> undefined + end + end, if C2SPid == undefined -> ok; - true -> - ejabberd_c2s:send_filtered(C2SPid, - {pep_message, <>}, - service_jid(From), jlib:make_jid(To), - Stanza) + true -> + NotificationType = get_option(Options, notification_type, headline), + Message = add_message_type(Stanza, NotificationType), + ejabberd_c2s:send_filtered(C2SPid, + {pep_message, <>}, + service_jid(From), jlib:make_jid(To), + Message) end; -dispatch_items(From, To, _Node, Options, BaseStanza) -> +dispatch_items(From, To, _Node, Options, Stanza) -> NotificationType = get_option(Options, notification_type, headline), - Stanza = add_message_type(BaseStanza, NotificationType), - ejabberd_router:route(service_jid(From), jlib:make_jid(To), Stanza). - -%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response} -%% Host = host() -%% JID = jid() -%% Plugins = [Plugin::string()] -%% Reason = stanzaError() -%% Response = [pubsubIQResponse()] + Message = add_message_type(Stanza, NotificationType), + ejabberd_router:route(service_jid(From), jlib:make_jid(To), Message). + %% @doc

    Return the list of affiliations as an XMPP response.

    -spec(get_affiliations/4 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - JID :: jid(), - Plugins :: [binary()]) + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + JID :: jid(), + Plugins :: [binary()]) -> {result, [xmlel(),...]} %%% - | {error, xmlel()} -). -get_affiliations(Host, <<>>, JID, Plugins) - when is_list(Plugins) -> - Result = lists:foldl(fun (Type, {Status, Acc}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"retrieve-affiliations">>, Features), - if not RetrieveFeature -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affiliations} = - node_action(Host, Type, - get_entity_affiliations, - [Host, JID]), - {Status, [Affiliations | Acc]} - end - end, - {ok, []}, Plugins), - case Result of - {ok, Affiliations} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({#pubsub_node{nodeid = {_, Node}}, - Affiliation}) -> - [#xmlel{name = <<"affiliation">>, - attrs = - [{<<"affiliation">>, - affiliation_to_string(Affiliation)} - | nodeAttr(Node)], - children = []}] - end, - lists:usort(lists:flatten(Affiliations))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"affiliations">>, attrs = [], - children = Entities}]}]}; - {Error, _} -> Error - end; -get_affiliations(Host, NodeId, JID, Plugins) - when is_list(Plugins) -> - Result = lists:foldl(fun (Type, {Status, Acc}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"retrieve-affiliations">>, - Features), - if not RetrieveFeature -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affiliations} = - node_action(Host, Type, - get_entity_affiliations, - [Host, JID]), - {Status, [Affiliations | Acc]} - end - end, - {ok, []}, Plugins), + | {error, xmlel()} + ). +get_affiliations(Host, Node, JID, Plugins) when is_list(Plugins) -> + Result = lists:foldl( fun (Type, {Status, Acc}) -> + Features = plugin_features(Host, Type), + RetrieveFeature = lists:member(<<"retrieve-affiliations">>, Features), + if not RetrieveFeature -> + {{error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, + unsupported, <<"retrieve-affiliations">>)}, + Acc}; + true -> + {result, Affs} = node_action(Host, Type, + get_entity_affiliations, + [Host, JID]), + {Status, [Affs | Acc]} + end + end, + {ok, []}, Plugins), case Result of - {ok, Affiliations} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({#pubsub_node{nodeid = {_, Node}}, - Affiliation}) - when NodeId == Node -> - [#xmlel{name = <<"affiliation">>, - attrs = - [{<<"affiliation">>, - affiliation_to_string(Affiliation)} - | nodeAttr(Node)], - children = []}]; - (_) -> [] - end, - lists:usort(lists:flatten(Affiliations))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"affiliations">>, attrs = [], - children = Entities}]}]}; - {Error, _} -> Error + {ok, Affs} -> + Entities = lists:flatmap(fun + ({_, none}) -> + []; + ({#pubsub_node{nodeid = {_, NodeId}}, Aff}) -> + if (Node == <<>>) or (Node == NodeId) -> + [#xmlel{name = <<"affiliation">>, + attrs = [{<<"affiliation">>, affiliation_to_string(Aff)} + | nodeAttr(NodeId)]}]; + true -> + [] + end; + (_) -> + [] + end, + lists:usort(lists:flatten(Affs))), + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"affiliations">>, attrs = [], + children = Entities}]}]}; + {Error, _} -> + Error end. -spec(get_affiliations/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - JID :: jid()) + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + JID :: jid()) -> {result, [xmlel(),...]} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). get_affiliations(Host, Node, JID) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"modify-affiliations">>, Features), - {result, Affiliation} = node_call(Type, get_affiliation, - [NodeId, JID]), - if not RetrieveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"modify-affiliations">>)}; - Affiliation /= owner -> {error, ?ERR_FORBIDDEN}; - true -> node_call(Type, get_node_affiliations, [NodeId]) - end - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + Features = plugin_features(Host, Type), + RetrieveFeature = lists:member(<<"modify-affiliations">>, Features), + {result, Affiliation} = node_call(Host, Type, get_affiliation, [Nidx, JID]), + if not RetrieveFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"modify-affiliations">>)}; + Affiliation /= owner -> + {error, ?ERR_FORBIDDEN}; + true -> + node_call(Host, Type, get_node_affiliations, [Nidx]) + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, []}} -> {error, ?ERR_ITEM_NOT_FOUND}; - {result, {_, Affiliations}} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({AJID, Affiliation}) -> - [#xmlel{name = <<"affiliation">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(AJID)}, - {<<"affiliation">>, - affiliation_to_string(Affiliation)}], - children = []}] - end, - Affiliations), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"affiliations">>, - attrs = nodeAttr(Node), children = Entities}]}]}; - Error -> Error + {result, {_, []}} -> + {error, ?ERR_ITEM_NOT_FOUND}; + {result, {_, Affs}} -> + Entities = lists:flatmap(fun + ({_, none}) -> + []; + ({AJID, Aff}) -> + [#xmlel{name = <<"affiliation">>, + attrs = [{<<"jid">>, jlib:jid_to_string(AJID)}, + {<<"affiliation">>, affiliation_to_string(Aff)}]}] + end, + Affs), + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], + children = [#xmlel{name = <<"affiliations">>, + attrs = nodeAttr(Node), children = Entities}]}]}; + Error -> + Error end. -spec(set_affiliations/4 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - EntitiesEls :: [xmlel()]) + ( + Host :: mod_pubsub:host(), + Node :: mod_pubsub:nodeId(), + From :: jid(), + EntitiesEls :: [xmlel()]) -> {result, []} %%% - | {error, xmlel()} -). + | {error, xmlel()} + ). set_affiliations(Host, Node, From, EntitiesEls) -> Owner = jlib:jid_tolower(jlib:jid_remove_resource(From)), - Entities = lists:foldl(fun (El, Acc) -> - case Acc of - error -> error; - _ -> - case El of - #xmlel{name = <<"affiliation">>, - attrs = Attrs} -> - JID = - jlib:string_to_jid(xml:get_attr_s(<<"jid">>, - Attrs)), - Affiliation = - string_to_affiliation(xml:get_attr_s(<<"affiliation">>, - Attrs)), - if (JID == error) or - (Affiliation == false) -> - error; - true -> - [{jlib:jid_tolower(JID), - Affiliation} - | Acc] - end - end - end - end, - [], EntitiesEls), + Entities = lists:foldl(fun + (_, error) -> + error; + (El, Acc) -> + case El of + #xmlel{name = <<"affiliation">>, attrs = Attrs} -> + JID = jlib:string_to_jid(xml:get_attr_s(<<"jid">>, Attrs)), + Affiliation = string_to_affiliation(xml:get_attr_s(<<"affiliation">>, Attrs)), + if (JID == error) or (Affiliation == false) -> error; + true -> [{jlib:jid_tolower(JID), Affiliation} | Acc] + end + end + end, + [], EntitiesEls), case Entities of - error -> {error, ?ERR_BAD_REQUEST}; - _ -> - Action = fun (#pubsub_node{owners = Owners, type = Type, - id = NodeId} = - N) -> - case lists:member(Owner, Owners) of - true -> - OwnerJID = jlib:make_jid(Owner), - FilteredEntities = case Owners of - [Owner] -> - [E - || E <- Entities, - element(1, E) =/= - OwnerJID]; - _ -> Entities - end, - lists:foreach(fun ({JID, Affiliation}) -> - node_call(Type, - set_affiliation, - [NodeId, JID, - Affiliation]), - case Affiliation of - owner -> - NewOwner = - jlib:jid_tolower(jlib:jid_remove_resource(JID)), - NewOwners = - [NewOwner - | Owners], - tree_call(Host, - set_node, - [N#pubsub_node{owners - = - NewOwners}]); - none -> - OldOwner = - jlib:jid_tolower(jlib:jid_remove_resource(JID)), - case - lists:member(OldOwner, - Owners) - of - true -> - NewOwners = - Owners -- - [OldOwner], - tree_call(Host, - set_node, - [N#pubsub_node{owners - = - NewOwners}]); - _ -> ok - end; - _ -> ok - end - end, - FilteredEntities), - {result, []}; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end + error -> + {error, ?ERR_BAD_REQUEST}; + _ -> + Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O} = N) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case lists:member(Owner, Owners) of + true -> + OwnerJID = jlib:make_jid(Owner), + FilteredEntities = case Owners of + [Owner] -> [E || E <- Entities, element(1, E) =/= OwnerJID]; + _ -> Entities + end, + lists:foreach(fun ({JID, Affiliation}) -> + node_call(Host, Type, set_affiliation, [Nidx, JID, Affiliation]), + case Affiliation of + owner -> + NewOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + NewOwners = [NewOwner | Owners], + tree_call(Host, + set_node, + [N#pubsub_node{owners = NewOwners}]); + none -> + OldOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + case lists:member(OldOwner, Owners) of + true -> + NewOwners = Owners -- [OldOwner], + tree_call(Host, + set_node, + [N#pubsub_node{owners = NewOwners}]); + _ -> + ok + end; + _ -> + ok + end + end, + FilteredEntities), + {result, []}; + _ -> + {error, ?ERR_FORBIDDEN} + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end end. -get_options(Host, Node, JID, SubID, Lang) -> - Action = fun (#pubsub_node{type = Type, id = NodeID}) -> - case lists:member(<<"subscription-options">>, features(Type)) of - true -> - get_options_helper(JID, Lang, Node, NodeID, SubID, Type); - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"subscription-options">>)} - end - end, +get_options(Host, Node, JID, SubId, Lang) -> + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + case lists:member(<<"subscription-options">>, plugin_features(Host, Type)) of + true -> + get_options_helper(Host, JID, Lang, Node, Nidx, SubId, Type); + false -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscription-options">>)} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_Node, XForm}} -> {result, [XForm]}; - Error -> Error + {result, {_Node, XForm}} -> {result, [XForm]}; + Error -> Error end. -get_options_helper(JID, Lang, Node, NodeID, SubID, Type) -> - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> case jlib:jid_tolower(J) of - error -> {<<"">>, <<"">>, <<"">>}; - J1 -> J1 - end - end, - {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun ({subscribed, SID}, Acc) -> - [SID | Acc]; - (_, Acc) -> Acc - end, - [], Subs), - case {SubID, SubIDs} of - {_, []} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"not-subscribed">>)}; - {<<>>, [SID]} -> - read_sub(Subscriber, Node, NodeID, SID, Lang); - {<<>>, _} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"subid-required">>)}; - {_, _} -> - ValidSubId = lists:member(SubID, SubIDs), - if ValidSubId -> - read_sub(Subscriber, Node, NodeID, SubID, Lang); - true -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)} - end +get_options_helper(Host, JID, Lang, Node, Nidx, SubId, Type) -> + Subscriber = string_to_ljid(JID), + {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), + SubIds = [Id || {Sub, Id} <- Subs, Sub == subscribed], + case {SubId, SubIds} of + {_, []} -> + {error, + extended_error(?ERR_NOT_ACCEPTABLE, <<"not-subscribed">>)}; + {<<>>, [SID]} -> + read_sub(Host, Node, Nidx, Subscriber, SID, Lang); + {<<>>, _} -> + {error, + extended_error(?ERR_NOT_ACCEPTABLE, <<"subid-required">>)}; + {_, _} -> + ValidSubId = lists:member(SubId, SubIds), + if ValidSubId -> + read_sub(Host, Node, Nidx, Subscriber, SubId, Lang); + true -> + {error, + extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)} + end end. -read_sub(Subscriber, Node, NodeID, SubID, Lang) -> - Children = case pubsub_subscription:get_subscription(Subscriber, NodeID, SubID) of +read_sub(Host, Node, Nidx, Subscriber, SubId, Lang) -> + SubModule = subscription_plugin(Host), + Children = case SubModule:get_subscription(Subscriber, Nidx, SubId) of {error, notfound} -> []; {result, #pubsub_subscription{options = Options}} -> - {result, XdataEl} = pubsub_subscription:get_options_xform(Lang, Options), + {result, XdataEl} = SubModule:get_options_xform(Lang, Options), [XdataEl] end, OptionsEl = #xmlel{name = <<"options">>, - attrs = - [{<<"jid">>, jlib:jid_to_string(Subscriber)}, - {<<"subid">>, SubID} - | nodeAttr(Node)], - children = Children}, + attrs = [{<<"jid">>, jlib:jid_to_string(Subscriber)}, + {<<"subid">>, SubId} + | nodeAttr(Node)], + children = Children}, PubsubEl = #xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [OptionsEl]}, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [OptionsEl]}, {result, PubsubEl}. -set_options(Host, Node, JID, SubID, Configuration) -> - Action = fun (#pubsub_node{type = Type, id = NodeID}) -> - case lists:member(<<"subscription-options">>, - features(Type)) - of - true -> - set_options_helper(Configuration, JID, NodeID, SubID, - Type); - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"subscription-options">>)} - end - end, +set_options(Host, Node, JID, SubId, Configuration) -> + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + case lists:member(<<"subscription-options">>, plugin_features(Host, Type)) of + true -> + set_options_helper(Host, Configuration, JID, Nidx, SubId, Type); + false -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscription-options">>)} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_Node, Result}} -> {result, Result}; - Error -> Error + {result, {_Node, Result}} -> {result, Result}; + Error -> Error end. -set_options_helper(Configuration, JID, NodeID, SubID, Type) -> - SubOpts = case pubsub_subscription:parse_options_xform(Configuration) of - {result, GoodSubOpts} -> GoodSubOpts; - _ -> invalid - end, - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> jlib:jid_tolower(J) - end, - {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun ({subscribed, SID}, Acc) -> - [SID | Acc]; - (_, Acc) -> Acc - end, - [], Subs), - case {SubID, SubIDs} of - {_, []} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, - <<"not-subscribed">>)}; - {<<>>, [SID]} -> - write_sub(Subscriber, NodeID, SID, SubOpts); - {<<>>, _} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, - <<"subid-required">>)}; - {_, _} -> write_sub(Subscriber, NodeID, SubID, SubOpts) +set_options_helper(Host, Configuration, JID, Nidx, SubId, Type) -> + SubModule = subscription_plugin(Host), + SubOpts = case SubModule:parse_options_xform(Configuration) of + {result, GoodSubOpts} -> GoodSubOpts; + _ -> invalid + end, + Subscriber = string_to_ljid(JID), + {result, Subs} = node_call(Host, Type, get_subscriptions, [Nidx, Subscriber]), + SubIds = [Id || {Sub, Id} <- Subs, Sub == subscribed], + case {SubId, SubIds} of + {_, []} -> + {error, + extended_error(?ERR_NOT_ACCEPTABLE, <<"not-subscribed">>)}; + {<<>>, [SID]} -> + write_sub(Host, Nidx, Subscriber, SID, SubOpts); + {<<>>, _} -> + {error, + extended_error(?ERR_NOT_ACCEPTABLE, <<"subid-required">>)}; + {_, _} -> + write_sub(Host, Nidx, Subscriber, SubId, SubOpts) end. -write_sub(_Subscriber, _NodeID, _SubID, invalid) -> - {error, extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; -write_sub(Subscriber, NodeID, SubID, Options) -> - case pubsub_subscription:set_subscription(Subscriber, NodeID, SubID, Options) of - {error, notfound} -> - {error, extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)}; - {result, _} -> - {result, []} +write_sub(_Host, _Nidx, _Subscriber, _SubId, invalid) -> + {error, + extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; +write_sub(_Host, _Nidx, _Subscriber, _SubId, []) -> + {result, []}; +write_sub(Host, Nidx, Subscriber, SubId, Options) -> + SubModule = subscription_plugin(Host), + case SubModule:set_subscription(Subscriber, Nidx, SubId, Options) of + {result, _} -> {result, []}; + {error, _} -> {error, extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)} end. %% @spec (Host, Node, JID, Plugins) -> {error, Reason} | {result, Response} -%% Host = host() -%% Node = pubsubNode() -%% JID = jid() -%% Plugins = [Plugin::string()] -%% Reason = stanzaError() -%% Response = [pubsubIQResponse()] +%% Host = host() +%% Node = pubsubNode() +%% JID = jid() +%% Plugins = [Plugin::string()] +%% Reason = stanzaError() +%% Response = [pubsubIQResponse()] %% @doc

    Return the list of subscriptions as an XMPP response.

    get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> - Result = lists:foldl( - fun(Type, {Status, Acc}) -> - Features = features(Type), - RetrieveFeature = lists:member(<<"retrieve-subscriptions">>, Features), - if - not RetrieveFeature -> - %% Service does not support retreive subscriptions - {{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"retrieve-subscriptions">>)}, Acc}; - true -> - Subscriber = jlib:jid_remove_resource(JID), - {result, Subscriptions} = node_action(Host, Type, get_entity_subscriptions, [Host, Subscriber]), - {Status, [Subscriptions|Acc]} - end - end, {ok, []}, Plugins), + Result = lists:foldl(fun (Type, {Status, Acc}) -> + Features = plugin_features(Host, Type), + RetrieveFeature = lists:member(<<"retrieve-subscriptions">>, Features), + if not RetrieveFeature -> + {{error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, + unsupported, <<"retrieve-subscriptions">>)}, + Acc}; + true -> + Subscriber = jlib:jid_remove_resource(JID), + {result, Subs} = node_action(Host, Type, + get_entity_subscriptions, + [Host, Subscriber]), + {Status, [Subs | Acc]} + end + end, + {ok, []}, Plugins), case Result of - {ok, Subscriptions} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, - Subscription}) -> - case Node of - <<>> -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"subscription">>, - subscription_to_string(Subscription)} - | nodeAttr(SubsNode)], - children = []}]; - SubsNode -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - _ -> [] - end; - ({_, none, _}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, - Subscription, SubID, SubJID}) -> - case Node of - <<>> -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subid">>, - SubID}, - {<<"subscription">>, - subscription_to_string(Subscription)} - | nodeAttr(SubsNode)], - children = []}]; - SubsNode -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subid">>, - SubID}, - {<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - _ -> [] - end; - ({#pubsub_node{nodeid = {_, SubsNode}}, - Subscription, SubJID}) -> - case Node of - <<>> -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)} - | nodeAttr(SubsNode)], - children = []}]; - SubsNode -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - _ -> [] - end - end, - lists:usort(lists:flatten(Subscriptions))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"subscriptions">>, attrs = [], - children = Entities}]}]}; - {Error, _} -> Error + {ok, Subs} -> + Entities = lists:flatmap(fun + ({_, none}) -> + []; + ({#pubsub_node{nodeid = {_, SubsNode}}, Sub}) -> + case Node of + <<>> -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"subscription">>, subscription_to_string(Sub)} + | nodeAttr(SubsNode)]}]; + SubsNode -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"subscription">>, subscription_to_string(Sub)}]}]; + _ -> + [] + end; + ({_, none, _}) -> + []; + ({#pubsub_node{nodeid = {_, SubsNode}}, Sub, SubId, SubJID}) -> + case Node of + <<>> -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"jid">>, jlib:jid_to_string(SubJID)}, + {<<"subid">>, SubId}, + {<<"subscription">>, subscription_to_string(Sub)} + | nodeAttr(SubsNode)]}]; + SubsNode -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"jid">>, jlib:jid_to_string(SubJID)}, + {<<"subid">>, SubId}, + {<<"subscription">>, subscription_to_string(Sub)}]}]; + _ -> + [] + end; + ({#pubsub_node{nodeid = {_, SubsNode}}, Sub, SubJID}) -> + case Node of + <<>> -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"jid">>, jlib:jid_to_string(SubJID)}, + {<<"subscription">>, subscription_to_string(Sub)} + | nodeAttr(SubsNode)]}]; + SubsNode -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"jid">>, jlib:jid_to_string(SubJID)}, + {<<"subscription">>, subscription_to_string(Sub)}]}]; + _ -> + [] + end + end, + lists:usort(lists:flatten(Subs))), + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = [#xmlel{name = <<"subscriptions">>, attrs = [], + children = Entities}]}]}; + {Error, _} -> + Error end. get_subscriptions(Host, Node, JID) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"manage-subscriptions">>, Features), - {result, Affiliation} = node_call(Type, get_affiliation, - [NodeId, JID]), - if not RetrieveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"manage-subscriptions">>)}; - Affiliation /= owner -> {error, ?ERR_FORBIDDEN}; - true -> - node_call(Type, get_node_subscriptions, [NodeId]) - end - end, + Action = fun (#pubsub_node{type = Type, id = Nidx}) -> + Features = plugin_features(Host, Type), + RetrieveFeature = lists:member(<<"manage-subscriptions">>, Features), + {result, Affiliation} = node_call(Host, Type, get_affiliation, [Nidx, JID]), + if not RetrieveFeature -> + {error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"manage-subscriptions">>)}; + Affiliation /= owner -> + {error, ?ERR_FORBIDDEN}; + true -> + node_call(Host, Type, get_node_subscriptions, [Nidx]) + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Subscriptions}} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({_, pending, _}) -> []; - ({AJID, Subscription}) -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(AJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - ({AJID, Subscription, SubId}) -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(AJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)}, - {<<"subid">>, SubId}], - children = []}] - end, - Subscriptions), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"subscriptions">>, - attrs = nodeAttr(Node), children = Entities}]}]}; - Error -> Error + {result, {_, Subs}} -> + Entities = lists:flatmap(fun + ({_, none}) -> + []; + ({_, pending, _}) -> + []; + ({AJID, Sub}) -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"jid">>, jlib:jid_to_string(AJID)}, + {<<"subscription">>, subscription_to_string(Sub)}]}]; + ({AJID, Sub, SubId}) -> + [#xmlel{name = <<"subscription">>, + attrs = + [{<<"jid">>, jlib:jid_to_string(AJID)}, + {<<"subscription">>, subscription_to_string(Sub)}, + {<<"subid">>, SubId}]}] + end, + Subs), + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], + children = [#xmlel{name = <<"subscriptions">>, + attrs = nodeAttr(Node), + children = Entities}]}]}; + Error -> + Error end. +get_subscriptions_for_send_last(Host, PType, mnesia, JID, LJID, BJID) -> + {result, Subs} = node_action(Host, PType, + get_entity_subscriptions, + [Host, JID]), + [{Node, Sub, SubId, SubJID} + || {Node, Sub, SubId, SubJID} <- Subs, + Sub =:= subscribed, (SubJID == LJID) or (SubJID == BJID), + match_option(Node, send_last_published_item, on_sub_and_presence)]; +get_subscriptions_for_send_last(Host, PType, odbc, JID, LJID, BJID) -> + case catch node_action(Host, PType, + get_entity_subscriptions_for_send_last, + [Host, JID]) + of + {result, Subs} -> + [{Node, Sub, SubId, SubJID} + || {Node, Sub, SubId, SubJID} <- Subs, + Sub =:= subscribed, (SubJID == LJID) or (SubJID == BJID)]; + _ -> + [] + end; +get_subscriptions_for_send_last(_Host, _PType, _, _JID, _LJID, _BJID) -> + []. + set_subscriptions(Host, Node, From, EntitiesEls) -> - Owner = - jlib:jid_tolower(jlib:jid_remove_resource(From)), - Entities = lists:foldl(fun (El, Acc) -> - case Acc of - error -> error; - _ -> - case El of - #xmlel{name = <<"subscription">>, - attrs = Attrs} -> - JID = - jlib:string_to_jid(xml:get_attr_s(<<"jid">>, - Attrs)), - Subscription = - string_to_subscription(xml:get_attr_s(<<"subscription">>, - Attrs)), - SubId = - xml:get_attr_s(<<"subid">>, - Attrs), - if (JID == error) or - (Subscription == false) -> - error; - true -> - [{jlib:jid_tolower(JID), - Subscription, SubId} - | Acc] - end - end - end - end, - [], EntitiesEls), + Owner = jlib:jid_tolower(jlib:jid_remove_resource(From)), + Entities = lists:foldl(fun + (_, error) -> + error; + (El, Acc) -> + case El of + #xmlel{name = <<"subscription">>, attrs = Attrs} -> + JID = jlib:string_to_jid(xml:get_attr_s(<<"jid">>, Attrs)), + Sub = string_to_subscription(xml:get_attr_s(<<"subscription">>, Attrs)), + SubId = xml:get_attr_s(<<"subid">>, Attrs), + if (JID == error) or (Sub == false) -> error; + true -> [{jlib:jid_tolower(JID), Sub, SubId} | Acc] + end + end + end, + [], EntitiesEls), case Entities of - error -> {error, ?ERR_BAD_REQUEST}; - _ -> - Notify = fun (JID, Sub, _SubId) -> - Stanza = #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"pubsub">>, - attrs = - [{<<"xmlns">>, - ?NS_PUBSUB}], - children = - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(JID)}, - {<<"subscription">>, - subscription_to_string(Sub)} - | nodeAttr(Node)], - children = - []}]}]}, - ejabberd_router:route(service_jid(Host), - jlib:make_jid(JID), Stanza) - end, - Action = fun (#pubsub_node{owners = Owners, type = Type, - id = NodeId}) -> - case lists:member(Owner, Owners) of - true -> - Result = lists:foldl(fun ({JID, Subscription, - SubId}, - Acc) -> - case - node_call(Type, - set_subscriptions, - [NodeId, - JID, - Subscription, - SubId]) - of - {error, Err} -> - [{error, - Err} - | Acc]; - _ -> - Notify(JID, - Subscription, - SubId), - Acc - end - end, - [], Entities), - case Result of - [] -> {result, []}; - _ -> {error, ?ERR_NOT_ACCEPTABLE} - end; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end + error -> + {error, ?ERR_BAD_REQUEST}; + _ -> + Notify = fun (JID, Sub, _SubId) -> + Stanza = #xmlel{name = <<"message">>, attrs = [], + children = + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB}], + children = + [#xmlel{name = <<"subscription">>, + attrs = [{<<"jid">>, jlib:jid_to_string(JID)}, + {<<"subscription">>, subscription_to_string(Sub)} + | nodeAttr(Node)]}]}]}, + ejabberd_router:route(service_jid(Host), jlib:make_jid(JID), Stanza) + end, + Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O}) -> + Owners = node_owners_call(Host, Type, Nidx, O), + case lists:member(Owner, Owners) of + true -> + Result = lists:foldl(fun ({JID, Sub, SubId}, Acc) -> + case + node_call(Host, Type, + set_subscriptions, + [Nidx, JID, Sub, SubId]) + of + {error, Err} -> + [{error, Err} | Acc]; + _ -> + Notify(JID, Sub, SubId), + Acc + end + end, + [], Entities), + case Result of + [] -> {result, []}; + _ -> {error, ?ERR_NOT_ACCEPTABLE} + end; + _ -> + {error, ?ERR_FORBIDDEN} + end + end, + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, Result}} -> {result, Result}; + Other -> Other + end end. -spec(get_presence_and_roster_permissions/5 :: -( - Host :: mod_pubsub:host(), - From :: ljid(), - Owners :: [ljid(),...], - AccessModel :: mod_pubsub:accessModel(), - AllowedGroups :: [binary()]) + ( + Host :: mod_pubsub:host(), + From :: ljid(), + Owners :: [ljid(),...], + AccessModel :: mod_pubsub:accessModel(), + AllowedGroups :: [binary()]) -> {PresenceSubscription::boolean(), RosterGroup::boolean()} -). - + ). get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) -> if (AccessModel == presence) or (AccessModel == roster) -> - case Host of - {User, Server, _} -> - get_roster_info(User, Server, From, AllowedGroups); - _ -> - [{OUser, OServer, _} | _] = Owners, - get_roster_info(OUser, OServer, From, AllowedGroups) - end; - true -> {true, true} + case Host of + {User, Server, _} -> + get_roster_info(User, Server, From, AllowedGroups); + _ -> + [{OUser, OServer, _} | _] = Owners, + get_roster_info(OUser, OServer, From, AllowedGroups) + end; + true -> + {true, true} end. -%% @spec (OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, SubscriberResource}, AllowedGroups) -%% -> {PresenceSubscription, RosterGroup} -get_roster_info(_, _, {<<"">>, <<"">>, _}, _) -> +get_roster_info(_, _, {<<>>, <<>>, _}, _) -> {false, false}; -get_roster_info(OwnerUser, OwnerServer, - {SubscriberUser, SubscriberServer, _}, AllowedGroups) -> - {Subscription, Groups} = - ejabberd_hooks:run_fold(roster_get_jid_info, - OwnerServer, {none, []}, - [OwnerUser, OwnerServer, - {SubscriberUser, SubscriberServer, <<"">>}]), +get_roster_info(OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, _}, AllowedGroups) -> + LJID = {SubscriberUser, SubscriberServer, <<>>}, + {Subscription, Groups} = ejabberd_hooks:run_fold(roster_get_jid_info, + OwnerServer, {none, []}, + [OwnerUser, OwnerServer, LJID]), PresenceSubscription = Subscription == both orelse - Subscription == from orelse - {OwnerUser, OwnerServer} == - {SubscriberUser, SubscriberServer}, + Subscription == from orelse + {OwnerUser, OwnerServer} == {SubscriberUser, SubscriberServer}, RosterGroup = lists:any(fun (Group) -> - lists:member(Group, AllowedGroups) - end, - Groups), + lists:member(Group, AllowedGroups) + end, + Groups), {PresenceSubscription, RosterGroup}; -get_roster_info(OwnerUser, OwnerServer, JID, - AllowedGroups) -> - get_roster_info(OwnerUser, OwnerServer, - jlib:jid_tolower(JID), AllowedGroups). +get_roster_info(OwnerUser, OwnerServer, JID, AllowedGroups) -> + get_roster_info(OwnerUser, OwnerServer, jlib:jid_tolower(JID), AllowedGroups). string_to_affiliation(<<"owner">>) -> owner; string_to_affiliation(<<"publisher">>) -> publisher; @@ -4141,8 +3082,7 @@ string_to_affiliation(_) -> false. string_to_subscription(<<"subscribed">>) -> subscribed; string_to_subscription(<<"pending">>) -> pending; -string_to_subscription(<<"unconfigured">>) -> - unconfigured; +string_to_subscription(<<"unconfigured">>) -> unconfigured; string_to_subscription(<<"none">>) -> none; string_to_subscription(_) -> false. @@ -4158,157 +3098,170 @@ subscription_to_string(unconfigured) -> <<"unconfigured">>; subscription_to_string(_) -> <<"none">>. -spec(service_jid/1 :: -( - Host :: mod_pubsub:host()) + ( + Host :: mod_pubsub:host()) -> jid() -). + ). service_jid(Host) -> case Host of - {U, S, _} -> {jid, U, S, <<"">>, U, S, <<"">>}; - _ -> {jid, <<"">>, Host, <<"">>, <<"">>, Host, <<"">>} + {U, S, _} -> {jid, U, S, <<>>, U, S, <<>>}; + _ -> {jid, <<>>, Host, <<>>, <<>>, Host, <<>>} end. %% @spec (LJID, NotifyType, Depth, NodeOptions, SubOptions) -> boolean() -%% LJID = jid() -%% NotifyType = items | nodes -%% Depth = integer() -%% NodeOptions = [{atom(), term()}] -%% SubOptions = [{atom(), term()}] +%% LJID = jid() +%% NotifyType = items | nodes +%% Depth = integer() +%% NodeOptions = [{atom(), term()}] +%% SubOptions = [{atom(), term()}] %% @doc

    Check if a notification must be delivered or not based on %% node and subscription options.

    -is_to_deliver(LJID, NotifyType, Depth, NodeOptions, - SubOptions) -> +is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) -> sub_to_deliver(LJID, NotifyType, Depth, SubOptions) - andalso node_to_deliver(LJID, NodeOptions). + andalso node_to_deliver(LJID, NodeOptions). sub_to_deliver(_LJID, NotifyType, Depth, SubOptions) -> lists:all(fun (Option) -> - sub_option_can_deliver(NotifyType, Depth, Option) - end, - SubOptions). + sub_option_can_deliver(NotifyType, Depth, Option) + end, + SubOptions). + +node_to_deliver(LJID, NodeOptions) -> + presence_can_deliver(LJID, get_option(NodeOptions, presence_based_delivery)). sub_option_can_deliver(items, _, {subscription_type, nodes}) -> false; sub_option_can_deliver(nodes, _, {subscription_type, items}) -> false; -sub_option_can_deliver(_, _, {subscription_depth, all}) -> true; -sub_option_can_deliver(_, Depth, {subscription_depth, D}) -> Depth =< D; -sub_option_can_deliver(_, _, {deliver, false}) -> false; -sub_option_can_deliver(_, _, {expire, When}) -> now() < When; -sub_option_can_deliver(_, _, _) -> true. - -node_to_deliver(LJID, NodeOptions) -> - PresenceDelivery = get_option(NodeOptions, presence_based_delivery), - presence_can_deliver(LJID, PresenceDelivery). +sub_option_can_deliver(_, _, {subscription_depth, all}) -> true; +sub_option_can_deliver(_, Depth, {subscription_depth, D}) -> Depth =< D; +sub_option_can_deliver(_, _, {deliver, false}) -> false; +sub_option_can_deliver(_, _, {expire, When}) -> now() < When; +sub_option_can_deliver(_, _, _) -> true. -spec(presence_can_deliver/2 :: -( - Entity :: ljid(), - _ :: boolean()) + ( + Entity :: ljid(), + _ :: boolean()) -> boolean() -). -presence_can_deliver(_, false) -> true; + ). +presence_can_deliver(_, false) -> + true; presence_can_deliver({User, Server, Resource}, true) -> case mnesia:dirty_match_object({session, '_', '_', {User, Server}, '_', '_'}) of - [] -> false; - Ss -> - lists:foldl(fun(_, true) -> true; - ({session, _, _ , _, undefined, _}, _Acc) -> false; - ({session, _, {_, _, R}, _, _Priority, _}, _Acc) -> - case Resource of - <<>> -> true; - R -> true; - _ -> false - end - end, false, Ss) + [] -> + false; + Ss -> + lists:foldl(fun + (_, true) -> + true; + ({session, _, _, _, undefined, _}, _Acc) -> + false; + ({session, {_, _, R}, _, _, _Priority, _}, _Acc) -> + case Resource of + <<>> -> true; + R -> true; + _ -> false + end + end, + false, Ss) end. -spec(state_can_deliver/2 :: -( - Entity::ljid(), - SubOptions :: mod_pubsub:subOptions() | []) + ( + Entity::ljid(), + SubOptions :: mod_pubsub:subOptions() | []) -> [ljid()] -). + ). state_can_deliver({U, S, R}, []) -> [{U, S, R}]; state_can_deliver({U, S, R}, SubOptions) -> - %% Check SubOptions for 'show_values' - case lists:keysearch('show_values', 1, SubOptions) of - %% If not in suboptions, item can be delivered, case doesn't apply - false -> [{U, S, R}]; - %% If in a suboptions ... - {_, {_, ShowValues}} -> - %% Get subscriber resources - Resources = case R of - %% If the subscriber JID is a bare one, get all its resources - <<>> -> user_resources(U, S); - %% If the subscriber JID is a full one, use its resource - R -> [R] - end, - %% For each resource, test if the item is allowed to be delivered - %% based on resource state - lists:foldl( - fun(Resource, Acc) -> - get_resource_state({U, S, Resource}, ShowValues, Acc) - end, [], Resources) + case lists:keysearch(show_values, 1, SubOptions) of + %% If not in suboptions, item can be delivered, case doesn't apply + false -> [{U, S, R}]; + %% If in a suboptions ... + {_, {_, ShowValues}} -> + Resources = case R of + %% If the subscriber JID is a bare one, get all its resources + <<>> -> user_resources(U, S); + %% If the subscriber JID is a full one, use its resource + R -> [R] + end, + lists:foldl(fun (Resource, Acc) -> + get_resource_state({U, S, Resource}, ShowValues, Acc) + end, + [], Resources) end. -spec(get_resource_state/3 :: -( - Entity :: ljid(), - ShowValues :: [binary()], - JIDs :: [ljid()]) + ( + Entity :: ljid(), + ShowValues :: [binary()], + JIDs :: [ljid()]) -> [ljid()] -). + ). get_resource_state({U, S, R}, ShowValues, JIDs) -> case ejabberd_sm:get_session_pid(U, S, R) of - %% If no PID, item can be delivered - none -> lists:append([{U, S, R}], JIDs); - %% If PID ... - Pid -> - %% Get user resource state - %% TODO : add a catch clause - Show = case ejabberd_c2s:get_presence(Pid) of - {_, _, <<"available">>, _} -> <<"online">>; - {_, _, State, _} -> State - end, - %% Is current resource state listed in 'show-values' suboption ? - case lists:member(Show, ShowValues) of %andalso Show =/= "online" of - %% If yes, item can be delivered - true -> lists:append([{U, S, R}], JIDs); - %% If no, item can't be delivered - false -> JIDs - end + none -> + %% If no PID, item can be delivered + lists:append([{U, S, R}], JIDs); + Pid -> + Show = case ejabberd_c2s:get_presence(Pid) of + {_, _, <<"available">>, _} -> <<"online">>; + {_, _, State, _} -> State + end, + case lists:member(Show, ShowValues) of + %% If yes, item can be delivered + true -> lists:append([{U, S, R}], JIDs); + %% If no, item can't be delivered + false -> JIDs + end end. -spec(payload_xmlelements/1 :: -( - Payload :: mod_pubsub:payload()) + ( + Payload :: mod_pubsub:payload()) -> Count :: non_neg_integer() -). -%% @spec (Payload) -> int() -%% Payload = term() -%% @doc

    Count occurence of XML elements in payload.

    -payload_xmlelements(Payload) -> payload_xmlelements(Payload, 0). + ). +payload_xmlelements(Payload) -> + payload_xmlelements(Payload, 0). + payload_xmlelements([], Count) -> Count; payload_xmlelements([#xmlel{} | Tail], Count) -> payload_xmlelements(Tail, Count + 1); payload_xmlelements([_ | Tail], Count) -> payload_xmlelements(Tail, Count). -%% @spec (Els) -> stanza() -%% Els = [xmlelement()] -%% @doc

    Build pubsub event stanza

    +items_event_stanza(Node, Items) -> + MoreEls = case Items of + [LastItem] -> + {ModifNow, ModifUSR} = LastItem#pubsub_item.modification, + DateTime = calendar:now_to_datetime(ModifNow), + {T_string, Tz_string} = jlib:timestamp_to_iso(DateTime, utc), + [#xmlel{name = <<"delay">>, attrs = [{<<"xmlns">>, ?NS_DELAY}, + {<<"from">>, jlib:jid_to_string(ModifUSR)}, + {<<"stamp">>, <>}], + children = [{xmlcdata, <<>>}]}]; + _ -> + [] + end, + event_stanza_with_els([#xmlel{name = <<"items">>, + attrs = [{<<"type">>, <<"headline">>} | nodeAttr(Node)], + children = itemsEls(Items)}], + MoreEls). + event_stanza(Els) -> + event_stanza_with_els(Els, []). +event_stanza_with_els(Els, MoreEls) -> #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"event">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}], - children = Els}]}. + children = [#xmlel{name = <<"event">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}], + children = Els} + | MoreEls]}. -event_stanza_with_delay(Els, ModifNow, ModifUSR) -> - jlib:add_delay_info(event_stanza(Els), ModifUSR, ModifNow). +event_stanza(Event, EvAttr) -> + event_stanza_with_els([#xmlel{name = Event, attrs = EvAttr}], []). %%%%%% broadcast functions -broadcast_publish_item(Host, Node, NodeId, Type, NodeOptions, Removed, ItemId, From, Payload) -> +broadcast_publish_item(Host, Node, Nidx, Type, NodeOptions, ItemId, From, Payload, Removed) -> case get_collection_subscriptions(Host, Node) of SubsByDepth when is_list(SubsByDepth) -> Content = case get_option(NodeOptions, deliver_payloads) of @@ -4316,11 +3269,11 @@ broadcast_publish_item(Host, Node, NodeId, Type, NodeOptions, Removed, ItemId, F false -> [] end, Stanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), - children = Content}]}]), - broadcast_stanza(Host, From, Node, NodeId, Type, - NodeOptions, SubsByDepth, items, Stanza, true), + [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), + children = [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), + children = Content}]}]), + broadcast_stanza(Host, From, Node, Nidx, Type, + NodeOptions, SubsByDepth, items, Stanza, true), case Removed of [] -> ok; @@ -4328,11 +3281,11 @@ broadcast_publish_item(Host, Node, NodeId, Type, NodeOptions, Removed, ItemId, F case get_option(NodeOptions, notify_retract) of true -> RetractStanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"retract">>, attrs = itemAttr(RId)} || RId <- Removed]}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, - items, RetractStanza, true); + [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), + children = [#xmlel{name = <<"retract">>, attrs = itemAttr(RId)} || RId <- Removed]}]), + broadcast_stanza(Host, Node, Nidx, Type, + NodeOptions, SubsByDepth, + items, RetractStanza, true); _ -> ok end @@ -4342,20 +3295,20 @@ broadcast_publish_item(Host, Node, NodeId, Type, NodeOptions, Removed, ItemId, F {result, false} end. -broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds) -> - broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds, false). -broadcast_retract_items(_Host, _Node, _NodeId, _Type, _NodeOptions, [], _ForceNotify) -> +broadcast_retract_items(Host, Node, Nidx, Type, NodeOptions, ItemIds) -> + broadcast_retract_items(Host, Node, Nidx, Type, NodeOptions, ItemIds, false). +broadcast_retract_items(_Host, _Node, _Nidx, _Type, _NodeOptions, [], _ForceNotify) -> {result, false}; -broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds, ForceNotify) -> +broadcast_retract_items(Host, Node, Nidx, Type, NodeOptions, ItemIds, ForceNotify) -> case (get_option(NodeOptions, notify_retract) or ForceNotify) of true -> case get_collection_subscriptions(Host, Node) of SubsByDepth when is_list(SubsByDepth) -> Stanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"retract">>, attrs = itemAttr(ItemId)} || ItemId <- ItemIds]}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, items, Stanza, true), + [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), + children = [#xmlel{name = <<"retract">>, attrs = itemAttr(ItemId)} || ItemId <- ItemIds]}]), + broadcast_stanza(Host, Node, Nidx, Type, + NodeOptions, SubsByDepth, items, Stanza, true), {result, true}; _ -> {result, false} @@ -4364,15 +3317,15 @@ broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds, ForceNot {result, false} end. -broadcast_purge_node(Host, Node, NodeId, Type, NodeOptions) -> +broadcast_purge_node(Host, Node, Nidx, Type, NodeOptions) -> case get_option(NodeOptions, notify_retract) of true -> case get_collection_subscriptions(Host, Node) of SubsByDepth when is_list(SubsByDepth) -> Stanza = event_stanza( - [#xmlel{name = <<"purge">>, attrs = nodeAttr(Node)}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, nodes, Stanza, false), + [#xmlel{name = <<"purge">>, attrs = nodeAttr(Node)}]), + broadcast_stanza(Host, Node, Nidx, Type, + NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true}; _ -> {result, false} @@ -4381,7 +3334,7 @@ broadcast_purge_node(Host, Node, NodeId, Type, NodeOptions) -> {result, false} end. -broadcast_removed_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth) -> +broadcast_removed_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth) -> case get_option(NodeOptions, notify_delete) of true -> case SubsByDepth of @@ -4389,9 +3342,9 @@ broadcast_removed_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth) -> {result, false}; _ -> Stanza = event_stanza( - [#xmlel{name = <<"delete">>, attrs = nodeAttr(Node)}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, nodes, Stanza, false), + [#xmlel{name = <<"delete">>, attrs = nodeAttr(Node)}]), + broadcast_stanza(Host, Node, Nidx, Type, + NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true} end; _ -> @@ -4400,12 +3353,12 @@ broadcast_removed_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth) -> broadcast_created_node(_, _, _, _, _, []) -> {result, false}; -broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth) -> +broadcast_created_node(Host, Node, Nidx, Type, NodeOptions, SubsByDepth) -> Stanza = event_stanza([#xmlel{name = <<"create">>, attrs = nodeAttr(Node)}]), - broadcast_stanza(Host, Node, NodeId, Type, NodeOptions, SubsByDepth, nodes, Stanza, true), + broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, nodes, Stanza, true), {result, true}. -broadcast_config_notification(Host, Node, NodeId, Type, NodeOptions, Lang) -> +broadcast_config_notification(Host, Node, Nidx, Type, NodeOptions, Lang) -> case get_option(NodeOptions, notify_config) of true -> case get_collection_subscriptions(Host, Node) of @@ -4418,9 +3371,9 @@ broadcast_config_notification(Host, Node, NodeId, Type, NodeOptions, Lang) -> [] end, Stanza = event_stanza( - [#xmlel{name = <<"configuration">>, attrs = nodeAttr(Node), children = Content}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, nodes, Stanza, false), + [#xmlel{name = <<"configuration">>, attrs = nodeAttr(Node), children = Content}]), + broadcast_stanza(Host, Node, Nidx, Type, + NodeOptions, SubsByDepth, nodes, Stanza, false), {result, true}; _ -> {result, false} @@ -4431,34 +3384,35 @@ broadcast_config_notification(Host, Node, NodeId, Type, NodeOptions, Lang) -> get_collection_subscriptions(Host, Node) -> Action = fun() -> - {result, lists:map(fun({Depth, Nodes}) -> - {Depth, [{N, get_node_subs(N)} || N <- Nodes]} - end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))} - end, - case transaction(Action, sync_dirty) of + {result, get_node_subs_by_depth(Host, Node, service_jid(Host))} + end, + case transaction(Host, Action, sync_dirty) of {result, CollSubs} -> CollSubs; _ -> [] end. -get_node_subs(#pubsub_node{type = Type, - id = NodeID}) -> - case node_call(Type, get_node_subscriptions, [NodeID]) of - {result, Subs} -> get_options_for_subs(NodeID, Subs); +get_node_subs_by_depth(Host, Node, From) -> + ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, From]), + [{Depth, [{N, get_node_subs(Host, N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree]. + +get_node_subs(Host, #pubsub_node{type = Type, id = Nidx}) -> + case node_call(Host, Type, get_node_subscriptions, [Nidx]) of + {result, Subs} -> get_options_for_subs(Host, Nidx, Subs); Other -> Other end. -get_options_for_subs(NodeID, Subs) -> +get_options_for_subs(Host, Nidx, Subs) -> + SubModule = subscription_plugin(Host), lists:foldl(fun({JID, subscribed, SubID}, Acc) -> - case pubsub_subscription:read_subscription(JID, NodeID, SubID) of - {error, notfound} -> [{JID, SubID, []} | Acc]; - #pubsub_subscription{options = Options} -> [{JID, SubID, Options} | Acc]; - _ -> Acc - end; - (_, Acc) -> - Acc - end, [], Subs). + case SubModule:get_subscription(JID, Nidx, SubID) of + #pubsub_subscription{options = Options} -> [{JID, SubID, Options} | Acc]; + {error, notfound} -> [{JID, SubID, []} | Acc] + end; + (_, Acc) -> + Acc + end, [], Subs). -broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> +broadcast_stanza(Host, _Node, _Nidx, _Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> NotificationType = get_option(NodeOptions, notification_type, headline), BroadcastAll = get_option(NodeOptions, broadcast_all_resources), %% XXX this is not standard, but usefull From = service_jid(Host), @@ -4466,30 +3420,30 @@ broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyTy %% Handles explicit subscriptions SubIDsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), lists:foreach(fun ({LJID, NodeName, SubIDs}) -> - LJIDs = case BroadcastAll of - true -> - {U, S, _} = LJID, - [{U, S, R} || R <- user_resources(U, S)]; - false -> - [LJID] - end, - %% Determine if the stanza should have SHIM ('SubID' and 'name') headers - StanzaToSend = case {SHIM, SubIDs} of - {false, _} -> - Stanza; - %% If there's only one SubID, don't add it - {true, [_]} -> - add_shim_headers(Stanza, collection_shim(NodeName)); - {true, SubIDs} -> - add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIDs))) - end, - lists:foreach(fun(To) -> - ejabberd_router:route(From, jlib:make_jid(To), StanzaToSend) - end, LJIDs) - end, SubIDsByJID). - -broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> - broadcast_stanza({LUser, LServer, LResource}, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM), + LJIDs = case BroadcastAll of + true -> + {U, S, _} = LJID, + [{U, S, R} || R <- user_resources(U, S)]; + false -> + [LJID] + end, + %% Determine if the stanza should have SHIM ('SubID' and 'name') headers + StanzaToSend = case {SHIM, SubIDs} of + {false, _} -> + Stanza; + %% If there's only one SubID, don't add it + {true, [_]} -> + add_shim_headers(Stanza, collection_shim(NodeName)); + {true, SubIDs} -> + add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIDs))) + end, + lists:foreach(fun(To) -> + ejabberd_router:route(From, jlib:make_jid(To), StanzaToSend) + end, LJIDs) + end, SubIDsByJID). + +broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, Nidx, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> + broadcast_stanza({LUser, LServer, LResource}, Node, Nidx, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM), %% Handles implicit presence subscriptions SenderResource = user_resource(LUser, LServer, LResource), case ejabberd_sm:get_session_pid(LUser, LServer, SenderResource) of @@ -4500,66 +3454,66 @@ broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, NodeId, Type, Nod %% Also, add "replyto" if entity has presence subscription to the account owner %% See XEP-0163 1.1 section 4.3.1 ejabberd_c2s:broadcast(C2SPid, - {pep_message, <<((Node))/binary, "+notify">>}, - _Sender = jlib:make_jid(LUser, LServer, <<"">>), - _StanzaToSend = add_extended_headers(Stanza, - _ReplyTo = extended_headers([jlib:jid_to_string(Publisher)]))); + {pep_message, <<((Node))/binary, "+notify">>}, + _Sender = jlib:make_jid(LUser, LServer, <<"">>), + _StanzaToSend = add_extended_headers(Stanza, + _ReplyTo = extended_headers([jlib:jid_to_string(Publisher)]))); _ -> ?DEBUG("~p@~p has no session; can't deliver ~p to contacts", [LUser, LServer, BaseStanza]) end; -broadcast_stanza(Host, _Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> - broadcast_stanza(Host, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM). +broadcast_stanza(Host, _Publisher, Node, Nidx, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> + broadcast_stanza(Host, Node, Nidx, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM). subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> - NodesToDeliver = fun(Depth, Node, Subs, Acc) -> + NodesToDeliver = fun (Depth, Node, Subs, Acc) -> NodeName = case Node#pubsub_node.nodeid of {_, N} -> N; Other -> Other end, NodeOptions = Node#pubsub_node.options, lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) -> - case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of - true -> - %% If is to deliver : - case state_can_deliver(LJID, SubOptions) of - [] -> {JIDs, Recipients}; - JIDsToDeliver -> - lists:foldl( - fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) -> - case lists:member(JIDToDeliver, JIDs) of - %% check if the JIDs co-accumulator contains the Subscription Jid, - false -> - %% - if not, - %% - add the Jid to JIDs list co-accumulator ; - %% - create a tuple of the Jid, NodeId, and SubID (as list), - %% and add the tuple to the Recipients list co-accumulator - {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubID]} | RecipientsAcc]}; - true -> - %% - if the JIDs co-accumulator contains the Jid - %% get the tuple containing the Jid from the Recipient list co-accumulator - {_, {JIDToDeliver, NodeName1, SubIDs}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), - %% delete the tuple from the Recipients list - % v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients), - % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, NodeId1, [SubID | SubIDs]}), - %% add the SubID to the SubIDs list in the tuple, - %% and add the tuple back to the Recipients list co-accumulator - % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, NodeId1, lists:append(SubIDs, [SubID])}])} - % v1.2 : {JIDs, [{LJID, NodeId1, [SubID | SubIDs]} | Recipients1]} - % v2: {JIDs, Recipients1} - {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubID | SubIDs]})} - end - end, {JIDs, Recipients}, JIDsToDeliver) - end; - false -> - {JIDs, Recipients} - end - end, Acc, Subs) - end, + case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of + true -> + %% If is to deliver : + case state_can_deliver(LJID, SubOptions) of + [] -> {JIDs, Recipients}; + JIDsToDeliver -> + lists:foldl( + fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) -> + case lists:member(JIDToDeliver, JIDs) of + %% check if the JIDs co-accumulator contains the Subscription Jid, + false -> + %% - if not, + %% - add the Jid to JIDs list co-accumulator ; + %% - create a tuple of the Jid, Nidx, and SubID (as list), + %% and add the tuple to the Recipients list co-accumulator + {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubID]} | RecipientsAcc]}; + true -> + %% - if the JIDs co-accumulator contains the Jid + %% get the tuple containing the Jid from the Recipient list co-accumulator + {_, {JIDToDeliver, NodeName1, SubIDs}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), + %% delete the tuple from the Recipients list + % v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients), + % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, Nidx1, [SubID | SubIDs]}), + %% add the SubID to the SubIDs list in the tuple, + %% and add the tuple back to the Recipients list co-accumulator + % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, Nidx1, lists:append(SubIDs, [SubID])}])} + % v1.2 : {JIDs, [{LJID, Nidx1, [SubID | SubIDs]} | Recipients1]} + % v2: {JIDs, Recipients1} + {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubID | SubIDs]})} + end + end, {JIDs, Recipients}, JIDsToDeliver) + end; + false -> + {JIDs, Recipients} + end + end, Acc, Subs) + end, DepthsToDeliver = fun({Depth, SubsByNode}, Acc1) -> lists:foldl(fun({Node, Subs}, Acc2) -> - NodesToDeliver(Depth, Node, Subs, Acc2) - end, Acc1, SubsByNode) - end, + NodesToDeliver(Depth, Node, Subs, Acc2) + end, Acc1, SubsByNode) + end, {_, JIDSubs} = lists:foldl(DepthsToDeliver, {[], []}, SubsByDepth), JIDSubs. @@ -4571,97 +3525,108 @@ user_resource(User, Server, <<>>) -> [R | _] -> R; _ -> <<>> end; -user_resource(_, _, Resource) -> Resource. +user_resource(_, _, Resource) -> + Resource. %%%%%%% Configuration handling -%%

    There are several reasons why the default node configuration options request might fail:

    -%%
      -%%
    • The service does not support node configuration.
    • -%%
    • The service does not support retrieval of default node configuration.
    • -%%
    get_configure(Host, ServerHost, Node, From, Lang) -> - Action = fun (#pubsub_node{options = Options, - type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, From]) of - {result, owner} -> - Groups = ejabberd_hooks:run_fold(roster_groups, - ServerHost, [], - [ServerHost]), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"configure">>, - attrs = nodeAttr(Node), + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx}) -> + case node_call(Host, Type, get_affiliation, [Nidx, From]) of + {result, owner} -> + Groups = ejabberd_hooks:run_fold(roster_groups, ServerHost, [], [ServerHost]), + {result, + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], + children = + [#xmlel{name = <<"configure">>, + attrs = nodeAttr(Node), + children = + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"form">>}], children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, - ?NS_XDATA}, - {<<"type">>, - <<"form">>}], - children = - get_configure_xfields(Type, - Options, - Lang, - Groups)}]}]}]}; - _ -> {error, ?ERR_FORBIDDEN} - end - end, + get_configure_xfields(Type, Options, Lang, Groups)}]}]}]}; + _ -> + {error, ?ERR_FORBIDDEN} + end + end, case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other + {result, {_, Result}} -> {result, Result}; + Other -> Other end. get_default(Host, Node, _From, Lang) -> Type = select_type(Host, Host, Node), - Options = node_options(Type), -%% Get node option -%% The result depend of the node type plugin system. + Options = node_options(Host, Type), {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"default">>, attrs = [], - children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - get_configure_xfields(Type, Options, - Lang, [])}]}]}]}. + [#xmlel{name = <<"pubsub">>, + attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], + children = + [#xmlel{name = <<"default">>, attrs = [], + children = + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"form">>}], + children = get_configure_xfields(Type, Options, Lang, [])}]}]}]}. + +match_option(Node, Var, Val) when is_record(Node, pubsub_node) -> + match_option(Node#pubsub_node.options, Var, Val); +match_option(Options, Var, Val) when is_list(Options) -> + get_option(Options, Var) == Val; +match_option(_, _, _) -> + false. get_option([], _) -> false; -get_option(Options, Var) -> - get_option(Options, Var, false). +get_option(Options, Var) -> get_option(Options, Var, false). get_option(Options, Var, Def) -> case lists:keysearch(Var, 1, Options) of - {value, {_Val, Ret}} -> Ret; - _ -> Def + {value, {_Val, Ret}} -> Ret; + _ -> Def end. -%% Get default options from the module plugin. -node_options(Type) -> - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary>>), +node_options(Host, Type) -> + Module = plugin(Host, Type), case catch Module:options() of - {'EXIT', {undef, _}} -> - DefaultModule = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - (?STDNODE)/binary>>), - DefaultModule:options(); - Result -> Result + {'EXIT', {undef, _}} -> + DefaultModule = plugin(Host, ?STDNODE), + DefaultModule:options(); + Result -> + Result end. +node_owners_action(Host, Type, Nidx, []) -> + case gen_mod:db_type(serverhost(Host), ?MODULE) of + odbc -> + case node_action(Host, Type, get_node_affiliations, [Nidx]) of + {result, Affs} -> [LJID || {LJID, Aff} <- Affs, Aff =:= owner]; + _ -> [] + end; + _ -> + [] + end; +node_owners_action(_Host, _Type, _Nidx, Owners) -> + Owners. + +node_owners_call(Host, Type, Nidx, []) -> + case gen_mod:db_type(serverhost(Host), ?MODULE) of + odbc -> + case node_call(Host, Type, get_node_affiliations, [Nidx]) of + {result, Affs} -> [LJID || {LJID, Aff} <- Affs, Aff =:= owner]; + _ -> [] + end; + _ -> + [] + end; +node_owners_call(_Host, _Type, _Nidx, Owners) -> + Owners. + %% @spec (Host, Options) -> MaxItems -%% Host = host() -%% Options = [Option] -%% Option = {Key::atom(), Value::term()} -%% MaxItems = integer() | unlimited +%% Host = host() +%% Options = [Option] +%% Option = {Key::atom(), Value::term()} +%% MaxItems = integer() | unlimited %% @doc

    Return the maximum number of items for a given node.

    %%

    Unlimited means that there is no limit in the number of items that can %% be stored.

    @@ -4670,116 +3635,99 @@ node_options(Type) -> %% version. max_items(Host, Options) -> case get_option(Options, persist_items) of - true -> - case get_option(Options, max_items) of - false -> unlimited; - Result when Result < 0 -> 0; - Result -> Result - end; - false -> - case get_option(Options, send_last_published_item) of - never -> 0; - _ -> - case is_last_item_cache_enabled(Host) of - true -> 0; - false -> 1 - end - end + true -> + case get_option(Options, max_items) of + false -> unlimited; + Result when Result < 0 -> 0; + Result -> Result + end; + false -> + case get_option(Options, send_last_published_item) of + never -> + 0; + _ -> + case is_last_item_cache_enabled(Host) of + true -> 0; + false -> 1 + end + end end. -define(BOOL_CONFIG_FIELD(Label, Var), - ?BOOLXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (get_option(Options, Var)))). + ?BOOLXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (get_option(Options, Var)))). -define(STRING_CONFIG_FIELD(Label, Var), - ?STRINGXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (get_option(Options, Var, <<"">>)))). + ?STRINGXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (get_option(Options, Var, <<>>)))). -define(INTEGER_CONFIG_FIELD(Label, Var), - ?STRINGXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (iolist_to_binary(integer_to_list(get_option(Options, - Var)))))). + ?STRINGXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (integer_to_binary(get_option(Options, Var))))). -define(JLIST_CONFIG_FIELD(Label, Var, Opts), - ?LISTXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (jlib:jid_to_string(get_option(Options, Var))), - [jlib:jid_to_string(O) || O <- Opts])). + ?LISTXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (jlib:jid_to_string(get_option(Options, Var))), + [jlib:jid_to_string(O) || O <- Opts])). -define(ALIST_CONFIG_FIELD(Label, Var, Opts), - ?LISTXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (iolist_to_binary(atom_to_list(get_option(Options, - Var)))), - [iolist_to_binary(atom_to_list(O)) || O <- Opts])). + ?LISTXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (atom_to_binary(get_option(Options, Var), latin1)), + [atom_to_binary(O, latin1) || O <- Opts])). -define(LISTM_CONFIG_FIELD(Label, Var, Opts), - ?LISTMXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (get_option(Options, Var)), Opts)). + ?LISTMXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + (get_option(Options, Var)), Opts)). -define(NLIST_CONFIG_FIELD(Label, Var), - ?STRINGMXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - get_option(Options, Var, []))). + ?STRINGMXFIELD(Label, + <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, + get_option(Options, Var, []))). get_configure_xfields(_Type, Options, Lang, Groups) -> - [?XFIELD(<<"hidden">>, <<"">>, <<"FORM_TYPE">>, - (?NS_PUBSUB_NODE_CONFIG)), - ?BOOL_CONFIG_FIELD(<<"Deliver payloads with event notifications">>, - deliver_payloads), - ?BOOL_CONFIG_FIELD(<<"Deliver event notifications">>, - deliver_notifications), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node configuratio" - "n changes">>, - notify_config), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node is " - "deleted">>, - notify_delete), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when items are removed " - "from the node">>, - notify_retract), - ?BOOL_CONFIG_FIELD(<<"Persist items to storage">>, - persist_items), - ?STRING_CONFIG_FIELD(<<"A friendly name for the node">>, - title), - ?INTEGER_CONFIG_FIELD(<<"Max # of items to persist">>, - max_items), - ?BOOL_CONFIG_FIELD(<<"Whether to allow subscriptions">>, - subscribe), - ?ALIST_CONFIG_FIELD(<<"Specify the access model">>, - access_model, - [open, authorize, presence, roster, whitelist]), - ?LISTM_CONFIG_FIELD(<<"Roster groups allowed to subscribe">>, - roster_groups_allowed, Groups), - ?ALIST_CONFIG_FIELD(<<"Specify the publisher model">>, - publish_model, [publishers, subscribers, open]), - ?BOOL_CONFIG_FIELD(<<"Purge all items when the relevant publisher " - "goes offline">>, - purge_offline), - ?ALIST_CONFIG_FIELD(<<"Specify the event message type">>, - notification_type, [headline, normal]), - ?INTEGER_CONFIG_FIELD(<<"Max payload size in bytes">>, - max_payload_size), - ?ALIST_CONFIG_FIELD(<<"When to send the last published item">>, - send_last_published_item, - [never, on_sub, on_sub_and_presence]), - ?BOOL_CONFIG_FIELD(<<"Only deliver notifications to available " - "users">>, - presence_based_delivery), - ?NLIST_CONFIG_FIELD(<<"The collections with which a node is " - "affiliated">>, - collection)]. + [?XFIELD(<<"hidden">>, <<>>, <<"FORM_TYPE">>, (?NS_PUBSUB_NODE_CONFIG)), + ?BOOL_CONFIG_FIELD(<<"Deliver payloads with event notifications">>, + deliver_payloads), + ?BOOL_CONFIG_FIELD(<<"Deliver event notifications">>, + deliver_notifications), + ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node configuration changes">>, + notify_config), + ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node is deleted">>, + notify_delete), + ?BOOL_CONFIG_FIELD(<<"Notify subscribers when items are removed from the node">>, + notify_retract), + ?BOOL_CONFIG_FIELD(<<"Persist items to storage">>, + persist_items), + ?STRING_CONFIG_FIELD(<<"A friendly name for the node">>, + title), + ?INTEGER_CONFIG_FIELD(<<"Max # of items to persist">>, + max_items), + ?BOOL_CONFIG_FIELD(<<"Whether to allow subscriptions">>, + subscribe), + ?ALIST_CONFIG_FIELD(<<"Specify the access model">>, + access_model, [open, authorize, presence, roster, whitelist]), + ?LISTM_CONFIG_FIELD(<<"Roster groups allowed to subscribe">>, + roster_groups_allowed, Groups), + ?ALIST_CONFIG_FIELD(<<"Specify the publisher model">>, + publish_model, [publishers, subscribers, open]), + ?BOOL_CONFIG_FIELD(<<"Purge all items when the relevant publisher goes offline">>, + purge_offline), + ?ALIST_CONFIG_FIELD(<<"Specify the event message type">>, + notification_type, [headline, normal]), + ?INTEGER_CONFIG_FIELD(<<"Max payload size in bytes">>, + max_payload_size), + ?ALIST_CONFIG_FIELD(<<"When to send the last published item">>, + send_last_published_item, [never, on_sub, on_sub_and_presence]), + ?BOOL_CONFIG_FIELD(<<"Only deliver notifications to available users">>, + presence_based_delivery), + ?NLIST_CONFIG_FIELD(<<"The collections with which a node is affiliated">>, + collection)]. %%

    There are several reasons why the node configuration request might fail:

    %%
      @@ -4791,193 +3739,143 @@ get_configure_xfields(_Type, Options, Lang, Groups) -> %%
    set_configure(Host, Node, From, Els, Lang) -> case xml:remove_cdata(Els) of - [#xmlel{name = <<"x">>} = XEl] -> - case {xml:get_tag_attr_s(<<"xmlns">>, XEl), - xml:get_tag_attr_s(<<"type">>, XEl)} - of - {?NS_XDATA, <<"cancel">>} -> {result, []}; - {?NS_XDATA, <<"submit">>} -> - Action = fun (#pubsub_node{options = Options, - type = Type, id = NodeId} = - N) -> - case node_call(Type, get_affiliation, - [NodeId, From]) - of - {result, owner} -> - case jlib:parse_xdata_submit(XEl) of - invalid -> {error, ?ERR_BAD_REQUEST}; - XData -> - OldOpts = case Options of - [] -> - node_options(Type); - _ -> Options - end, - case set_xoption(Host, XData, - OldOpts) - of - NewOpts - when is_list(NewOpts) -> - case tree_call(Host, - set_node, - [N#pubsub_node{options - = - NewOpts}]) - of - ok -> {result, ok}; - Err -> Err - end; - Err -> Err - end - end; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, transaction) of - {result, {TNode, ok}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_config_notification(Host, Node, NodeId, Type, - Options, Lang), - {result, []}; - Other -> Other - end; - _ -> {error, ?ERR_BAD_REQUEST} - end; - _ -> {error, ?ERR_BAD_REQUEST} + [#xmlel{name = <<"x">>} = XEl] -> + case {xml:get_tag_attr_s(<<"xmlns">>, XEl), xml:get_tag_attr_s(<<"type">>, XEl)} of + {?NS_XDATA, <<"cancel">>} -> + {result, []}; + {?NS_XDATA, <<"submit">>} -> + Action = fun (#pubsub_node{options = Options, type = Type, id = Nidx} = N) -> + case node_call(Host, Type, get_affiliation, [Nidx, From]) of + {result, owner} -> + case jlib:parse_xdata_submit(XEl) of + invalid -> + {error, ?ERR_BAD_REQUEST}; + XData -> + OldOpts = case Options of + [] -> node_options(Host, Type); + _ -> Options + end, + case set_xoption(Host, XData, OldOpts) of + NewOpts when is_list(NewOpts) -> + case tree_call(Host, + set_node, + [N#pubsub_node{options = NewOpts}]) + of + ok -> {result, ok}; + Err -> Err + end; + Error -> + Error + end + end; + _ -> + {error, ?ERR_FORBIDDEN} + end + end, + case transaction(Host, Node, Action, transaction) of + {result, {TNode, ok}} -> + Nidx = TNode#pubsub_node.id, + Type = TNode#pubsub_node.type, + Options = TNode#pubsub_node.options, + broadcast_config_notification(Host, Node, Nidx, Type, Options, Lang), + {result, []}; + Other -> + Other + end; + _ -> + {error, ?ERR_BAD_REQUEST} + end; + _ -> + {error, ?ERR_BAD_REQUEST} end. add_opt(Key, Value, Opts) -> - Opts1 = lists:keydelete(Key, 1, Opts), - [{Key, Value} | Opts1]. + [{Key, Value} | lists:keydelete(Key, 1, Opts)]. -define(SET_BOOL_XOPT(Opt, Val), - BoolVal = case Val of - <<"0">> -> false; - <<"1">> -> true; - <<"false">> -> false; - <<"true">> -> true; - _ -> error - end, - case BoolVal of - error -> {error, ?ERR_NOT_ACCEPTABLE}; - _ -> - set_xoption(Host, Opts, add_opt(Opt, BoolVal, NewOpts)) - end). + BoolVal = case Val of + <<"0">> -> false; + <<"1">> -> true; + <<"false">> -> false; + <<"true">> -> true; + _ -> error + end, + case BoolVal of + error -> {error, ?ERR_NOT_ACCEPTABLE}; + _ -> set_xoption(Host, Opts, add_opt(Opt, BoolVal, NewOpts)) + end). -define(SET_STRING_XOPT(Opt, Val), - set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). + set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). -define(SET_INTEGER_XOPT(Opt, Val, Min, Max), - case catch jlib:binary_to_integer(Val) of - IVal when is_integer(IVal), IVal >= Min, IVal =< Max -> - set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); - _ -> {error, ?ERR_NOT_ACCEPTABLE} - end). + case catch jlib:binary_to_integer(Val) of + IVal when is_integer(IVal), IVal >= Min, IVal =< Max -> + set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); + _ -> + {error, ?ERR_NOT_ACCEPTABLE} + end). -define(SET_ALIST_XOPT(Opt, Val, Vals), - case lists:member(Val, - [iolist_to_binary(atom_to_list(V)) || V <- Vals]) - of - true -> - set_xoption(Host, Opts, - add_opt(Opt, jlib:binary_to_atom(Val), NewOpts)); - false -> {error, ?ERR_NOT_ACCEPTABLE} - end). + case lists:member(Val, [atom_to_binary(V, latin1) || V <- Vals]) of + true -> + set_xoption(Host, Opts, add_opt(Opt, jlib:binary_to_atom(Val), NewOpts)); + false -> + {error, ?ERR_NOT_ACCEPTABLE} + end). -define(SET_LIST_XOPT(Opt, Val), - set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). + set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). set_xoption(_Host, [], NewOpts) -> NewOpts; -set_xoption(Host, [{<<"FORM_TYPE">>, _} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"FORM_TYPE">>, _} | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts); -set_xoption(Host, - [{<<"pubsub#roster_groups_allowed">>, Value} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#roster_groups_allowed">>, Value} | Opts], NewOpts) -> ?SET_LIST_XOPT(roster_groups_allowed, Value); -set_xoption(Host, - [{<<"pubsub#deliver_payloads">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#deliver_payloads">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(deliver_payloads, Val); -set_xoption(Host, - [{<<"pubsub#deliver_notifications">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#deliver_notifications">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(deliver_notifications, Val); -set_xoption(Host, - [{<<"pubsub#notify_config">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#notify_config">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(notify_config, Val); -set_xoption(Host, - [{<<"pubsub#notify_delete">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#notify_delete">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(notify_delete, Val); -set_xoption(Host, - [{<<"pubsub#notify_retract">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#notify_retract">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(notify_retract, Val); -set_xoption(Host, - [{<<"pubsub#persist_items">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#persist_items">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(persist_items, Val); -set_xoption(Host, - [{<<"pubsub#max_items">>, [Val]} | Opts], NewOpts) -> +set_xoption(Host, [{<<"pubsub#max_items">>, [Val]} | Opts], NewOpts) -> MaxItems = get_max_items_node(Host), ?SET_INTEGER_XOPT(max_items, Val, 0, MaxItems); -set_xoption(Host, - [{<<"pubsub#subscribe">>, [Val]} | Opts], NewOpts) -> +set_xoption(Host, [{<<"pubsub#subscribe">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(subscribe, Val); -set_xoption(Host, - [{<<"pubsub#access_model">>, [Val]} | Opts], NewOpts) -> - ?SET_ALIST_XOPT(access_model, Val, - [open, authorize, presence, roster, whitelist]); -set_xoption(Host, - [{<<"pubsub#publish_model">>, [Val]} | Opts], - NewOpts) -> - ?SET_ALIST_XOPT(publish_model, Val, - [publishers, subscribers, open]); -set_xoption(Host, - [{<<"pubsub#notification_type">>, [Val]} | Opts], - NewOpts) -> - ?SET_ALIST_XOPT(notification_type, Val, - [headline, normal]); -set_xoption(Host, - [{<<"pubsub#node_type">>, [Val]} | Opts], NewOpts) -> +set_xoption(Host, [{<<"pubsub#access_model">>, [Val]} | Opts], NewOpts) -> + ?SET_ALIST_XOPT(access_model, Val, [open, authorize, presence, roster, whitelist]); +set_xoption(Host, [{<<"pubsub#publish_model">>, [Val]} | Opts], NewOpts) -> + ?SET_ALIST_XOPT(publish_model, Val, [publishers, subscribers, open]); +set_xoption(Host, [{<<"pubsub#notification_type">>, [Val]} | Opts], NewOpts) -> + ?SET_ALIST_XOPT(notification_type, Val, [headline, normal]); +set_xoption(Host, [{<<"pubsub#node_type">>, [Val]} | Opts], NewOpts) -> ?SET_ALIST_XOPT(node_type, Val, [leaf, collection]); -set_xoption(Host, - [{<<"pubsub#max_payload_size">>, [Val]} | Opts], - NewOpts) -> - ?SET_INTEGER_XOPT(max_payload_size, Val, 0, - (?MAX_PAYLOAD_SIZE)); -set_xoption(Host, - [{<<"pubsub#send_last_published_item">>, [Val]} | Opts], - NewOpts) -> - ?SET_ALIST_XOPT(send_last_published_item, Val, - [never, on_sub, on_sub_and_presence]); -set_xoption(Host, - [{<<"pubsub#presence_based_delivery">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#max_payload_size">>, [Val]} | Opts], NewOpts) -> + ?SET_INTEGER_XOPT(max_payload_size, Val, 0, (?MAX_PAYLOAD_SIZE)); +set_xoption(Host, [{<<"pubsub#send_last_published_item">>, [Val]} | Opts], NewOpts) -> + ?SET_ALIST_XOPT(send_last_published_item, Val, [never, on_sub, on_sub_and_presence]); +set_xoption(Host, [{<<"pubsub#presence_based_delivery">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(presence_based_delivery, Val); -set_xoption(Host, - [{<<"pubsub#purge_offline">>, [Val]} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#purge_offline">>, [Val]} | Opts], NewOpts) -> ?SET_BOOL_XOPT(purge_offline, Val); -set_xoption(Host, [{<<"pubsub#title">>, Value} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#title">>, Value} | Opts], NewOpts) -> ?SET_STRING_XOPT(title, Value); -set_xoption(Host, [{<<"pubsub#type">>, Value} | Opts], - NewOpts) -> +set_xoption(Host, [{<<"pubsub#type">>, Value} | Opts], NewOpts) -> ?SET_STRING_XOPT(type, Value); -set_xoption(Host, - [{<<"pubsub#body_xslt">>, Value} | Opts], NewOpts) -> +set_xoption(Host, [{<<"pubsub#body_xslt">>, Value} | Opts], NewOpts) -> ?SET_STRING_XOPT(body_xslt, Value); -set_xoption(Host, - [{<<"pubsub#collection">>, Value} | Opts], NewOpts) -> -% NewValue = [string_to_node(V) || V <- Value], +set_xoption(Host, [{<<"pubsub#collection">>, Value} | Opts], NewOpts) -> + % NewValue = [string_to_node(V) || V <- Value], ?SET_LIST_XOPT(collection, Value); -set_xoption(Host, [{<<"pubsub#node">>, [Value]} | Opts], - NewOpts) -> -% NewValue = string_to_node(Value), +set_xoption(Host, [{<<"pubsub#node">>, [Value]} | Opts], NewOpts) -> + % NewValue = string_to_node(Value), ?SET_LIST_XOPT(node, Value); set_xoption(Host, [_ | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts). @@ -4985,164 +3883,180 @@ set_xoption(Host, [_ | Opts], NewOpts) -> get_max_items_node({_, ServerHost, _}) -> get_max_items_node(ServerHost); get_max_items_node(Host) -> - case catch ets:lookup(gen_mod:get_module_proc(Host, - config), - max_items_node) - of - [{max_items_node, Integer}] -> Integer; - _ -> ?MAXITEMS - end. + config(serverhost(Host), max_items_node, ?MAXITEMS). %%%% last item cache handling is_last_item_cache_enabled({_, ServerHost, _}) -> is_last_item_cache_enabled(ServerHost); is_last_item_cache_enabled(Host) -> - case catch ets:lookup(gen_mod:get_module_proc(Host, - config), - last_item_cache) - of - [{last_item_cache, true}] -> true; - _ -> false - end. + config(serverhost(Host), last_item_cache, false). -set_cached_item({_, ServerHost, _}, NodeId, ItemId, - Publisher, Payload) -> - set_cached_item(ServerHost, NodeId, ItemId, Publisher, - Payload); -set_cached_item(Host, NodeId, ItemId, Publisher, - Payload) -> +set_cached_item({_, ServerHost, _}, Nidx, ItemId, Publisher, Payload) -> + set_cached_item(ServerHost, Nidx, ItemId, Publisher, Payload); +set_cached_item(Host, Nidx, ItemId, Publisher, Payload) -> case is_last_item_cache_enabled(Host) of - true -> - mnesia:dirty_write({pubsub_last_item, NodeId, ItemId, - {now(), - jlib:jid_tolower(jlib:jid_remove_resource(Publisher))}, - Payload}); - _ -> ok + true -> mnesia:dirty_write({pubsub_last_item, Nidx, ItemId, + {now(), jlib:jid_tolower(jlib:jid_remove_resource(Publisher))}, + Payload}); + _ -> ok end. -unset_cached_item({_, ServerHost, _}, NodeId) -> - unset_cached_item(ServerHost, NodeId); -unset_cached_item(Host, NodeId) -> +unset_cached_item({_, ServerHost, _}, Nidx) -> + unset_cached_item(ServerHost, Nidx); +unset_cached_item(Host, Nidx) -> case is_last_item_cache_enabled(Host) of - true -> mnesia:dirty_delete({pubsub_last_item, NodeId}); - _ -> ok + true -> mnesia:dirty_delete({pubsub_last_item, Nidx}); + _ -> ok end. -spec(get_cached_item/2 :: -( - Host :: mod_pubsub:host(), - NodeIdx :: mod_pubsub:nodeIdx()) + ( + Host :: mod_pubsub:host(), + Nidx :: mod_pubsub:nodeIdx()) -> undefined | mod_pubsub:pubsubItem() -). -get_cached_item({_, ServerHost, _}, NodeId) -> - get_cached_item(ServerHost, NodeId); -get_cached_item(Host, NodeIdx) -> + ). +get_cached_item({_, ServerHost, _}, Nidx) -> + get_cached_item(ServerHost, Nidx); +get_cached_item(Host, Nidx) -> case is_last_item_cache_enabled(Host) of - true -> - case mnesia:dirty_read({pubsub_last_item, NodeIdx}) of - [#pubsub_last_item{itemid = ItemId, creation = Creation, payload = Payload}] -> -% [{pubsub_last_item, NodeId, ItemId, Creation, -% Payload}] -> - #pubsub_item{itemid = {ItemId, NodeIdx}, - payload = Payload, creation = Creation, - modification = Creation}; - _ -> undefined - end; - _ -> undefined + true -> + case mnesia:dirty_read({pubsub_last_item, Nidx}) of + [#pubsub_last_item{itemid = ItemId, creation = Creation, payload = Payload}] -> + % [{pubsub_last_item, Nidx, ItemId, Creation, + % Payload}] -> + #pubsub_item{itemid = {ItemId, Nidx}, + payload = Payload, creation = Creation, + modification = Creation}; + _ -> + undefined + end; + _ -> + undefined end. %%%% plugin handling host(ServerHost) -> - case catch - ets:lookup(gen_mod:get_module_proc(ServerHost, config), - host) - of - [{host, Host}] -> Host; - _ -> <<"pubsub.", ServerHost/binary>> + config(ServerHost, host, <<"pubsub.", ServerHost/binary>>). + +serverhost({_U, Server, _R})-> + Server; +serverhost(Host) -> + case binary:match(Host, <<"pubsub.">>) of + {0,7} -> + [_,ServerHost] = binary:split(Host, <<".">>), + ServerHost; + _ -> + Host + end. + +tree(Host) -> + case config(serverhost(Host), nodetree) of + undefined -> tree(Host, ?STDTREE); + Tree -> Tree + end. + +tree(Host, Name) -> + case gen_mod:db_type(serverhost(Host), ?MODULE) of + mnesia -> jlib:binary_to_atom(<<"nodetree_", Name/binary>>); + odbc -> jlib:binary_to_atom(<<"nodetree_", Name/binary, "_odbc">>); + _ -> Name + end. + +plugin(Host, Name) -> + case gen_mod:db_type(serverhost(Host), ?MODULE) of + mnesia -> jlib:binary_to_atom(<<"node_", Name/binary>>); + odbc -> jlib:binary_to_atom(<<"node_", Name/binary, "_odbc">>); + _ -> Name end. plugins(Host) -> - case catch ets:lookup(gen_mod:get_module_proc(Host, - config), - plugins) - of - [{plugins, []}] -> [?STDNODE]; - [{plugins, PL}] -> PL; - _ -> [?STDNODE] + case config(serverhost(Host), plugins) of + undefined -> [?STDNODE]; + [] -> [?STDNODE]; + Plugins -> Plugins + end. + +subscription_plugin(Host) -> + case gen_mod:db_type(serverhost(Host), ?MODULE) of + mnesia -> pubsub_subscription; + odbc -> pubsub_subscription_odbc; + _ -> none + end. + +config(ServerHost, Key) -> + config(ServerHost, Key, undefined). +config(ServerHost, Key, Default) -> + case catch ets:lookup(gen_mod:get_module_proc(ServerHost, config), Key) of + [{Key, Value}] -> Value; + _ -> Default end. select_type(ServerHost, Host, Node, Type) -> SelectedType = case Host of - {_User, _Server, _Resource} -> - case catch - ets:lookup(gen_mod:get_module_proc(ServerHost, - config), - pep_mapping) - of - [{pep_mapping, PM}] -> - proplists:get_value(Node, PM, ?PEPNODE); - _ -> ?PEPNODE - end; - _ -> Type - end, + {_User, _Server, _Resource} -> + case config(ServerHost, pep_mapping) of + undefined -> ?PEPNODE; + Mapping -> proplists:get_value(Node, Mapping, ?PEPNODE) + end; + _ -> + Type + end, ConfiguredTypes = plugins(ServerHost), case lists:member(SelectedType, ConfiguredTypes) of - true -> SelectedType; - false -> hd(ConfiguredTypes) + true -> SelectedType; + false -> hd(ConfiguredTypes) end. select_type(ServerHost, Host, Node) -> - select_type(ServerHost, Host, Node, - hd(plugins(ServerHost))). + select_type(ServerHost, Host, Node, hd(plugins(ServerHost))). + +feature(<<"rsm">>) -> ?NS_RSM; +feature(Feature) -> <<(?NS_PUBSUB)/binary, "#", Feature/binary>>. features() -> [% see plugin "access-authorize", % OPTIONAL - <<"access-open">>, % OPTIONAL this relates to access_model option in node_hometree - <<"access-presence">>, % OPTIONAL this relates to access_model option in node_pep - <<"access-whitelist">>, % OPTIONAL - <<"collections">>, % RECOMMENDED - <<"config-node">>, % RECOMMENDED - <<"create-and-configure">>, % RECOMMENDED - <<"item-ids">>, % RECOMMENDED - <<"last-published">>, % RECOMMENDED - <<"member-affiliation">>, % RECOMMENDED - <<"presence-notifications">>, % OPTIONAL - <<"presence-subscribe">>, % RECOMMENDED - <<"publisher-affiliation">>, % RECOMMENDED - <<"retrieve-default">>]. - - % see plugin "retrieve-items", % RECOMMENDED - % see plugin "retrieve-subscriptions", % RECOMMENDED - %TODO "shim", % OPTIONAL - % see plugin "subscribe", % REQUIRED - % see plugin "subscription-options", % OPTIONAL - % see plugin "subscription-notifications" % OPTIONAL - -features(Type) -> - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary>>), - features() ++ - case catch Module:features() of + <<"access-open">>, % OPTIONAL this relates to access_model option in node_hometree + <<"access-presence">>, % OPTIONAL this relates to access_model option in node_pep + <<"access-whitelist">>, % OPTIONAL + <<"collections">>, % RECOMMENDED + <<"config-node">>, % RECOMMENDED + <<"create-and-configure">>, % RECOMMENDED + <<"item-ids">>, % RECOMMENDED + <<"last-published">>, % RECOMMENDED + <<"member-affiliation">>, % RECOMMENDED + <<"presence-notifications">>, % OPTIONAL + <<"presence-subscribe">>, % RECOMMENDED + <<"publisher-affiliation">>, % RECOMMENDED + <<"retrieve-default">>, + <<"shim">>]. % RECOMMENDED + +% see plugin "retrieve-items", % RECOMMENDED +% see plugin "retrieve-subscriptions", % RECOMMENDED +% see plugin "subscribe", % REQUIRED +% see plugin "subscription-options", % OPTIONAL +% see plugin "subscription-notifications" % OPTIONAL + +plugin_features(Host, Type) -> + Module = plugin(Host, Type), + case catch Module:features() of {'EXIT', {undef, _}} -> []; Result -> Result - end. + end. features(Host, <<>>) -> lists:usort(lists:foldl(fun (Plugin, Acc) -> - Acc ++ features(Plugin) - end, - [], plugins(Host))); -features(Host, Node) -> + Acc ++ plugin_features(Host, Plugin) + end, + features(), plugins(Host))); +features(Host, Node) when is_binary(Node) -> Action = fun (#pubsub_node{type = Type}) -> - {result, features(Type)} - end, + {result, plugin_features(Host, Type)} + end, case transaction(Host, Node, Action, sync_dirty) of - {result, Features} -> - lists:usort(features() ++ Features); - _ -> features() + {result, Features} -> lists:usort(features() ++ Features); + _ -> features() end. %% @doc

    node tree plugin call.

    @@ -5150,113 +4064,143 @@ tree_call({_User, Server, _Resource}, Function, Args) -> tree_call(Server, Function, Args); tree_call(Host, Function, Args) -> ?DEBUG("tree_call ~p ~p ~p", [Host, Function, Args]), - Module = case catch - ets:lookup(gen_mod:get_module_proc(Host, config), - nodetree) - of - [{nodetree, N}] -> N; - _ -> - jlib:binary_to_atom(<<(?TREE_PREFIX)/binary, - (?STDTREE)/binary>>) - end, - catch apply(Module, Function, Args). + catch apply(tree(Host), Function, Args). tree_action(Host, Function, Args) -> ?DEBUG("tree_action ~p ~p ~p", [Host, Function, Args]), + ServerHost = serverhost(Host), Fun = fun () -> tree_call(Host, Function, Args) end, - catch mnesia:sync_dirty(Fun). + case gen_mod:db_type(ServerHost, ?MODULE) of + mnesia -> + catch mnesia:sync_dirty(Fun); + odbc -> + case catch ejabberd_odbc:sql_bloc(ServerHost, Fun) of + {atomic, Result} -> + Result; + {aborted, Reason} -> + ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), + {error, ?ERR_INTERNAL_SERVER_ERROR} + end; + Other -> + ?ERROR_MSG("unsupported backend: ~p~n", [Other]), + {error, ?ERR_INTERNAL_SERVER_ERROR} + end. %% @doc

    node plugin call.

    -node_call(Type, Function, Args) -> +node_call(Host, Type, Function, Args) -> ?DEBUG("node_call ~p ~p ~p", [Type, Function, Args]), - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary>>), + Module = plugin(Host, Type), case apply(Module, Function, Args) of - {result, Result} -> {result, Result}; - {error, Error} -> {error, Error}; - {'EXIT', {undef, Undefined}} -> - case Type of - ?STDNODE -> {error, {undef, Undefined}}; - _ -> node_call(?STDNODE, Function, Args) - end; - {'EXIT', Reason} -> {error, Reason}; - Result -> - {result, - Result} %% any other return value is forced as result + {result, Result} -> + {result, Result}; + {error, Error} -> + {error, Error}; + {'EXIT', {undef, Undefined}} -> + case Type of + ?STDNODE -> {error, {undef, Undefined}}; + _ -> node_call(Host, ?STDNODE, Function, Args) + end; + {'EXIT', Reason} -> + {error, Reason}; + Result -> + {result, Result} %% any other return value is forced as result end. node_action(Host, Type, Function, Args) -> - ?DEBUG("node_action ~p ~p ~p ~p", - [Host, Type, Function, Args]), - transaction(fun () -> node_call(Type, Function, Args) - end, - sync_dirty). + ?DEBUG("node_action ~p ~p ~p ~p", [Host, Type, Function, Args]), + transaction(Host, fun () -> + node_call(Host, Type, Function, Args) + end, + sync_dirty). %% @doc

    plugin transaction handling.

    transaction(Host, Node, Action, Trans) -> - transaction(fun () -> - case tree_call(Host, get_node, [Host, Node]) of - N when is_record(N, pubsub_node) -> - case Action(N) of - {result, Result} -> {result, {N, Result}}; - {atomic, {result, Result}} -> - {result, {N, Result}}; - Other -> Other - end; - Error -> Error - end - end, - Trans). - -transaction(Host, Action, Trans) -> - transaction(fun () -> - {result, - lists:foldl(Action, [], - tree_call(Host, get_nodes, [Host]))} - end, - Trans). - -transaction(Fun, Trans) -> - case catch mnesia:Trans(Fun) of - {result, Result} -> {result, Result}; - {error, Error} -> {error, Error}; - {atomic, {result, Result}} -> {result, Result}; - {atomic, {error, Error}} -> {error, Error}; - {aborted, Reason} -> - ?ERROR_MSG("transaction return internal error: ~p~n", - [{aborted, Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; - {'EXIT', Reason} -> - ?ERROR_MSG("transaction return internal error: ~p~n", - [{'EXIT', Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; - Other -> - ?ERROR_MSG("transaction return internal error: ~p~n", - [Other]), - {error, ?ERR_INTERNAL_SERVER_ERROR} + transaction(Host, fun () -> + case tree_call(Host, get_node, [Host, Node]) of + N when is_record(N, pubsub_node) -> + case Action(N) of + {result, Result} -> {result, {N, Result}}; + {atomic, {result, Result}} -> {result, {N, Result}}; + Other -> Other + end; + Error -> + Error + end + end, + Trans). + +transaction(Host, Fun, Trans) -> + ServerHost = serverhost(Host), + DBType = gen_mod:db_type(ServerHost, ?MODULE), + Retry = case DBType of + odbc -> 2; + _ -> 1 + end, + transaction_retry(Host, ServerHost, Fun, Trans, DBType, Retry). + +transaction_retry(_Host, _ServerHost, _Fun, _Trans, _DBType, 0) -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; +transaction_retry(Host, ServerHost, Fun, Trans, DBType, Count) -> + Res = case DBType of + mnesia -> + catch mnesia:Trans(Fun); + odbc -> + SqlFun = case Trans of + transaction -> sql_transaction; + _ -> sql_bloc + end, + catch ejabberd_odbc:SqlFun(ServerHost, Fun); + _ -> + {unsupported, DBType} + end, + case Res of + {result, Result} -> + {result, Result}; + {error, Error} -> + {error, Error}; + {atomic, {result, Result}} -> + {result, Result}; + {atomic, {error, Error}} -> + {error, Error}; + {aborted, Reason} -> + ?ERROR_MSG("transaction return internal error: ~p~n", [{aborted, Reason}]), + {error, ?ERR_INTERNAL_SERVER_ERROR}; + {'EXIT', {timeout, _} = Reason} -> + ?ERROR_MSG("transaction return internal error: ~p~n", [Reason]), + transaction_retry(Host, ServerHost, Fun, Trans, DBType, Count - 1); + {'EXIT', Reason} -> + ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), + {error, ?ERR_INTERNAL_SERVER_ERROR}; + Other -> + ?ERROR_MSG("transaction return internal error: ~p~n", [Other]), + {error, ?ERR_INTERNAL_SERVER_ERROR} end. %%%% helpers %% Add pubsub-specific error element extended_error(Error, Ext) -> - extended_error(Error, Ext, - [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}]). + extended_error(Error, Ext, [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}]). extended_error(Error, unsupported, Feature) -> -%% Give a uniq identifier + %% Give a uniq identifier extended_error(Error, <<"unsupported">>, - [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}, - {<<"feature">>, Feature}]); -extended_error(#xmlel{name = Error, attrs = Attrs, - children = SubEls}, - Ext, ExtAttrs) -> + [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}, + {<<"feature">>, Feature}]); +extended_error(#xmlel{name = Error, attrs = Attrs, children = SubEls}, Ext, ExtAttrs) -> #xmlel{name = Error, attrs = Attrs, - children = - lists:reverse([#xmlel{name = Ext, attrs = ExtAttrs, - children = []} - | SubEls])}. + children = lists:reverse([#xmlel{name = Ext, attrs = ExtAttrs} | SubEls])}. + +string_to_ljid(JID) -> + case jlib:string_to_jid(JID) of + error -> + {<<>>, <<>>, <<>>}; + J -> + case jlib:jid_tolower(J) of + error -> {<<>>, <<>>, <<>>}; + J1 -> J1 + end + end. -spec(uniqid/0 :: () -> mod_pubsub:itemId()). uniqid() -> @@ -5269,24 +4213,23 @@ itemAttr([]) -> []; itemAttr(ItemId) -> [{<<"id">>, ItemId}]. itemsEls(Items) -> - lists:map(fun (#pubsub_item{itemid = {ItemId, _}, payload = Payload}) -> - #xmlel{name = <<"item">>, attrs = itemAttr(ItemId), children = Payload} - end, Items). + [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), children = Payload} + || #pubsub_item{itemid = {ItemId, _}, payload = Payload} <- Items]. -spec(add_message_type/2 :: -( - Message :: xmlel(), - Type :: atom()) + ( + Message :: xmlel(), + Type :: atom()) -> xmlel() -). + ). add_message_type(Message, normal) -> Message; -add_message_type(#xmlel{name = <<"message">>, attrs = Attrs, children = Els}, - Type) -> +add_message_type(#xmlel{name = <<"message">>, attrs = Attrs, children = Els}, Type) -> #xmlel{name = <<"message">>, - attrs = [{<<"type">>, jlib:atom_to_binary(Type)} | Attrs], - children = Els}; -add_message_type(XmlEl, _Type) -> XmlEl. + attrs = [{<<"type">>, jlib:atom_to_binary(Type)} | Attrs], + children = Els}; +add_message_type(XmlEl, _Type) -> + XmlEl. %% Place of changed at the bottom of the stanza %% cf. http://xmpp.org/extensions/xep-0060.html#publisher-publish-success-subid @@ -5298,230 +4241,98 @@ add_shim_headers(Stanza, HeaderEls) -> add_headers(Stanza, <<"headers">>, ?NS_SHIM, HeaderEls). add_extended_headers(Stanza, HeaderEls) -> - add_headers(Stanza, <<"addresses">>, ?NS_ADDRESS, - HeaderEls). + add_headers(Stanza, <<"addresses">>, ?NS_ADDRESS, HeaderEls). -add_headers(#xmlel{name = Name, attrs = Attrs, children = Els}, - HeaderName, HeaderNS, HeaderEls) -> +add_headers(#xmlel{name = Name, attrs = Attrs, children = Els}, HeaderName, HeaderNS, HeaderEls) -> HeaderEl = #xmlel{name = HeaderName, - attrs = [{<<"xmlns">>, HeaderNS}], - children = HeaderEls}, + attrs = [{<<"xmlns">>, HeaderNS}], + children = HeaderEls}, #xmlel{name = Name, attrs = Attrs, - children = lists:append(Els, [HeaderEl])}. - -%% Removed multiple
    Foo
    elements -%% Didn't seem compliant, but not sure. Confirmation required. -%% cf. http://xmpp.org/extensions/xep-0248.html#notify -%% -%% "If an item is published to a node which is also included by a collection, -%% and an entity is subscribed to that collection with a subscription type of -%% "items" (Is there a way to check that currently ?), then the notifications -%% generated by the service MUST contain additional information. The -%% element contained in the notification message MUST specify the node -%% identifier of the node that generated the notification (not the collection) -%% and the element MUST contain a SHIM header that specifies the node -%% identifier of the collection". + children = lists:append(Els, [HeaderEl])}. collection_shim(Node) -> [#xmlel{name = <<"header">>, attrs = [{<<"name">>, <<"Collection">>}], children = [{xmlcdata, Node}]}]. -subid_shim(SubIDs) -> +subid_shim(SubIds) -> [#xmlel{name = <<"header">>, - attrs = [{<<"name">>, <<"SubID">>}], - children = [{xmlcdata, SubID}]} - || SubID <- SubIDs]. + attrs = [{<<"name">>, <<"SubId">>}], + children = [{xmlcdata, SubId}]} + || SubId <- SubIds]. %% The argument is a list of Jids because this function could be used %% with the 'pubsub#replyto' (type=jid-multi) node configuration. extended_headers(Jids) -> [#xmlel{name = <<"address">>, - attrs = [{<<"type">>, <<"replyto">>}, {<<"jid">>, Jid}], - children = []} - || Jid <- Jids]. + attrs = [{<<"type">>, <<"replyto">>}, {<<"jid">>, Jid}]} + || Jid <- Jids]. on_user_offline(_, JID, _) -> {User, Server, Resource} = jlib:jid_tolower(JID), - case ejabberd_sm:get_user_resources(User, Server) of + case user_resources(User, Server) of [] -> purge_offline({User, Server, Resource}); - _ -> true + _ -> true end. purge_offline({User, Server, _} = LJID) -> Host = host(element(2, LJID)), Plugins = plugins(Host), Result = lists:foldl(fun (Type, {Status, Acc}) -> - case lists:member(<<"retrieve-affiliations">>, - features(Type)) - of - false -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affiliations} = - node_action(Host, Type, - get_entity_affiliations, - [Host, LJID]), - {Status, [Affiliations | Acc]} - end - end, - {ok, []}, Plugins), + case lists:member(<<"retrieve-affiliations">>, plugin_features(Host, Type)) of + false -> + {{error, + extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, + unsupported, <<"retrieve-affiliations">>)}, + Acc}; + true -> + {result, Affs} = node_action(Host, Type, + get_entity_affiliations, + [Host, LJID]), + {Status, [Affs | Acc]} + end + end, + {ok, []}, Plugins), case Result of - {ok, Affiliations} -> - lists:foreach(fun ({#pubsub_node{nodeid = {_, NodeId}, - options = Options, type = Type}, - Affiliation}) - when Affiliation == owner orelse - Affiliation == publisher -> - Action = fun (#pubsub_node{type = NType, - id = NodeIdx}) -> - node_call(NType, get_items, - [NodeIdx, - service_jid(Host)]) - end, - case transaction(Host, NodeId, Action, - sync_dirty) - of - {result, {_, []}} -> true; - {result, {_, Items}} -> - Features = features(Type), - case {lists:member(<<"retract-items">>, - Features), - lists:member(<<"persistent-items">>, - Features), - get_option(Options, persist_items), - get_option(Options, purge_offline)} - of - {true, true, true, true} -> - ForceNotify = get_option(Options, - notify_retract), - lists:foreach(fun - (#pubsub_item{itemid - = - {ItemId, - _}, - modification - = - {_, - Modification}}) -> - case - Modification - of - {User, Server, - _} -> - delete_item(Host, - NodeId, - LJID, - ItemId, - ForceNotify); - _ -> true - end; - (_) -> true - end, - Items); - _ -> true - end; - Error -> Error - end; - (_) -> true + {ok, Affs} -> + lists:foreach(fun + ({#pubsub_node{nodeid = {_, Node}, options = Options, type = Type}, Aff}) + when Aff == owner orelse Aff == publisher -> + Action = fun (#pubsub_node{type = NType, id = Nidx}) -> + node_call(Host, NType, get_items, [Nidx, service_jid(Host), none]) end, - lists:usort(lists:flatten(Affiliations))); - {Error, _} -> ?DEBUG("on_user_offline ~p", [Error]) + case transaction(Host, Node, Action, sync_dirty) of + {result, {_, {[], _}}} -> + true; + {result, {_, {Items, _}}} -> + Features = plugin_features(Host, Type), + case {lists:member(<<"retract-items">>, Features), + lists:member(<<"persistent-items">>, Features), + get_option(Options, persist_items), + get_option(Options, purge_offline)} + of + {true, true, true, true} -> + ForceNotify = get_option(Options, notify_retract), + lists:foreach(fun + (#pubsub_item{itemid = {ItemId, _}, + modification = {_, {U, S, _}}}) + when (U == User) and (S == Server) -> + delete_item(Host, Node, LJID, ItemId, ForceNotify); + (_) -> + true + end, + Items); + _ -> + true + end; + Error -> + Error + end; + (_) -> + true + end, + lists:usort(lists:flatten(Affs))); + {Error, _} -> + ?DEBUG("on_user_offline ~p", [Error]) end. - - -%% REVIEW: -%% * this code takes NODEID from Itemid2, and forgets about Nodeidx -%% * this code assumes Payload only contains one xmlelement() -%% * PUBLISHER is taken from Creation -export(_Server) -> - [{pubsub_item, - fun(_Host, #pubsub_item{itemid = {Itemid1, Itemid2}, - %nodeidx = _Nodeidx, - creation = {{C1, C2, C3}, Cusr}, - modification = {{M1, M2, M3}, _Musr}, - payload = Payload}) -> - ITEMID = ejabberd_odbc:escape(Itemid1), - NODEID = integer_to_list(Itemid2), - CREATION = ejabberd_odbc:escape( - string:join([string:right(integer_to_list(I),6,$0)||I<-[C1,C2,C3]],":")), - MODIFICATION = ejabberd_odbc:escape( - string:join([string:right(integer_to_list(I),6,$0)||I<-[M1,M2,M3]],":")), - PUBLISHER = ejabberd_odbc:escape(jlib:jid_to_string(Cusr)), - [PayloadEl] = [El || {xmlelement,_,_,_} = El <- Payload], - PAYLOAD = ejabberd_odbc:escape(xml:element_to_binary(PayloadEl)), - ["delete from pubsub_item where itemid='", ITEMID, "';\n" - "insert into pubsub_item(itemid,nodeid,creation,modification,publisher,payload) \n" - " values ('", ITEMID, "', ", NODEID, ", '", CREATION, "', '", - MODIFICATION, "', '", PUBLISHER, "', '", PAYLOAD, "');\n"]; - (_Host, _R) -> - [] - end}, -%% REVIEW: -%% * From the mnesia table, the #pubsub_state.items is not used in ODBC -%% * Right now AFFILIATION is the first letter of Affiliation -%% * Right now SUBSCRIPTIONS expects only one Subscription -%% * Right now SUBSCRIPTIONS letter is the first letter of Subscription - {pubsub_state, - fun(_Host, #pubsub_state{stateid = {Jid, Stateid}, - %nodeidx = Nodeidx, - items = _Items, - affiliation = Affiliation, - subscriptions = Subscriptions}) -> - STATEID = integer_to_list(Stateid), - JID = ejabberd_odbc:escape(jlib:jid_to_string(Jid)), - NODEID = "unknown", %% TODO: integer_to_list(Nodeidx), - AFFILIATION = string:substr(atom_to_list(Affiliation),1,1), - SUBSCRIPTIONS = parse_subscriptions(Subscriptions), - ["delete from pubsub_state where stateid='", STATEID, "';\n" - "insert into pubsub_state(stateid,jid,nodeid,affiliation,subscriptions) \n" - " values (", STATEID, ", '", JID, "', ", NODEID, ", '", - AFFILIATION, "', '", SUBSCRIPTIONS, "');\n"]; - (_Host, _R) -> - [] - end}, - -%% REVIEW: -%% * Parents is not migrated to PARENTs -%% * Probably some option VALs are not correctly represented in mysql - {pubsub_node, - fun(_Host, #pubsub_node{nodeid = {Hostid, Nodeid}, - id = Id, - parents = _Parents, - type = Type, - owners = Owners, - options = Options}) -> - HOST = case Hostid of - {U,S,R} -> ejabberd_odbc:escape(jlib:jid_to_string({U,S,R})); - _ -> ejabberd_odbc:escape(Hostid) - end, - NODE = ejabberd_odbc:escape(Nodeid), - NODEID = integer_to_list(Id), - PARENT = "", - TYPE = ejabberd_odbc:escape(Type++"_odbc"), - ["delete from pubsub_node where nodeid='", NODEID, "';\n" - "insert into pubsub_node(host,node,nodeid,parent,type) \n" - " values ('", HOST, "', '", NODE, "', ", NODEID, ", '", PARENT, "', '", TYPE, "');\n" - "delete from pubsub_node_option where nodeid='", NODEID, "';\n", - [["insert into pubsub_node_option(nodeid,name,val)\n" - " values (", NODEID, ", '", atom_to_list(Name), "', '", - io_lib:format("~p", [Val]), "');\n"] || {Name,Val} <- Options], - "delete from pubsub_node_owner where nodeid='", NODEID, "';\n", - [["insert into pubsub_node_owner(nodeid,owner)\n" - " values (", NODEID, ", '", jlib:jid_to_string(Usr), "');\n"] || Usr <- Owners],"\n"]; - (_Host, _R) -> - [] - end}]. - -parse_subscriptions([]) -> - ""; -parse_subscriptions([{State, Item}]) -> - STATE = case State of - subscribed -> "s" - end, - string:join([STATE, Item],":"). diff --git a/src/mod_pubsub_odbc.erl b/src/mod_pubsub_odbc.erl deleted file mode 100644 index 8b32b83e2f1..00000000000 --- a/src/mod_pubsub_odbc.erl +++ /dev/null @@ -1,5103 +0,0 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% -%%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% -%%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. -%%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - -%%% @doc The module {@module} is the core of the PubSub -%%% extension. It relies on PubSub plugins for a large part of its functions. -%%% -%%% @headerfile "pubsub.hrl" -%%% -%%% @reference See XEP-0060: Pubsub for -%%% the latest version of the PubSub specification. -%%% This module uses version 1.12 of the specification as a base. -%%% Most of the specification is implemented. -%%% Functions concerning configuration should be rewritten. -%%% -%%% Support for subscription-options and multi-subscribe features was -%%% added by Brian Cully (bjc AT kublai.com). Subscriptions and options are -%%% stored in the pubsub_subscription table, with a link to them provided -%%% by the subscriptions field of pubsub_state. For information on -%%% subscription-options and mulit-subscribe see XEP-0060 sections 6.1.6, -%%% 6.2.3.1, 6.2.3.5, and 6.3. For information on subscription leases see -%%% XEP-0060 section 12.18. - --module(mod_pubsub_odbc). - --author('christophe.romain@process-one.net'). - --version('1.13-0'). - --behaviour(gen_server). - --behaviour(gen_mod). - --include("ejabberd.hrl"). --include("logger.hrl"). - --include("adhoc.hrl"). - --include("jlib.hrl"). - --include("pubsub.hrl"). - --define(STDTREE, <<"tree">>). - --define(STDNODE, <<"flat">>). - --define(PEPNODE, <<"pep">>). - -%% exports for hooks --export([presence_probe/3, caps_update/3, - in_subscription/6, out_subscription/4, - on_user_offline/3, remove_user/2, - disco_local_identity/5, disco_local_features/5, - disco_local_items/5, disco_sm_identity/5, - disco_sm_features/5, disco_sm_items/5]). - -%% exported iq handlers --export([iq_sm/3]). - -%% exports for console debug manual use --export([create_node/5, - delete_node/3, - subscribe_node/5, - unsubscribe_node/5, - publish_item/6, - delete_item/4, - send_items/7, - get_items/2, - get_item/3, - get_cached_item/2, - broadcast_stanza/9, - get_configure/5, - set_configure/5, - tree_action/3, - node_action/4 - ]). - -%% general helpers for plugins --export([subscription_to_string/1, affiliation_to_string/1, - string_to_subscription/1, string_to_affiliation/1, - extended_error/2, extended_error/3, - escape/1]). - -%% API and gen_server callbacks --export([start_link/2, start/2, stop/1, init/1, - handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - -%% calls for parallel sending of last items --export([send_loop/1]). - --define(PROCNAME, ejabberd_mod_pubsub_odbc). - --define(LOOPNAME, ejabberd_mod_pubsub_loop). - -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- --define(PLUGIN_PREFIX, <<"node_">>). - --define(TREE_PREFIX, <<"nodetree_">>). - --define(ODBC_SUFFIX, <<"_odbc">>). - -% --export_type([ - host/0, - hostPubsub/0, - hostPEP/0, - %% - nodeIdx/0, - nodeId/0, - itemId/0, - subId/0, - payload/0, - %% - nodeOption/0, - nodeOptions/0, - subOption/0, - subOptions/0, - %% - affiliation/0, - subscription/0, - accessModel/0, - publishModel/0 -]). - -%% -type payload() defined here because the -type xmlel() is not accessible -%% from pubsub.hrl --type(payload() :: [] | [xmlel(),...]). - --export_type([ - pubsubNode/0, - pubsubState/0, - pubsubItem/0, - pubsubSubscription/0, - pubsubLastItem/0 -]). - --type(pubsubNode() :: - #pubsub_node{ - nodeid :: {Host::mod_pubsub:host(), NodeId::mod_pubsub:nodeId()}, - id :: mod_pubsub:nodeIdx(), - parents :: [Parent_NodeId::mod_pubsub:nodeId()], - type :: binary(), - owners :: [Owner::ljid(),...], - options :: mod_pubsub:nodeOptions() - } -). - --type(pubsubState() :: - #pubsub_state{ - stateid :: {Entity::ljid(), NodeIdx::mod_pubsub:nodeIdx()}, - items :: [ItemId::mod_pubsub:itemId()], - affiliation :: mod_pubsub:affiliation(), - subscriptions :: [{mod_pubsub:subscription(), mod_pubsub:subId()}] - } -). - --type(pubsubItem() :: - #pubsub_item{ - itemid :: {mod_pubsub:itemId(), mod_pubsub:nodeIdx()}, - creation :: {erlang:timestamp(), ljid()}, - modification :: {erlang:timestamp(), ljid()}, - payload :: mod_pubsub:payload() - } -). - --type(pubsubSubscription() :: - #pubsub_subscription{ - subid :: mod_pubsub:subId(), - options :: [] | mod_pubsub:subOptions() - } -). - --type(pubsubLastItem() :: - #pubsub_last_item{ - nodeid :: mod_pubsub:nodeIdx(), - itemid :: mod_pubsub:itemId(), - creation :: {erlang:timestamp(), ljid()}, - payload :: mod_pubsub:payload() - } -). - --record(state, -{ - server_host, - host, - access, - pep_mapping = [], - ignore_pep_from_offline = true, - last_item_cache = false, - max_items_node = ?MAXITEMS, - nodetree = ?STDTREE, - plugins = [?STDNODE] -}). - --type(state() :: - #state{ - server_host :: binary(), - host :: mod_pubsub:hostPubsub(), - access :: atom(), - pep_mapping :: [{binary(), binary()}], - ignore_pep_from_offline :: boolean(), - last_item_cache :: boolean(), - max_items_node :: non_neg_integer(), - nodetree :: binary(), - plugins :: [binary(),...] - } - -). - - -start_link(Host, Opts) -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - gen_server:start_link({local, Proc}, ?MODULE, - [Host, Opts], []). - -start(Host, Opts) -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, - transient, 1000, worker, [?MODULE]}, - supervisor:start_child(ejabberd_sup, ChildSpec). - -stop(Host) -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - gen_server:call(Proc, stop), - supervisor:delete_child(ejabberd_sup, Proc). - -%%==================================================================== -%% gen_server callbacks -%%==================================================================== - -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- --spec(init/1 :: -( - _:: _) - -> {ok, state()} -). - -init([ServerHost, Opts]) -> - ?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]), - Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>), - Access = gen_mod:get_opt(access_createnode, Opts, - fun(A) when is_atom(A) -> A end, all), - PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, - fun(A) when is_boolean(A) -> A end, true), - IQDisc = gen_mod:get_opt(iqdisc, Opts, - fun(A) when is_atom(A) -> A end, one_queue), - LastItemCache = gen_mod:get_opt(last_item_cache, Opts, - fun(A) when is_boolean(A) -> A end, false), - MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, - fun(A) when is_integer(A) andalso A >= 0 -> A end, ?MAXITEMS), - pubsub_index:init(Host, ServerHost, Opts), - ets:new(gen_mod:get_module_proc(Host, config), - [set, named_table]), - ets:new(gen_mod:get_module_proc(ServerHost, config), - [set, named_table]), - {Plugins, NodeTree, PepMapping} = init_plugins(Host, - ServerHost, Opts), - mnesia:create_table(pubsub_last_item, - [{ram_copies, [node()]}, - {attributes, record_info(fields, pubsub_last_item)}]), - mod_disco:register_feature(ServerHost, ?NS_PUBSUB), - ets:insert(gen_mod:get_module_proc(Host, config), - {nodetree, NodeTree}), - ets:insert(gen_mod:get_module_proc(Host, config), - {plugins, Plugins}), - ets:insert(gen_mod:get_module_proc(Host, config), - {last_item_cache, LastItemCache}), - ets:insert(gen_mod:get_module_proc(Host, config), - {max_items_node, MaxItemsNode}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {nodetree, NodeTree}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {plugins, Plugins}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {last_item_cache, LastItemCache}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {max_items_node, MaxItemsNode}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {pep_mapping, PepMapping}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {ignore_pep_from_offline, PepOffline}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), - {host, Host}), - ejabberd_hooks:add(sm_remove_connection_hook, - ServerHost, ?MODULE, on_user_offline, 75), - ejabberd_hooks:add(disco_local_identity, ServerHost, - ?MODULE, disco_local_identity, 75), - ejabberd_hooks:add(disco_local_features, ServerHost, - ?MODULE, disco_local_features, 75), - ejabberd_hooks:add(disco_local_items, ServerHost, - ?MODULE, disco_local_items, 75), - ejabberd_hooks:add(presence_probe_hook, ServerHost, - ?MODULE, presence_probe, 80), - ejabberd_hooks:add(roster_in_subscription, ServerHost, - ?MODULE, in_subscription, 50), - ejabberd_hooks:add(roster_out_subscription, ServerHost, - ?MODULE, out_subscription, 50), - ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, - remove_user, 50), - ejabberd_hooks:add(anonymous_purge_hook, ServerHost, - ?MODULE, remove_user, 50), - case lists:member(?PEPNODE, Plugins) of - true -> - ejabberd_hooks:add(caps_update, ServerHost, ?MODULE, - caps_update, 80), - ejabberd_hooks:add(disco_sm_identity, ServerHost, - ?MODULE, disco_sm_identity, 75), - ejabberd_hooks:add(disco_sm_features, ServerHost, - ?MODULE, disco_sm_features, 75), - ejabberd_hooks:add(disco_sm_items, ServerHost, ?MODULE, - disco_sm_items, 75), - gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, - ?NS_PUBSUB, ?MODULE, iq_sm, IQDisc), - gen_iq_handler:add_iq_handler(ejabberd_sm, ServerHost, - ?NS_PUBSUB_OWNER, ?MODULE, iq_sm, - IQDisc); - false -> ok - end, - ejabberd_router:register_route(Host), - put(server_host, ServerHost), - init_nodes(Host, ServerHost, NodeTree, Plugins), - State = #state{host = Host, server_host = ServerHost, - access = Access, pep_mapping = PepMapping, - ignore_pep_from_offline = PepOffline, - last_item_cache = LastItemCache, - max_items_node = MaxItemsNode, nodetree = NodeTree, - plugins = Plugins}, - init_send_loop(ServerHost, State), - {ok, State}. - -init_send_loop(ServerHost, State) -> - Proc = gen_mod:get_module_proc(ServerHost, ?LOOPNAME), - SendLoop = spawn(?MODULE, send_loop, [State]), - register(Proc, SendLoop), - SendLoop. - -%% @spec (Host, ServerHost, Opts) -> Plugins -%% Host = mod_pubsub:host() Opts = [{Key,Value}] -%% ServerHost = host() -%% Key = atom() -%% Value = term() -%% Plugins = [Plugin::string()] -%% @doc Call the init/1 function for each plugin declared in the config file. -%% The default plugin module is implicit. -%%

    The Erlang code for the plugin is located in a module called -%% node_plugin. The 'node_' prefix is mandatory.

    -%%

    The modules are initialized in alphetical order and the list is checked -%% and sorted to ensure that each module is initialized only once.

    -%%

    See {@link node_hometree:init/1} for an example implementation.

    -init_plugins(Host, ServerHost, Opts) -> - TreePlugin = - jlib:binary_to_atom(<<(?TREE_PREFIX)/binary, - (gen_mod:get_opt(nodetree, Opts, fun(A) when is_binary(A) -> A end, - ?STDTREE))/binary, - (?ODBC_SUFFIX)/binary>>), - ?DEBUG("** tree plugin is ~p", [TreePlugin]), - TreePlugin:init(Host, ServerHost, Opts), - Plugins = gen_mod:get_opt(plugins, Opts, - fun(A) when is_list(A) -> A end, [?STDNODE]), - PepMapping = gen_mod:get_opt(pep_mapping, Opts, - fun(A) when is_list(A) -> A end, []), - ?DEBUG("** PEP Mapping : ~p~n", [PepMapping]), - PluginsOK = lists:foldl(fun (Name, Acc) -> - Plugin = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Name/binary, - (?ODBC_SUFFIX)/binary>>), - case catch apply(Plugin, init, - [Host, ServerHost, Opts]) - of - {'EXIT', _Error} -> Acc; - _ -> - ?DEBUG("** init ~s plugin", [Name]), - [Name | Acc] - end - end, - [], Plugins), - {lists:reverse(PluginsOK), TreePlugin, PepMapping}. - -terminate_plugins(Host, ServerHost, Plugins, - TreePlugin) -> - lists:foreach(fun (Name) -> - ?DEBUG("** terminate ~s plugin", [Name]), - Plugin = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Name/binary, - (?ODBC_SUFFIX)/binary>>), - Plugin:terminate(Host, ServerHost) - end, - Plugins), - TreePlugin:terminate(Host, ServerHost), - ok. - -init_nodes(Host, ServerHost, _NodeTree, Plugins) -> - case lists:member(<<"hometree_odbc">>, Plugins) of - true -> - create_node(Host, ServerHost, <<"/home">>, service_jid(Host), <<"hometree_odbc">>), - create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, service_jid(Host), - <<"hometree_odbc">>); - false -> ok - end. - -send_loop(State) -> - receive - {presence, JID, Pid} -> - Host = State#state.host, - ServerHost = State#state.server_host, - LJID = jlib:jid_tolower(JID), - BJID = jlib:jid_remove_resource(LJID), - lists:foreach(fun (PType) -> - Subscriptions = case catch node_action(Host, - PType, - get_entity_subscriptions_for_send_last, - [Host, JID]) of - {result, S} -> S; - _ -> [] - end, - lists:foreach(fun ({Node, subscribed, _, - SubJID}) -> - if (SubJID == LJID) or - (SubJID == BJID) -> - #pubsub_node{nodeid - = - {H, - N}, - type = - Type, - id = - NodeId, - options - = - Options} = - Node, - send_items(H, - N, - NodeId, - Type, - Options, - LJID, - last); - true -> - % resource not concerned about that subscription - ok - end; - (_) -> ok - end, - lists:usort(Subscriptions)) - end, - State#state.plugins), - if not State#state.ignore_pep_from_offline -> - {User, Server, Resource} = jlib:jid_tolower(JID), - case catch ejabberd_c2s:get_subscribed(Pid) of - Contacts when is_list(Contacts) -> - lists:foreach(fun ({U, S, R}) -> - case S of - ServerHost -> %% local contacts - case user_resources(U, S) of - [] -> %% offline - PeerJID = - jlib:make_jid(U, S, - R), - self() ! - {presence, User, - Server, [Resource], - PeerJID}; - _ -> %% online - % this is already handled by presence probe - ok - end; - _ -> %% remote contacts - % we can not do anything in any cases - ok - end - end, - Contacts); - _ -> ok - end; - true -> ok - end, - send_loop(State); - {presence, User, Server, Resources, JID} -> - spawn(fun () -> - Host = State#state.host, - Owner = jlib:jid_remove_resource(jlib:jid_tolower(JID)), - lists:foreach(fun (#pubsub_node{nodeid = {_, Node}, - type = Type, - id = NodeId, - options = Options}) -> - case get_option(Options, - send_last_published_item) - of - on_sub_and_presence -> - lists:foreach(fun - (Resource) -> - LJID = - {User, - Server, - Resource}, - Subscribed = - case - get_option(Options, - access_model) - of - open -> - true; - presence -> - true; - whitelist -> - false; % subscribers are added manually - authorize -> - false; % likewise - roster -> - Grps = - get_option(Options, - roster_groups_allowed, - []), - {OU, - OS, - _} = - Owner, - element(2, - get_roster_info(OU, - OS, - LJID, - Grps)) - end, - if - Subscribed -> - send_items(Owner, - Node, - NodeId, - Type, - Options, - LJID, - last); - true -> - ok - end - end, - Resources); - _ -> ok - end - end, - tree_action(Host, get_nodes, - [Owner, JID])) - end), - send_loop(State); - stop -> ok - end. - -%% ------- -%% disco hooks handling functions -%% - --spec(disco_local_identity/5 :: -( - Acc :: [xmlel()], - _From :: jid(), - To :: jid(), - NodeId :: <<>> | mod_pubsub:nodeId(), - Lang :: binary()) - -> [xmlel()] -). -disco_local_identity(Acc, _From, To, <<>>, _Lang) -> - case lists:member(?PEPNODE, plugins(To#jid.lserver)) of - true -> - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}], - children = []} - | Acc]; - false -> Acc - end; -disco_local_identity(Acc, _From, _To, _Node, _Lang) -> - Acc. - --spec(disco_local_features/5 :: -( - Acc :: [xmlel()], - _From :: jid(), - To :: jid(), - NodeId :: <<>> | mod_pubsub:nodeId(), - Lang :: binary()) - -> [binary(),...] -). -disco_local_features(Acc, _From, To, <<>>, _Lang) -> - Host = To#jid.lserver, - Feats = case Acc of - {result, I} -> I; - _ -> [] - end, - {result, - Feats ++ - lists:map(fun (Feature) -> - <<(?NS_PUBSUB)/binary, "#", Feature/binary>> - end, - features(Host, <<>>))}; -disco_local_features(Acc, _From, _To, _Node, _Lang) -> - Acc. - -disco_local_items(Acc, _From, _To, <<>>, _Lang) -> Acc; -disco_local_items(Acc, _From, _To, _Node, _Lang) -> Acc. - -%disco_sm_identity(Acc, From, To, Node, Lang) -% when is_binary(Node) -> -% disco_sm_identity(Acc, From, To, iolist_to_binary(Node), -% Lang); --spec(disco_sm_identity/5 :: -( - Acc :: empty | [xmlel()], - From :: jid(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Lang :: binary()) - -> [xmlel()] -). -disco_sm_identity(empty, From, To, Node, Lang) -> - disco_sm_identity([], From, To, Node, Lang); -disco_sm_identity(Acc, From, To, Node, _Lang) -> - disco_identity(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From) - ++ Acc. - -disco_identity(_Host, <<>>, _From) -> - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}], - children = []}]; -disco_identity(Host, Node, From) -> - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options}) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - {result, _} -> - {result, - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"pep">>}], - children = []}, - #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"leaf">>} - | case get_option(Options, title) of - false -> []; - [Title] -> [{<<"name">>, Title}] - end], - children = []}]}; - _ -> {result, []} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> Result; - _ -> [] - end. - --spec(disco_sm_features/5 :: -( - Acc :: empty | {result, Features::[Feature::binary()]}, - From :: jid(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Lang :: binary()) - -> {result, Features::[Feature::binary()]} -). -%disco_sm_features(Acc, From, To, Node, Lang) -% when is_binary(Node) -> -% disco_sm_features(Acc, From, To, iolist_to_binary(Node), -% Lang); -disco_sm_features(empty, From, To, Node, Lang) -> - disco_sm_features({result, []}, From, To, Node, Lang); -disco_sm_features({result, OtherFeatures} = _Acc, From, To, Node, _Lang) -> - {result, - OtherFeatures ++ - disco_features(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From)}; -disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. - -disco_features(_Host, <<>>, _From) -> - [?NS_PUBSUB | [<<(?NS_PUBSUB)/binary, "#", Feature/binary>> - || Feature <- features(<<"pep">>)]]; -disco_features(Host, Node, From) -> - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options}) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - {result, _} -> - {result, - [?NS_PUBSUB | [<<(?NS_PUBSUB)/binary, "#", - Feature/binary>> - || Feature <- features(<<"pep">>)]]}; - _ -> {result, []} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> Result; - _ -> [] - end. - --spec(disco_sm_items/5 :: -( - Acc :: empty | {result, [xmlel()]}, - From :: jid(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Lang :: binary()) - -> {result, [xmlel()]} -). -%disco_sm_items(Acc, From, To, Node, Lang) -% when is_binary(Node) -> -% disco_sm_items(Acc, From, To, iolist_to_binary(Node), -% Lang); -disco_sm_items(empty, From, To, Node, Lang) -> - disco_sm_items({result, []}, From, To, Node, Lang); -disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> - {result, - lists:usort(OtherItems ++ - disco_items(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From))}; -disco_sm_items(Acc, _From, _To, _Node, _Lang) -> Acc. - --spec(disco_items/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid()) - -> [xmlel()] -). -disco_items(Host, <<>>, From) -> - Action = fun (#pubsub_node{nodeid = {_, NodeID}, - options = Options, type = Type, id = Idx}, - Acc) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, Options, Owners) of - {result, _} -> - [#xmlel{name = <<"item">>, - attrs = - [{<<"node">>, (NodeID)}, - {<<"jid">>, - case Host of - {_, _, _} -> - jlib:jid_to_string(Host); - _Host -> Host - end} - | case get_option(Options, title) of - false -> []; - [Title] -> [{<<"name">>, Title}] - end], - children = []} - | Acc]; - _ -> Acc - end - end, - case transaction_on_nodes(Host, Action, sync_dirty) of - {result, Items} -> Items; - _ -> [] - end; -disco_items(Host, Node, From) -> - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options}) -> - Owners = node_owners_call(Type, Idx), - case get_allowed_items_call(Host, Idx, From, Type, - Options, Owners) - of - {result, Items} -> - {result, - [#xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, - case Host of - {_, _, _} -> - jlib:jid_to_string(Host); - _Host -> Host - end}, - {<<"name">>, ItemID}], - children = []} - || #pubsub_item{itemid = {ItemID, _}} <- Items]}; - _ -> {result, []} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> Result; - _ -> [] - end. - -%% ------- -%% presence hooks handling functions -%% - -caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) - when Host =/= S -> - presence(Host, {presence, U, S, [R], JID}); -caps_update(_From, _To, _Feature) -> - ok. - -presence_probe(#jid{luser = U, lserver = S, lresource = R} = JID, JID, Pid) -> - presence(S, {presence, JID, Pid}), - presence(S, {presence, U, S, [R], JID}); -presence_probe(#jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}, _Pid) -> - %% ignore presence_probe from my other ressources - %% to not get duplicated last items - ok; -presence_probe(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = S} = JID, _Pid) -> - presence(S, {presence, U, S, [R], JID}); -presence_probe(_Host, _JID, _Pid) -> - %% ignore presence_probe from remote contacts, - %% those are handled via caps_update - ok. - -presence(ServerHost, Presence) -> - SendLoop = case - whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) - of - undefined -> - Host = host(ServerHost), - Plugins = plugins(Host), - PepOffline = case catch - ets:lookup(gen_mod:get_module_proc(ServerHost, - config), - ignore_pep_from_offline) - of - [{ignore_pep_from_offline, PO}] -> PO; - _ -> true - end, - State = #state{host = Host, server_host = ServerHost, - ignore_pep_from_offline = PepOffline, - plugins = Plugins}, - init_send_loop(ServerHost, State); - Pid -> Pid - end, - SendLoop ! Presence. - -%% ------- -%% subscription hooks handling functions -%% - -out_subscription(User, Server, JID, subscribed) -> - Owner = jlib:make_jid(User, Server, <<"">>), - {PUser, PServer, PResource} = jlib:jid_tolower(JID), - PResources = case PResource of - <<>> -> user_resources(PUser, PServer); - _ -> [PResource] - end, - presence(Server, - {presence, PUser, PServer, PResources, Owner}), - true; -out_subscription(_, _, _, _) -> true. - -in_subscription(_, User, Server, Owner, unsubscribed, - _) -> - unsubscribe_user(jlib:make_jid(User, Server, <<"">>), - Owner), - true; -in_subscription(_, _, _, _, _, _) -> true. - -unsubscribe_user(Entity, Owner) -> - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - Host = host(element(2, BJID)), - spawn(fun () -> - lists:foreach(fun (PType) -> - case node_action(Host, PType, - get_entity_subscriptions, - [Host, Entity]) of - {result, Subscriptions} -> - lists:foreach(fun ({#pubsub_node{options - = - Options, - id = - NodeId}, - subscribed, _, - JID}) -> - case - get_option(Options, - access_model) - of - presence -> - case - lists:member(BJID, - node_owners(Host, PType, NodeId)) - of - true -> - node_action(Host, - PType, - unsubscribe_node, - [NodeId, - Entity, - JID, - all]); - false -> - {result, - ok} - end; - _ -> - {result, ok} - end; - (_) -> ok - end, - Subscriptions); - Error -> - ?DEBUG("Error at node_action: ~p", [Error]) - end - end, - plugins(Host)) - end). - -%% ------- -%% user remove hook handling function -%% - -remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - Entity = jlib:make_jid(LUser, LServer, <<"">>), - Host = host(LServer), - HomeTreeBase = <<"/home/", LServer/binary, "/", LUser/binary>>, - spawn(fun () -> - lists:foreach(fun (PType) -> - {result, Subscriptions} = - node_action(Host, PType, - get_entity_subscriptions, - [Host, Entity]), - lists:foreach(fun ({#pubsub_node{id = - NodeId}, - _, _, JID}) -> - node_action(Host, - PType, - unsubscribe_node, - [NodeId, - Entity, - JID, - all]); - (_) -> ok - end, - Subscriptions), - {result, Affiliations} = - node_action(Host, PType, - get_entity_affiliations, - [Host, Entity]), - lists:foreach(fun ({#pubsub_node{nodeid - = - {H, - N}, - parents - = - []}, - owner}) -> - delete_node(H, N, - Entity); - ({#pubsub_node{nodeid - = - {H, - N}, - type = - <<"hometree">>}, - owner}) - when N == - HomeTreeBase -> - delete_node(H, N, - Entity); - ({#pubsub_node{id = - NodeId}, - publisher}) -> - node_action(Host, - PType, - set_affiliation, - [NodeId, - Entity, - none]); - (_) -> ok - end, - Affiliations) - end, - plugins(Host)) - end). - -handle_call(server_host, _From, State) -> - {reply, State#state.server_host, State}; -handle_call(plugins, _From, State) -> - {reply, State#state.plugins, State}; -handle_call(pep_mapping, _From, State) -> - {reply, State#state.pep_mapping, State}; -handle_call(nodetree, _From, State) -> - {reply, State#state.nodetree, State}; -handle_call(stop, _From, State) -> - {stop, normal, ok, State}. - -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- -%% @private -handle_cast(_Msg, State) -> {noreply, State}. - --spec(handle_info/2 :: -( - _ :: {route, From::jid(), To::jid(), Packet::xmlel()}, - State :: state()) - -> {noreply, state()} -). - -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- -%% @private -handle_info({route, From, To, Packet}, - #state{server_host = ServerHost, access = Access, - plugins = Plugins} = - State) -> - case catch do_route(ServerHost, Access, Plugins, - To#jid.lserver, From, To, Packet) - of - {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); - _ -> ok - end, - {noreply, State}; -handle_info(_Info, State) -> - {noreply, State}. - -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- -%% @private -terminate(_Reason, - #state{host = Host, server_host = ServerHost, - nodetree = TreePlugin, plugins = Plugins}) -> - ejabberd_router:unregister_route(Host), - case lists:member(?PEPNODE, Plugins) of - true -> - ejabberd_hooks:delete(caps_update, ServerHost, ?MODULE, - caps_update, 80), - ejabberd_hooks:delete(disco_sm_identity, ServerHost, - ?MODULE, disco_sm_identity, 75), - ejabberd_hooks:delete(disco_sm_features, ServerHost, - ?MODULE, disco_sm_features, 75), - ejabberd_hooks:delete(disco_sm_items, ServerHost, - ?MODULE, disco_sm_items, 75), - gen_iq_handler:remove_iq_handler(ejabberd_sm, - ServerHost, ?NS_PUBSUB), - gen_iq_handler:remove_iq_handler(ejabberd_sm, - ServerHost, ?NS_PUBSUB_OWNER); - false -> ok - end, - ejabberd_hooks:delete(sm_remove_connection_hook, - ServerHost, ?MODULE, on_user_offline, 75), - ejabberd_hooks:delete(disco_local_identity, ServerHost, - ?MODULE, disco_local_identity, 75), - ejabberd_hooks:delete(disco_local_features, ServerHost, - ?MODULE, disco_local_features, 75), - ejabberd_hooks:delete(disco_local_items, ServerHost, - ?MODULE, disco_local_items, 75), - ejabberd_hooks:delete(presence_probe_hook, ServerHost, - ?MODULE, presence_probe, 80), - ejabberd_hooks:delete(roster_in_subscription, - ServerHost, ?MODULE, in_subscription, 50), - ejabberd_hooks:delete(roster_out_subscription, - ServerHost, ?MODULE, out_subscription, 50), - ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, - remove_user, 50), - ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, - ?MODULE, remove_user, 50), - mod_disco:unregister_feature(ServerHost, ?NS_PUBSUB), - gen_mod:get_module_proc(ServerHost, ?LOOPNAME) ! stop, - terminate_plugins(Host, ServerHost, Plugins, - TreePlugin). - -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- -%% @private -code_change(_OldVsn, State, _Extra) -> {ok, State}. - --spec(do_route/7 :: -( - ServerHost :: binary(), - Access :: atom(), - Plugins :: [binary(),...], - Host :: mod_pubsub:hostPubsub(), - From :: jid(), - To :: jid(), - Packet :: xmlel()) - -> ok -). - -%%-------------------------------------------------------------------- -%%% Internal functions -%%-------------------------------------------------------------------- -do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> - #xmlel{name = Name, attrs = Attrs} = Packet, - case To of - #jid{luser = <<"">>, lresource = <<"">>} -> - case Name of - <<"iq">> -> - case jlib:iq_query_info(Packet) of - #iq{type = get, xmlns = ?NS_DISCO_INFO, sub_el = SubEl, - lang = Lang} = - IQ -> - #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), - Info = ejabberd_hooks:run_fold(disco_info, ServerHost, - [], - [ServerHost, ?MODULE, - <<"">>, <<"">>]), - Res = case iq_disco_info(Host, Node, From, Lang) of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = - [#xmlel{name = - <<"query">>, - attrs = - QAttrs, - children = - IQRes ++ - Info}]}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = get, xmlns = ?NS_DISCO_ITEMS, - sub_el = SubEl} = - IQ -> - #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), - Rsm = jlib:rsm_decode(IQ), - Res = case iq_disco_items(Host, Node, From, Rsm) of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = - [#xmlel{name = - <<"query">>, - attrs = - QAttrs, - children = - IQRes}]}) -% {error, Error} -> -% jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = IQType, xmlns = ?NS_PUBSUB, lang = Lang, - sub_el = SubEl} = - IQ -> - Res = case iq_pubsub(Host, ServerHost, From, IQType, - SubEl, Lang, Access, Plugins) - of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = IQRes}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = IQType, xmlns = ?NS_PUBSUB_OWNER, - lang = Lang, sub_el = SubEl} = - IQ -> - Res = case iq_pubsub_owner(Host, ServerHost, From, - IQType, SubEl, Lang) - of - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = IQRes}); - {error, Error} -> - jlib:make_error_reply(Packet, Error) - end, - ejabberd_router:route(To, From, Res); - #iq{type = get, xmlns = (?NS_VCARD) = XMLNS, - lang = Lang, sub_el = _SubEl} = - IQ -> - Res = IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"vCard">>, - attrs = [{<<"xmlns">>, XMLNS}], - children = iq_get_vcard(Lang)}]}, - ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); - #iq{type = set, xmlns = ?NS_COMMANDS} = IQ -> - Res = case iq_command(Host, ServerHost, From, IQ, - Access, Plugins) - of - {error, Error} -> - jlib:make_error_reply(Packet, Error); - {result, IQRes} -> - jlib:iq_to_xml(IQ#iq{type = result, - sub_el = IQRes}) - end, - ejabberd_router:route(To, From, Res); - #iq{} -> - Err = jlib:make_error_reply(Packet, - ?ERR_FEATURE_NOT_IMPLEMENTED), - ejabberd_router:route(To, From, Err); - _ -> ok - end; - <<"message">> -> - case xml:get_attr_s(<<"type">>, Attrs) of - <<"error">> -> ok; - _ -> - case find_authorization_response(Packet) of - none -> ok; - invalid -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, - ?ERR_BAD_REQUEST)); - XFields -> - handle_authorization_response(Host, From, To, - Packet, XFields) - end - end; - _ -> ok - end; - _ -> - case xml:get_attr_s(<<"type">>, Attrs) of - <<"error">> -> ok; - <<"result">> -> ok; - _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_ITEM_NOT_FOUND), - ejabberd_router:route(To, From, Err) - end - end. - -command_disco_info(_Host, ?NS_COMMANDS, _From) -> - IdentityEl = #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"automation">>}, - {<<"type">>, <<"command-list">>}], - children = []}, - {result, [IdentityEl]}; -command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, - _From) -> - IdentityEl = #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"automation">>}, - {<<"type">>, <<"command-node">>}], - children = []}, - FeaturesEl = #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_COMMANDS}], children = []}, - {result, [IdentityEl, FeaturesEl]}. - -node_disco_info(Host, Node, From) -> - node_disco_info(Host, Node, From, true, true). - -node_disco_info(Host, Node, From, _Identity, _Features) -> -% Action = -% fun(#pubsub_node{type = Type, id = NodeId}) -> -% I = case Identity of -% false -> -% []; -% true -> -% Types = -% case tree_call(Host, get_subnodes, [Host, Node, From]) of -% [] -> -% [<<"leaf">>]; %% No sub-nodes: it's a leaf node -% _ -> -% case node_call(Type, get_items, [NodeId, From, none]) of -% {result, []} -> [<<"collection">>]; -% {result, _} -> [<<"leaf">>, <<"collection">>]; -% _ -> [] -% end -% end, -% lists:map(fun(T) -> -% #xmlel{name = <<"identity">>, -% attrs = -% [{<<"category">>, -% <<"pubsub">>}, -% {<<"type">>, T}], -% children = []} -% end, Types) -% end, -% F = case Features of -% false -> -% []; -% true -> -% [#xmlel{name = <<"feature">>, -% attrs = [{<<"var">>, ?NS_PUBSUB}], -% children = []} -% | lists:map(fun -% (<<"rsm">>)-> -% #xmlel{name = <<"feature">>, -% attrs = [{<<"var">>, ?NS_RSM}]}; -% (T) -> -% #xmlel{name = <<"feature">>, -% attrs = -% [{<<"var">>, -% <<(?NS_PUBSUB)/binary, -% "#", -% T/binary>>}], -% children = []} -% end, -% features(Type))] -% end, -% %% TODO: add meta-data info (spec section 5.4) -% {result, I ++ F} -% end, -% case transaction(Host, Node, Action, sync_dirty) of -% {result, {_, Result}} -> {result, Result}; -% Other -> Other -% end. - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - Types = case tree_call(Host, get_subnodes, - [Host, Node, From]) - of - [] -> [<<"leaf">>]; - _ -> - case node_call(Type, get_items, - [NodeId, From, none]) - of - {result, []} -> - [<<"collection">>]; - {result, _} -> - [<<"leaf">>, - <<"collection">>]; - _ -> [] - end - end, - I = lists:map(fun (T) -> - #xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, - <<"pubsub">>}, - {<<"type">>, T}], - children = []} - end, - Types), - F = [#xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_PUBSUB}], - children = []} - | lists:map(fun - (<<"rsm">>)-> - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_RSM}]}; - (T) -> - #xmlel{name = <<"feature">>, - attrs = - [{<<"var">>, - <<(?NS_PUBSUB)/binary, - "#", - T/binary>>}], - children = []} - end, - features(Type))], - {result, I ++ F} - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end. - -iq_disco_info(Host, SNode, From, Lang) -> - [Node | _] = case SNode of - <<>> -> [<<>>]; - _ -> str:tokens(SNode, <<"!">>) - end, - % Node = string_to_node(RealSNode), - case Node of - <<>> -> - {result, - [#xmlel{name = <<"identity">>, - attrs = - [{<<"category">>, <<"pubsub">>}, - {<<"type">>, <<"service">>}, - {<<"name">>, - translate:translate(Lang, <<"Publish-Subscribe">>)}], - children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_DISCO_INFO}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_DISCO_ITEMS}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_PUBSUB}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_COMMANDS}], children = []}, - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_VCARD}], children = []}] - ++ - lists:map(fun - (<<"rsm">>)-> - #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_RSM}]}; - (Feature) -> - #xmlel{name = <<"feature">>, - attrs = - [{<<"var">>, <<(?NS_PUBSUB)/binary, "#", Feature/binary>>}], - children = []} - end, - features(Host, Node))}; - ?NS_COMMANDS -> command_disco_info(Host, Node, From); - ?NS_PUBSUB_GET_PENDING -> - command_disco_info(Host, Node, From); - _ -> node_disco_info(Host, Node, From) - end. - --spec(iq_disco_items/4 :: -( - Host :: mod_pubsub:host(), - NodeId :: <<>> | mod_pubsub:nodeId(), - From :: jid(), - Rsm :: any()) - -> {result, [xmlel()]} -). -iq_disco_items(Host, <<>>, From, _RSM) -> - {result, - lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, - options = Options}) -> - Attrs = case get_option(Options, title) of - false -> - [{<<"jid">>, Host} - | nodeAttr(SubNode)]; - Title -> - [{<<"jid">>, Host}, - {<<"name">>, Title} - | nodeAttr(SubNode)] - end, - #xmlel{name = <<"item">>, attrs = Attrs, - children = []} - end, - tree_action(Host, get_subnodes, [Host, <<>>, From]))}; -% case tree_action(Host, get_subnodes, [Host, <<>>, From]) of -% Nodes when is_list(Nodes) -> -% {result, -% lists:map(fun (#pubsub_node{nodeid = {_, SubNode}, -% options = Options}) -> -% Attrs = case get_option(Options, title) of -% false -> -% [{<<"jid">>, Host} -% | nodeAttr(SubNode)]; -% Title -> -% [{<<"jid">>, Host}, -% {<<"name">>, Title} -% | nodeAttr(SubNode)] -% end, -% #xmlel{name = <<"item">>, attrs = Attrs, -% children = []} -% end, -% Nodes)}; -% Other -> Other -% end; -iq_disco_items(Host, ?NS_COMMANDS, _From, _RSM) -> - CommandItems = [#xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, Host}, - {<<"node">>, ?NS_PUBSUB_GET_PENDING}, - {<<"name">>, <<"Get Pending">>}], - children = []}], - {result, CommandItems}; -iq_disco_items(_Host, ?NS_PUBSUB_GET_PENDING, _From, _RSM) -> - CommandItems = [], {result, CommandItems}; -iq_disco_items(Host, Item, From, RSM) -> - case str:tokens(Item, <<"!">>) of - [_Node, _ItemID] -> {result, []}; - [Node] -> -% Node = string_to_node(SNode), - Action = fun (#pubsub_node{id = Idx, type = Type, - options = Options}) -> - Owners = node_owners_call(Type, Idx), - {NodeItems, RsmOut} = case get_allowed_items_call(Host, Idx, From, Type, Options, Owners, RSM) of - {result, R} -> R; - _ -> {[], none} - end, - Nodes = lists:map(fun (#pubsub_node{nodeid = - {_, SubNode}, - options = - SubOptions}) -> - Attrs = case - get_option(SubOptions, - title) - of - false -> - [{<<"jid">>, - Host} - | nodeAttr(SubNode)]; - Title -> - [{<<"jid">>, - Host}, - {<<"name">>, - Title} - | nodeAttr(SubNode)] - end, - #xmlel{name = <<"item">>, - attrs = Attrs, - children = []} - end, - tree_call(Host, get_subnodes, - [Host, Node, From])), - Items = lists:map(fun (#pubsub_item{itemid = - {RN, _}}) -> - {result, Name} = - node_call(Type, - get_item_name, - [Host, Node, - RN]), - #xmlel{name = <<"item">>, - attrs = - [{<<"jid">>, - Host}, - {<<"name">>, - Name}], - children = []} - end, - NodeItems), - {result, Nodes ++ Items ++ jlib:rsm_encode(RsmOut)} - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end - end. - --spec(iq_sm/3 :: -( - From :: jid(), - To :: jid(), - IQ :: iq_request()) - -> iq_result() | iq_error() -). -iq_sm(From, To, #iq{type = Type, sub_el = SubEl, xmlns = XMLNS, lang = Lang} = IQ) -> - ServerHost = To#jid.lserver, - LOwner = jlib:jid_tolower(jlib:jid_remove_resource(To)), - Res = case XMLNS of - ?NS_PUBSUB -> - iq_pubsub(LOwner, ServerHost, From, Type, SubEl, Lang); - ?NS_PUBSUB_OWNER -> - iq_pubsub_owner(LOwner, ServerHost, From, Type, SubEl, - Lang) - end, - case Res of - {result, IQRes} -> IQ#iq{type = result, sub_el = IQRes}; - {error, Error} -> - IQ#iq{type = error, sub_el = [Error, SubEl]} - end. - -iq_get_vcard(Lang) -> - [#xmlel{name = <<"FN">>, attrs = [], - children = [{xmlcdata, <<"ejabberd/mod_pubsub">>}]}, - #xmlel{name = <<"URL">>, attrs = [], - children = [{xmlcdata, ?EJABBERD_URI}]}, - #xmlel{name = <<"DESC">>, attrs = [], - children = - [{xmlcdata, - <<(translate:translate(Lang, - <<"ejabberd Publish-Subscribe module">>))/binary, - "\nCopyright (c) 2004-2015 ProcessOne">>}]}]. - --spec(iq_pubsub/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - From :: jid(), - IQType :: 'get' | 'set', - SubEl :: xmlel(), - Lang :: binary()) - -> {result, [xmlel()]} - %%% - | {error, xmlel()} -). - -iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) -> - iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(ServerHost)). - --spec(iq_pubsub/8 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - From :: jid(), - IQType :: 'get' | 'set', - SubEl :: xmlel(), - Lang :: binary(), - Access :: atom(), - Plugins :: [binary(),...]) - -> {result, [xmlel()]} - %%% - | {error, xmlel()} -). - -iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> - #xmlel{children = SubEls} = SubEl, - case xml:remove_cdata(SubEls) of - [#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] -> - Node = xml:get_attr_s(<<"node">>, Attrs), - case {IQType, Name} of - {set, <<"create">>} -> - Config = case Rest of - [#xmlel{name = <<"configure">>, children = C}] -> C; - _ -> [] - end, - Type = case xml:get_attr_s(<<"type">>, Attrs) of - <<>> -> hd(Plugins); - T -> T - end, - case lists:member(Type, Plugins) of - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"create-nodes">>)}; - true -> - create_node(Host, ServerHost, Node, From, Type, Access, Config) - end; - {set, <<"publish">>} -> - case xml:remove_cdata(Els) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs, - children = Payload}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), - publish_item(Host, ServerHost, Node, From, ItemId, Payload, Access); - [] -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; - _ -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)} - end; - {set, <<"retract">>} -> - ForceNotify = case xml:get_attr_s(<<"notify">>, Attrs) - of - <<"1">> -> true; - <<"true">> -> true; - _ -> false - end, - case xml:remove_cdata(Els) of - [#xmlel{name = <<"item">>, attrs = ItemAttrs}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), - delete_item(Host, Node, From, ItemId, ForceNotify); - _ -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)} - end; - {set, <<"subscribe">>} -> - Config = case Rest of - [#xmlel{name = <<"options">>, children = C}] -> C; - _ -> [] - end, - JID = xml:get_attr_s(<<"jid">>, Attrs), - subscribe_node(Host, Node, From, JID, Config); - {set, <<"unsubscribe">>} -> - JID = xml:get_attr_s(<<"jid">>, Attrs), - SubId = xml:get_attr_s(<<"subid">>, Attrs), - unsubscribe_node(Host, Node, From, JID, SubId); - {get, <<"items">>} -> - MaxItems = xml:get_attr_s(<<"max_items">>, Attrs), - SubId = xml:get_attr_s(<<"subid">>, Attrs), - ItemIDs = lists:foldl(fun (#xmlel{name = <<"item">>, - attrs = ItemAttrs}, - Acc) -> - case xml:get_attr_s(<<"id">>, - ItemAttrs) - of - <<"">> -> Acc; - ItemID -> [ItemID | Acc] - end; - (_, Acc) -> Acc - end, - [], xml:remove_cdata(Els)), - RSM = jlib:rsm_decode(SubEl), - get_items(Host, Node, From, SubId, MaxItems, ItemIDs, RSM); - {get, <<"subscriptions">>} -> - get_subscriptions(Host, Node, From, Plugins); - {get, <<"affiliations">>} -> - get_affiliations(Host, Node, From, Plugins); - {get, <<"options">>} -> - SubID = xml:get_attr_s(<<"subid">>, Attrs), - JID = xml:get_attr_s(<<"jid">>, Attrs), - get_options(Host, Node, JID, SubID, Lang); - {set, <<"options">>} -> - SubID = xml:get_attr_s(<<"subid">>, Attrs), - JID = xml:get_attr_s(<<"jid">>, Attrs), - set_options(Host, Node, JID, SubID, Els); - _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} - end; - Other -> - ?INFO_MSG("Too many actions: ~p", [Other]), - {error, ?ERR_BAD_REQUEST} - end. - - --spec(iq_pubsub_owner/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - From :: jid(), - IQType :: 'get' | 'set', - SubEl :: xmlel(), - Lang :: binary()) - -> {result, [xmlel()]} - %%% - | {error, xmlel()} -). -iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> - #xmlel{children = SubEls} = SubEl, - Action = lists:filter(fun(#xmlel{name = <<"set">>, _ = '_'}) -> false; - (_) -> true - end, xml:remove_cdata(SubEls)), - case Action of - [#xmlel{name = Name, attrs = Attrs, children = Els}] -> - Node = xml:get_attr_s(<<"node">>, Attrs), - case {IQType, Name} of - {get, <<"configure">>} -> - get_configure(Host, ServerHost, Node, From, Lang); - {set, <<"configure">>} -> - set_configure(Host, Node, From, Els, Lang); - {get, <<"default">>} -> - get_default(Host, Node, From, Lang); - {set, <<"delete">>} -> delete_node(Host, Node, From); - {set, <<"purge">>} -> purge_node(Host, Node, From); - {get, <<"subscriptions">>} -> - get_subscriptions(Host, Node, From); - {set, <<"subscriptions">>} -> - set_subscriptions(Host, Node, From, - xml:remove_cdata(Els)); - {get, <<"affiliations">>} -> - get_affiliations(Host, Node, From); - {set, <<"affiliations">>} -> - set_affiliations(Host, Node, From, xml:remove_cdata(Els)); - _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} - end; - _ -> - ?INFO_MSG("Too many actions: ~p", [Action]), - {error, ?ERR_BAD_REQUEST} - end. - -iq_command(Host, ServerHost, From, IQ, Access, Plugins) -> - case adhoc:parse_request(IQ) of - Req when is_record(Req, adhoc_request) -> - case adhoc_request(Host, ServerHost, From, Req, Access, - Plugins) - of - Resp when is_record(Resp, adhoc_response) -> - {result, [adhoc:produce_response(Req, Resp)]}; - Error -> Error - end; - Err -> Err - end. - -%% @doc

    Processes an Ad Hoc Command.

    -adhoc_request(Host, _ServerHost, Owner, - #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - lang = Lang, action = <<"execute">>, - xdata = false}, - _Access, Plugins) -> - send_pending_node_form(Host, Owner, Lang, Plugins); -adhoc_request(Host, _ServerHost, Owner, - #adhoc_request{node = ?NS_PUBSUB_GET_PENDING, - action = <<"execute">>, xdata = XData}, - _Access, _Plugins) -> - ParseOptions = case XData of - #xmlel{name = <<"x">>} = XEl -> - case jlib:parse_xdata_submit(XEl) of - invalid -> {error, ?ERR_BAD_REQUEST}; - XData2 -> - case set_xoption(Host, XData2, []) of - NewOpts when is_list(NewOpts) -> - {result, NewOpts}; - Err -> Err - end - end; - _ -> - ?INFO_MSG("Bad XForm: ~p", [XData]), - {error, ?ERR_BAD_REQUEST} - end, - case ParseOptions of - {result, XForm} -> - case lists:keysearch(node, 1, XForm) of - {value, {_, Node}} -> - send_pending_auth_events(Host, Node, Owner); - false -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"bad-payload">>)} - end; - Error -> Error - end; -adhoc_request(_Host, _ServerHost, _Owner, - #adhoc_request{action = <<"cancel">>}, _Access, - _Plugins) -> - #adhoc_response{status = canceled}; -adhoc_request(Host, ServerHost, Owner, - #adhoc_request{action = <<>>} = R, Access, Plugins) -> - adhoc_request(Host, ServerHost, Owner, - R#adhoc_request{action = <<"execute">>}, Access, - Plugins); -adhoc_request(_Host, _ServerHost, _Owner, Other, - _Access, _Plugins) -> - ?DEBUG("Couldn't process ad hoc command:~n~p", [Other]), - {error, ?ERR_ITEM_NOT_FOUND}. - -%% @spec (Host, Owner, Lang, Plugins) -> iqRes() -%% @doc

    Sends the process pending subscriptions XForm for Host to -%% Owner.

    -send_pending_node_form(Host, Owner, _Lang, Plugins) -> - Filter = fun (Plugin) -> - lists:member(<<"get-pending">>, features(Plugin)) - end, - case lists:filter(Filter, Plugins) of - [] -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED}; - Ps -> - XOpts = lists:map(fun (Node) -> - #xmlel{name = <<"option">>, attrs = [], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Node}]}]} - end, - get_pending_nodes(Host, Owner, Ps)), - XForm = #xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [#xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"list-single">>}, - {<<"var">>, <<"pubsub#node">>}], - children = lists:usort(XOpts)}]}, - #adhoc_response{status = executing, - defaultaction = <<"execute">>, elements = [XForm]} - end. - -get_pending_nodes(Host, Owner, Plugins) -> - Tr = fun (Type) -> - case node_call(Type, get_pending_nodes, [Host, Owner]) - of - {result, Nodes} -> Nodes; - _ -> [] - end - end, - case transaction(Host, - fun () -> - {result, lists:flatmap(Tr, Plugins)} - end, - sync_dirty) - of - {result, Res} -> Res; - Err -> Err - end. - -%% @spec (Host, Node, Owner) -> iqRes() -%% @doc

    Send a subscription approval form to Owner for all pending -%% subscriptions on Host and Node.

    -send_pending_auth_events(Host, Node, Owner) -> - ?DEBUG("Sending pending auth events for ~s on " - "~s:~s", - [jlib:jid_to_string(Owner), Host, Node]), - Action = fun (#pubsub_node{id = NodeID, type = Type}) -> - case lists:member(<<"get-pending">>, features(Type)) of - true -> - case node_call(Type, get_affiliation, - [NodeID, Owner]) - of - {result, owner} -> - node_call(Type, get_node_subscriptions, - [NodeID]); - _ -> {error, ?ERR_FORBIDDEN} - end; - false -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {N, Subscriptions}} -> - lists:foreach(fun ({J, pending, _SubID}) -> - send_authorization_request(N, jlib:make_jid(J)); - ({J, pending}) -> - send_authorization_request(N, jlib:make_jid(J)); - (_) -> ok - end, - Subscriptions), - #adhoc_response{}; - Err -> Err - end. - -%%% authorization handling - -send_authorization_request(#pubsub_node{nodeid = {Host, Node}, - type = Type, id = NodeId}, - Subscriber) -> - Lang = <<"en">>, - Stanza = #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - [#xmlel{name = <<"title">>, attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, - <<"PubSub subscriber request">>)}]}, - #xmlel{name = <<"instructions">>, - attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, - <<"Choose whether to approve this entity's " - "subscription.">>)}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"FORM_TYPE">>}, - {<<"type">>, <<"hidden">>}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - ?NS_PUBSUB_SUB_AUTH}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"pubsub#node">>}, - {<<"type">>, - <<"text-single">>}, - {<<"label">>, - translate:translate(Lang, - <<"Node ID">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Node}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, - <<"pubsub#subscriber_jid">>}, - {<<"type">>, <<"jid-single">>}, - {<<"label">>, - translate:translate(Lang, - <<"Subscriber Address">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - jlib:jid_to_string(Subscriber)}]}]}, - #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, - <<"pubsub#allow">>}, - {<<"type">>, <<"boolean">>}, - {<<"label">>, - translate:translate(Lang, - <<"Allow this Jabber ID to subscribe to " - "this pubsub node?">>)}], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, - <<"false">>}]}]}]}]}, - lists:foreach(fun (Owner) -> - ejabberd_router:route(service_jid(Host), - jlib:make_jid(Owner), Stanza) - end, - node_owners(Host, Type, NodeId)). - -find_authorization_response(Packet) -> - #xmlel{children = Els} = Packet, - XData1 = lists:map(fun (#xmlel{name = <<"x">>, - attrs = XAttrs} = - XEl) -> - case xml:get_attr_s(<<"xmlns">>, XAttrs) of - ?NS_XDATA -> - case xml:get_attr_s(<<"type">>, XAttrs) of - <<"cancel">> -> none; - _ -> jlib:parse_xdata_submit(XEl) - end; - _ -> none - end; - (_) -> none - end, - xml:remove_cdata(Els)), - XData = lists:filter(fun (E) -> E /= none end, XData1), - case XData of - [invalid] -> invalid; - [] -> none; - [XFields] when is_list(XFields) -> - ?DEBUG("XFields: ~p", [XFields]), - case lists:keysearch(<<"FORM_TYPE">>, 1, XFields) of - {value, {_, [?NS_PUBSUB_SUB_AUTH]}} -> XFields; - _ -> invalid - end - end. -%% @spec (Host, JID, Node, Subscription) -> void -%% Host = mod_pubsub:host() -%% JID = jlib:jid() -%% SNode = string() -%% Subscription = atom() | {atom(), mod_pubsub:subid()} -%% @doc Send a message to JID with the supplied Subscription -%% TODO : ask Christophe's opinion -send_authorization_approval(Host, JID, SNode, Subscription) -> - SubAttrs = case Subscription of -% {S, SID} -> -% [{<<"subscription">>, subscription_to_string(S)}, -% {<<"subid">>, SID}]; - S -> [{<<"subscription">>, subscription_to_string(S)}] - end, - Stanza = event_stanza([#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, jlib:jid_to_string(JID)} - | nodeAttr(SNode)] - ++ SubAttrs, - children = []}]), - ejabberd_router:route(service_jid(Host), JID, Stanza). - -handle_authorization_response(Host, From, To, Packet, XFields) -> - case {lists:keysearch(<<"pubsub#node">>, 1, XFields), - lists:keysearch(<<"pubsub#subscriber_jid">>, 1, XFields), - lists:keysearch(<<"pubsub#allow">>, 1, XFields)} - of - {{value, {_, [Node]}}, {value, {_, [SSubscriber]}}, - {value, {_, [SAllow]}}} -> -% Node = string_to_node(SNode), - Subscriber = jlib:string_to_jid(SSubscriber), - Allow = case SAllow of - <<"1">> -> true; - <<"true">> -> true; - _ -> false - end, - Action = fun (#pubsub_node{type = Type, - id = NodeId}) -> - IsApprover = - lists:member(jlib:jid_tolower(jlib:jid_remove_resource(From)), - node_owners_call(Type, NodeId)), - {result, Subscriptions} = node_call(Type, - get_subscriptions, - [NodeId, - Subscriber]), - if not IsApprover -> {error, ?ERR_FORBIDDEN}; - true -> - update_auth(Host, Node, Type, NodeId, - Subscriber, Allow, Subscriptions) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {error, Error} -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, Error)); - {result, {_, _NewSubscription}} -> - %% XXX: notify about subscription state change, section 12.11 - ok; - _ -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, - ?ERR_INTERNAL_SERVER_ERROR)) - end; - _ -> - ejabberd_router:route(To, From, - jlib:make_error_reply(Packet, - ?ERR_NOT_ACCEPTABLE)) - end. - -update_auth(Host, Node, Type, NodeId, Subscriber, Allow, - Subscriptions) -> - Subscription = lists:filter(fun ({pending, _}) -> true; - (_) -> false - end, - Subscriptions), - case Subscription of - [{pending, SubID}] -> - NewSubscription = case Allow of - true -> subscribed; - false -> none - end, - node_call(Type, set_subscriptions, - [NodeId, Subscriber, NewSubscription, SubID]), - send_authorization_approval(Host, Subscriber, Node, - NewSubscription), - {result, ok}; - _ -> {error, ?ERR_UNEXPECTED_REQUEST} - end. - --define(XFIELD(Type, Label, Var, Val), - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]}]}). - --define(BOOLXFIELD(Label, Var, Val), - ?XFIELD(<<"boolean">>, Label, Var, - case Val of - true -> <<"1">>; - _ -> <<"0">> - end)). - --define(STRINGXFIELD(Label, Var, Val), - ?XFIELD(<<"text-single">>, Label, Var, Val)). - --define(STRINGMXFIELD(Label, Var, Vals), - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"text-multi">>}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, V}]} - || V <- Vals]}). - --define(XFIELDOPT(Type, Label, Var, Val, Opts), - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - lists:map(fun (Opt) -> - #xmlel{name = <<"option">>, attrs = [], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Opt}]}]} - end, - Opts) - ++ - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]}]}). - --define(LISTXFIELD(Label, Var, Val, Opts), - ?XFIELDOPT(<<"list-single">>, Label, Var, Val, Opts)). - --define(LISTMXFIELD(Label, Var, Vals, Opts), -%% @spec (Host::host(), ServerHost::host(), Node::pubsubNode(), Owner::jid(), NodeType::nodeType()) -> -%% {error, Reason::stanzaError()} | -%% {result, []} -%% @doc

    Create new pubsub nodes

    -%%

    In addition to method-specific error conditions, there are several general reasons why the node creation request might fail:

    -%%
      -%%
    • The service does not support node creation.
    • -%%
    • Only entities that are registered with the service are allowed to create nodes but the requesting entity is not registered.
    • -%%
    • The requesting entity does not have sufficient privileges to create nodes.
    • -%%
    • The requested NodeID already exists.
    • -%%
    • The request did not include a NodeID and "instant nodes" are not supported.
    • -%%
    -%%

    ote: node creation is a particular case, error return code is evaluated at many places:

    -%%
      -%%
    • iq_pubsub checks if service supports node creation (type exists)
    • -%%
    • create_node checks if instant nodes are supported
    • -%%
    • create_node asks node plugin if entity have sufficient privilege
    • -%%
    • nodetree create_node checks if nodeid already exists
    • -%%
    • node plugin create_node just sets default affiliation/subscription
    • -%%
    - #xmlel{name = <<"field">>, - attrs = - [{<<"type">>, <<"list-multi">>}, - {<<"label">>, translate:translate(Lang, Label)}, - {<<"var">>, Var}], - children = - lists:map(fun (Opt) -> - #xmlel{name = <<"option">>, attrs = [], - children = - [#xmlel{name = <<"value">>, - attrs = [], - children = - [{xmlcdata, Opt}]}]} - end, - Opts) - ++ - lists:map(fun (Val) -> - #xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Val}]} - end, - Vals)}). - --spec(create_node/5 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: <<>> | mod_pubsub:nodeId(), - Owner :: jid(), - Type :: binary()) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). - -create_node(Host, ServerHost, Node, Owner, Type) -> - create_node(Host, ServerHost, Node, Owner, Type, all, []). - --spec(create_node/7 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: <<>> | mod_pubsub:nodeId(), - Owner :: jid(), - Type :: binary(), - Access :: atom(), - Configuration :: [xmlel()]) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) -> - case lists:member(<<"instant-nodes">>, features(Type)) of - true -> - NewNode = randoms:get_string(), - case create_node(Host, ServerHost, NewNode, Owner, Type, - Access, Configuration) - of - {result, _} -> - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"create">>, - attrs = nodeAttr(NewNode), - children = []}]}]}; - Error -> Error - end; - false -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, - <<"nodeid-required">>)} - end; -create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> - Type = select_type(ServerHost, Host, Node, GivenType), - ParseOptions = case xml:remove_cdata(Configuration) of - [] -> {result, node_options(Type)}; - [#xmlel{name = <<"x">>} = XEl] -> - case jlib:parse_xdata_submit(XEl) of - invalid -> {error, ?ERR_BAD_REQUEST}; - XData -> - case set_xoption(Host, XData, node_options(Type)) - of - NewOpts when is_list(NewOpts) -> - {result, NewOpts}; - Err -> Err - end - end; - _ -> - ?INFO_MSG("Node ~p; bad configuration: ~p", - [Node, Configuration]), - {error, ?ERR_BAD_REQUEST} - end, - case ParseOptions of - {result, NodeOptions} -> - CreateNode = - fun() -> - Parent = case node_call(Type, node_to_path, [Node]) of - {result, [Node]} -> <<>>; - {result, Path} -> element(2, node_call(Type, path_to_node, [lists:sublist(Path, length(Path)-1)])) - end, - Parents = case Parent of - <<>> -> []; - _ -> [Parent] - end, - case node_call(Type, create_node_permission, [Host, ServerHost, Node, Parent, Owner, Access]) of - {result, true} -> - case tree_call(Host, create_node, [Host, Node, Type, Owner, NodeOptions, Parents]) of - {ok, NodeId} -> - ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, Owner]), - SubsByDepth = [{Depth, [{N, get_node_subs(N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree], - case node_call(Type, create_node, [NodeId, Owner]) of - {result, Result} -> {result, {NodeId, SubsByDepth, Result}}; - Error -> Error - end; - {error, {virtual, NodeId}} -> - case node_call(Type, create_node, [NodeId, Owner]) of - {result, Result} -> {result, {NodeId, [], Result}}; - Error -> Error - end; - Error -> - Error - end; - _ -> - {error, ?ERR_FORBIDDEN} - end - end, - Reply = [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [#xmlel{name = <<"create">>, - attrs = nodeAttr(Node), - children = []}]}], - case transaction(Host, CreateNode, transaction) of - {result, {NodeId, SubsByDepth, {Result, broadcast}}} -> - broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth), - ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {NodeId, _SubsByDepth, default}} -> - ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]), - {result, Reply}; - {result, {NodeId, _SubsByDepth, _Result}} -> - ejabberd_hooks:run(pubsub_create_node, ServerHost, [ServerHost, Host, Node, NodeId, NodeOptions]), - {result, Reply}; - Error -> - %% in case we change transaction to sync_dirty... - %% node_call(Type, delete_node, [Host, Node]), - %% tree_call(Host, delete_node, [Host, Node]), - Error - end; - Error -> - Error - end. - -%% @spec (Host, Node, Owner) -> -%% {error, Reason} | {result, []} -%% Host = host() -%% Node = pubsubNode() -%% Owner = jid() -%% Reason = stanzaError() --spec(delete_node/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - Owner :: jid()) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -%% @doc

    Delete specified node and all childs.

    -%%

    There are several reasons why the node deletion request might fail:

    -%%
      -%%
    • The requesting entity does not have sufficient privileges to delete the node.
    • -%%
    • The node is the root collection node, which cannot be deleted.
    • -%%
    • The specified node does not exist.
    • -%%
    -delete_node(_Host, <<>>, _Owner) -> - {error, ?ERR_NOT_ALLOWED}; -delete_node(Host, Node, Owner) -> - Action = fun(#pubsub_node{type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, Owner]) of - {result, owner} -> - ParentTree = tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]), - SubsByDepth = [{Depth, [{N, get_node_subs(N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree], - Removed = tree_call(Host, delete_node, [Host, Node]), - case node_call(Type, delete_node, [Removed]) of - {result, Res} -> {result, {SubsByDepth, Res}}; - Error -> Error - end; - _ -> - %% Entity is not an owner - {error, ?ERR_FORBIDDEN} - end - end, - Reply = [], - ServerHost = get(server_host), - case transaction(Host, Node, Action, transaction) of - {result, {_TNode, {SubsByDepth, {Result, broadcast, Removed}}}} -> - lists:foreach(fun({RNode, _RSubscriptions}) -> - {RH, RN} = RNode#pubsub_node.nodeid, - NodeId = RNode#pubsub_node.id, - Type = RNode#pubsub_node.type, - Options = RNode#pubsub_node.options, - broadcast_removed_node(RH, RN, NodeId, Type, Options, SubsByDepth), - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId]) - end, Removed), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {_TNode, {_, {Result, Removed}}}} -> - lists:foreach(fun({RNode, _RSubscriptions}) -> - {RH, RN} = RNode#pubsub_node.nodeid, - NodeId = RNode#pubsub_node.id, - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, RH, RN, NodeId]) - end, Removed), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {TNode, {_, default}}} -> - NodeId = TNode#pubsub_node.id, - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]), - {result, Reply}; - {result, {TNode, {_, Result}}} -> - NodeId = TNode#pubsub_node.id, - ejabberd_hooks:run(pubsub_delete_node, ServerHost, [ServerHost, Host, Node, NodeId]), - {result, Result}; - Error -> - Error - end. - -%% @spec (Host, Node, From, JID, Configuration) -> -%% {error, Reason::stanzaError()} | -%% {result, []} -%% Host = host() -%% Node = pubsubNode() -%% From = jid() -%% JID = jid() --spec(subscribe_node/5 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - JID :: binary(), - Configuration :: [xmlel()]) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -%% @see node_hometree:subscribe_node/5 -%% @doc

    Accepts or rejects subcription requests on a PubSub node.

    -%%

    There are several reasons why the subscription request might fail:

    -%%
      -%%
    • The bare JID portions of the JIDs do not match.
    • -%%
    • The node has an access model of "presence" and the requesting entity is not subscribed to the owner's presence.
    • -%%
    • The node has an access model of "roster" and the requesting entity is not in one of the authorized roster groups.
    • -%%
    • The node has an access model of "whitelist" and the requesting entity is not on the whitelist.
    • -%%
    • The service requires payment for subscriptions to the node.
    • -%%
    • The requesting entity is anonymous and the service does not allow anonymous entities to subscribe.
    • -%%
    • The requesting entity has a pending subscription.
    • -%%
    • The requesting entity is blocked from subscribing (e.g., because having an affiliation of outcast).
    • -%%
    • The node does not support subscriptions.
    • -%%
    • The node does not exist.
    • -%%
    -subscribe_node(Host, Node, From, JID, Configuration) -> - SubOpts = case - pubsub_subscription_odbc:parse_options_xform(Configuration) - of - {result, GoodSubOpts} -> GoodSubOpts; - _ -> invalid - end, - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> - case jlib:jid_tolower(J) of - error -> {<<"">>, <<"">>, <<"">>}; - J1 -> J1 - end - end, - Action = fun (#pubsub_node{options = Options, - type = Type, id = NodeId}) -> - Features = features(Type), - SubscribeFeature = lists:member(<<"subscribe">>, Features), - OptionsFeature = lists:member(<<"subscription-options">>, Features), - HasOptions = not (SubOpts == []), - SubscribeConfig = get_option(Options, subscribe), - AccessModel = get_option(Options, access_model), - SendLast = get_option(Options, send_last_published_item), - AllowedGroups = get_option(Options, roster_groups_allowed, []), - Owners = node_owners_call(Type, NodeId), - {PresenceSubscription, RosterGroup} = - get_presence_and_roster_permissions(Host, Subscriber, - Owners, AccessModel, AllowedGroups), - if not SubscribeFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"subscribe">>)}; - not SubscribeConfig -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"subscribe">>)}; - HasOptions andalso not OptionsFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"subscription-options">>)}; - SubOpts == invalid -> - {error, - extended_error(?ERR_BAD_REQUEST, - <<"invalid-options">>)}; - true -> - node_call(Type, subscribe_node, - [NodeId, From, Subscriber, AccessModel, - SendLast, PresenceSubscription, - RosterGroup, SubOpts]) - end - end, - Reply = fun (Subscription) -> - SubAttrs = case Subscription of - {subscribed, SubId} -> - [{<<"subscription">>, - subscription_to_string(subscribed)}, - {<<"subid">>, SubId}, {<<"node">>, Node}]; - Other -> - [{<<"subscription">>, - subscription_to_string(Other)}, - {<<"node">>, Node}] - end, - Fields = [{<<"jid">>, jlib:jid_to_string(Subscriber)} - | SubAttrs], - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"subscription">>, - attrs = Fields, children = []}]}] - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, - {TNode, {Result, subscribed, SubId, send_last}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - send_items(Host, Node, NodeId, Type, Options, Subscriber, last), - case Result of - default -> {result, Reply({subscribed, SubId})}; - _ -> {result, Result} - end; - {result, {_TNode, {default, subscribed, SubId}}} -> - {result, Reply({subscribed, SubId})}; - {result, {_TNode, {Result, subscribed, _SubId}}} -> - {result, Result}; - {result, {TNode, {default, pending, _SubId}}} -> - send_authorization_request(TNode, Subscriber), - {result, Reply(pending)}; - {result, {TNode, {Result, pending}}} -> - send_authorization_request(TNode, Subscriber), - {result, Result}; - {result, {_, Result}} -> {result, Result}; - Error -> Error - end. - -%% @spec (Host, Noce, From, JID, SubId) -> {error, Reason} | {result, []} -%% Host = host() -%% Node = pubsubNode() -%% From = jid() -%% JID = string() -%% SubId = string() -%% Reason = stanzaError() -%% @doc

    Unsubscribe JID from the Node.

    -%%

    There are several reasons why the unsubscribe request might fail:

    -%%
      -%%
    • The requesting entity has multiple subscriptions to the node but does not specify a subscription ID.
    • -%%
    • The request does not specify an existing subscriber.
    • -%%
    • The requesting entity does not have sufficient privileges to unsubscribe the specified JID.
    • -%%
    • The node does not exist.
    • -%%
    • The request specifies a subscription ID that is not valid or current.
    • -%%
    --spec(unsubscribe_node/5 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - JID :: binary() | ljid(), - SubId :: mod_pubsub:subId()) - -> {result, []} - %%% - | {error, xmlel()} -). -unsubscribe_node(Host, Node, From, JID, SubId) - when is_binary(JID) -> - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> - case jlib:jid_tolower(J) of - error -> {<<"">>, <<"">>, <<"">>}; - J1 -> J1 - end - end, - unsubscribe_node(Host, Node, From, Subscriber, SubId); -unsubscribe_node(Host, Node, From, Subscriber, SubId) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, unsubscribe_node, - [NodeId, From, Subscriber, SubId]) - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, default}} -> {result, []}; -% {result, {_, Result}} -> {result, Result}; - Error -> Error - end. - -%% @spec (Host::host(), ServerHost::host(), JID::jid(), Node::pubsubNode(), ItemId::string(), Payload::term()) -> -%% {error, Reason::stanzaError()} | -%% {result, []} -%% @doc

    Publish item to a PubSub node.

    -%%

    The permission to publish an item must be verified by the plugin implementation.

    -%%

    There are several reasons why the publish request might fail:

    -%%
      -%%
    • The requesting entity does not have sufficient privileges to publish.
    • -%%
    • The node does not support item publication.
    • -%%
    • The node does not exist.
    • -%%
    • The payload size exceeds a service-defined limit.
    • -%%
    • The item contains more than one payload element or the namespace of the root payload element does not match the configured namespace for the node.
    • -%%
    • The request does not match the node configuration.
    • -%%
    --spec(publish_item/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: mod_pubsub:nodeId(), - Publisher :: jid(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> - publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, all). -publish_item(Host, ServerHost, Node, Publisher, <<>>, Payload, Access) -> - publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload, Access); -publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, Access) -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - PublishFeature = lists:member(<<"publish">>, Features), - PublishModel = get_option(Options, publish_model), - DeliverPayloads = get_option(Options, deliver_payloads), - PersistItems = get_option(Options, persist_items), - MaxItems = max_items(Host, Options), - PayloadCount = payload_xmlelements(Payload), - PayloadSize = byte_size(term_to_binary(Payload)) - 2, - PayloadMaxSize = get_option(Options, max_payload_size), - if not PublishFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"publish">>)}; - PayloadSize > PayloadMaxSize -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"payload-too-big">>)}; - (PayloadCount == 0) and (Payload == []) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"payload-required">>)}; - (PayloadCount > 1) or (PayloadCount == 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)}; - (DeliverPayloads == false) and (PersistItems == false) and - (PayloadSize > 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-forbidden">>)}; - ((DeliverPayloads == true) or (PersistItems == true)) and - (PayloadSize == 0) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; - true -> - node_call(Type, publish_item, [NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload]) - end - end, - ejabberd_hooks:run(pubsub_publish_item, ServerHost, [ServerHost, Node, Publisher, service_jid(Host), ItemId, Payload]), - Reply = [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"publish">>, attrs = nodeAttr(Node), - children = - [#xmlel{name = <<"item">>, - attrs = itemAttr(ItemId), - children = []}]}]}], - case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, Broadcast, Removed}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - case get_option(Options, deliver_notifications) of - true -> - BroadcastPayload = case Broadcast of - default -> Payload; - broadcast -> Payload; - PluginPayload -> PluginPayload - end, - broadcast_publish_item(Host, Node, NodeId, Type, Options, - Removed, ItemId, jlib:jid_tolower(Publisher), - BroadcastPayload); - false -> - ok - end, - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {TNode, {default, Removed}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), - {result, Reply}; - {result, {TNode, {Result, Removed}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, Options, Removed), - set_cached_item(Host, NodeId, ItemId, Publisher, Payload), - {result, Result}; - {result, {_, default}} -> - {result, Reply}; - {result, {_, Result}} -> - {result, Result}; - {error, ?ERR_ITEM_NOT_FOUND} -> - %% handles auto-create feature - %% for automatic node creation. we'll take the default node type: - %% first listed into the plugins configuration option, or pep - Type = select_type(ServerHost, Host, Node), - case lists:member(<<"auto-create">>, features(Type)) of - true -> - case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of - {result, [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"create">>, - attrs = [{<<"node">>, NewNode}], - children = []}]}]} -> - publish_item(Host, ServerHost, NewNode, - Publisher, ItemId, Payload); - _ -> - {error, ?ERR_ITEM_NOT_FOUND} - end; - false -> - {error, ?ERR_ITEM_NOT_FOUND} - end; - Error -> - Error - end. - -%% @spec (Host::host(), JID::jid(), Node::pubsubNode(), ItemId::string()) -> -%% {error, Reason::stanzaError()} | -%% {result, []} --spec(delete_item/4 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - Publisher :: jid(), - ItemId :: mod_pubsub:itemId()) - -> {result, []} - %%% - | {error, xmlel()} -). -%% @doc

    Delete item from a PubSub node.

    -%%

    The permission to delete an item must be verified by the plugin implementation.

    -%%

    There are several reasons why the item retraction request might fail:

    -%%
      -%%
    • The publisher does not have sufficient privileges to delete the requested item.
    • -%%
    • The node or item does not exist.
    • -%%
    • The request does not specify a node.
    • -%%
    • The request does not include an element or the element does not specify an ItemId.
    • -%%
    • The node does not support persistent items.
    • -%%
    • The service does not support the deletion of items.
    • -%%
    -delete_item(Host, Node, Publisher, ItemId) -> - delete_item(Host, Node, Publisher, ItemId, false). - - -delete_item(_, <<"">>, _, _, _) -> - {error, - extended_error(?ERR_BAD_REQUEST, <<"node-required">>)}; -delete_item(Host, Node, Publisher, ItemId, ForceNotify) -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - PersistentFeature = lists:member(<<"persistent-items">>, Features), - DeleteFeature = lists:member(<<"delete-items">>, Features), - PublishModel = get_option(Options, publish_model), - if %%-> iq_pubsub just does that matchs - %% %% Request does not specify an item - %% {error, extended_error(?ERR_BAD_REQUEST, "item-required")}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - not DeleteFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"delete-items">>)}; - true -> - node_call(Type, delete_item, - [NodeId, Publisher, PublishModel, ItemId]) - end - end, - Reply = [], - case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_retract_items(Host, Node, NodeId, Type, - Options, [ItemId], ForceNotify), - case get_cached_item(Host, NodeId) of - #pubsub_item{itemid = {ItemId, NodeId}} -> - unset_cached_item(Host, NodeId); - _ -> ok - end, - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {_, default}} -> {result, Reply}; - {result, {_, Result}} -> {result, Result}; - Error -> Error - end. - -%% @spec (Host, JID, Node) -> -%% {error, Reason} | {result, []} -%% Host = host() -%% Node = pubsubNode() -%% JID = jid() -%% Reason = stanzaError() -%% @doc

    Delete all items of specified node owned by JID.

    -%%

    There are several reasons why the node purge request might fail:

    -%%
      -%%
    • The node or service does not support node purging.
    • -%%
    • The requesting entity does not have sufficient privileges to purge the node.
    • -%%
    • The node is not configured to persist items.
    • -%%
    • The specified node does not exist.
    • -%%
    --spec(purge_node/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - Owner :: jid()) - -> {result, []} - %%% - | {error, xmlel()} -). -purge_node(Host, Node, Owner) -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - PurgeFeature = lists:member(<<"purge-nodes">>, Features), - PersistentFeature = lists:member(<<"persistent-items">>, Features), - PersistentConfig = get_option(Options, persist_items), - if not PurgeFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, <<"purge-nodes">>)}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - not PersistentConfig -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - true -> node_call(Type, purge_node, [NodeId, Owner]) - end - end, - Reply = [], - case transaction(Host, Node, Action, sync_dirty) of - {result, {TNode, {Result, broadcast}}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_purge_node(Host, Node, NodeId, Type, Options), - unset_cached_item(Host, NodeId), - case Result of - default -> {result, Reply}; - _ -> {result, Result} - end; - {result, {_, default}} -> {result, Reply}; - {result, {_, Result}} -> {result, Result}; - Error -> Error - end. - -%% @doc

    Return the items of a given node.

    -%%

    The number of items to return is limited by MaxItems.

    -%%

    The permission are not checked in this function.

    -%% @todo We probably need to check that the user doing the query has the right -%% to read the items. --spec(get_items/7 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - SubId :: mod_pubsub:subId(), - SMaxItems :: binary(), - ItemIDs :: [mod_pubsub:itemId()], - Rsm :: any()) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -get_items(Host, Node, From, SubId, SMaxItems, ItemIDs, RSM) -> - MaxItems = if SMaxItems == <<"">> -> - get_max_items_node(Host); - true -> - case catch jlib:binary_to_integer(SMaxItems) of - {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; - Val -> Val - end - end, - case MaxItems of - {error, Error} -> {error, Error}; - _ -> - Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> - Features = features(Type), - RetreiveFeature = lists:member(<<"retrieve-items">>, Features), - PersistentFeature = lists:member(<<"persistent-items">>, Features), - AccessModel = get_option(Options, access_model), - AllowedGroups = get_option(Options, roster_groups_allowed, []), - Owners = node_owners_call(Type, NodeId), - {PresenceSubscription, RosterGroup} = - get_presence_and_roster_permissions(Host, From, Owners, - AccessModel, AllowedGroups), - if not RetreiveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-items">>)}; - not PersistentFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"persistent-items">>)}; - true -> - node_call(Type, get_items, - [NodeId, From, AccessModel, - PresenceSubscription, RosterGroup, - SubId, RSM]) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, {Items, RSMOut}}} -> - SendItems = case ItemIDs of - [] -> Items; - _ -> - lists:filter(fun (#pubsub_item{itemid = - {ItemId, - _}}) -> - lists:member(ItemId, - ItemIDs) - end, - Items) - end, - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = - itemsEls(lists:sublist(SendItems, MaxItems))} - | jlib:rsm_encode(RSMOut)]}]}; - Error -> Error - end - end. - -get_items(Host, Node) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_items, [NodeId, service_jid(Host)]) - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Items}} -> Items; - Error -> Error - end. - -get_item(Host, Node, ItemId) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - node_call(Type, get_item, [NodeId, ItemId]) - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Items}} -> Items; - Error -> Error - end. - -get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners) -> - case get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners, none) of - {result, {I, _}} -> {result, I}; - Error -> Error - end. -get_allowed_items_call(Host, NodeIdx, From, Type, Options, Owners, RSM) -> - AccessModel = get_option(Options, access_model), - AllowedGroups = get_option(Options, roster_groups_allowed, []), - {PresenceSubscription, RosterGroup} = - get_presence_and_roster_permissions(Host, From, Owners, AccessModel, - AllowedGroups), - node_call(Type, get_items, - [NodeIdx, From, AccessModel, PresenceSubscription, RosterGroup, undefined, RSM]). - -%% @spec (Host, Node, NodeId, Type, LJID, Number) -> any() -%% Host = pubsubHost() -%% Node = pubsubNode() -%% NodeId = pubsubNodeId() -%% Type = pubsubNodeType() -%% Options = mod_pubsubnodeOptions() -%% LJID = {U, S, []} -%% Number = last | integer() -%% @doc

    Resend the items of a node to the user.

    -%% @todo use cache-last-item feature -send_items(Host, Node, NodeId, Type, Options, LJID, last) -> - Stanza = case get_cached_item(Host, NodeId) of - undefined -> - % special ODBC optimization, works only with node_hometree_odbc, node_flat_odbc and node_pep_odbc - case node_action(Host, Type, get_last_items, [NodeId, LJID, 1]) of - {result, [LastItem]} -> - {ModifNow, ModifUSR} = LastItem#pubsub_item.modification, - event_stanza_with_delay( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = itemsEls([LastItem])}], ModifNow, ModifUSR); - _ -> - event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = itemsEls([])}]) - end; - LastItem -> - {ModifNow, ModifUSR} = - LastItem#pubsub_item.modification, - event_stanza_with_delay([#xmlel{name = - <<"items">>, - attrs = nodeAttr(Node), - children = - itemsEls([LastItem])}], - ModifNow, ModifUSR) - end, - dispatch_items(Host, LJID, Node, Options, Stanza); -send_items(Host, Node, NodeId, Type, Options, LJID, Number) -> - ToSend = case node_action(Host, Type, get_items, - [NodeId, LJID]) - of - {result, []} -> []; - {result, Items} -> - case Number of - N when N > 0 -> lists:sublist(Items, N); - _ -> Items - end; - _ -> [] - end, - Stanza = case ToSend of - [] -> - undefined; - [LastItem] -> - {ModifNow, ModifUSR} = - LastItem#pubsub_item.modification, - event_stanza_with_delay([#xmlel{name = <<"items">>, - attrs = nodeAttr(Node), - children = - itemsEls(ToSend)}], - ModifNow, ModifUSR); - _ -> - event_stanza([#xmlel{name = <<"items">>, - attrs = nodeAttr(Node), - children = itemsEls(ToSend)}]) - end, - dispatch_items(Host, LJID, Node, Options, Stanza). - --spec(dispatch_items/5 :: -( - From :: mod_pubsub:host(), - To :: jid(), - Node :: mod_pubsub:nodeId(), - Options :: mod_pubsub:nodeOptions(), - Stanza :: xmlel() | undefined) - -> any() -). - -dispatch_items(_From, _To, _Node, _Options, _Stanza = undefined) -> ok; -dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To, Node, - Options, BaseStanza) -> - NotificationType = get_option(Options, notification_type, headline), - Stanza = add_message_type(BaseStanza, NotificationType), - C2SPid = case ejabberd_sm:get_session_pid(ToU, ToS, ToR) of - ToPid when is_pid(ToPid) -> ToPid; - _ -> - R = user_resource(FromU, FromS, FromR), - case ejabberd_sm:get_session_pid(FromU, FromS, R) of - FromPid when is_pid(FromPid) -> FromPid; - _ -> undefined - end - end, - if C2SPid == undefined -> ok; - true -> - ejabberd_c2s:send_filtered(C2SPid, - {pep_message, <>}, - service_jid(From), jlib:make_jid(To), - Stanza) - end; -dispatch_items(From, To, _Node, Options, BaseStanza) -> - NotificationType = get_option(Options, notification_type, headline), - Stanza = add_message_type(BaseStanza, NotificationType), - ejabberd_router:route(service_jid(From), jlib:make_jid(To), Stanza). - -%% @spec (Host, JID, Plugins) -> {error, Reason} | {result, Response} -%% Host = host() -%% JID = jid() -%% Plugins = [Plugin::string()] -%% Reason = stanzaError() -%% Response = [pubsubIQResponse()] -%% @doc

    Return the list of affiliations as an XMPP response.

    --spec(get_affiliations/4 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - JID :: jid(), - Plugins :: [binary()]) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -get_affiliations(Host, <<>>, JID, Plugins) - when is_list(Plugins) -> - Result = lists:foldl(fun (Type, {Status, Acc}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"retrieve-affiliations">>, Features), - if not RetrieveFeature -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affiliations} = - node_action(Host, Type, - get_entity_affiliations, - [Host, JID]), - {Status, [Affiliations | Acc]} - end - end, - {ok, []}, Plugins), - case Result of - {ok, Affiliations} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({#pubsub_node{nodeid = {_, Node}}, - Affiliation}) -> - [#xmlel{name = <<"affiliation">>, - attrs = - [{<<"affiliation">>, - affiliation_to_string(Affiliation)} - | nodeAttr(Node)], - children = []}] - end, - lists:usort(lists:flatten(Affiliations))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"affiliations">>, attrs = [], - children = Entities}]}]}; - {Error, _} -> Error - end; -get_affiliations(Host, NodeId, JID, Plugins) - when is_list(Plugins) -> - Result = lists:foldl(fun (Type, {Status, Acc}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"retrieve-affiliations">>, - Features), - if not RetrieveFeature -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affiliations} = - node_action(Host, Type, - get_entity_affiliations, - [Host, JID]), - {Status, [Affiliations | Acc]} - end - end, - {ok, []}, Plugins), - case Result of - {ok, Affiliations} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({#pubsub_node{nodeid = {_, Node}}, - Affiliation}) - when NodeId == Node -> - [#xmlel{name = <<"affiliation">>, - attrs = - [{<<"affiliation">>, - affiliation_to_string(Affiliation)} - | nodeAttr(Node)], - children = []}]; - (_) -> [] - end, - lists:usort(lists:flatten(Affiliations))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"affiliations">>, attrs = [], - children = Entities}]}]}; - {Error, _} -> Error - end. - --spec(get_affiliations/3 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - JID :: jid()) - -> {result, [xmlel(),...]} - %%% - | {error, xmlel()} -). -get_affiliations(Host, Node, JID) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"modify-affiliations">>, Features), - {result, Affiliation} = node_call(Type, get_affiliation, - [NodeId, JID]), - if not RetrieveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"modify-affiliations">>)}; - Affiliation /= owner -> {error, ?ERR_FORBIDDEN}; - true -> node_call(Type, get_node_affiliations, [NodeId]) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, []}} -> {error, ?ERR_ITEM_NOT_FOUND}; - {result, {_, Affiliations}} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({AJID, Affiliation}) -> - [#xmlel{name = <<"affiliation">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(AJID)}, - {<<"affiliation">>, - affiliation_to_string(Affiliation)}], - children = []}] - end, - Affiliations), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"affiliations">>, - attrs = nodeAttr(Node), children = Entities}]}]}; - Error -> Error - end. - --spec(set_affiliations/4 :: -( - Host :: mod_pubsub:host(), - Node :: mod_pubsub:nodeId(), - From :: jid(), - EntitiesEls :: [xmlel()]) - -> {result, []} - %%% - | {error, xmlel()} -). -set_affiliations(Host, Node, From, EntitiesEls) -> - Owner = jlib:jid_tolower(jlib:jid_remove_resource(From)), - Entities = lists:foldl(fun (El, Acc) -> - case Acc of - error -> error; - _ -> - case El of - #xmlel{name = <<"affiliation">>, - attrs = Attrs} -> - JID = - jlib:string_to_jid(xml:get_attr_s(<<"jid">>, - Attrs)), - Affiliation = - string_to_affiliation(xml:get_attr_s(<<"affiliation">>, - Attrs)), - if (JID == error) or - (Affiliation == false) -> - error; - true -> - [{jlib:jid_tolower(JID), - Affiliation} - | Acc] - end - end - end - end, - [], EntitiesEls), - case Entities of - error -> {error, ?ERR_BAD_REQUEST}; - _ -> - Action = fun (#pubsub_node{type = Type, - id = NodeId}) -> - Owners = node_owners_call(Type, NodeId), - case lists:member(Owner, Owners) of - true -> - OwnerJID = jlib:make_jid(Owner), - FilteredEntities = case Owners of - [Owner] -> - [E - || E <- Entities, - element(1, E) =/= - OwnerJID]; - _ -> Entities - end, - lists:foreach(fun ({JID, Affiliation}) -> - node_call(Type, set_affiliation, [NodeId, JID, Affiliation]) - end, - FilteredEntities), - {result, []}; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end - end. - -get_options(Host, Node, JID, SubID, Lang) -> - Action = fun (#pubsub_node{type = Type, id = NodeID}) -> - case lists:member(<<"subscription-options">>, features(Type)) of - true -> - get_options_helper(JID, Lang, Node, NodeID, SubID, Type); - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"subscription-options">>)} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_Node, XForm}} -> {result, [XForm]}; - Error -> Error - end. - -get_options_helper(JID, Lang, Node, NodeID, SubID, Type) -> - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> case jlib:jid_tolower(J) of - error -> {<<"">>, <<"">>, <<"">>}; - J1 -> J1 - end - end, - {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun ({subscribed, SID}, Acc) -> - [SID | Acc]; - (_, Acc) -> Acc - end, - [], Subs), - case {SubID, SubIDs} of - {_, []} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"not-subscribed">>)}; - {<<>>, [SID]} -> - read_sub(Subscriber, Node, NodeID, SID, Lang); - {<<>>, _} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"subid-required">>)}; - {_, _} -> - ValidSubId = lists:member(SubID, SubIDs), - if ValidSubId -> - read_sub(Subscriber, Node, NodeID, SubID, Lang); - true -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)} - end - end. - -read_sub(Subscriber, Node, NodeID, SubID, Lang) -> - Children = case pubsub_subscription_odbc:get_subscription(Subscriber, NodeID, SubID) of - {error, notfound} -> - []; - {result, #pubsub_subscription{options = Options}} -> - {result, XdataEl} = pubsub_subscription_odbc:get_options_xform(Lang, Options), - [XdataEl] - end, - OptionsEl = #xmlel{name = <<"options">>, - attrs = - [{<<"jid">>, jlib:jid_to_string(Subscriber)}, - {<<"subid">>, SubID} - | nodeAttr(Node)], - children = Children}, - PubsubEl = #xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = [OptionsEl]}, - {result, PubsubEl}. - -set_options(Host, Node, JID, SubID, Configuration) -> - Action = fun (#pubsub_node{type = Type, id = NodeID}) -> - case lists:member(<<"subscription-options">>, - features(Type)) - of - true -> - set_options_helper(Configuration, JID, NodeID, SubID, - Type); - false -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"subscription-options">>)} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_Node, Result}} -> {result, Result}; - Error -> Error - end. - -set_options_helper(Configuration, JID, NodeID, SubID, Type) -> - SubOpts = case pubsub_subscription_odbc:parse_options_xform(Configuration) of - {result, GoodSubOpts} -> GoodSubOpts; - _ -> invalid - end, - Subscriber = case jlib:string_to_jid(JID) of - error -> {<<"">>, <<"">>, <<"">>}; - J -> jlib:jid_tolower(J) - end, - {result, Subs} = node_call(Type, get_subscriptions, - [NodeID, Subscriber]), - SubIDs = lists:foldl(fun ({subscribed, SID}, Acc) -> - [SID | Acc]; - (_, Acc) -> Acc - end, - [], Subs), - case {SubID, SubIDs} of - {_, []} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, - <<"not-subscribed">>)}; - {<<>>, [SID]} -> - write_sub(Subscriber, NodeID, SID, SubOpts); - {<<>>, _} -> - {error, - extended_error(?ERR_NOT_ACCEPTABLE, - <<"subid-required">>)}; - {_, _} -> write_sub(Subscriber, NodeID, SubID, SubOpts) - end. - -write_sub(_Subscriber, _NodeID, _SubID, invalid) -> - {error, extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; -write_sub(Subscriber, NodeID, SubID, Options) -> - case pubsub_subscription_odbc:set_subscription(Subscriber, NodeID, SubID, Options) of - {error, notfound} -> - {error, extended_error(?ERR_NOT_ACCEPTABLE, <<"invalid-subid">>)}; - {result, _} -> - {result, []} - end. - -%% @spec (Host, Node, JID, Plugins) -> {error, Reason} | {result, Response} -%% Host = host() -%% Node = pubsubNode() -%% JID = jid() -%% Plugins = [Plugin::string()] -%% Reason = stanzaError() -%% Response = [pubsubIQResponse()] -%% @doc

    Return the list of subscriptions as an XMPP response.

    -get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> - Result = lists:foldl( - fun(Type, {Status, Acc}) -> - Features = features(Type), - RetrieveFeature = lists:member(<<"retrieve-subscriptions">>, Features), - if - not RetrieveFeature -> - %% Service does not support retreive subscriptions - {{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"retrieve-subscriptions">>)}, Acc}; - true -> - Subscriber = jlib:jid_remove_resource(JID), - {result, Subscriptions} = node_action(Host, Type, get_entity_subscriptions, [Host, Subscriber]), - {Status, [Subscriptions|Acc]} - end - end, {ok, []}, Plugins), - case Result of - {ok, Subscriptions} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, - Subscription}) -> - case Node of - <<>> -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"subscription">>, - subscription_to_string(Subscription)} - | nodeAttr(SubsNode)], - children = []}]; - SubsNode -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - _ -> [] - end; - ({_, none, _}) -> []; - ({#pubsub_node{nodeid = {_, SubsNode}}, - Subscription, SubID, SubJID}) -> - case Node of - <<>> -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subid">>, - SubID}, - {<<"subscription">>, - subscription_to_string(Subscription)} - | nodeAttr(SubsNode)], - children = []}]; - SubsNode -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subid">>, - SubID}, - {<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - _ -> [] - end; - ({#pubsub_node{nodeid = {_, SubsNode}}, - Subscription, SubJID}) -> - case Node of - <<>> -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)} - | nodeAttr(SubsNode)], - children = []}]; - SubsNode -> - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(SubJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - _ -> [] - end - end, - lists:usort(lists:flatten(Subscriptions))), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB}], - children = - [#xmlel{name = <<"subscriptions">>, attrs = [], - children = Entities}]}]}; - {Error, _} -> Error - end. - -get_subscriptions(Host, Node, JID) -> - Action = fun (#pubsub_node{type = Type, id = NodeId}) -> - Features = features(Type), - RetrieveFeature = - lists:member(<<"manage-subscriptions">>, Features), - {result, Affiliation} = node_call(Type, get_affiliation, - [NodeId, JID]), - if not RetrieveFeature -> - {error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"manage-subscriptions">>)}; - Affiliation /= owner -> {error, ?ERR_FORBIDDEN}; - true -> - node_call(Type, get_node_subscriptions, [NodeId]) - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Subscriptions}} -> - Entities = lists:flatmap(fun ({_, none}) -> []; - ({_, pending, _}) -> []; - ({AJID, Subscription}) -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(AJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)}], - children = []}]; - ({AJID, Subscription, SubId}) -> - [#xmlel{name = <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(AJID)}, - {<<"subscription">>, - subscription_to_string(Subscription)}, - {<<"subid">>, SubId}], - children = []}] - end, - Subscriptions), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"subscriptions">>, - attrs = nodeAttr(Node), children = Entities}]}]}; - Error -> Error - end. - -set_subscriptions(Host, Node, From, EntitiesEls) -> - Owner = - jlib:jid_tolower(jlib:jid_remove_resource(From)), - Entities = lists:foldl(fun (El, Acc) -> - case Acc of - error -> error; - _ -> - case El of - #xmlel{name = <<"subscription">>, - attrs = Attrs} -> - JID = - jlib:string_to_jid(xml:get_attr_s(<<"jid">>, - Attrs)), - Subscription = - string_to_subscription(xml:get_attr_s(<<"subscription">>, - Attrs)), - SubId = - xml:get_attr_s(<<"subid">>, - Attrs), - if (JID == error) or - (Subscription == false) -> - error; - true -> - [{jlib:jid_tolower(JID), - Subscription, SubId} - | Acc] - end - end - end - end, - [], EntitiesEls), - case Entities of - error -> {error, ?ERR_BAD_REQUEST}; - _ -> - Notify = fun (JID, Sub, _SubId) -> - Stanza = #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"pubsub">>, - attrs = - [{<<"xmlns">>, - ?NS_PUBSUB}], - children = - [#xmlel{name = - <<"subscription">>, - attrs = - [{<<"jid">>, - jlib:jid_to_string(JID)}, - {<<"subscription">>, - subscription_to_string(Sub)} - | nodeAttr(Node)], - children = - []}]}]}, - ejabberd_router:route(service_jid(Host), - jlib:make_jid(JID), Stanza) - end, - Action = fun (#pubsub_node{type = Type, - id = NodeId}) -> - case lists:member(Owner, node_owners_call(Type, NodeId)) of - true -> - Result = lists:foldl(fun ({JID, Subscription, - SubId}, - Acc) -> - case - node_call(Type, - set_subscriptions, - [NodeId, - JID, - Subscription, - SubId]) - of - {error, Err} -> - [{error, - Err} - | Acc]; - _ -> - Notify(JID, - Subscription, - SubId), - Acc - end - end, - [], Entities), - case Result of - [] -> {result, []}; - _ -> {error, ?ERR_NOT_ACCEPTABLE} - end; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end - end. - --spec(get_presence_and_roster_permissions/5 :: -( - Host :: mod_pubsub:host(), - From :: ljid(), - Owners :: [ljid(),...], - AccessModel :: mod_pubsub:accessModel(), - AllowedGroups :: [binary()]) - -> {PresenceSubscription::boolean(), RosterGroup::boolean()} -). - -get_presence_and_roster_permissions(Host, From, Owners, AccessModel, AllowedGroups) -> - if (AccessModel == presence) or (AccessModel == roster) -> - case Host of - {User, Server, _} -> - get_roster_info(User, Server, From, AllowedGroups); - _ -> - [{OUser, OServer, _} | _] = Owners, - get_roster_info(OUser, OServer, From, AllowedGroups) - end; - true -> {true, true} - end. - -%% @spec (OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, SubscriberResource}, AllowedGroups) -%% -> {PresenceSubscription, RosterGroup} -get_roster_info(_, _, {<<"">>, <<"">>, _}, _) -> - {false, false}; -get_roster_info(OwnerUser, OwnerServer, - {SubscriberUser, SubscriberServer, _}, AllowedGroups) -> - {Subscription, Groups} = - ejabberd_hooks:run_fold(roster_get_jid_info, - OwnerServer, {none, []}, - [OwnerUser, OwnerServer, - {SubscriberUser, SubscriberServer, <<"">>}]), - PresenceSubscription = Subscription == both orelse - Subscription == from orelse - {OwnerUser, OwnerServer} == - {SubscriberUser, SubscriberServer}, - RosterGroup = lists:any(fun (Group) -> - lists:member(Group, AllowedGroups) - end, - Groups), - {PresenceSubscription, RosterGroup}; -get_roster_info(OwnerUser, OwnerServer, JID, - AllowedGroups) -> - get_roster_info(OwnerUser, OwnerServer, - jlib:jid_tolower(JID), AllowedGroups). - -string_to_affiliation(<<"owner">>) -> owner; -string_to_affiliation(<<"publisher">>) -> publisher; -string_to_affiliation(<<"member">>) -> member; -string_to_affiliation(<<"outcast">>) -> outcast; -string_to_affiliation(<<"none">>) -> none; -string_to_affiliation(_) -> false. - -string_to_subscription(<<"subscribed">>) -> subscribed; -string_to_subscription(<<"pending">>) -> pending; -string_to_subscription(<<"unconfigured">>) -> - unconfigured; -string_to_subscription(<<"none">>) -> none; -string_to_subscription(_) -> false. - -affiliation_to_string(owner) -> <<"owner">>; -affiliation_to_string(publisher) -> <<"publisher">>; -affiliation_to_string(member) -> <<"member">>; -affiliation_to_string(outcast) -> <<"outcast">>; -affiliation_to_string(_) -> <<"none">>. - -subscription_to_string(subscribed) -> <<"subscribed">>; -subscription_to_string(pending) -> <<"pending">>; -subscription_to_string(unconfigured) -> <<"unconfigured">>; -subscription_to_string(_) -> <<"none">>. - --spec(service_jid/1 :: -( - Host :: mod_pubsub:host()) - -> jid() -). -service_jid(Host) -> - case Host of - {U, S, _} -> {jid, U, S, <<"">>, U, S, <<"">>}; - _ -> {jid, <<"">>, Host, <<"">>, <<"">>, Host, <<"">>} - end. - -%% @spec (LJID, NotifyType, Depth, NodeOptions, SubOptions) -> boolean() -%% LJID = jid() -%% NotifyType = items | nodes -%% Depth = integer() -%% NodeOptions = [{atom(), term()}] -%% SubOptions = [{atom(), term()}] -%% @doc

    Check if a notification must be delivered or not based on -%% node and subscription options.

    -is_to_deliver(LJID, NotifyType, Depth, NodeOptions, - SubOptions) -> - sub_to_deliver(LJID, NotifyType, Depth, SubOptions) - andalso node_to_deliver(LJID, NodeOptions). - -sub_to_deliver(_LJID, NotifyType, Depth, SubOptions) -> - lists:all(fun (Option) -> - sub_option_can_deliver(NotifyType, Depth, Option) - end, - SubOptions). - -sub_option_can_deliver(items, _, {subscription_type, nodes}) -> false; -sub_option_can_deliver(nodes, _, {subscription_type, items}) -> false; -sub_option_can_deliver(_, _, {subscription_depth, all}) -> true; -sub_option_can_deliver(_, Depth, {subscription_depth, D}) -> Depth =< D; -sub_option_can_deliver(_, _, {deliver, false}) -> false; -sub_option_can_deliver(_, _, {expire, When}) -> now() < When; -sub_option_can_deliver(_, _, _) -> true. - -node_to_deliver(LJID, NodeOptions) -> - PresenceDelivery = get_option(NodeOptions, presence_based_delivery), - presence_can_deliver(LJID, PresenceDelivery). - --spec(presence_can_deliver/2 :: -( - Entity :: ljid(), - _ :: boolean()) - -> boolean() -). -presence_can_deliver(_, false) -> true; -presence_can_deliver({User, Server, Resource}, true) -> - case mnesia:dirty_match_object({session, '_', '_', {User, Server}, '_', '_'}) of - [] -> false; - Ss -> - lists:foldl(fun(_, true) -> true; - ({session, _, _ , _, undefined, _}, _Acc) -> false; - ({session, _, {_, _, R}, _, _Priority, _}, _Acc) -> - case Resource of - [] -> true; - R -> true; - _ -> false - end - end, false, Ss) - end. - --spec(state_can_deliver/2 :: -( - Entity::ljid(), - SubOptions :: mod_pubsub:subOptions() | []) - -> [ljid()] -). -state_can_deliver({U, S, R}, []) -> [{U, S, R}]; -state_can_deliver({U, S, R}, SubOptions) -> - %% Check SubOptions for 'show_values' - case lists:keysearch('show_values', 1, SubOptions) of - %% If not in suboptions, item can be delivered, case doesn't apply - false -> [{U, S, R}]; - %% If in a suboptions ... - {_, {_, ShowValues}} -> - %% Get subscriber resources - Resources = case R of - %% If the subscriber JID is a bare one, get all its resources - <<>> -> user_resources(U, S); - %% If the subscriber JID is a full one, use its resource - R -> [R] - end, - %% For each resource, test if the item is allowed to be delivered - %% based on resource state - lists:foldl( - fun(Resource, Acc) -> - get_resource_state({U, S, Resource}, ShowValues, Acc) - end, [], Resources) - end. - --spec(get_resource_state/3 :: -( - Entity :: ljid(), - ShowValues :: [binary()], - JIDs :: [ljid()]) - -> [ljid()] -). -get_resource_state({U, S, R}, ShowValues, JIDs) -> - case ejabberd_sm:get_session_pid(U, S, R) of - %% If no PID, item can be delivered - none -> lists:append([{U, S, R}], JIDs); - %% If PID ... - Pid -> - %% Get user resource state - %% TODO : add a catch clause - Show = case ejabberd_c2s:get_presence(Pid) of - {_, _, <<"available">>, _} -> <<"online">>; - {_, _, State, _} -> State - end, - %% Is current resource state listed in 'show-values' suboption ? - case lists:member(Show, ShowValues) of %andalso Show =/= "online" of - %% If yes, item can be delivered - true -> lists:append([{U, S, R}], JIDs); - %% If no, item can't be delivered - false -> JIDs - end - end. - --spec(payload_xmlelements/1 :: -( - Payload :: mod_pubsub:payload()) - -> Count :: non_neg_integer() -). -%% @spec (Payload) -> int() -%% Payload = term() -%% @doc

    Count occurence of XML elements in payload.

    -payload_xmlelements(Payload) -> payload_xmlelements(Payload, 0). -payload_xmlelements([], Count) -> Count; -payload_xmlelements([#xmlel{} | Tail], Count) -> - payload_xmlelements(Tail, Count + 1); -payload_xmlelements([_ | Tail], Count) -> - payload_xmlelements(Tail, Count). - -%% @spec (Els) -> stanza() -%% Els = [xmlelement()] -%% @doc

    Build pubsub event stanza

    -event_stanza(Els) -> - #xmlel{name = <<"message">>, attrs = [], - children = - [#xmlel{name = <<"event">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_EVENT}], - children = Els}]}. - -event_stanza_with_delay(Els, ModifNow, ModifUSR) -> - jlib:add_delay_info(event_stanza(Els), ModifUSR, ModifNow). - -%%%%%% broadcast functions - -broadcast_publish_item(Host, Node, NodeId, Type, NodeOptions, Removed, ItemId, From, Payload) -> - case get_collection_subscriptions(Host, Node) of - SubsByDepth when is_list(SubsByDepth) -> - Content = case get_option(NodeOptions, deliver_payloads) of - true -> Payload; - false -> [] - end, - Stanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), - children = Content}]}]), - broadcast_stanza(Host, From, Node, NodeId, Type, - NodeOptions, SubsByDepth, items, Stanza, true), - case Removed of - [] -> - ok; - _ -> - case get_option(NodeOptions, notify_retract) of - true -> - RetractStanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"retract">>, attrs = itemAttr(RId)} || RId <- Removed]}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, - items, RetractStanza, true); - _ -> - ok - end - end, - {result, true}; - _ -> - {result, false} - end. - -broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds) -> - broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds, false). -broadcast_retract_items(_Host, _Node, _NodeId, _Type, _NodeOptions, [], _ForceNotify) -> - {result, false}; -broadcast_retract_items(Host, Node, NodeId, Type, NodeOptions, ItemIds, ForceNotify) -> - case (get_option(NodeOptions, notify_retract) or ForceNotify) of - true -> - case get_collection_subscriptions(Host, Node) of - SubsByDepth when is_list(SubsByDepth) -> - Stanza = event_stanza( - [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"retract">>, attrs = itemAttr(ItemId)} || ItemId <- ItemIds]}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, items, Stanza, true), - {result, true}; - _ -> - {result, false} - end; - _ -> - {result, false} - end. - -broadcast_purge_node(Host, Node, NodeId, Type, NodeOptions) -> - case get_option(NodeOptions, notify_retract) of - true -> - case get_collection_subscriptions(Host, Node) of - SubsByDepth when is_list(SubsByDepth) -> - Stanza = event_stanza( - [#xmlel{name = <<"purge">>, attrs = nodeAttr(Node)}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, nodes, Stanza, false), - {result, true}; - _ -> - {result, false} - end; - _ -> - {result, false} - end. - -broadcast_removed_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth) -> - case get_option(NodeOptions, notify_delete) of - true -> - case SubsByDepth of - [] -> - {result, false}; - _ -> - Stanza = event_stanza( - [#xmlel{name = <<"delete">>, attrs = nodeAttr(Node)}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, nodes, Stanza, false), - {result, true} - end; - _ -> - {result, false} - end. - -broadcast_created_node(_, _, _, _, _, []) -> - {result, false}; -broadcast_created_node(Host, Node, NodeId, Type, NodeOptions, SubsByDepth) -> - Stanza = event_stanza([#xmlel{name = <<"create">>, attrs = nodeAttr(Node)}]), - broadcast_stanza(Host, Node, NodeId, Type, NodeOptions, SubsByDepth, nodes, Stanza, true), - {result, true}. - -broadcast_config_notification(Host, Node, NodeId, Type, NodeOptions, Lang) -> - case get_option(NodeOptions, notify_config) of - true -> - case get_collection_subscriptions(Host, Node) of - SubsByDepth when is_list(SubsByDepth) -> - Content = case get_option(NodeOptions, deliver_payloads) of - true -> - [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], - children = get_configure_xfields(Type, NodeOptions, Lang, [])}]; - false -> - [] - end, - Stanza = event_stanza( - [#xmlel{name = <<"configuration">>, attrs = nodeAttr(Node), children = Content}]), - broadcast_stanza(Host, Node, NodeId, Type, - NodeOptions, SubsByDepth, nodes, Stanza, false), - {result, true}; - _ -> - {result, false} - end; - _ -> - {result, false} - end. - -get_collection_subscriptions(Host, Node) -> - Action = fun() -> - {result, lists:map(fun({Depth, Nodes}) -> - {Depth, [{N, get_node_subs(N)} || N <- Nodes]} - end, tree_call(Host, get_parentnodes_tree, [Host, Node, service_jid(Host)]))} - end, - case transaction(Host, Action, sync_dirty) of - {result, CollSubs} -> CollSubs; - _ -> [] - end. - -get_node_subs(#pubsub_node{type = Type, - id = NodeID}) -> - case node_call(Type, get_node_subscriptions, [NodeID]) of - {result, Subs} -> get_options_for_subs(NodeID, Subs); - Other -> Other - end. - -get_options_for_subs(NodeID, Subs) -> - lists:foldl(fun({JID, subscribed, SubID}, Acc) -> - case pubsub_subscription_odbc:get_subscription(JID, NodeID, SubID) of - {error, notfound} -> [{JID, SubID, []} | Acc]; - {result, #pubsub_subscription{options = Options}} -> [{JID, SubID, Options} | Acc]; - _ -> Acc - end; - (_, Acc) -> - Acc - end, [], Subs). - -broadcast_stanza(Host, _Node, _NodeId, _Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> - NotificationType = get_option(NodeOptions, notification_type, headline), - BroadcastAll = get_option(NodeOptions, broadcast_all_resources), %% XXX this is not standard, but usefull - From = service_jid(Host), - Stanza = add_message_type(BaseStanza, NotificationType), - %% Handles explicit subscriptions - SubIDsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), - lists:foreach(fun ({LJID, NodeName, SubIDs}) -> - LJIDs = case BroadcastAll of - true -> - {U, S, _} = LJID, - [{U, S, R} || R <- user_resources(U, S)]; - false -> - [LJID] - end, - %% Determine if the stanza should have SHIM ('SubID' and 'name') headers - StanzaToSend = case {SHIM, SubIDs} of - {false, _} -> - Stanza; - %% If there's only one SubID, don't add it - {true, [_]} -> - add_shim_headers(Stanza, collection_shim(NodeName)); - {true, SubIDs} -> - add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIDs))) - end, - lists:foreach(fun(To) -> - ejabberd_router:route(From, jlib:make_jid(To), StanzaToSend) - end, LJIDs) - end, SubIDsByJID). - -broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> - broadcast_stanza({LUser, LServer, LResource}, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM), - %% Handles implicit presence subscriptions - SenderResource = user_resource(LUser, LServer, LResource), - case ejabberd_sm:get_session_pid(LUser, LServer, SenderResource) of - C2SPid when is_pid(C2SPid) -> - NotificationType = get_option(NodeOptions, notification_type, headline), - Stanza = add_message_type(BaseStanza, NotificationType), - %% set the from address on the notification to the bare JID of the account owner - %% Also, add "replyto" if entity has presence subscription to the account owner - %% See XEP-0163 1.1 section 4.3.1 - ejabberd_c2s:broadcast(C2SPid, - {pep_message, <<((Node))/binary, "+notify">>}, - _Sender = jlib:make_jid(LUser, LServer, <<"">>), - _StanzaToSend = add_extended_headers(Stanza, - _ReplyTo = extended_headers([jlib:jid_to_string(Publisher)]))); - _ -> - ?DEBUG("~p@~p has no session; can't deliver ~p to contacts", [LUser, LServer, BaseStanza]) - end; -broadcast_stanza(Host, _Publisher, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM) -> - broadcast_stanza(Host, Node, NodeId, Type, NodeOptions, SubsByDepth, NotifyType, BaseStanza, SHIM). - -subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> - NodesToDeliver = fun(Depth, Node, Subs, Acc) -> - NodeName = case Node#pubsub_node.nodeid of - {_, N} -> N; - Other -> Other - end, - NodeOptions = Node#pubsub_node.options, - lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) -> - case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of - true -> - %% If is to deliver : - case state_can_deliver(LJID, SubOptions) of - [] -> {JIDs, Recipients}; - JIDsToDeliver -> - lists:foldl( - fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) -> - case lists:member(JIDToDeliver, JIDs) of - %% check if the JIDs co-accumulator contains the Subscription Jid, - false -> - %% - if not, - %% - add the Jid to JIDs list co-accumulator ; - %% - create a tuple of the Jid, NodeId, and SubID (as list), - %% and add the tuple to the Recipients list co-accumulator - {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubID]} | RecipientsAcc]}; - true -> - %% - if the JIDs co-accumulator contains the Jid - %% get the tuple containing the Jid from the Recipient list co-accumulator - {_, {JIDToDeliver, NodeName1, SubIDs}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), - %% delete the tuple from the Recipients list - % v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients), - % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, NodeId1, [SubID | SubIDs]}), - %% add the SubID to the SubIDs list in the tuple, - %% and add the tuple back to the Recipients list co-accumulator - % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, NodeId1, lists:append(SubIDs, [SubID])}])} - % v1.2 : {JIDs, [{LJID, NodeId1, [SubID | SubIDs]} | Recipients1]} - % v2: {JIDs, Recipients1} - {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubID | SubIDs]})} - end - end, {JIDs, Recipients}, JIDsToDeliver) - end; - false -> - {JIDs, Recipients} - end - end, Acc, Subs) - end, - DepthsToDeliver = fun({Depth, SubsByNode}, Acc1) -> - lists:foldl(fun({Node, Subs}, Acc2) -> - NodesToDeliver(Depth, Node, Subs, Acc2) - end, Acc1, SubsByNode) - end, - {_, JIDSubs} = lists:foldl(DepthsToDeliver, {[], []}, SubsByDepth), - JIDSubs. - -user_resources(User, Server) -> - ejabberd_sm:get_user_resources(User, Server). - -user_resource(User, Server, <<>>) -> - case user_resources(User, Server) of - [R | _] -> R; - _ -> <<>> - end; -user_resource(_, _, Resource) -> Resource. - -%%%%%%% Configuration handling - -%%

    There are several reasons why the default node configuration options request might fail:

    -%%
      -%%
    • The service does not support node configuration.
    • -%%
    • The service does not support retrieval of default node configuration.
    • -%%
    -get_configure(Host, ServerHost, Node, From, Lang) -> - Action = fun (#pubsub_node{options = Options, - type = Type, id = NodeId}) -> - case node_call(Type, get_affiliation, [NodeId, From]) of - {result, owner} -> - Groups = ejabberd_hooks:run_fold(roster_groups, - ServerHost, [], - [ServerHost]), - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"configure">>, - attrs = nodeAttr(Node), - children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, - ?NS_XDATA}, - {<<"type">>, - <<"form">>}], - children = - get_configure_xfields(Type, - Options, - Lang, - Groups)}]}]}]}; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, Result}} -> {result, Result}; - Other -> Other - end. - -get_default(Host, Node, _From, Lang) -> - Type = select_type(Host, Host, Node), - Options = node_options(Type), -%% Get node option -%% The result depend of the node type plugin system. - {result, - [#xmlel{name = <<"pubsub">>, - attrs = [{<<"xmlns">>, ?NS_PUBSUB_OWNER}], - children = - [#xmlel{name = <<"default">>, attrs = [], - children = - [#xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, ?NS_XDATA}, - {<<"type">>, <<"form">>}], - children = - get_configure_xfields(Type, Options, - Lang, [])}]}]}]}. - -get_option([], _) -> false; -get_option(Options, Var) -> - get_option(Options, Var, false). - -get_option(Options, Var, Def) -> - case lists:keysearch(Var, 1, Options) of - {value, {_Val, Ret}} -> Ret; - _ -> Def - end. - -%% Get default options from the module plugin. -node_options(Type) -> - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary, - (?ODBC_SUFFIX)/binary>>), - case catch Module:options() of - {'EXIT', {undef, _}} -> - DefaultModule = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - (?STDNODE)/binary, - (?ODBC_SUFFIX)/binary>>), - DefaultModule:options(); - Result -> Result - end. - -%% @spec (Host, Options) -> MaxItems -%% Host = host() -%% Options = [Option] -%% Option = {Key::atom(), Value::term()} -%% MaxItems = integer() | unlimited -%% @doc

    Return the maximum number of items for a given node.

    -%%

    Unlimited means that there is no limit in the number of items that can -%% be stored.

    -%% @todo In practice, the current data structure means that we cannot manage -%% millions of items on a given node. This should be addressed in a new -%% version. -max_items(Host, Options) -> - case get_option(Options, persist_items) of - true -> - case get_option(Options, max_items) of - false -> unlimited; - Result when Result < 0 -> 0; - Result -> Result - end; - false -> - case get_option(Options, send_last_published_item) of - never -> 0; - _ -> - case is_last_item_cache_enabled(Host) of - true -> 0; - false -> 1 - end - end - end. - --define(BOOL_CONFIG_FIELD(Label, Var), - ?BOOLXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (get_option(Options, Var)))). - --define(STRING_CONFIG_FIELD(Label, Var), - ?STRINGXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (get_option(Options, Var, <<"">>)))). - --define(INTEGER_CONFIG_FIELD(Label, Var), - ?STRINGXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (iolist_to_binary(integer_to_list(get_option(Options, - Var)))))). - --define(JLIST_CONFIG_FIELD(Label, Var, Opts), - ?LISTXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (jlib:jid_to_string(get_option(Options, Var))), - [jlib:jid_to_string(O) || O <- Opts])). - --define(ALIST_CONFIG_FIELD(Label, Var, Opts), - ?LISTXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (iolist_to_binary(atom_to_list(get_option(Options, - Var)))), - [iolist_to_binary(atom_to_list(O)) || O <- Opts])). - --define(LISTM_CONFIG_FIELD(Label, Var, Opts), - ?LISTMXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - (get_option(Options, Var)), Opts)). - --define(NLIST_CONFIG_FIELD(Label, Var), - ?STRINGMXFIELD(Label, - <<"pubsub#", - (iolist_to_binary(atom_to_list(Var)))/binary>>, - get_option(Options, Var, []))). - -get_configure_xfields(_Type, Options, Lang, Groups) -> - [?XFIELD(<<"hidden">>, <<"">>, <<"FORM_TYPE">>, - (?NS_PUBSUB_NODE_CONFIG)), - ?BOOL_CONFIG_FIELD(<<"Deliver payloads with event notifications">>, - deliver_payloads), - ?BOOL_CONFIG_FIELD(<<"Deliver event notifications">>, - deliver_notifications), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node configuratio" - "n changes">>, - notify_config), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when the node is " - "deleted">>, - notify_delete), - ?BOOL_CONFIG_FIELD(<<"Notify subscribers when items are removed " - "from the node">>, - notify_retract), - ?BOOL_CONFIG_FIELD(<<"Persist items to storage">>, - persist_items), - ?STRING_CONFIG_FIELD(<<"A friendly name for the node">>, - title), - ?INTEGER_CONFIG_FIELD(<<"Max # of items to persist">>, - max_items), - ?BOOL_CONFIG_FIELD(<<"Whether to allow subscriptions">>, - subscribe), - ?ALIST_CONFIG_FIELD(<<"Specify the access model">>, - access_model, - [open, authorize, presence, roster, whitelist]), - ?LISTM_CONFIG_FIELD(<<"Roster groups allowed to subscribe">>, - roster_groups_allowed, Groups), - ?ALIST_CONFIG_FIELD(<<"Specify the publisher model">>, - publish_model, [publishers, subscribers, open]), - ?BOOL_CONFIG_FIELD(<<"Purge all items when the relevant publisher " - "goes offline">>, - purge_offline), - ?ALIST_CONFIG_FIELD(<<"Specify the event message type">>, - notification_type, [headline, normal]), - ?INTEGER_CONFIG_FIELD(<<"Max payload size in bytes">>, - max_payload_size), - ?ALIST_CONFIG_FIELD(<<"When to send the last published item">>, - send_last_published_item, - [never, on_sub, on_sub_and_presence]), - ?BOOL_CONFIG_FIELD(<<"Only deliver notifications to available " - "users">>, - presence_based_delivery), - ?NLIST_CONFIG_FIELD(<<"The collections with which a node is " - "affiliated">>, - collection)]. - -%%

    There are several reasons why the node configuration request might fail:

    -%%
      -%%
    • The service does not support node configuration.
    • -%%
    • The requesting entity does not have sufficient privileges to configure the node.
    • -%%
    • The request did not specify a node.
    • -%%
    • The node has no configuration options.
    • -%%
    • The specified node does not exist.
    • -%%
    -set_configure(Host, Node, From, Els, Lang) -> - case xml:remove_cdata(Els) of - [#xmlel{name = <<"x">>} = XEl] -> - case {xml:get_tag_attr_s(<<"xmlns">>, XEl), - xml:get_tag_attr_s(<<"type">>, XEl)} - of - {?NS_XDATA, <<"cancel">>} -> {result, []}; - {?NS_XDATA, <<"submit">>} -> - Action = fun (#pubsub_node{options = Options, - type = Type, id = NodeId} = - N) -> - case node_call(Type, get_affiliation, - [NodeId, From]) - of - {result, owner} -> - case jlib:parse_xdata_submit(XEl) of - invalid -> {error, ?ERR_BAD_REQUEST}; - XData -> - OldOpts = case Options of - [] -> - node_options(Type); - _ -> Options - end, - case set_xoption(Host, XData, - OldOpts) - of - NewOpts - when is_list(NewOpts) -> - case tree_call(Host, - set_node, - [N#pubsub_node{options - = - NewOpts}]) - of - ok -> {result, ok}; - Err -> Err - end; - Err -> Err - end - end; - _ -> {error, ?ERR_FORBIDDEN} - end - end, - case transaction(Host, Node, Action, transaction) of - {result, {TNode, ok}} -> - NodeId = TNode#pubsub_node.id, - Type = TNode#pubsub_node.type, - Options = TNode#pubsub_node.options, - broadcast_config_notification(Host, Node, NodeId, Type, - Options, Lang), - {result, []}; - Other -> Other - end; - _ -> {error, ?ERR_BAD_REQUEST} - end; - _ -> {error, ?ERR_BAD_REQUEST} - end. - -add_opt(Key, Value, Opts) -> - Opts1 = lists:keydelete(Key, 1, Opts), - [{Key, Value} | Opts1]. - --define(SET_BOOL_XOPT(Opt, Val), - BoolVal = case Val of - <<"0">> -> false; - <<"1">> -> true; - <<"false">> -> false; - <<"true">> -> true; - _ -> error - end, - case BoolVal of - error -> {error, ?ERR_NOT_ACCEPTABLE}; - _ -> - set_xoption(Host, Opts, add_opt(Opt, BoolVal, NewOpts)) - end). - --define(SET_STRING_XOPT(Opt, Val), - set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). - --define(SET_INTEGER_XOPT(Opt, Val, Min, Max), - case catch jlib:binary_to_integer(Val) of - IVal when is_integer(IVal), IVal >= Min, IVal =< Max -> - set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); - _ -> {error, ?ERR_NOT_ACCEPTABLE} - end). - --define(SET_ALIST_XOPT(Opt, Val, Vals), - case lists:member(Val, - [iolist_to_binary(atom_to_list(V)) || V <- Vals]) - of - true -> - set_xoption(Host, Opts, - add_opt(Opt, jlib:binary_to_atom(Val), NewOpts)); - false -> {error, ?ERR_NOT_ACCEPTABLE} - end). - --define(SET_LIST_XOPT(Opt, Val), - set_xoption(Host, Opts, add_opt(Opt, Val, NewOpts))). - -set_xoption(_Host, [], NewOpts) -> NewOpts; -set_xoption(Host, [{<<"FORM_TYPE">>, _} | Opts], - NewOpts) -> - set_xoption(Host, Opts, NewOpts); -set_xoption(Host, - [{<<"pubsub#roster_groups_allowed">>, Value} | Opts], - NewOpts) -> - ?SET_LIST_XOPT(roster_groups_allowed, Value); -set_xoption(Host, - [{<<"pubsub#deliver_payloads">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(deliver_payloads, Val); -set_xoption(Host, - [{<<"pubsub#deliver_notifications">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(deliver_notifications, Val); -set_xoption(Host, - [{<<"pubsub#notify_config">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(notify_config, Val); -set_xoption(Host, - [{<<"pubsub#notify_delete">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(notify_delete, Val); -set_xoption(Host, - [{<<"pubsub#notify_retract">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(notify_retract, Val); -set_xoption(Host, - [{<<"pubsub#persist_items">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(persist_items, Val); -set_xoption(Host, - [{<<"pubsub#max_items">>, [Val]} | Opts], NewOpts) -> - MaxItems = get_max_items_node(Host), - ?SET_INTEGER_XOPT(max_items, Val, 0, MaxItems); -set_xoption(Host, - [{<<"pubsub#subscribe">>, [Val]} | Opts], NewOpts) -> - ?SET_BOOL_XOPT(subscribe, Val); -set_xoption(Host, - [{<<"pubsub#access_model">>, [Val]} | Opts], NewOpts) -> - ?SET_ALIST_XOPT(access_model, Val, - [open, authorize, presence, roster, whitelist]); -set_xoption(Host, - [{<<"pubsub#publish_model">>, [Val]} | Opts], - NewOpts) -> - ?SET_ALIST_XOPT(publish_model, Val, - [publishers, subscribers, open]); -set_xoption(Host, - [{<<"pubsub#notification_type">>, [Val]} | Opts], - NewOpts) -> - ?SET_ALIST_XOPT(notification_type, Val, - [headline, normal]); -set_xoption(Host, - [{<<"pubsub#node_type">>, [Val]} | Opts], NewOpts) -> - ?SET_ALIST_XOPT(node_type, Val, [leaf, collection]); -set_xoption(Host, - [{<<"pubsub#max_payload_size">>, [Val]} | Opts], - NewOpts) -> - ?SET_INTEGER_XOPT(max_payload_size, Val, 0, - (?MAX_PAYLOAD_SIZE)); -set_xoption(Host, - [{<<"pubsub#send_last_published_item">>, [Val]} | Opts], - NewOpts) -> - ?SET_ALIST_XOPT(send_last_published_item, Val, - [never, on_sub, on_sub_and_presence]); -set_xoption(Host, - [{<<"pubsub#presence_based_delivery">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(presence_based_delivery, Val); -set_xoption(Host, - [{<<"pubsub#purge_offline">>, [Val]} | Opts], - NewOpts) -> - ?SET_BOOL_XOPT(purge_offline, Val); -set_xoption(Host, [{<<"pubsub#title">>, Value} | Opts], - NewOpts) -> - ?SET_STRING_XOPT(title, Value); -set_xoption(Host, [{<<"pubsub#type">>, Value} | Opts], - NewOpts) -> - ?SET_STRING_XOPT(type, Value); -set_xoption(Host, - [{<<"pubsub#body_xslt">>, Value} | Opts], NewOpts) -> - ?SET_STRING_XOPT(body_xslt, Value); -set_xoption(Host, - [{<<"pubsub#collection">>, Value} | Opts], NewOpts) -> -% NewValue = [string_to_node(V) || V <- Value], - ?SET_LIST_XOPT(collection, Value); -set_xoption(Host, [{<<"pubsub#node">>, [Value]} | Opts], - NewOpts) -> -% NewValue = string_to_node(Value), - ?SET_LIST_XOPT(node, Value); -set_xoption(Host, [_ | Opts], NewOpts) -> - set_xoption(Host, Opts, NewOpts). - -get_max_items_node({_, ServerHost, _}) -> - get_max_items_node(ServerHost); -get_max_items_node(Host) -> - case catch ets:lookup(gen_mod:get_module_proc(Host, - config), - max_items_node) - of - [{max_items_node, Integer}] -> Integer; - _ -> ?MAXITEMS - end. - -%%%% last item cache handling - -is_last_item_cache_enabled({_, ServerHost, _}) -> - is_last_item_cache_enabled(ServerHost); -is_last_item_cache_enabled(Host) -> - case catch ets:lookup(gen_mod:get_module_proc(Host, - config), - last_item_cache) - of - [{last_item_cache, true}] -> true; - _ -> false - end. - -set_cached_item({_, ServerHost, _}, NodeId, ItemId, - Publisher, Payload) -> - set_cached_item(ServerHost, NodeId, ItemId, Publisher, - Payload); -set_cached_item(Host, NodeId, ItemId, Publisher, - Payload) -> - case is_last_item_cache_enabled(Host) of - true -> - mnesia:dirty_write({pubsub_last_item, NodeId, ItemId, - {now(), - jlib:jid_tolower(jlib:jid_remove_resource(Publisher))}, - Payload}); - _ -> ok - end. - -unset_cached_item({_, ServerHost, _}, NodeId) -> - unset_cached_item(ServerHost, NodeId); -unset_cached_item(Host, NodeId) -> - case is_last_item_cache_enabled(Host) of - true -> mnesia:dirty_delete({pubsub_last_item, NodeId}); - _ -> ok - end. - --spec(get_cached_item/2 :: -( - Host :: mod_pubsub:host(), - NodeIdx :: mod_pubsub:nodeIdx()) - -> undefined | mod_pubsub:pubsubItem() -). -get_cached_item({_, ServerHost, _}, NodeId) -> - get_cached_item(ServerHost, NodeId); -get_cached_item(Host, NodeIdx) -> - case is_last_item_cache_enabled(Host) of - true -> - case mnesia:dirty_read({pubsub_last_item, NodeIdx}) of - [#pubsub_last_item{itemid = ItemId, creation = Creation, payload = Payload}] -> -% [{pubsub_last_item, NodeId, ItemId, Creation, -% Payload}] -> - #pubsub_item{itemid = {ItemId, NodeIdx}, - payload = Payload, creation = Creation, - modification = Creation}; - _ -> undefined - end; - _ -> undefined - end. - -%%%% plugin handling - -host(ServerHost) -> - case catch - ets:lookup(gen_mod:get_module_proc(ServerHost, config), - host) - of - [{host, Host}] -> Host; - _ -> <<"pubsub.", ServerHost/binary>> - end. - -plugins(Host) -> - case catch ets:lookup(gen_mod:get_module_proc(Host, - config), - plugins) - of - [{plugins, []}] -> [?STDNODE]; - [{plugins, PL}] -> PL; - _ -> [?STDNODE] - end. - -select_type(ServerHost, Host, Node, Type) -> - SelectedType = case Host of - {_User, _Server, _Resource} -> - case catch - ets:lookup(gen_mod:get_module_proc(ServerHost, - config), - pep_mapping) - of - [{pep_mapping, PM}] -> - proplists:get_value(Node, PM, ?PEPNODE); - _ -> ?PEPNODE - end; - _ -> Type - end, - ConfiguredTypes = plugins(ServerHost), - case lists:member(SelectedType, ConfiguredTypes) of - true -> SelectedType; - false -> hd(ConfiguredTypes) - end. - -select_type(ServerHost, Host, Node) -> - select_type(ServerHost, Host, Node, - hd(plugins(ServerHost))). - -features() -> - [% see plugin "access-authorize", % OPTIONAL - <<"access-open">>, % OPTIONAL this relates to access_model option in node_hometree - <<"access-presence">>, % OPTIONAL this relates to access_model option in node_pep - <<"access-whitelist">>, % OPTIONAL - <<"collections">>, % RECOMMENDED - <<"config-node">>, % RECOMMENDED - <<"create-and-configure">>, % RECOMMENDED - <<"item-ids">>, % RECOMMENDED - <<"last-published">>, % RECOMMENDED - <<"member-affiliation">>, % RECOMMENDED - <<"presence-notifications">>, % OPTIONAL - <<"presence-subscribe">>, % RECOMMENDED - <<"publisher-affiliation">>, % RECOMMENDED - <<"retrieve-default">>]. - - % see plugin "retrieve-items", % RECOMMENDED - % see plugin "retrieve-subscriptions", % RECOMMENDED - %TODO "shim", % OPTIONAL - % see plugin "subscribe", % REQUIRED - % see plugin "subscription-options", % OPTIONAL - % see plugin "subscription-notifications" % OPTIONAL - -features(Type) -> - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary, - (?ODBC_SUFFIX)/binary>>), - features() ++ - case catch Module:features() of - {'EXIT', {undef, _}} -> []; - Result -> Result - end. - -features(Host, <<>>) -> - lists:usort(lists:foldl(fun (Plugin, Acc) -> - Acc ++ features(Plugin) - end, - [], plugins(Host))); -features(Host, Node) -> - Action = fun (#pubsub_node{type = Type}) -> - {result, features(Type)} - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, Features} -> - lists:usort(features() ++ Features); - _ -> features() - end. - -%% @spec (Host, Type, NodeId) -> [ljid()] -%% NodeId = pubsubNodeId() -%% @doc

    Return list of node owners.

    -node_owners(Host, Type, NodeId) -> - case node_action(Host, Type, get_node_affiliations, [NodeId]) of - {result, Affiliations} -> - lists:foldl( - fun({LJID, owner}, Acc) -> [LJID|Acc]; - (_, Acc) -> Acc - end, [], Affiliations); - _ -> - [] - end. -node_owners_call(Type, NodeId) -> - case node_call(Type, get_node_affiliations, [NodeId]) of - {result, Affiliations} -> - lists:foldl( - fun({LJID, owner}, Acc) -> [LJID|Acc]; - (_, Acc) -> Acc - end, [], Affiliations); - _ -> - [] - end. - -%% @doc

    node tree plugin call.

    -tree_call({_User, Server, _Resource}, Function, Args) -> - tree_call(Server, Function, Args); -tree_call(Host, Function, Args) -> - ?DEBUG("tree_call ~p ~p ~p", [Host, Function, Args]), - Module = case catch - ets:lookup(gen_mod:get_module_proc(Host, config), - nodetree) - of - [{nodetree, N}] -> N; - _ -> - jlib:binary_to_atom(<<(?TREE_PREFIX)/binary, - (?STDTREE)/binary, - (?ODBC_SUFFIX)/binary>>) - end, - catch apply(Module, Function, Args). - -tree_action(Host, Function, Args) -> - ?DEBUG("tree_action ~p ~p ~p", [Host, Function, Args]), - Fun = fun () -> tree_call(Host, Function, Args) end, - case catch ejabberd_odbc:sql_bloc(odbc_conn(Host), Fun) of - {atomic, Result} -> - Result; - {aborted, Reason} -> - ?ERROR_MSG("transaction return internal error: ~p~n",[{aborted, Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR} - end. - -%% @doc

    node plugin call.

    -node_call(Type, Function, Args) -> - ?DEBUG("node_call ~p ~p ~p", [Type, Function, Args]), - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary, - (?ODBC_SUFFIX)/binary>>), - case apply(Module, Function, Args) of - {result, Result} -> {result, Result}; - {error, Error} -> {error, Error}; - {'EXIT', {undef, Undefined}} -> - case Type of - ?STDNODE -> {error, {undef, Undefined}}; - _ -> node_call(?STDNODE, Function, Args) - end; - {'EXIT', Reason} -> {error, Reason}; - Result -> - {result, - Result} %% any other return value is forced as result - end. - -node_action(Host, Type, Function, Args) -> - ?DEBUG("node_action ~p ~p ~p ~p", - [Host, Type, Function, Args]), - transaction(Host, fun () -> node_call(Type, Function, Args) end, - sync_dirty). - -%% @doc

    plugin transaction handling.

    -transaction(Host, Node, Action, Trans) -> - transaction(Host, fun () -> - case tree_call(Host, get_node, [Host, Node]) of - N when is_record(N, pubsub_node) -> - case Action(N) of - {result, Result} -> {result, {N, Result}}; - {atomic, {result, Result}} -> - {result, {N, Result}}; - Other -> Other - end; - Error -> Error - end - end, - Trans). - -transaction_on_nodes(Host, Action, Trans) -> - transaction(Host, fun () -> - {result, - lists:foldl(Action, [], - tree_call(Host, get_nodes, [Host]))} - end, - Trans). - -transaction(Host, Fun, Trans) -> - transaction_retry(Host, Fun, Trans, 2). -transaction_retry(Host, Fun, Trans, Count) -> - SqlFun = case Trans of - transaction -> sql_transaction; - _ -> sql_bloc - end, - case catch ejabberd_odbc:SqlFun(odbc_conn(Host), Fun) of - {result, Result} -> {result, Result}; - {error, Error} -> {error, Error}; - {atomic, {result, Result}} -> {result, Result}; - {atomic, {error, Error}} -> {error, Error}; - {aborted, Reason} -> - ?ERROR_MSG("transaction return internal error: ~p~n", - [{aborted, Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; - {'EXIT', {timeout, _} = Reason} -> - case Count of - 0 -> - ?ERROR_MSG("transaction return internal error: ~p~n", [{'EXIT', Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; - N -> - erlang:yield(), - transaction_retry(Host, Fun, Trans, N-1) - end; - {'EXIT', Reason} -> - ?ERROR_MSG("transaction return internal error: ~p~n", - [{'EXIT', Reason}]), - {error, ?ERR_INTERNAL_SERVER_ERROR}; - Other -> - ?ERROR_MSG("transaction return internal error: ~p~n", - [Other]), - {error, ?ERR_INTERNAL_SERVER_ERROR} - end. - -odbc_conn({_U, Host, _R})-> Host; -odbc_conn(<<$., Host/binary>>) -> Host; -odbc_conn(<<_, Host/binary>>) -> odbc_conn(Host). - -%% escape value for database storage -escape({_U, _H, _R}=JID)-> - ejabberd_odbc:escape(jlib:jid_to_string(JID)); -escape(Value)-> - ejabberd_odbc:escape(Value). - -%%%% helpers - -%% Add pubsub-specific error element -extended_error(Error, Ext) -> - extended_error(Error, Ext, - [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}]). - -extended_error(Error, unsupported, Feature) -> -%% Give a uniq identifier - extended_error(Error, <<"unsupported">>, - [{<<"xmlns">>, ?NS_PUBSUB_ERRORS}, - {<<"feature">>, Feature}]); -extended_error(#xmlel{name = Error, attrs = Attrs, - children = SubEls}, - Ext, ExtAttrs) -> - #xmlel{name = Error, attrs = Attrs, - children = - lists:reverse([#xmlel{name = Ext, attrs = ExtAttrs, - children = []} - | SubEls])}. - --spec(uniqid/0 :: () -> mod_pubsub:itemId()). -uniqid() -> - {T1, T2, T3} = now(), - iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). - -nodeAttr(Node) -> [{<<"node">>, Node}]. - -itemAttr([]) -> []; -itemAttr(ItemId) -> [{<<"id">>, ItemId}]. - -itemsEls(Items) -> - lists:map(fun (#pubsub_item{itemid = {ItemId, _}, payload = Payload}) -> - #xmlel{name = <<"item">>, attrs = itemAttr(ItemId), children = Payload} - end, Items). - --spec(add_message_type/2 :: -( - Message :: xmlel(), - Type :: atom()) - -> xmlel() -). - -add_message_type(Message, normal) -> Message; -add_message_type(#xmlel{name = <<"message">>, attrs = Attrs, children = Els}, - Type) -> - #xmlel{name = <<"message">>, - attrs = [{<<"type">>, jlib:atom_to_binary(Type)} | Attrs], - children = Els}; -add_message_type(XmlEl, _Type) -> XmlEl. - -%% Place of changed at the bottom of the stanza -%% cf. http://xmpp.org/extensions/xep-0060.html#publisher-publish-success-subid -%% -%% "[SHIM Headers] SHOULD be included after the event notification information -%% (i.e., as the last child of the stanza)". - -add_shim_headers(Stanza, HeaderEls) -> - add_headers(Stanza, <<"headers">>, ?NS_SHIM, HeaderEls). - -add_extended_headers(Stanza, HeaderEls) -> - add_headers(Stanza, <<"addresses">>, ?NS_ADDRESS, - HeaderEls). - -add_headers(#xmlel{name = Name, attrs = Attrs, children = Els}, - HeaderName, HeaderNS, HeaderEls) -> - HeaderEl = #xmlel{name = HeaderName, - attrs = [{<<"xmlns">>, HeaderNS}], - children = HeaderEls}, - #xmlel{name = Name, attrs = Attrs, - children = lists:append(Els, [HeaderEl])}. - -%% Removed multiple
    Foo
    elements -%% Didn't seem compliant, but not sure. Confirmation required. -%% cf. http://xmpp.org/extensions/xep-0248.html#notify -%% -%% "If an item is published to a node which is also included by a collection, -%% and an entity is subscribed to that collection with a subscription type of -%% "items" (Is there a way to check that currently ?), then the notifications -%% generated by the service MUST contain additional information. The -%% element contained in the notification message MUST specify the node -%% identifier of the node that generated the notification (not the collection) -%% and the element MUST contain a SHIM header that specifies the node -%% identifier of the collection". - -collection_shim(Node) -> - [#xmlel{name = <<"header">>, - attrs = [{<<"name">>, <<"Collection">>}], - children = [{xmlcdata, Node}]}]. - -subid_shim(SubIDs) -> - [#xmlel{name = <<"header">>, - attrs = [{<<"name">>, <<"SubID">>}], - children = [{xmlcdata, SubID}]} - || SubID <- SubIDs]. - -%% The argument is a list of Jids because this function could be used -%% with the 'pubsub#replyto' (type=jid-multi) node configuration. - -extended_headers(Jids) -> - [#xmlel{name = <<"address">>, - attrs = [{<<"type">>, <<"replyto">>}, {<<"jid">>, Jid}], - children = []} - || Jid <- Jids]. - -on_user_offline(_, JID, _) -> - {User, Server, Resource} = jlib:jid_tolower(JID), - case ejabberd_sm:get_user_resources(User, Server) of - [] -> purge_offline({User, Server, Resource}); - _ -> true - end. - -purge_offline({User, Server, _} = LJID) -> - Host = host(element(2, LJID)), - Plugins = plugins(Host), - Result = lists:foldl(fun (Type, {Status, Acc}) -> - case lists:member(<<"retrieve-affiliations">>, - features(Type)) - of - false -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, - unsupported, - <<"retrieve-affiliations">>)}, - Acc}; - true -> - {result, Affiliations} = - node_action(Host, Type, - get_entity_affiliations, - [Host, LJID]), - {Status, [Affiliations | Acc]} - end - end, - {ok, []}, Plugins), - case Result of - {ok, Affiliations} -> - lists:foreach(fun ({#pubsub_node{nodeid = {_, NodeId}, - options = Options, type = Type}, - Affiliation}) - when Affiliation == owner orelse - Affiliation == publisher -> - Action = fun (#pubsub_node{type = NType, - id = NodeIdx}) -> - node_call(NType, get_items, - [NodeIdx, - service_jid(Host)]) - end, - case transaction(Host, NodeId, Action, - sync_dirty) - of - {result, {_, []}} -> true; - {result, {_, Items}} -> - Features = features(Type), - case {lists:member(<<"retract-items">>, - Features), - lists:member(<<"persistent-items">>, - Features), - get_option(Options, persist_items), - get_option(Options, purge_offline)} - of - {true, true, true, true} -> - ForceNotify = get_option(Options, - notify_retract), - lists:foreach(fun - (#pubsub_item{itemid - = - {ItemId, - _}, - modification - = - {_, - Modification}}) -> - case - Modification - of - {User, Server, - _} -> - delete_item(Host, - NodeId, - LJID, - ItemId, - ForceNotify); - _ -> true - end; - (_) -> true - end, - Items); - _ -> true - end; - Error -> Error - end; - (_) -> true - end, - lists:usort(lists:flatten(Affiliations))); - {Error, _} -> ?DEBUG("on_user_offline ~p", [Error]) - end. diff --git a/src/node.template b/src/node.template deleted file mode 100644 index 89b4a310aad..00000000000 --- a/src/node.template +++ /dev/null @@ -1,194 +0,0 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. -%%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - --module(__TO_BE_DEFINED__). --author(__TO_BE_DEFINED__). - --include("pubsub.hrl"). --include("jlib.hrl"). - --behaviour(gen_pubsub_node). - -%% Note on function definition -%% included is all defined plugin function -%% it's possible not to define some function at all -%% in that case, warning will be generated at compilation -%% and function call will fail, -%% then mod_pubsub will call function from node_hometree -%% (this makes code cleaner, but execution a little bit longer) - -%% API definition --export([init/3, terminate/2, - options/0, features/0, - create_node_permission/6, - create_node/2, - delete_node/1, - purge_node/2, - subscribe_node/8, - unsubscribe_node/4, - publish_item/6, - delete_item/4, - remove_extra_items/3, - get_entity_affiliations/2, - get_node_affiliations/1, - get_affiliation/2, - set_affiliation/3, - get_entity_subscriptions/2, - get_node_subscriptions/1, - get_subscriptions/2, - set_subscriptions/4, - get_pending_nodes/2, - get_states/1, - get_state/2, - set_state/1, - get_items/6, - get_items/2, - get_item/7, - get_item/2, - set_item/1, - get_item_name/3 - ]). - - -init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts). - -terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost). - -options() -> - [{deliver_payloads, true}, - {notify_config, false}, - {notify_delete, false}, - {notify_retract, true}, - {purge_offline, false}, - {persist_items, true}, - {max_items, ?MAXITEMS}, - {subscribe, true}, - {access_model, open}, - {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. - -features() -> - ["create-nodes", - "delete-nodes", - "delete-items", - "instant-nodes", - "outcast-affiliation", - "persistent-items", - "publish", - "purge-nodes", - "retract-items", - "retrieve-affiliations", - "retrieve-items", - "retrieve-subscriptions", - "subscribe", - "subscription-notifications" - ]. - -create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). - -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). - -delete_node(Removed) -> - node_hometree:delete_node(Removed). - -subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). - -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeId, Sender, Subscriber, SubID). - -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(NodeId, Publisher, Model, MaxItems, ItemId, Payload). - -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, ItemIds). - -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeId, Publisher, PublishModel, ItemId). - -purge_node(NodeId, Owner) -> - node_hometree:purge_node(NodeId, Owner). - -get_entity_affiliations(Host, Owner) -> - node_hometree:get_entity_affiliations(Host, Owner). - -get_node_affiliations(NodeId) -> - node_hometree:get_node_affiliations(NodeId). - -get_affiliation(NodeId, Owner) -> - node_hometree:get_affiliation(NodeId, Owner). - -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, Affiliation). - -get_entity_subscriptions(Host, Owner) -> - node_hometree:get_entity_subscriptions(Host, Owner). - -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). - -get_subscriptions(NodeId, Owner) -> - node_hometree:get_subscriptions(NodeId, Owner). - -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, Subscription, SubId). - -get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). - -get_states(NodeId) -> - node_hometree:get_states(NodeId). - -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). - -set_state(State) -> - node_hometree:set_state(State). - -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). - -get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). - -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). - -get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). - -set_item(Item) -> - node_hometree:set_item(Item). - -get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). diff --git a/src/node_buddy.erl b/src/node_buddy.erl index e7ab2799cca..a6ff0d4525b 100644 --- a/src/node_buddy.erl +++ b/src/node_buddy.erl @@ -4,58 +4,45 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne -%%% @author Christophe romain +%%% @author Christophe Romain %%% [http://www.process-one.net/] %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -module(node_buddy). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% Note on function definition -%% included is all defined plugin function -%% it's possible not to define some function at all -%% in that case, warning will be generated at compilation -%% and function call will fail, -%% then mod_pubsub will call function from node_hometree -%% (this makes code cleaner, but execution a little bit longer) - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). @@ -64,121 +51,127 @@ terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, presence}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, never}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, presence}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, true}, + {presence_based_delivery, false}]. features() -> - [<<"create-nodes">>, <<"delete-nodes">>, - <<"delete-items">>, <<"instant-nodes">>, <<"item-ids">>, - <<"outcast-affiliation">>, <<"persistent-items">>, - <<"publish">>, <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, <<"retrieve-items">>, - <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>]. - -create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, - Node, ParentNode, Owner, Access). - -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"instant-nodes">>, + <<"item-ids">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeId, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeId, Sender, - Subscriber, SubID). +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_hometree:publish_item(NodeId, Publisher, Model, - MaxItems, ItemId, Payload). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, - ItemIds). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeId, Publisher, - PublishModel, ItemId). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeId, Owner) -> - node_hometree:purge_node(NodeId, Owner). +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_hometree:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_hometree:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_hometree:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_hometree:get_states(NodeId). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat:node_to_path(Node). +node_to_path(Node) -> + node_flat:node_to_path(Node). -path_to_node(Path) -> node_flat:path_to_node(Path). +path_to_node(Path) -> + node_flat:path_to_node(Path). diff --git a/src/node_club.erl b/src/node_club.erl index f91723030a0..6917312f2d4 100644 --- a/src/node_club.erl +++ b/src/node_club.erl @@ -1,61 +1,48 @@ -%%% ==================================================================== +%% ==================================================================== %%% ``The contents of this file are subject to the Erlang Public License, %%% Version 1.1, (the "License"); you may not use this file except in %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne -%%% @author Christophe romain +%%% @author Christophe Romain %%% [http://www.process-one.net/] %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -module(node_club). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% Note on function definition -%% included is all defined plugin function -%% it's possible not to define some function at all -%% in that case, warning will be generated at compilation -%% and function call will fail, -%% then mod_pubsub will call function from node_hometree -%% (this makes code cleaner, but execution a little bit longer) - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). @@ -64,121 +51,126 @@ terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, authorize}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, never}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, authorize}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, true}, + {presence_based_delivery, false}]. features() -> - [<<"create-nodes">>, <<"delete-nodes">>, - <<"delete-items">>, <<"instant-nodes">>, - <<"outcast-affiliation">>, <<"persistent-items">>, - <<"publish">>, <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, <<"retrieve-items">>, - <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>]. - -create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, - Node, ParentNode, Owner, Access). - -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"instant-nodes">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeId, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeId, Sender, - Subscriber, SubID). +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_hometree:publish_item(NodeId, Publisher, Model, - MaxItems, ItemId, Payload). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, - ItemIds). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeId, Publisher, - PublishModel, ItemId). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeId, Owner) -> - node_hometree:purge_node(NodeId, Owner). +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_hometree:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_hometree:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_hometree:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_hometree:get_states(NodeId). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat:node_to_path(Node). +node_to_path(Node) -> + node_flat:node_to_path(Node). -path_to_node(Path) -> node_flat:path_to_node(Path). +path_to_node(Path) -> + node_flat:path_to_node(Path). diff --git a/src/node_dag.erl b/src/node_dag.erl index 9a36a4c4a4c..f0cbf17b8ba 100644 --- a/src/node_dag.erl +++ b/src/node_dag.erl @@ -5,39 +5,37 @@ %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. %%% +%%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. %%% +%%% %%% @author Brian Cully %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -module(node_dag). - +-behaviour(gen_pubsub_node). -author('bjc@kublai.com'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). @@ -51,113 +49,108 @@ options() -> features() -> [<<"multi-collection">> | node_hometree:features()]. -create_node_permission(_Host, _ServerHost, _Node, - _ParentNode, _Owner, _Access) -> +create_node_permission(_Host, _ServerHost, _Node, _ParentNode, _Owner, _Access) -> {result, true}. -create_node(NodeID, Owner) -> - node_hometree:create_node(NodeID, Owner). +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). -subscribe_node(NodeID, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeID, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). - -unsubscribe_node(NodeID, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeID, Sender, - Subscriber, SubID). - -publish_item(NodeID, Publisher, Model, MaxItems, ItemID, - Payload) -> - case nodetree_dag:get_node(NodeID) of - #pubsub_node{options = Options} -> - case find_opt(node_type, Options) of - collection -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"publish">>)}; - _ -> - node_hometree:publish_item(NodeID, Publisher, Model, - MaxItems, ItemID, Payload) - end; - Err -> Err +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). + +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + case nodetree_dag:get_node(Nidx) of + #pubsub_node{options = Options} -> + case find_opt(node_type, Options) of + collection -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"publish">>)}; + _ -> + node_hometree:publish_item(Nidx, Publisher, Model, + MaxItems, ItemId, Payload) + end; + Err -> Err end. find_opt(_, []) -> false; find_opt(Option, [{Option, Value} | _]) -> Value; find_opt(Option, [_ | T]) -> find_opt(Option, T). -remove_extra_items(NodeID, MaxItems, ItemIDs) -> - node_hometree:remove_extra_items(NodeID, MaxItems, - ItemIDs). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeID, Publisher, PublishModel, ItemID) -> - node_hometree:delete_item(NodeID, Publisher, - PublishModel, ItemID). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeID, Owner) -> - node_hometree:purge_node(NodeID, Owner). +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeID) -> - node_hometree:get_node_affiliations(NodeID). +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). -get_affiliation(NodeID, Owner) -> - node_hometree:get_affiliation(NodeID, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). -set_affiliation(NodeID, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeID, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_hometree:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeID) -> - node_hometree:get_node_subscriptions(NodeID). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(NodeID, Owner) -> - node_hometree:get_subscriptions(NodeID, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeID, Owner, Subscription, SubID) -> - node_hometree:set_subscriptions(NodeID, Owner, - Subscription, SubID). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeID) -> node_hometree:get_states(NodeID). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeID, JID) -> - node_hometree:get_state(NodeID, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeID, From) -> - node_hometree:get_items(NodeID, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeID, JID, AccessModel, - PresenceSubscription, RosterGroup, SubID) -> - node_hometree:get_items(NodeID, JID, AccessModel, - PresenceSubscription, RosterGroup, SubID). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeID, ItemID) -> - node_hometree:get_item(NodeID, ItemID). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeID, ItemID, JID, AccessModel, - PresenceSubscription, RosterGroup, SubID) -> - node_hometree:get_item(NodeID, ItemID, JID, AccessModel, - PresenceSubscription, RosterGroup, SubID). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). -get_item_name(Host, Node, ID) -> - node_hometree:get_item_name(Host, Node, ID). +get_item_name(Host, Node, Id) -> + node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_hometree:node_to_path(Node). +node_to_path(Node) -> + node_hometree:node_to_path(Node). -path_to_node(Path) -> node_hometree:path_to_node(Path). +path_to_node(Path) -> + node_hometree:path_to_node(Path). diff --git a/src/node_dispatch.erl b/src/node_dispatch.erl index 3bf20cc6303..7a12318400a 100644 --- a/src/node_dispatch.erl +++ b/src/node_dispatch.erl @@ -4,56 +4,51 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne -%%% @author Christophe romain +%%% @author Christophe Romain %%% [http://www.process-one.net/] %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -module(node_dispatch). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - %%% @doc

    The {@module} module is a PubSub plugin whose %%% goal is to republished each published item to all its children.

    %%%

    Users cannot subscribe to this node, but are supposed to subscribe to %%% its children.

    %%% This module can not work with virtual nodetree -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). @@ -62,115 +57,129 @@ terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, open}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, never}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, presence}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, true}, + {presence_based_delivery, false}]. features() -> - [<<"create-nodes">>, <<"delete-nodes">>, - <<"instant-nodes">>, <<"outcast-affiliation">>, - <<"persistent-items">>, <<"publish">>, - <<"retrieve-items">>]. + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"instant-nodes">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"retrieve-items">>]. -create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, - Node, ParentNode, Owner, Access). +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). -delete_node(Removed) -> - node_hometree:delete_node(Removed). +delete_node(Nodes) -> + node_hometree:delete_node(Nodes). -subscribe_node(_NodeId, _Sender, _Subscriber, - _AccessModel, _SendLast, _PresenceSubscription, - _RosterGroup, _Options) -> +subscribe_node(_Nidx, _Sender, _Subscriber, _AccessModel, _SendLast, _PresenceSubscription, + _RosterGroup, _Options) -> {error, ?ERR_FORBIDDEN}. -unsubscribe_node(_NodeId, _Sender, _Subscriber, - _SubID) -> +unsubscribe_node(_Nidx, _Sender, _Subscriber, _SubId) -> {error, ?ERR_FORBIDDEN}. -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - lists:foreach(fun (SubNode) -> - node_hometree:publish_item(SubNode#pubsub_node.id, - Publisher, Model, MaxItems, - ItemId, Payload) - end, - nodetree_tree:get_subnodes(NodeId, Publisher, - Publisher)). - -remove_extra_items(_NodeId, _MaxItems, ItemIds) -> +publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> + case nodetree_tree:get_node(Nidx) of + #pubsub_node{nodeid = {Host, Node}} -> + lists:foreach(fun (SubNode) -> + node_hometree:publish_item(SubNode#pubsub_node.id, + Publisher, PublishModel, MaxItems, + ItemId, Payload) + end, + nodetree_tree:get_subnodes(Host, Node, Publisher)), + {result, {default, broadcast, []}}; + Error -> + Error + end. + +remove_extra_items(_Nidx, _MaxItems, ItemIds) -> {result, {ItemIds, []}}. -delete_item(_NodeId, _Publisher, _PublishModel, - _ItemId) -> +delete_item(_Nidx, _Publisher, _PublishModel, _ItemId) -> {error, ?ERR_ITEM_NOT_FOUND}. -purge_node(_NodeId, _Owner) -> {error, ?ERR_FORBIDDEN}. +purge_node(_Nidx, _Owner) -> + {error, ?ERR_FORBIDDEN}. -get_entity_affiliations(_Host, _Owner) -> {result, []}. +get_entity_affiliations(_Host, _Owner) -> + {result, []}. -get_node_affiliations(_NodeId) -> {result, []}. +get_node_affiliations(_Nidx) -> + {result, []}. -get_affiliation(_NodeId, _Owner) -> {result, []}. +get_affiliation(_Nidx, _Owner) -> + {result, none}. -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). -get_entity_subscriptions(_Host, _Owner) -> {result, []}. +get_entity_subscriptions(_Host, _Owner) -> + {result, []}. -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(_NodeId, _Owner) -> {result, []}. +get_subscriptions(_Nidx, _Owner) -> + {result, []}. -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_hometree:get_states(NodeId). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat:node_to_path(Node). +node_to_path(Node) -> + node_flat:node_to_path(Node). -path_to_node(Path) -> node_flat:path_to_node(Path). +path_to_node(Path) -> + node_flat:path_to_node(Path). diff --git a/src/node_flat.erl b/src/node_flat.erl index ff37f13e573..e261543801c 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -4,13 +4,13 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne @@ -25,162 +25,156 @@ %%% ==================================================================== -module(node_flat). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). - -init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). + +init(_Host, _ServerHost, _Opts) -> + pubsub_subscription:init(), + mnesia:create_table(pubsub_state, + [{disc_copies, [node()]}, + {type, ordered_set}, + {attributes, record_info(fields, pubsub_state)}]), + mnesia:create_table(pubsub_item, + [{disc_only_copies, [node()]}, + {attributes, record_info(fields, pubsub_item)}]), + ItemsFields = record_info(fields, pubsub_item), + case mnesia:table_info(pubsub_item, attributes) of + ItemsFields -> ok; + _ -> mnesia:transform_table(pubsub_item, ignore, ItemsFields) + end, + ok. terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, open}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. - -features() -> node_hometree:features(). + node_hometree:options(). + +features() -> + node_hometree:features(). %% use same code as node_hometree, but do not limite node to %% the home/localhost/user/... hierarchy %% any node is allowed -create_node_permission(Host, ServerHost, _Node, - _ParentNode, Owner, Access) -> +create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> LOwner = jlib:jid_tolower(Owner), Allowed = case LOwner of - {<<"">>, Host, <<"">>} -> - true; % pubsub service always allowed - _ -> - acl:match_rule(ServerHost, Access, LOwner) =:= allow - end, + {<<"">>, Host, <<"">>} -> + true; % pubsub service always allowed + _ -> + acl:match_rule(ServerHost, Access, LOwner) =:= allow + end, {result, Allowed}. -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeId, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, + AccessModel, SendLast, PresenceSubscription, + RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeId, Sender, - Subscriber, SubID). +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_hometree:publish_item(NodeId, Publisher, Model, - MaxItems, ItemId, Payload). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, - ItemIds). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeId, Publisher, - PublishModel, ItemId). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeId, Owner) -> - node_hometree:purge_node(NodeId, Owner). +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_hometree:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_hometree:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_hometree:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_hometree:get_states(NodeId). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> [(Node)]. +node_to_path(Node) -> + [(Node)]. path_to_node(Path) -> case Path of - % default slot - [Node] -> iolist_to_binary(Node); - % handle old possible entries, used when migrating database content to new format - [Node | _] when is_binary(Node) -> - iolist_to_binary(str:join([<<"">> | Path], <<"/">>)); - % default case (used by PEP for example) - _ -> iolist_to_binary(Path) + % default slot + [Node] -> iolist_to_binary(Node); + % handle old possible entries, used when migrating database content to new format + [Node | _] when is_binary(Node) -> + iolist_to_binary(str:join([<<"">> | Path], <<"/">>)); + % default case (used by PEP for example) + _ -> iolist_to_binary(Path) end. diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 1baf38e7144..9ac2643f8c1 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -4,13 +4,13 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne @@ -25,30 +25,25 @@ %%% ==================================================================== -module(node_flat_odbc). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, - get_entity_subscriptions_for_send_last/2, - get_node_subscriptions/1, get_subscriptions/2, - set_subscriptions/4, get_pending_nodes/2, get_states/1, - get_state/2, set_state/1, get_items/7, get_items/6, - get_items/3, get_items/2, get_item/7, get_item/2, - set_item/1, get_item_name/3, get_last_items/3, - node_to_path/1, path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1, + get_entity_subscriptions_for_send_last/2, get_last_items/3]). init(Host, ServerHost, Opts) -> node_hometree_odbc:init(Host, ServerHost, Opts). @@ -57,157 +52,115 @@ terminate(Host, ServerHost) -> node_hometree_odbc:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, - {notify_config, false}, - {notify_delete, false}, - {notify_retract, true}, - {purge_offline, false}, - {persist_items, true}, - {max_items, ?MAXITEMS}, - {subscribe, true}, - {access_model, open}, - {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}, {odbc, true}, - {rsm, true}]. - -features() -> node_hometree_odbc:features(). + [{odbc, true}, {rsm, true} | node_flat:options()]. + +features() -> + [<<"rsm">> | node_flat:features()]. %% use same code as node_hometree_odbc, but do not limite node to %% the home/localhost/user/... hierarchy %% any node is allowed -create_node_permission(Host, ServerHost, _Node, - _ParentNode, Owner, Access) -> - LOwner = jlib:jid_tolower(Owner), - Allowed = case LOwner of - {<<"">>, Host, <<"">>} -> - true; % pubsub service always allowed - _ -> - acl:match_rule(ServerHost, Access, LOwner) =:= allow - end, - {result, Allowed}. - -create_node(NodeId, Owner) -> - node_hometree_odbc:create_node(NodeId, Owner). +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_hometree_odbc:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree_odbc:delete_node(Removed). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree_odbc:subscribe_node(NodeId, Sender, - Subscriber, AccessModel, SendLast, - PresenceSubscription, RosterGroup, - Options). +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree_odbc:unsubscribe_node(NodeId, Sender, - Subscriber, SubID). +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_hometree_odbc:publish_item(NodeId, Publisher, - Model, MaxItems, ItemId, Payload). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree_odbc:remove_extra_items(NodeId, MaxItems, - ItemIds). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree_odbc:delete_item(NodeId, Publisher, - PublishModel, ItemId). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeId, Owner) -> - node_hometree_odbc:purge_node(NodeId, Owner). +purge_node(Nidx, Owner) -> + node_hometree_odbc:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree_odbc:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_hometree_odbc:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_hometree_odbc:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_hometree_odbc:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree_odbc:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree_odbc:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree_odbc:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> - node_hometree_odbc:get_entity_subscriptions(Host, - Owner). + node_hometree_odbc:get_entity_subscriptions(Host, Owner). get_entity_subscriptions_for_send_last(Host, Owner) -> - node_hometree_odbc:get_entity_subscriptions_for_send_last(Host, - Owner). + node_hometree_odbc:get_entity_subscriptions_for_send_last(Host, Owner). -get_node_subscriptions(NodeId) -> - node_hometree_odbc:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree_odbc:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree_odbc:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree_odbc:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree_odbc:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree_odbc:get_pending_nodes(Host, Owner). -get_states(NodeId) -> - node_hometree_odbc:get_states(NodeId). - -get_state(NodeId, JID) -> - node_hometree_odbc:get_state(NodeId, JID). - -set_state(State) -> node_hometree_odbc:set_state(State). +get_states(Nidx) -> + node_hometree_odbc:get_states(Nidx). -get_items(NodeId, From) -> - node_hometree_odbc:get_items(NodeId, From). +get_state(Nidx, JID) -> + node_hometree_odbc:get_state(Nidx, JID). -get_items(NodeId, From, RSM) -> - node_hometree_odbc:get_items(NodeId, From, RSM). +set_state(State) -> + node_hometree_odbc:set_state(State). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, none). +get_items(Nidx, From, RSM) -> + node_hometree_odbc:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree_odbc:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, RSM). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree_odbc:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree_odbc:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree_odbc:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree_odbc:get_item(NodeId, ItemId, JID, - AccessModel, PresenceSubscription, RosterGroup, - SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree_odbc:get_item(Nidx, ItemId, JID, + AccessModel, PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree_odbc:set_item(Item). +set_item(Item) -> + node_hometree_odbc:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree_odbc:get_item_name(Host, Node, Id). -get_last_items(NodeId, From, Count) -> - node_hometree_odbc:get_last_items(NodeId, From, Count). +get_last_items(Nidx, From, Count) -> + node_hometree_odbc:get_last_items(Nidx, From, Count). -node_to_path(Node) -> [(Node)]. +node_to_path(Node) -> + [(Node)]. path_to_node(Path) -> case Path of - % default slot - [Node] -> iolist_to_binary(Node); - % handle old possible entries, used when migrating database content to new format - [Node | _] when is_binary(Node) -> - iolist_to_binary(str:join([<<"">> | Path], <<"/">>)); - % default case (used by PEP for example) - _ -> iolist_to_binary(Path) + % default slot + [Node] -> iolist_to_binary(Node); + % handle old possible entries, used when migrating database content to new format + [Node | _] when is_binary(Node) -> + iolist_to_binary(str:join([<<"">> | Path], <<"/">>)); + % default case (used by PEP for example) + _ -> iolist_to_binary(Path) end. diff --git a/src/node_hometree.erl b/src/node_hometree.erl index 6f3c4de7472..2840c1850b1 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -4,20 +4,19 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne %%% @author Christophe Romain %%% [http://www.process-one.net/] @@ -41,122 +40,89 @@ %%% improvements.

    -module(node_hometree). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). - -%% ================ -%% API definition -%% ================ - -%% @spec (Host, ServerHost, Options) -> ok -%% Host = string() -%% ServerHost = string() -%% Options = [{atom(), term()}] -%% @doc

    Called during pubsub modules initialisation. Any pubsub plugin must -%% implement this function. It can return anything.

    -%%

    This function is mainly used to trigger the setup task necessary for the -%% plugin. It can be used for example by the developer to create the specific -%% module database schema if it does not exists yet.

    -init(_Host, _ServerHost, _Options) -> + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/6, get_items/2, + get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). + +init(Host, ServerHost, _Opts) -> pubsub_subscription:init(), mnesia:create_table(pubsub_state, - [{disc_copies, [node()]}, - {attributes, record_info(fields, pubsub_state)}]), + [{disc_copies, [node()]}, + {type, ordered_set}, + {attributes, record_info(fields, pubsub_state)}]), mnesia:create_table(pubsub_item, - [{disc_only_copies, [node()]}, - {attributes, record_info(fields, pubsub_item)}]), + [{disc_only_copies, [node()]}, + {attributes, record_info(fields, pubsub_item)}]), ItemsFields = record_info(fields, pubsub_item), case mnesia:table_info(pubsub_item, attributes) of - ItemsFields -> ok; - _ -> - mnesia:transform_table(pubsub_item, ignore, ItemsFields) + ItemsFields -> ok; + _ -> mnesia:transform_table(pubsub_item, ignore, ItemsFields) end, + Owner = mod_pubsub:service_jid(Host), + mod_pubsub:create_node(Host, ServerHost, <<"/home">>, Owner, <<"hometree">>), + mod_pubsub:create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, Owner, <<"hometree">>), ok. -%% @spec (Host, ServerHost) -> ok -%% Host = string() -%% ServerHost = string() -%% @doc

    Called during pubsub modules termination. Any pubsub plugin must -%% implement this function. It can return anything.

    -terminate(_Host, _ServerHost) -> ok. - --spec(options/0 :: () -> NodeOptions::mod_pubsub:nodeOptions()). +terminate(_Host, _ServerHost) -> + ok. -%% @spec () -> Options -%% Options = [mod_pubsub:nodeOption()] -%% @doc Returns the default pubsub node options. -%%

    Example of function return value:

    -%% ``` -%% [{deliver_payloads, true}, -%% {notify_config, false}, -%% {notify_delete, false}, -%% {notify_retract, true}, -%% {persist_items, true}, -%% {max_items, 10}, -%% {subscribe, true}, -%% {access_model, open}, -%% {publish_model, publishers}, -%% {max_payload_size, 100000}, -%% {send_last_published_item, never}, -%% {presence_based_delivery, false}]''' options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, open}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, open}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, on_sub_and_presence}, + {deliver_notifications, true}, + {presence_based_delivery, false}]. -%% @spec () -> Features -%% Features = [string()] -%% @doc Returns the node features --spec(features/0 :: () -> Features::[binary(),...]). features() -> - [<<"create-nodes">>, <<"auto-create">>, - <<"access-authorize">>, <<"delete-nodes">>, - <<"delete-items">>, <<"get-pending">>, - <<"instant-nodes">>, <<"manage-subscriptions">>, - <<"modify-affiliations">>, <<"multi-subscribe">>, - <<"outcast-affiliation">>, <<"persistent-items">>, - <<"publish">>, <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, <<"retrieve-items">>, - <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>, - <<"subscription-options">>]. + [<<"create-nodes">>, + <<"auto-create">>, + <<"access-authorize">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"get-pending">>, + <<"instant-nodes">>, + <<"manage-subscriptions">>, + <<"modify-affiliations">>, + <<"multi-subscribe">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>, + <<"subscription-options">>]. -%% @spec (Host, ServerHost, NodeId, ParentNodeId, Owner, Access) -> {result, Allowed} -%% Host = mod_pubsub:hostPubsub() -%% ServerHost = string() -%% NodeId = mod_pubsub:nodeId() -%% ParentNodeId = mod_pubsub:nodeId() -%% Owner = mod_pubsub:jid() -%% Access = all | atom() -%% Allowed = boolean() %% @doc Checks if the current user has the permission to create the requested node %%

    In {@link node_default}, the permission is decided by the place in the %% hierarchy where the user is creating the node. The access parameter is also @@ -164,99 +130,44 @@ features() -> %% access_createnode ACL value in ejabberd config file.

    %%

    This function also check that node can be created a a children of its %% parent node

    -%%

    PubSub plugins can redefine the PubSub node creation rights as they -%% which. They can simply delegate this check to the {@link node_default} -%% module by implementing this function like this: -%% ```check_create_user_permission(Host, ServerHost, NodeId, ParentNodeId, Owner, Access) -> -%% node_default:check_create_user_permission(Host, ServerHost, NodeId, ParentNodeId, Owner, Access).'''

    --spec(create_node_permission/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - NodeId :: mod_pubsub:nodeId(), - _ParentNodeId :: mod_pubsub:nodeId(), - Owner :: jid(), - Access :: atom()) - -> {result, boolean()} -). - -create_node_permission(Host, ServerHost, NodeId, _ParentNodeId, Owner, Access) -> +create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> LOwner = jlib:jid_tolower(Owner), {User, Server, _Resource} = LOwner, Allowed = case LOwner of - {<<"">>, Host, <<"">>} -> - true; % pubsub service always allowed - _ -> - case acl:match_rule(ServerHost, Access, LOwner) of - allow -> - case node_to_path(NodeId) of - [<<"home">>, Server, User | _] -> true; - _ -> false - end; - _ -> false - end - end, + {<<"">>, Host, <<"">>} -> + true; % pubsub service always allowed + _ -> + case acl:match_rule(ServerHost, Access, LOwner) of + allow -> + case node_to_path(Node) of + [<<"home">>, Server, User | _] -> true; + _ -> false + end; + _ -> false + end + end, {result, Allowed}. -%% @spec (NodeIdx, Owner) -> {result, {default, broadcast}} -%% NodeIdx = mod_pubsub:nodeIdx() -%% Owner = mod_pubsub:jid() -%% @doc

    --spec(create_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} -). - -create_node(NodeIdx, Owner) -> +create_node(Nidx, Owner) -> OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - set_state(#pubsub_state{stateid = {OwnerKey, NodeIdx}, affiliation = owner}), + set_state(#pubsub_state{stateid = {OwnerKey, Nidx}, + affiliation = owner}), {result, {default, broadcast}}. -%% @spec (Nodes) -> {result, {default, broadcast, Reply}} -%% Nodes = [mod_pubsub:pubsubNode()] -%% Reply = [{mod_pubsub:pubsubNode(), -%% [{mod_pubsub:ljid(), [{mod_pubsub:subscription(), mod_pubsub:subId()}]}]}] -%% @doc

    purge items of deleted nodes after effective deletion.

    --spec(delete_node/1 :: -( - Nodes :: [mod_pubsub:pubsubNode(),...]) - -> {result, - {default, broadcast, - [{mod_pubsub:pubsubNode(), - [{ljid(), [{mod_pubsub:subscription(), mod_pubsub:subId()}]},...]},...] - } - } -). delete_node(Nodes) -> Tr = fun (#pubsub_state{stateid = {J, _}, subscriptions = Ss}) -> - lists:map(fun (S) -> {J, S} end, Ss) - end, - Reply = lists:map(fun (#pubsub_node{id = NodeIdx} = PubsubNode) -> - {result, States} = get_states(NodeIdx), - lists:foreach(fun (#pubsub_state{stateid = {LJID, _}, items = Items}) -> - del_items(NodeIdx, Items), - del_state(NodeIdx, LJID) - end, States), - {PubsubNode, lists:flatmap(Tr, States)} - end, Nodes), + lists:map(fun (S) -> {J, S} end, Ss) + end, + Reply = lists:map(fun (#pubsub_node{id = Nidx} = PubsubNode) -> + {result, States} = get_states(Nidx), + lists:foreach(fun (#pubsub_state{stateid = {LJID, _}, items = Items}) -> + del_items(Nidx, Items), + del_state(Nidx, LJID) + end, States), + {PubsubNode, lists:flatmap(Tr, States)} + end, Nodes), {result, {default, broadcast, Reply}}. -%% @spec (NodeIdx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> {error, Reason} | {result, Result} -%% NodeIdx = mod_pubsub:nodeIdx() -%% Sender = mod_pubsub:jid() -%% Subscriber = mod_pubsub:jid() -%% AccessModel = mod_pubsub:accessModel() -%% SendLast = atom() -%% PresenceSubscription = boolean() -%% RosterGroup = boolean() -%% Options = [mod_pubsub:nodeOption()] -%% Reason = mod_pubsub:stanzaError() -%% Result = {result, {default, subscribed, mod_pubsub:subId()}} -%% | {result, {default, subscribed, mod_pubsub:subId(), send_last}} -%% | {result, {default, pending, mod_pubsub:subId()}} -%% %% @doc

    Accepts or rejects subcription requests on a PubSub node.

    %%

    The mechanism works as follow: %%

      @@ -288,199 +199,138 @@ delete_node(Nodes) -> %% to completly disable persistance.
    %%

    %%

    In the default plugin module, the record is unchanged.

    --spec(subscribe_node/8 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - AccessModel :: mod_pubsub:accessModel(), - SendLast :: 'never' | 'on_sub' | 'on_sub_and_presence', - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - Options :: mod_pubsub:subOptions()) - -> {result, {default, subscribed, mod_pubsub:subId()}} - | {result, {default, subscribed, mod_pubsub:subId(), send_last}} - | {result, {default, pending, mod_pubsub:subId()}} - %%% - | {error, xmlel()} -). -subscribe_node(NodeIdx, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), - Authorized = - jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == - GenKey, - GenState = get_state(NodeIdx, GenKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + GenState = get_state(Nidx, GenKey), SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(NodeIdx, SubKey) - end, + GenKey -> GenState; + _ -> get_state(Nidx, SubKey) + end, Affiliation = GenState#pubsub_state.affiliation, Subscriptions = SubState#pubsub_state.subscriptions, - Whitelisted = lists:member(Affiliation, - [member, publisher, owner]), - PendingSubscription = lists:any(fun ({pending, _}) -> - true; - (_) -> false - end, - Subscriptions), + Whitelisted = lists:member(Affiliation, [member, publisher, owner]), + PendingSubscription = lists:any(fun + ({pending, _}) -> true; + (_) -> false + end, + Subscriptions), if not Authorized -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; - Affiliation == outcast -> {error, ?ERR_FORBIDDEN}; - PendingSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"pending-subscription">>)}; - (AccessModel == presence) and - not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - %%ForbiddenAnonymous -> - %% % Requesting entity is anonymous - %% {error, ?ERR_FORBIDDEN}; - true -> - SubId = pubsub_subscription:add_subscription(Subscriber, NodeIdx, Options), - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed - end, - set_state(SubState#pubsub_state{subscriptions = - [{NewSub, SubId} | Subscriptions]}), - case {NewSub, SendLast} of - {subscribed, never} -> - {result, {default, subscribed, SubId}}; - {subscribed, _} -> - {result, {default, subscribed, SubId, send_last}}; - {_, _} -> {result, {default, pending, SubId}} - end + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; + Affiliation == outcast -> + {error, ?ERR_FORBIDDEN}; + PendingSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + %%ForbiddenAnonymous -> + %% % Requesting entity is anonymous + %% {error, ?ERR_FORBIDDEN}; + true -> + SubId = pubsub_subscription:add_subscription(Subscriber, Nidx, Options), + NewSub = case AccessModel of + authorize -> pending; + _ -> subscribed + end, + set_state(SubState#pubsub_state{subscriptions = + [{NewSub, SubId} | Subscriptions]}), + case {NewSub, SendLast} of + {subscribed, never} -> + {result, {default, subscribed, SubId}}; + {subscribed, _} -> + {result, {default, subscribed, SubId, send_last}}; + {_, _} -> + {result, {default, pending, SubId}} + end end. -%% @spec (NodeIdx, Sender, Subscriber, SubId) -> {error, Reason} | {result, default} -%% NodeIdx = mod_pubsub:nodeIdx() -%% Sender = mod_pubsub:jid() -%% Subscriber = mod_pubsub:jid() -%% SubId = mod_pubsub:subId() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Unsubscribe the Subscriber from the Node.

    --spec(unsubscribe_node/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - SubId :: subId()) - -> {result, default} - % - | {error, xmlel()} -). - -unsubscribe_node(NodeIdx, Sender, Subscriber, SubId) -> +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), - Authorized = - jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == - GenKey, - GenState = get_state(NodeIdx, GenKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + GenState = get_state(Nidx, GenKey), SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(NodeIdx, SubKey) - end, - Subscriptions = lists:filter(fun ({_Sub, _SubId}) -> - true; - (_SubId) -> false - end, - SubState#pubsub_state.subscriptions), + GenKey -> GenState; + _ -> get_state(Nidx, SubKey) + end, + Subscriptions = lists:filter(fun + ({_Sub, _SubId}) -> true; + (_SubId) -> false + end, + SubState#pubsub_state.subscriptions), SubIdExists = case SubId of - <<>> -> false; - Binary when is_binary(Binary) -> true; - _ -> false - end, + <<>> -> false; + Binary when is_binary(Binary) -> true; + _ -> false + end, if - %% Requesting entity is prohibited from unsubscribing entity - not Authorized -> {error, ?ERR_FORBIDDEN}; - %% Entity did not specify SubId - %%SubId == "", ?? -> - %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %% Invalid subscription identifier - %%InvalidSubId -> - %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - %% Requesting entity is not a subscriber - Subscriptions == [] -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), - <<"not-subscribed">>)}; - %% Subid supplied, so use that. - SubIdExists -> - Sub = first_in_list(fun (S) -> - case S of - {_Sub, SubId} -> true; - _ -> false - end - end, - SubState#pubsub_state.subscriptions), - case Sub of - {value, S} -> - delete_subscriptions(SubKey, NodeIdx, [S], SubState), - {result, default}; - false -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), - <<"not-subscribed">>)} - end; - %% Asking to remove all subscriptions to the given node - SubId == all -> - delete_subscriptions(SubKey, NodeIdx, Subscriptions, SubState), - {result, default}; - %% No subid supplied, but there's only one matching subscription - length(Subscriptions) == 1 -> - delete_subscriptions(SubKey, NodeIdx, Subscriptions, SubState), - {result, default}; - %% No subid and more than one possible subscription match. - true -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} + %% Requesting entity is prohibited from unsubscribing entity + not Authorized -> + {error, ?ERR_FORBIDDEN}; + %% Entity did not specify SubId + %%SubId == "", ?? -> + %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %% Invalid subscription identifier + %%InvalidSubId -> + %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + %% Requesting entity is not a subscriber + Subscriptions == [] -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; + %% Subid supplied, so use that. + SubIdExists -> + Sub = first_in_list(fun + ({_, S}) when S == SubId -> true; + (_) -> false + end, + SubState#pubsub_state.subscriptions), + case Sub of + {value, S} -> + delete_subscriptions(SubKey, Nidx, [S], SubState), + {result, default}; + false -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} + end; + %% Asking to remove all subscriptions to the given node + SubId == all -> + delete_subscriptions(SubKey, Nidx, Subscriptions, SubState), + {result, default}; + %% No subid supplied, but there's only one matching subscription + length(Subscriptions) == 1 -> + delete_subscriptions(SubKey, Nidx, Subscriptions, SubState), + {result, default}; + %% No subid and more than one possible subscription match. + true -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} end. --spec(delete_subscriptions/4 :: -( - SubKey :: ljid(), - NodeIdx :: mod_pubsub:nodeIdx(), - Subscriptions :: [{mod_pubsub:subscription(), mod_pubsub:subId()}], - SubState :: mod_pubsub:pubsubState()) - -> ok -). -delete_subscriptions(SubKey, NodeIdx, Subscriptions, SubState) -> +delete_subscriptions(SubKey, Nidx, Subscriptions, SubState) -> NewSubs = lists:foldl(fun ({Subscription, SubId}, Acc) -> - pubsub_subscription:delete_subscription(SubKey, NodeIdx, SubId), - Acc -- [{Subscription, SubId}] - end, SubState#pubsub_state.subscriptions, Subscriptions), + pubsub_subscription:delete_subscription(SubKey, Nidx, SubId), + Acc -- [{Subscription, SubId}] + end, SubState#pubsub_state.subscriptions, Subscriptions), case {SubState#pubsub_state.affiliation, NewSubs} of - {none, []} -> del_state(NodeIdx, SubKey); - _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) + {none, []} -> del_state(Nidx, SubKey); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) end. -%% @spec (NodeIdx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> -%% {result, {default, broadcast, ItemIds}} | {error, Reason} -%% NodeIdx = mod_pubsub:nodeIdx() -%% Publisher = mod_pubsub:jid() -%% PublishModel = atom() -%% MaxItems = integer() -%% ItemId = mod_pubsub:itemId() -%% Payload = mod_pubsub:payload() -%% ItemIds = [mod_pubsub:itemId()] | [] -%% Reason = mod_pubsub:stanzaError() %% @doc

    Publishes the item passed as parameter.

    %%

    The mechanism works as follow: %%

      @@ -511,70 +361,48 @@ delete_subscriptions(SubKey, NodeIdx, Subscriptions, SubState) -> %% to completly disable persistance.
    %%

    %%

    In the default plugin module, the record is unchanged.

    --spec(publish_item/6 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - Max_Items :: non_neg_integer(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) - -> {result, {default, broadcast, [mod_pubsub:itemId()]}} - %%% - | {error, xmlel()} -). - -publish_item(NodeIdx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> +publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> SubKey = jlib:jid_tolower(Publisher), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), + GenState = get_state(Nidx, GenKey), SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(NodeIdx, SubKey) - end, + GenKey -> GenState; + _ -> get_state(Nidx, SubKey) + end, Affiliation = GenState#pubsub_state.affiliation, Subscribed = case PublishModel of - subscribers -> - is_subscribed(SubState#pubsub_state.subscriptions); - _ -> undefined - end, - if not - ((PublishModel == open) or - (PublishModel == publishers) and - ((Affiliation == owner) or (Affiliation == publisher)) - or (Subscribed == true)) -> - {error, ?ERR_FORBIDDEN}; - true -> - if MaxItems > 0 -> - Now = now(), - PubId = {Now, SubKey}, - Item = case get_item(NodeIdx, ItemId) of - {result, OldItem} -> - OldItem#pubsub_item{modification = PubId, - payload = Payload}; - _ -> - #pubsub_item{itemid = {ItemId, NodeIdx}, - creation = {Now, GenKey}, - modification = PubId, - payload = Payload} - end, - Items = [ItemId | GenState#pubsub_state.items -- - [ItemId]], - {result, {NI, OI}} = remove_extra_items(NodeIdx, - MaxItems, Items), - set_item(Item), - set_state(GenState#pubsub_state{items = NI}), - {result, {default, broadcast, OI}}; - true -> {result, {default, broadcast, []}} - end + subscribers -> is_subscribed(SubState#pubsub_state.subscriptions); + _ -> undefined + end, + if not ((PublishModel == open) or + (PublishModel == publishers) and + ((Affiliation == owner) or (Affiliation == publisher)) + or (Subscribed == true)) -> + {error, ?ERR_FORBIDDEN}; + true -> + if MaxItems > 0 -> + Now = now(), + PubId = {Now, SubKey}, + Item = case get_item(Nidx, ItemId) of + {result, OldItem} -> + OldItem#pubsub_item{modification = PubId, + payload = Payload}; + _ -> + #pubsub_item{itemid = {ItemId, Nidx}, + creation = {Now, GenKey}, + modification = PubId, + payload = Payload} + end, + Items = [ItemId | GenState#pubsub_state.items -- [ItemId]], + {result, {NI, OI}} = remove_extra_items(Nidx, MaxItems, Items), + set_item(Item), + set_state(GenState#pubsub_state{items = NI}), + {result, {default, broadcast, OI}}; + true -> + {result, {default, broadcast, []}} + end end. -%% @spec (NodeIdx, MaxItems, ItemIds) -> {result, {NewItemIds,OldItemIds}} -%% NodeIdx = mod_pubsub:nodeIdx() -%% MaxItems = integer() | unlimited -%% ItemIds = [mod_pubsub:itemId()] -%% NewItemIds = [mod_pubsub:itemId()] -%% OldItemIds = [mod_pubsub:itemId()] | [] %% @doc

    This function is used to remove extra items, most notably when the %% maximum number of items has been reached.

    %%

    This function is used internally by the core PubSub module, as no @@ -583,119 +411,84 @@ publish_item(NodeIdx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% rules can be used.

    %%

    If another PubSub plugin wants to delegate the item removal (and if the %% plugin is using the default pubsub storage), it can implements this function like this: -%% ```remove_extra_items(NodeIdx, MaxItems, ItemIds) -> -%% node_default:remove_extra_items(NodeIdx, MaxItems, ItemIds).'''

    --spec(remove_extra_items/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Max_Items :: unlimited | non_neg_integer(), - ItemIds :: [mod_pubsub:itemId()]) - -> {result, - {NewItems::[mod_pubsub:itemId()], - OldItems::[mod_pubsub:itemId()]} - } -). -remove_extra_items(_NodeIdx, unlimited, ItemIds) -> +%% ```remove_extra_items(Nidx, MaxItems, ItemIds) -> +%% node_default:remove_extra_items(Nidx, MaxItems, ItemIds).'''

    +remove_extra_items(_Nidx, unlimited, ItemIds) -> {result, {ItemIds, []}}; -remove_extra_items(NodeIdx, MaxItems, ItemIds) -> +remove_extra_items(Nidx, MaxItems, ItemIds) -> NewItems = lists:sublist(ItemIds, MaxItems), OldItems = lists:nthtail(length(NewItems), ItemIds), - del_items(NodeIdx, OldItems), + del_items(Nidx, OldItems), {result, {NewItems, OldItems}}. -%% @spec (NodeIdx, Publisher, PublishModel, ItemId) -> -%% {result, {default, broadcast}} | {error, Reason} -%% NodeIdx = mod_pubsub:nodeIdx() -%% Publisher = mod_pubsub:jid() -%% PublishModel = atom() -%% ItemId = mod_pubsub:itemId() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Triggers item deletion.

    %%

    Default plugin: The user performing the deletion must be the node owner %% or a publisher, or PublishModel being open.

    --spec(delete_item/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - ItemId :: <<>> | mod_pubsub:itemId()) - -> {result, {default, broadcast}} - %%% - | {error, xmlel()} -). -delete_item(NodeIdx, Publisher, PublishModel, ItemId) -> +delete_item(Nidx, Publisher, PublishModel, ItemId) -> SubKey = jlib:jid_tolower(Publisher), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), + GenState = get_state(Nidx, GenKey), #pubsub_state{affiliation = Affiliation, items = Items} = GenState, Allowed = Affiliation == publisher orelse - Affiliation == owner orelse - PublishModel == open orelse - case get_item(NodeIdx, ItemId) of - {result, #pubsub_item{creation = {_, GenKey}}} -> true; - _ -> false - end, - if not Allowed -> {error, ?ERR_FORBIDDEN}; - true -> - case lists:member(ItemId, Items) of - true -> - del_item(NodeIdx, ItemId), - set_state(GenState#pubsub_state{items = lists:delete(ItemId, Items)}), - {result, {default, broadcast}}; - false -> - case Affiliation of - owner -> - {result, States} = get_states(NodeIdx), - lists:foldl(fun (#pubsub_state{items = PI} = S, Res) -> - case lists:member(ItemId, PI) of - true -> - del_item(NodeIdx, ItemId), - set_state(S#pubsub_state{items - = lists:delete(ItemId, PI)}), - {result, {default, broadcast}}; - false -> Res - end; - (_, Res) -> Res - end, - {error, ?ERR_ITEM_NOT_FOUND}, States); - _ -> {error, ?ERR_ITEM_NOT_FOUND} - end - end + Affiliation == owner orelse + PublishModel == open orelse + case get_item(Nidx, ItemId) of + {result, #pubsub_item{creation = {_, GenKey}}} -> true; + _ -> false + end, + if not Allowed -> + {error, ?ERR_FORBIDDEN}; + true -> + case lists:member(ItemId, Items) of + true -> + del_item(Nidx, ItemId), + set_state(GenState#pubsub_state{items = lists:delete(ItemId, Items)}), + {result, {default, broadcast}}; + false -> + case Affiliation of + owner -> + {result, States} = get_states(Nidx), + lists:foldl(fun + (#pubsub_state{items = PI} = S, Res) -> + case lists:member(ItemId, PI) of + true -> + Nitems = lists:delete(ItemId, PI), + del_item(Nidx, ItemId), + set_state(S#pubsub_state{items = Nitems}), + {result, {default, broadcast}}; + false -> + Res + end; + (_, Res) -> + Res + end, + {error, ?ERR_ITEM_NOT_FOUND}, States); + _ -> + {error, ?ERR_ITEM_NOT_FOUND} + end + end end. -%% @spec (NodeIdx, Owner) -> {error, Reason} | {result, {default, broadcast}} -%% NodeIdx = mod_pubsub:nodeIdx() -%% Owner = mod_pubsub:jid() -%% Reason = mod_pubsub:stanzaError() --spec(purge_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} - | {error, xmlel()} -). - -purge_node(NodeIdx, Owner) -> +purge_node(Nidx, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), + GenState = get_state(Nidx, GenKey), case GenState of - #pubsub_state{affiliation = owner} -> - {result, States} = get_states(NodeIdx), - lists:foreach(fun (#pubsub_state{items = []}) -> ok; - (#pubsub_state{items = Items} = S) -> - del_items(NodeIdx, Items), - set_state(S#pubsub_state{items = []}) - end, - States), - {result, {default, broadcast}}; - _ -> {error, ?ERR_FORBIDDEN} + #pubsub_state{affiliation = owner} -> + {result, States} = get_states(Nidx), + lists:foreach(fun + (#pubsub_state{items = []}) -> + ok; + (#pubsub_state{items = Items} = S) -> + del_items(Nidx, Items), + set_state(S#pubsub_state{items = []}) + end, + States), + {result, {default, broadcast}}; + _ -> + {error, ?ERR_FORBIDDEN} end. -%% @spec (Host, Owner) -> {result, Reply} -%% Host = mod_pubsub:hostPubsub() -%% Owner = mod_pubsub:jid() -%% Reply = [] | [{mod_pubsub:pubsubNode(), mod_pubsub:affiliation()}] %% @doc

    Return the current affiliations for the given user

    %%

    The default module reads affiliations in the main Mnesia %% pubsub_state table. If a plugin stores its data in the same @@ -703,88 +496,40 @@ purge_node(NodeIdx, Owner) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% pubsub_state table.

    --spec(get_entity_affiliations/2 :: -( - Host :: mod_pubsub:host(), - Owner :: jid()) - -> {result, [{mod_pubsub:pubsubNode(), mod_pubsub:affiliation()}]} -). - get_entity_affiliations(Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), - NodeTree = case catch - ets:lookup(gen_mod:get_module_proc(Host, config), - nodetree) - of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, - Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {Host, _}} = Node -> - [{Node, A} | Acc]; - _ -> Acc - end - end, - [], States), + NodeTree = mod_pubsub:tree(Host), + Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {Host, _}} = Node -> [{Node, A} | Acc]; + _ -> Acc + end + end, + [], States), {result, Reply}. --spec(get_node_affiliations/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [{ljid(), mod_pubsub:affiliation()}]} -). - -get_node_affiliations(NodeIdx) -> - {result, States} = get_states(NodeIdx), - Tr = fun (#pubsub_state{stateid = {J, _}, - affiliation = A}) -> - {J, A} - end, +get_node_affiliations(Nidx) -> + {result, States} = get_states(Nidx), + Tr = fun (#pubsub_state{stateid = {J, _}, affiliation = A}) -> {J, A} end, {result, lists:map(Tr, States)}. --spec(get_affiliation/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, mod_pubsub:affiliation()} -). - -get_affiliation(NodeIdx, Owner) -> +get_affiliation(Nidx, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - #pubsub_state{affiliation = Affiliation} = get_state(NodeIdx, GenKey), + #pubsub_state{affiliation = Affiliation} = get_state(Nidx, GenKey), {result, Affiliation}. --spec(set_affiliation/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid(), - Affiliation :: mod_pubsub:affiliation()) - -> ok -). -set_affiliation(NodeIdx, Owner, Affiliation) -> +set_affiliation(Nidx, Owner, Affiliation) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), + GenState = get_state(Nidx, GenKey), case {Affiliation, GenState#pubsub_state.subscriptions} of - {none, []} -> del_state(NodeIdx, GenKey); - _ -> set_state(GenState#pubsub_state{affiliation = Affiliation}) + {none, []} -> del_state(Nidx, GenKey); + _ -> set_state(GenState#pubsub_state{affiliation = Affiliation}) end. -%% @spec (Host, Owner) -> -%% {'result', [] -%% | [{Node, Subscription, SubId, Entity}] -%% | [{Node, Subscription, Entity}]} -%% Host = mod_pubsub:hostPubsub() -%% Owner = mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% Subscription = mod_pubsub:subscription() -%% SubId = mod_pubsub:subId() -%% Entity = mod_pubsub:ljid() %% @doc

    Return the current subscriptions for the given user

    %%

    The default module reads subscriptions in the main Mnesia %% pubsub_state table. If a plugin stores its data in the same @@ -792,130 +537,79 @@ set_affiliation(NodeIdx, Owner, Affiliation) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% pubsub_state table.

    --spec(get_entity_subscriptions/2 :: -( - Host :: mod_pubsub:host(), - Owner :: jid()) - -> {result, - [{mod_pubsub:pubsubNode(), - mod_pubsub:subscription(), - mod_pubsub:subId(), - ljid()}] - } -). - get_entity_subscriptions(Host, Owner) -> {U, D, _} = SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), States = case SubKey of - GenKey -> - mnesia:match_object(#pubsub_state{stateid = - {{U, D, '_'}, '_'}, - _ = '_'}); - _ -> - mnesia:match_object(#pubsub_state{stateid = - {GenKey, '_'}, - _ = '_'}) - ++ - mnesia:match_object(#pubsub_state{stateid = - {SubKey, '_'}, - _ = '_'}) - end, - NodeTree = case catch - ets:lookup(gen_mod:get_module_proc(Host, config), - nodetree) - of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, subscriptions = Ss}, - Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {Host, _}} = Node -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, J} | Acc2] - end, - Acc, Ss); - _ -> Acc - end - end, - [], States), + GenKey -> + mnesia:match_object(#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); + _ -> + mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) + ++ + mnesia:match_object(#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) + end, + NodeTree = mod_pubsub:tree(Host), + Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {Host, _}} = Node -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, J} | Acc2] + end, + Acc, Ss); + _ -> + Acc + end + end, + [], States), {result, Reply}. --spec(get_node_subscriptions/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, - [{ljid(), mod_pubsub:subscription(), mod_pubsub:subId()}] | - [{ljid(), none},...] - } -). -get_node_subscriptions(NodeIdx) -> - {result, States} = get_states(NodeIdx), - Tr = fun (#pubsub_state{stateid = {J, _}, - subscriptions = Subscriptions}) -> - case Subscriptions of - [_ | _] -> - lists:foldl(fun ({S, SubId}, Acc) -> - [{J, S, SubId} | Acc] - end, - [], Subscriptions); - [] -> []; - _ -> [{J, none}] - end - end, +get_node_subscriptions(Nidx) -> + {result, States} = get_states(Nidx), + Tr = fun (#pubsub_state{stateid = {J, _}, subscriptions = Subscriptions}) -> + case Subscriptions of + [_ | _] -> + lists:foldl(fun ({S, SubId}, Acc) -> + [{J, S, SubId} | Acc] + end, + [], Subscriptions); + [] -> + []; + _ -> + [{J, none}] + end + end, {result, lists:flatmap(Tr, States)}. --spec(get_subscriptions/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid()) - -> {result, [{mod_pubsub:subscription(), mod_pubsub:subId()}]} -). -get_subscriptions(NodeIdx, Owner) -> +get_subscriptions(Nidx, Owner) -> SubKey = jlib:jid_tolower(Owner), - SubState = get_state(NodeIdx, SubKey), + SubState = get_state(Nidx, SubKey), {result, SubState#pubsub_state.subscriptions}. --spec(set_subscriptions/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid(), - Subscription :: mod_pubsub:subscription(), - SubId :: mod_pubsub:subId()) - -> ok - %%% - | {error, xmlel()} -). - -set_subscriptions(NodeIdx, Owner, Subscription, SubId) -> +set_subscriptions(Nidx, Owner, Subscription, SubId) -> SubKey = jlib:jid_tolower(Owner), - SubState = get_state(NodeIdx, SubKey), + SubState = get_state(Nidx, SubKey), case {SubId, SubState#pubsub_state.subscriptions} of - {_, []} -> - case Subscription of - none -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), - <<"not-subscribed">>)}; - _ -> - new_subscription(NodeIdx, Owner, Subscription, SubState) - end; - {<<>>, [{_, SID}]} -> - case Subscription of - none -> unsub_with_subid(NodeIdx, SID, SubState); - _ -> replace_subscription({Subscription, SID}, SubState) - end; - {<<>>, [_ | _]} -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), - <<"subid-required">>)}; - _ -> - case Subscription of - none -> unsub_with_subid(NodeIdx, SubId, SubState); - _ -> - replace_subscription({Subscription, SubId}, SubState) - end + {_, []} -> + case Subscription of + none -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; + _ -> + new_subscription(Nidx, Owner, Subscription, SubState) + end; + {<<>>, [{_, SID}]} -> + case Subscription of + none -> unsub_with_subid(Nidx, SID, SubState); + _ -> replace_subscription({Subscription, SID}, SubState) + end; + {<<>>, [_ | _]} -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; + _ -> + case Subscription of + none -> unsub_with_subid(Nidx, SubId, SubState); + _ -> replace_subscription({Subscription, SubId}, SubState) + end end. replace_subscription(NewSub, SubState) -> @@ -923,103 +617,64 @@ replace_subscription(NewSub, SubState) -> set_state(SubState#pubsub_state{subscriptions = NewSubs}). replace_subscription(_, [], Acc) -> Acc; -replace_subscription({Sub, SubId}, [{_, SubID} | T], Acc) -> - replace_subscription({Sub, SubId}, T, [{Sub, SubID} | Acc]). - -new_subscription(NodeId, Owner, Subscription, SubState) -> - SubId = pubsub_subscription:add_subscription(Owner, NodeId, []), - Subscriptions = SubState#pubsub_state.subscriptions, - set_state(SubState#pubsub_state{subscriptions = - [{Subscription, SubId} | Subscriptions]}), - {Subscription, SubId}. - --spec(unsub_with_subid/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - SubId :: mod_pubsub:subId(), - SubState :: mod_pubsub:pubsubState()) - -> ok -). -unsub_with_subid(NodeIdx, SubId, #pubsub_state{stateid = {Entity, _}} = SubState) -> - pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, - NodeIdx, SubId), - NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID - end, - SubState#pubsub_state.subscriptions), +replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> + replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). + +new_subscription(Nidx, Owner, Sub, SubState) -> + SubId = pubsub_subscription:add_subscription(Owner, Nidx, []), + Subs = SubState#pubsub_state.subscriptions, + set_state(SubState#pubsub_state{subscriptions = [{Sub, SubId} | Subs]}), + {Sub, SubId}. + +unsub_with_subid(Nidx, SubId, #pubsub_state{stateid = {Entity, _}} = SubState) -> + pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, Nidx, SubId), + NewSubs = [{S, Sid} + || {S, Sid} <- SubState#pubsub_state.subscriptions, + SubId =/= Sid], case {NewSubs, SubState#pubsub_state.affiliation} of - {[], none} -> - del_state(NodeIdx, Entity); - _ -> - set_state(SubState#pubsub_state{subscriptions = NewSubs}) + {[], none} -> del_state(Nidx, Entity); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) end. -%% TODO : doc -%% @spec (Host, Owner) -> {result, Reply} | {error, Reason} -%% Host = mod_pubsub:hostPubsub() -%% Owner = mod_pubsub:jid() -%% Reply = [] | [mod_pubsub:nodeId()] %% @doc

    Returns a list of Owner's nodes on Host with pending %% subscriptions.

    --spec(get_pending_nodes/2 :: -( - Host :: mod_pubsub:host(), - Owner :: jid()) - -> {result, [mod_pubsub:nodeId()]} -). - get_pending_nodes(Host, Owner) -> GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), - States = mnesia:match_object(#pubsub_state{stateid = - {GenKey, '_'}, - affiliation = owner, _ = '_'}), - NodeIDs = [ID - || #pubsub_state{stateid = {_, ID}} <- States], - NodeTree = case catch - ets:lookup(gen_mod:get_module_proc(Host, config), - nodetree) - of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, NID}} = S, - Acc) -> - case lists:member(NID, NodeIDs) of - true -> - case get_nodes_helper(NodeTree, S) of - {value, Node} -> [Node | Acc]; - false -> Acc - end; - false -> Acc - end - end, - [], pubsub_state), + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, + affiliation = owner, + _ = '_'}), + NodeIdxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], + NodeTree = mod_pubsub:tree(Host), + Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, Nidx}} = S, Acc) -> + case lists:member(Nidx, NodeIdxs) of + true -> + case get_nodes_helper(NodeTree, S) of + {value, Node} -> [Node | Acc]; + false -> Acc + end; + false -> + Acc + end + end, + [], pubsub_state), {result, Reply}. --spec(get_nodes_helper/2 :: -( - NodeTree :: module(), - Pubsub_State :: mod_pubsub:pubsubState()) - -> {value, NodeId::mod_pubsub:nodeId()} - | false - -). get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> - HasPending = fun ({pending, _}) -> true; - (pending) -> true; - (_) -> false - end, + HasPending = fun + ({pending, _}) -> true; + (pending) -> true; + (_) -> false + end, case lists:any(HasPending, Subs) of - true -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {_, Node}} -> {value, Node}; - _ -> false - end; - false -> false + true -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {_, Node}} -> {value, Node}; + _ -> false + end; + false -> + false end. -%% @spec (NodeIdx) -> {result, States} -%% NodeIdx = mod_pubsub:nodeIdx() -%% States = [] | [mod_pubsub:pubsubState()] %% @doc Returns the list of stored states for a given node. %%

    For the default PubSub module, states are stored in Mnesia database.

    %%

    We can consider that the pubsub_state table have been created by the main @@ -1028,72 +683,33 @@ get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs} %% relational database).

    %%

    If a PubSub plugin wants to delegate the states storage to the default node, %% they can implement this function like this: -%% ```get_states(NodeIdx) -> -%% node_default:get_states(NodeIdx).'''

    --spec(get_states/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [mod_pubsub:pubsubState()]} -). - -get_states(NodeIdx) -> +%% ```get_states(Nidx) -> +%% node_default:get_states(Nidx).'''

    +get_states(Nidx) -> States = case catch mnesia:match_object( - #pubsub_state{stateid = {'_', NodeIdx}, _ = '_'}) of + #pubsub_state{stateid = {'_', Nidx}, _ = '_'}) of List when is_list(List) -> List; _ -> [] end, {result, States}. -%% @spec (NodeIdx, JID) -> State -%% NodeIdx = mod_pubsub:nodeIdx() -%% JID = mod_pubsub:jid() -%% State = mod_pubsub:pubsubState() %% @doc

    Returns a state (one state list), given its reference.

    --spec(get_state/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: ljid()) - -> mod_pubsub:pubsubState() -). - -get_state(NodeIdx, JID) -> - StateId = {JID, NodeIdx}, +get_state(Nidx, Key) -> + StateId = {Key, Nidx}, case catch mnesia:read({pubsub_state, StateId}) of [State] when is_record(State, pubsub_state) -> State; - _ -> #pubsub_state{stateid=StateId} + _ -> #pubsub_state{stateid = StateId} end. -%% @spec (State) -> ok | {error, Reason} -%% State = mod_pubsub:pubsubState() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Write a state into database.

    --spec(set_state/1 :: -( - State::mod_pubsub:pubsubState()) - -> ok -). set_state(State) when is_record(State, pubsub_state) -> mnesia:write(State). %set_state(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. -%% @spec (NodeIdx, JID) -> ok | {error, Reason} -%% NodeIdx = mod_pubsub:nodeIdx() -%% JID = mod_pubsub:jid() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Delete a state from database.

    --spec(del_state/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: ljid()) - -> ok -). -del_state(NodeIdx, JID) -> - mnesia:delete({pubsub_state, {JID, NodeIdx}}). +del_state(Nidx, Key) -> + mnesia:delete({pubsub_state, {Key, Nidx}}). -%% @spec (NodeIdx, From) -> {result, Items} -%% NodeIdx = mod_pubsub:nodeIdx() -%% From = mod_pubsub:jid() -%% Items = [] | [mod_pubsub:pubsubItem()] %% @doc Returns the list of stored items for a given node. %%

    For the default PubSub module, items are stored in Mnesia database.

    %%

    We can consider that the pubsub_item table have been created by the main @@ -1102,228 +718,134 @@ del_state(NodeIdx, JID) -> %% relational database), or they can even decide not to persist any items.

    %%

    If a PubSub plugin wants to delegate the item storage to the default node, %% they can implement this function like this: -%% ```get_items(NodeIdx, From) -> -%% node_default:get_items(NodeIdx, From).'''

    --spec(get_items/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - _From :: jid()) - -> {result, [mod_pubsub:pubsubItem()]} -). - -get_items(NodeIdx, _From) -> - Items = mnesia:match_object(#pubsub_item{itemid = {'_', NodeIdx}, _ = '_'}), - {result, lists:reverse(lists:keysort(#pubsub_item.modification, Items))}. - --spec(get_items/6 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: jid(), - AccessModel :: mod_pubsub:accessModel(), - Presence_Subscription :: boolean(), - RosterGroup :: boolean(), - _SubId :: mod_pubsub:subId()) - -> {result, [mod_pubsub:pubsubItem()]} - %%% - | {error, xmlel()} -). - -get_items(NodeIdx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> +%% ```get_items(Nidx, From) -> +%% node_default:get_items(Nidx, From).'''

    +get_items(Nidx, From) -> + get_items(Nidx, From, none). +get_items(Nidx, _From, _RSM) -> + Items = mnesia:match_object(#pubsub_item{itemid = {'_', Nidx}, _ = '_'}), + {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), none}}. + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RSM) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), - SubState = get_state(NodeIdx, SubKey), + GenState = get_state(Nidx, GenKey), + SubState = get_state(Nidx, SubKey), Affiliation = GenState#pubsub_state.affiliation, Subscriptions = SubState#pubsub_state.subscriptions, Whitelisted = can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - GenState#pubsub_state.affiliation == outcast -> - {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and - not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> get_items(NodeIdx, JID) + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + Affiliation == outcast -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_items(Nidx, JID) end. -%% @spec (NodeIdx, ItemId) -> {result, Item} | {error, 'item-not-found'} -%% NodeIdx = mod_pubsub:nodeIdx() -%% ItemId = mod_pubsub:itemId() -%% Item = mod_pubsub:pubsubItem() %% @doc

    Returns an item (one item list), given its reference.

    --spec(get_item/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - ItemId :: mod_pubsub:itemId()) - -> {result, mod_pubsub:pubsubItem()} - | {error, xmlel()} -). -get_item(NodeIdx, ItemId) -> - case mnesia:read({pubsub_item, {ItemId, NodeIdx}}) of - [Item] when is_record(Item, pubsub_item) -> {result, Item}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} +get_item(Nidx, ItemId) -> + case mnesia:read({pubsub_item, {ItemId, Nidx}}) of + [Item] when is_record(Item, pubsub_item) -> {result, Item}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} end. -%% @spec (NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> {result, Item} | {error, Reason} -%% NodeIdx = mod_pubsub:nodeIdx() -%% ItemId = mod_pubsub:itemId() -%% JID = mod_pubsub:jid() -%% AccessModel = mod_pubsub:accessModel() -%% PresenceSubscription = boolean() -%% RosterGroup = boolean() -%% SubId = mod_pubsub:subId() -%% Item = mod_pubsub:pubsubItem() -%% Reason = mod_pubsub:stanzaError() | 'item-not-found' --spec(get_item/7 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - ItemId :: mod_pubsub:itemId(), - JID :: jid(), - AccessModel :: mod_pubsub:accessModel(), - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - SubId :: mod_pubsub:subId()) - -> {result, mod_pubsub:pubsubItem()} - | {error, xmlel()} -). - -get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, - _SubId) -> +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), + GenState = get_state(Nidx, GenKey), Affiliation = GenState#pubsub_state.affiliation, Subscriptions = GenState#pubsub_state.subscriptions, Whitelisted = can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - GenState#pubsub_state.affiliation == outcast -> - {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and - not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> get_item(NodeIdx, ItemId) + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + Affiliation == outcast -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_item(Nidx, ItemId) end. -%% @spec (Item) -> ok | {error, Reason} -%% Item = mod_pubsub:pubsubItem() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Write an item into database.

    --spec(set_item/1 :: -( - Item::mod_pubsub:pubsubItem()) - -> ok -). set_item(Item) when is_record(Item, pubsub_item) -> mnesia:write(Item). %set_item(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. -%% @spec (NodeIdx, ItemId) -> ok | {error, Reason} -%% NodeIdx = mod_pubsub:nodeIdx() -%% ItemId = mod_pubsub:itemId() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Delete an item from database.

    --spec(del_item/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - ItemId :: mod_pubsub:itemId()) - -> ok -). -del_item(NodeIdx, ItemId) -> - mnesia:delete({pubsub_item, {ItemId, NodeIdx}}). +del_item(Nidx, ItemId) -> + mnesia:delete({pubsub_item, {ItemId, Nidx}}). --spec(del_items/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - ItemIds :: [mod_pubsub:pubsubItem(),...]) - -> ok -). - -del_items(NodeIdx, ItemIds) -> - lists:foreach(fun (ItemId) -> del_item(NodeIdx, ItemId) - end, - ItemIds). +del_items(Nidx, ItemIds) -> + lists:foreach(fun (ItemId) -> del_item(Nidx, ItemId) + end, + ItemIds). -get_item_name(_Host, _Node, Id) -> Id. +get_item_name(_Host, _Node, Id) -> + Id. %% @doc

    Return the name of the node if known: Default is to return %% node id.

    --spec(node_to_path/1 :: -( - Node::binary()) - -> [binary()] -). -node_to_path(Node) -> str:tokens((Node), <<"/">>). - --spec(path_to_node/1 :: -( - Path :: [binary()]) - -> binary() -). +node_to_path(Node) -> + str:tokens(Node, <<"/">>). path_to_node([]) -> <<>>; -path_to_node(Path) -> - iolist_to_binary(str:join([<<"">> | Path], <<"/">>)). +path_to_node(Path) -> iolist_to_binary(str:join([<<"">> | Path], <<"/">>)). -%% @spec (Affiliation, Subscription) -> true | false -%% Affiliation = owner | member | publisher | outcast | none -%% Subscription = subscribed | none -%% @doc Determines if the combination of Affiliation and Subscribed -%% are allowed to get items from a node. can_fetch_item(owner, _) -> true; can_fetch_item(member, _) -> true; can_fetch_item(publisher, _) -> true; can_fetch_item(outcast, _) -> false; -can_fetch_item(none, Subscriptions) -> - is_subscribed(Subscriptions). +can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). %can_fetch_item(_Affiliation, _Subscription) -> false. is_subscribed(Subscriptions) -> - lists:any(fun ({subscribed, _SubId}) -> true; - (_) -> false - end, - Subscriptions). + lists:any(fun + ({subscribed, _SubId}) -> true; + (_) -> false + end, + Subscriptions). -%% Returns the first item where Pred() is true in List -first_in_list(_Pred, []) -> false; +first_in_list(_Pred, []) -> + false; first_in_list(Pred, [H | T]) -> case Pred(H) of - true -> {value, H}; - _ -> first_in_list(Pred, T) + true -> {value, H}; + _ -> first_in_list(Pred, T) end. diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index 0678b9898e8..d0cfad0f1ea 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -4,20 +4,19 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne %%% @author Christophe Romain %%% [http://www.process-one.net/] @@ -41,116 +40,48 @@ %%% improvements.

    -module(node_hometree_odbc). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --define(PUBSUB, mod_pubsub_odbc). +-export([init/3, terminate/2, options/0, features/0, + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, + get_items/6, get_items/2, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1, + get_entity_subscriptions_for_send_last/2, get_last_items/3]). + +-export([decode_jid/1, encode_jid/1, + decode_affiliation/1, decode_subscriptions/1, + encode_affiliation/1, encode_subscriptions/1, + encode_host/1]). + +init(Host, ServerHost, _Opts) -> + pubsub_subscription_odbc:init(), + Owner = mod_pubsub:service_jid(Host), + mod_pubsub:create_node(Host, ServerHost, <<"/home">>, Owner, <<"hometree">>), + mod_pubsub:create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, Owner, <<"hometree">>), + ok. --behaviour(gen_pubsub_node). +terminate(_Host, _ServerHost) -> + ok. -%% API definition --export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, - get_entity_subscriptions_for_send_last/2, - get_node_subscriptions/1, get_subscriptions/2, - set_subscriptions/4, get_pending_nodes/2, get_states/1, - get_state/2, set_state/1, get_items/7, get_items/6, - get_items/3, get_items/2, get_item/7, get_item/2, - set_item/1, get_item_name/3, get_last_items/3, - path_to_node/1, node_to_path/1]). - --export([decode_jid/1, - decode_affiliation/1, decode_subscriptions/1, - encode_jid/1, encode_affiliation/1, - encode_subscriptions/1]). - -%% ================ -%% API definition -%% ================ - -%% @spec (Host, ServerHost, Opts) -> any() -%% Host = mod_pubsub:host() -%% ServerHost = mod_pubsub:host() -%% Opts = list() -%% @doc

    Called during pubsub modules initialisation. Any pubsub plugin must -%% implement this function. It can return anything.

    -%%

    This function is mainly used to trigger the setup task necessary for the -%% plugin. It can be used for example by the developer to create the specific -%% module database schema if it does not exists yet.

    -init(_Host, _ServerHost, _Opts) -> - pubsub_subscription_odbc:init(), ok. - -%% @spec (Host, ServerHost) -> any() -%% Host = mod_pubsub:host() -%% ServerHost = host() -%% @doc

    Called during pubsub modules termination. Any pubsub plugin must -%% implement this function. It can return anything.

    -terminate(_Host, _ServerHost) -> ok. - -%% @spec () -> [Option] -%% Option = mod_pubsub:nodeOption() -%% @doc Returns the default pubsub node options. -%%

    Example of function return value:

    -%% ``` -%% [{deliver_payloads, true}, -%% {notify_config, false}, -%% {notify_delete, false}, -%% {notify_retract, true}, -%% {persist_items, true}, -%% {max_items, 10}, -%% {subscribe, true}, -%% {access_model, open}, -%% {publish_model, publishers}, -%% {max_payload_size, 100000}, -%% {send_last_published_item, never}, -%% {presence_based_delivery, false}]''' --spec(options/0 :: () -> NodeOptions::mod_pubsub:nodeOptions()). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, open}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}, {odbc, true}, - {rsm, true}]. - -%% @spec () -> [] -%% @doc Returns the node features --spec(features/0 :: () -> Features::[Feature::binary(),...]). + [{odbc, true}, {rsm, true} | node_hometree:options()]. + features() -> - [<<"create-nodes">>, <<"auto-create">>, - <<"access-authorize">>, <<"delete-nodes">>, - <<"delete-items">>, <<"get-pending">>, - <<"instant-nodes">>, <<"manage-subscriptions">>, - <<"modify-affiliations">>, <<"multi-subscribe">>, - <<"outcast-affiliation">>, <<"persistent-items">>, - <<"publish">>, <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, <<"retrieve-items">>, - <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>, - <<"subscription-options">>, <<"rsm">>]. - -%% @spec (Host, ServerHost, Node, ParentNode, Owner, Access) -> bool() -%% Host = mod_pubsub:host() -%% ServerHost = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% ParentNode = mod_pubsub:pubsubNode() -%% Owner = mod_pubsub:jid() -%% Access = all | atom() + [<<"rsm">> | node_hometree:features()]. + %% @doc Checks if the current user has the permission to create the requested node %%

    In {@link node_default}, the permission is decided by the place in the %% hierarchy where the user is creating the node. The access parameter is also @@ -158,95 +89,32 @@ features() -> %% access_createnode ACL value in ejabberd config file.

    %%

    This function also check that node can be created a a children of its %% parent node

    -%%

    PubSub plugins can redefine the PubSub node creation rights as they -%% which. They can simply delegate this check to the {@link node_default} -%% module by implementing this function like this: -%% ```check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> -%% node_default:check_create_user_permission(Host, ServerHost, Node, ParentNode, Owner, Access).'''

    --spec(create_node_permission/6 :: -( - Host :: mod_pubsub:host(), - ServerHost :: binary(), - Node :: mod_pubsub:nodeId(), - _ParentNode :: _, - Owner :: jid(), - Access :: atom()) - -> {result, boolean()} -). -create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> - LOwner = jlib:jid_tolower(Owner), - {User, Server, _Resource} = LOwner, - Allowed = case LOwner of - {<<"">>, Host, <<"">>} -> - true; % pubsub service always allowed - _ -> - case acl:match_rule(ServerHost, Access, LOwner) of - allow -> - case node_to_path(Node) of - [<<"home">>, Server, User | _] -> true; - _ -> false - end; - _ -> false - end - end, - {result, Allowed}. - -%% @spec (NodeId, Owner) -> -%% {result, Result} | exit -%% NodeId = mod_pubsub:pubsubNodeId() -%% Owner = mod_pubsub:jid() -%% @doc

    --spec(create_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} -). -create_node(NodeIdx, Owner) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - State = #pubsub_state{stateid = {OwnerKey, NodeIdx}, affiliation = owner}, - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, " - "affiliation, subscriptions) values(">>, - state_to_raw(NodeIdx, State), <<");">>]), +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + {_U, _S, _R} = OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + State = #pubsub_state{stateid = {OwnerKey, Nidx}, affiliation = owner}, + catch ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values(">>, state_to_raw(Nidx, State), <<");">>]), {result, {default, broadcast}}. -%% @spec (Removed) -> ok -%% Removed = [mod_pubsub:pubsubNode()] -%% @doc

    purge items of deleted nodes after effective deletion.

    --spec(delete_node/1 :: -( - Removed :: [mod_pubsub:pubsubNode(),...]) - -> {result, {default, broadcast, _}} -). -delete_node(Removed) -> - Reply = lists:map(fun (#pubsub_node{id = NodeId} = - PubsubNode) -> - Subscriptions = case catch - ejabberd_odbc:sql_query_t([<<"select jid, subscriptions from pubsub_state " - "where nodeid='">>, - NodeId, - <<"';">>]) - of - {selected, - [<<"jid">>, - <<"subscriptions">>], - RItems} -> - lists:map(fun ([SJID, - Subscriptions]) -> - {decode_jid(SJID), - decode_subscriptions(Subscriptions)} - end, - RItems); - _ -> [] - end, - {PubsubNode, Subscriptions} - end, - Removed), +delete_node(Nodes) -> + Reply = lists:map(fun (#pubsub_node{id = Nidx} = Node) -> + Subscriptions = case catch + ejabberd_odbc:sql_query_t([<<"select jid, subscriptions " + "from pubsub_state where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> + [{decode_jid(SJID), decode_subscriptions(Subs)} || [SJID, Subs] <- RItems]; + _ -> + [] + end, + {Node, Subscriptions} + end, + Nodes), {result, {default, broadcast, Reply}}. -%% @spec (NodeId, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> -%% {error, Reason} | {result, Result} %% @doc

    Accepts or rejects subcription requests on a PubSub node.

    %%

    The mechanism works as follow: %%

      @@ -278,192 +146,118 @@ delete_node(Removed) -> %% to completly disable persistance.
    %%

    %%

    In the default plugin module, the record is unchanged.

    --spec(subscribe_node/8 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - AccessModel :: mod_pubsub:accessModel(), - SendLast :: 'never' | 'on_sub' | 'on_sub_and_presence', - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - Options :: mod_pubsub:subOptions()) - -> {result, {default, subscribed, mod_pubsub:subId()}} - | {result, {default, subscribed, mod_pubsub:subId(), send_last}} - | {result, {default, pending, mod_pubsub:subId()}} - %%% - | {error, _} - | {error, _, binary()} -). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), - Authorized = - jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == - GenKey, - {Affiliation, Subscriptions} = - select_affiliation_subscriptions(NodeId, GenKey, - SubKey), - Whitelisted = lists:member(Affiliation, - [member, publisher, owner]), - PendingSubscription = lists:any(fun ({pending, _}) -> - true; - (_) -> false - end, - Subscriptions), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Whitelisted = lists:member(Affiliation, [member, publisher, owner]), + PendingSubscription = lists:any(fun + ({pending, _}) -> true; + (_) -> false + end, + Subscriptions), if not Authorized -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; - Affiliation == outcast -> {error, ?ERR_FORBIDDEN}; - PendingSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"pending-subscription">>)}; - (AccessModel == presence) and - not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - %%ForbiddenAnonymous -> - %% % Requesting entity is anonymous - %% {error, ?ERR_FORBIDDEN}; - true -> - {result, SubId} = pubsub_subscription_odbc:subscribe_node(Subscriber, NodeId, Options), - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed - end, - update_subscription(NodeId, SubKey, - [{NewSub, SubId} | Subscriptions]), - case {NewSub, SendLast} of - {subscribed, never} -> - {result, {default, subscribed, SubId}}; - {subscribed, _} -> - {result, {default, subscribed, SubId, send_last}}; - {_, _} -> {result, {default, pending, SubId}} - end + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; + Affiliation == outcast -> + {error, ?ERR_FORBIDDEN}; + PendingSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + %%ForbiddenAnonymous -> + %% % Requesting entity is anonymous + %% {error, ?ERR_FORBIDDEN}; + true -> + {result, SubId} = pubsub_subscription_odbc:subscribe_node(Subscriber, Nidx, Options), + NewSub = case AccessModel of + authorize -> pending; + _ -> subscribed + end, + update_subscription(Nidx, SubKey, [{NewSub, SubId} | Subscriptions]), + case {NewSub, SendLast} of + {subscribed, never} -> {result, {default, subscribed, SubId}}; + {subscribed, _} -> {result, {default, subscribed, SubId, send_last}}; + {_, _} -> {result, {default, pending, SubId}} + end end. -%% @spec (NodeId, Sender, Subscriber, SubId) -> -%% {error, Reason} | {result, []} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Sender = mod_pubsub:jid() -%% Subscriber = mod_pubsub:jid() -%% SubId = mod_pubsub:subid() -%% Reason = mod_pubsub:stanzaError() %% @doc

    Unsubscribe the Subscriber from the Node.

    --spec(unsubscribe_node/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: jid(), - SubId :: subId()) - -> {result, default} - % - | {error, _} - | {error, _, binary()} -). -unsubscribe_node(NodeId, Sender, Subscriber, SubId) -> +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> SubKey = jlib:jid_tolower(Subscriber), GenKey = jlib:jid_remove_resource(SubKey), - Authorized = - jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == - GenKey, - {Affiliation, Subscriptions} = - select_affiliation_subscriptions(NodeId, SubKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, SubKey), SubIdExists = case SubId of - <<>> -> false; - List when is_binary(List) -> true; - _ -> false - end, + <<>> -> false; + Binary when is_binary(Binary) -> true; + _ -> false + end, if - %% Requesting entity is prohibited from unsubscribing entity - not Authorized -> {error, ?ERR_FORBIDDEN}; - %% Entity did not specify SubId - %%SubId == "", ?? -> - %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %% Invalid subscription identifier - %%InvalidSubId -> - %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - %% Requesting entity is not a subscriber - Subscriptions == [] -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), - <<"not-subscribed">>)}; - %% Subid supplied, so use that. - SubIdExists -> - Sub = first_in_list(fun (S) -> - case S of - {_Sub, SubId} -> true; - _ -> false - end - end, - Subscriptions), - case Sub of - {value, S} -> - delete_subscription(SubKey, NodeId, S, Affiliation, - Subscriptions), - {result, default}; - false -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), - <<"not-subscribed">>)} - end; - %% Asking to remove all subscriptions to the given node - SubId == all -> - [delete_subscription(SubKey, NodeId, S, Affiliation, - Subscriptions) - || S <- Subscriptions], - {result, default}; - %% No subid supplied, but there's only one matching - %% subscription, so use that. - length(Subscriptions) == 1 -> - delete_subscription(SubKey, NodeId, hd(Subscriptions), - Affiliation, Subscriptions), - {result, default}; - %% No subid and more than one possible subscription match. - true -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} + %% Requesting entity is prohibited from unsubscribing entity + not Authorized -> + {error, ?ERR_FORBIDDEN}; + %% Entity did not specify SubId + %%SubId == "", ?? -> + %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %% Invalid subscription identifier + %%InvalidSubId -> + %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + %% Requesting entity is not a subscriber + Subscriptions == [] -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; + %% Subid supplied, so use that. + SubIdExists -> + Sub = first_in_list(fun + ({_, S}) when S == SubId -> true; + (_) -> false + end, + Subscriptions), + case Sub of + {value, S} -> + delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions), + {result, default}; + false -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} + end; + %% Asking to remove all subscriptions to the given node + SubId == all -> + [delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions) + || S <- Subscriptions], + {result, default}; + %% No subid supplied, but there's only one matching subscription + length(Subscriptions) == 1 -> + delete_subscription(SubKey, Nidx, hd(Subscriptions), Affiliation, Subscriptions), + {result, default}; + %% No subid and more than one possible subscription match. + true -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} end. -%-spec(delete_subscriptions/5 :: -%( -% SubKey :: ljid(), -% NodeIdx :: mod_pubsub:nodeIdx(), -% _ :: {mod_pubsub:subscription(), mod_pubsub:subId()}, -% SubState :: mod_pubsub:pubsubState(), -% Subscriptions :: [{mod_pubsub:subscription(), mod_pubsub:subId()}]) -% -> ok -%). -delete_subscription(SubKey, NodeIdx, - {Subscription, SubId}, Affiliation, Subscriptions) -> +delete_subscription(SubKey, Nidx, {Subscription, SubId}, Affiliation, Subscriptions) -> NewSubs = Subscriptions -- [{Subscription, SubId}], - pubsub_subscription_odbc:unsubscribe_node(SubKey, NodeIdx, SubId), + pubsub_subscription_odbc:unsubscribe_node(SubKey, Nidx, SubId), case {Affiliation, NewSubs} of - {none, []} -> del_state(NodeIdx, SubKey); - _ -> update_subscription(NodeIdx, SubKey, NewSubs) + {none, []} -> del_state(Nidx, SubKey); + _ -> update_subscription(Nidx, SubKey, NewSubs) end. -%% @spec (NodeId, Publisher, PublishModel, MaxItems, ItemId, Payload) -> -%% {true, PubsubItem} | {result, Reply} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Publisher = mod_pubsub:jid() -%% PublishModel = atom() -%% MaxItems = integer() -%% ItemId = string() -%% Payload = term() %% @doc

    Publishes the item passed as parameter.

    %%

    The mechanism works as follow: %%

      @@ -494,53 +288,34 @@ delete_subscription(SubKey, NodeIdx, %% to completly disable persistance.
    %%

    %%

    In the default plugin module, the record is unchanged.

    - --spec(publish_item/6 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - Max_Items :: non_neg_integer(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) - -> {result, {default, broadcast, [mod_pubsub:itemId()]}} - %%% - | {error, _} -). -publish_item(NodeIdx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> +publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> SubKey = jlib:jid_tolower(Publisher), GenKey = jlib:jid_remove_resource(SubKey), - {Affiliation, Subscriptions} = - select_affiliation_subscriptions(NodeIdx, GenKey, SubKey), + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), Subscribed = case PublishModel of - subscribers -> is_subscribed(Subscriptions); - _ -> undefined - end, - if not - ((PublishModel == open) or - (PublishModel == publishers) and - ((Affiliation == owner) or (Affiliation == publisher)) - or (Subscribed == true)) -> - {error, ?ERR_FORBIDDEN}; - true -> - if MaxItems > 0 -> - PubId = {now(), SubKey}, - set_item(#pubsub_item{itemid = {ItemId, NodeIdx}, - creation = {now(), GenKey}, - modification = PubId, - payload = Payload}), - Items = [ItemId | itemids(NodeIdx, GenKey) -- [ItemId]], - {result, {_, OI}} = remove_extra_items(NodeIdx, MaxItems, Items), - {result, {default, broadcast, OI}}; - true -> {result, {default, broadcast, []}} - end + subscribers -> is_subscribed(Subscriptions); + _ -> undefined + end, + if not ((PublishModel == open) or + (PublishModel == publishers) and + ((Affiliation == owner) or (Affiliation == publisher)) + or (Subscribed == true)) -> + {error, ?ERR_FORBIDDEN}; + true -> + if MaxItems > 0 -> + PubId = {now(), SubKey}, + set_item(#pubsub_item{itemid = {ItemId, Nidx}, + creation = {now(), GenKey}, + modification = PubId, + payload = Payload}), + Items = [ItemId | itemids(Nidx, GenKey) -- [ItemId]], + {result, {_, OI}} = remove_extra_items(Nidx, MaxItems, Items), + {result, {default, broadcast, OI}}; + true -> + {result, {default, broadcast, []}} + end end. -%% @spec (NodeId, MaxItems, ItemIds) -> {NewItemIds,OldItemIds} -%% NodeId = mod_pubsub:pubsubNodeId() -%% MaxItems = integer() | unlimited -%% ItemIds = [ItemId::string()] -%% NewItemIds = [ItemId::string()] %% @doc

    This function is used to remove extra items, most notably when the %% maximum number of items has been reached.

    %%

    This function is used internally by the core PubSub module, as no @@ -549,86 +324,56 @@ publish_item(NodeIdx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> %% rules can be used.

    %%

    If another PubSub plugin wants to delegate the item removal (and if the %% plugin is using the default pubsub storage), it can implements this function like this: -%% ```remove_extra_items(NodeId, MaxItems, ItemIds) -> -%% node_default:remove_extra_items(NodeId, MaxItems, ItemIds).'''

    -remove_extra_items(_NodeId, unlimited, ItemIds) -> +%% ```remove_extra_items(Nidx, MaxItems, ItemIds) -> +%% node_default:remove_extra_items(Nidx, MaxItems, ItemIds).'''

    +remove_extra_items(_Nidx, unlimited, ItemIds) -> {result, {ItemIds, []}}; -remove_extra_items(NodeId, MaxItems, ItemIds) -> +remove_extra_items(Nidx, MaxItems, ItemIds) -> NewItems = lists:sublist(ItemIds, MaxItems), OldItems = lists:nthtail(length(NewItems), ItemIds), - del_items(NodeId, OldItems), + del_items(Nidx, OldItems), {result, {NewItems, OldItems}}. -%% @spec (NodeId, Publisher, PublishModel, ItemId) -> -%% {error, Reason::stanzaError()} | -%% {result, []} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Publisher = mod_pubsub:jid() -%% PublishModel = atom() -%% ItemId = string() %% @doc

    Triggers item deletion.

    %%

    Default plugin: The user performing the deletion must be the node owner -%% or a publisher.

    --spec(delete_item/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - ItemId :: <<>> | mod_pubsub:itemId()) - -> {result, {default, broadcast}} - %%% - | {error, _} -). -delete_item(NodeIdx, Publisher, PublishModel, ItemId) -> +%% or a publisher, or PublishModel being open.

    +delete_item(Nidx, Publisher, PublishModel, ItemId) -> SubKey = jlib:jid_tolower(Publisher), GenKey = jlib:jid_remove_resource(SubKey), - {result, Affiliation} = get_affiliation(NodeIdx, GenKey), + {result, Affiliation} = get_affiliation(Nidx, GenKey), Allowed = Affiliation == publisher orelse - Affiliation == owner orelse - PublishModel == open orelse - case get_item(NodeIdx, ItemId) of - {result, #pubsub_item{creation = {_, GenKey}}} -> true; - _ -> false - end, - if not Allowed -> {error, ?ERR_FORBIDDEN}; - true -> - case del_item(NodeIdx, ItemId) of - {updated, 1} -> {result, {default, broadcast}}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} - end + Affiliation == owner orelse + PublishModel == open orelse + case get_item(Nidx, ItemId) of + {result, #pubsub_item{creation = {_, GenKey}}} -> true; + _ -> false + end, + if not Allowed -> + {error, ?ERR_FORBIDDEN}; + true -> + case del_item(Nidx, ItemId) of + {updated, 1} -> {result, {default, broadcast}}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} + end end. -%% @spec (NodeId, Owner) -> -%% {error, Reason::stanzaError()} | -%% {result, {default, broadcast}} -%% NodeId = mod_pubsub:pubsubNodeId() -%% Owner = mod_pubsub:jid() --spec(purge_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} - | {error, _} -). -purge_node(NodeIdx, Owner) -> +purge_node(Nidx, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(NodeIdx, GenKey), + GenState = get_state(Nidx, GenKey), case GenState of - #pubsub_state{affiliation = owner} -> - {result, States} = get_states(NodeIdx), - lists:foreach(fun (#pubsub_state{items = []}) -> ok; - (#pubsub_state{items = Items}) -> - del_items(NodeIdx, Items) - end, - States), - {result, {default, broadcast}}; - _ -> {error, ?ERR_FORBIDDEN} + #pubsub_state{affiliation = owner} -> + {result, States} = get_states(Nidx), + lists:foreach(fun + (#pubsub_state{items = []}) -> ok; + (#pubsub_state{items = Items}) -> del_items(Nidx, Items) + end, + States), + {result, {default, broadcast}}; + _ -> + {error, ?ERR_FORBIDDEN} end. -%% @spec (Host, JID) -> [{Node,Affiliation}] -%% Host = host() -%% JID = mod_pubsub:jid() %% @doc

    Return the current affiliations for the given user

    %%

    The default module reads affiliations in the main Mnesia %% pubsub_state table. If a plugin stores its data in the same @@ -636,103 +381,60 @@ purge_node(NodeIdx, Owner) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% pubsub_state table.

    --spec(get_entity_affiliations/2 :: -( - Host :: mod_pubsub:hostPubsub(), - Owner :: jid()) - -> {result, [{mod_pubsub:pubsubNode(), mod_pubsub:affiliation()}]} -). get_entity_affiliations(Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - H = (?PUBSUB):escape(Host), + H = encode_host(Host), J = encode_jid(GenKey), Reply = case catch - ejabberd_odbc:sql_query_t([<<"select node, type, i.nodeid, affiliation " - "from pubsub_state i, pubsub_node n where " - "i.nodeid = n.nodeid and jid='">>, - J, <<"' and host='">>, H, - <<"';">>]) - of - {selected, - [<<"node">>, <<"type">>, <<"nodeid">>, - <<"affiliation">>], - RItems} -> - lists:map(fun ([N, T, I, A]) -> - Node = nodetree_tree_odbc:raw_to_node(Host, - [N, - <<"">>, - T, - I]), - {Node, decode_affiliation(A)} - end, - RItems); - _ -> [] - end, + ejabberd_odbc:sql_query_t([<<"select node, type, i.nodeid, affiliation " + "from pubsub_state i, pubsub_node n where " + "i.nodeid = n.nodeid and jid='">>, J, <<"' and host='">>, H, <<"';">>]) + of + {selected, [<<"node">>, <<"type">>, <<"nodeid">>, <<"affiliation">>], RItems} -> + [{nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), decode_affiliation(A)} + || [N, T, I, A] <- RItems]; + _ -> + [] + end, {result, Reply}. --spec(get_node_affiliations/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [{ljid(), mod_pubsub:affiliation()}]} -). -get_node_affiliations(NodeIdx) -> +get_node_affiliations(Nidx) -> Reply = case catch - ejabberd_odbc:sql_query_t([<<"select jid, affiliation from pubsub_state " - "where nodeid='">>, - NodeIdx, <<"';">>]) - of - {selected, [<<"jid">>, <<"affiliation">>], RItems} -> - lists:map(fun ([J, A]) -> - {decode_jid(J), decode_affiliation(A)} - end, - RItems); - _ -> [] - end, + ejabberd_odbc:sql_query_t([<<"select jid, affiliation from pubsub_state " + "where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"jid">>, <<"affiliation">>], RItems} -> + [{decode_jid(J), decode_affiliation(A)} || [J, A] <- RItems]; + _ -> + [] + end, {result, Reply}. --spec(get_affiliation/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid()) - -> {result, mod_pubsub:affiliation()} -). - -get_affiliation(NodeIdx, Owner) -> +get_affiliation(Nidx, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), J = encode_jid(GenKey), Reply = case catch - ejabberd_odbc:sql_query_t([<<"select affiliation from pubsub_state " - "where nodeid='">>, - NodeIdx, <<"' and jid='">>, J, - <<"';">>]) - of - {selected, [<<"affiliation">>], [[A]]} -> - decode_affiliation(A); - _ -> none - end, + ejabberd_odbc:sql_query_t([<<"select affiliation from pubsub_state " + "where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {selected, [<<"affiliation">>], [[A]]} -> + decode_affiliation(A); + _ -> + none + end, {result, Reply}. --spec(set_affiliation/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid(), - Affiliation :: mod_pubsub:affiliation()) - -> ok -). -set_affiliation(NodeIdx, Owner, Affiliation) -> +set_affiliation(Nidx, Owner, Affiliation) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - {_, Subscriptions} = select_affiliation_subscriptions(NodeIdx, GenKey), + {_, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey), case {Affiliation, Subscriptions} of - {none, none} -> del_state(NodeIdx, GenKey); - _ -> update_affiliation(NodeIdx, GenKey, Affiliation) + {none, []} -> del_state(Nidx, GenKey); + _ -> update_affiliation(Nidx, GenKey, Affiliation) end. -%% @spec (Host, Owner) -> [{Node,Subscription}] -%% Host = host() -%% Owner = mod_pubsub:jid() %% @doc

    Return the current subscriptions for the given user

    %%

    The default module reads subscriptions in the main Mnesia %% pubsub_state table. If a plugin stores its data in the same @@ -740,338 +442,225 @@ set_affiliation(NodeIdx, Owner, Affiliation) -> %% the default PubSub module. Otherwise, it should return its own affiliation, %% that will be added to the affiliation stored in the main %% pubsub_state table.

    - --spec(get_entity_subscriptions/2 :: -( - Host :: mod_pubsub:host(), - Owner :: jid()) - -> {result, - [{mod_pubsub:pubsubNode(), - mod_pubsub:subscription(), - mod_pubsub:subId(), - ljid()}] - } -). get_entity_subscriptions(Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - H = (?PUBSUB):escape(Host), + H = encode_host(Host), SJ = encode_jid(SubKey), GJ = encode_jid(GenKey), Query = case SubKey of - GenKey -> - [<<"select node, type, i.nodeid, jid, subscriptio" - "ns from pubsub_state i, pubsub_node " - "n where i.nodeid = n.nodeid and jid " - "like '">>, - GJ, <<"%' and host='">>, H, <<"';">>]; - _ -> - [<<"select node, type, i.nodeid, jid, subscriptio" - "ns from pubsub_state i, pubsub_node " - "n where i.nodeid = n.nodeid and jid " - "in ('">>, - SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] - end, + GenKey -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n " + "where i.nodeid = n.nodeid and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>]; + _ -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n " + "where i.nodeid = n.nodeid and jid in ('">>, SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] + end, Reply = case catch ejabberd_odbc:sql_query_t(Query) of - {selected, - [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, - <<"subscriptions">>], - RItems} -> - lists:foldl(fun ([N, T, I, J, S], Acc) -> - Node = - nodetree_tree_odbc:raw_to_node(Host, - [N, - <<"">>, - T, - I]), - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> [{Node, none, Jid} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, Jid} | Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> [] - end, + {selected, + [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> + lists:foldl(fun ([N, T, I, J, S], Acc) -> + Node = nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Node, none, Jid} | Acc]; + Subs -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, Jid} | Acc2] + end, + Acc, Subs) + end + end, + [], RItems); + _ -> + [] + end, {result, Reply}. %% do the same as get_entity_subscriptions but filter result only to %% nodes having send_last_published_item=on_sub_and_presence %% as this call avoid seeking node, it must return node and type as well -spec(get_entity_subscriptions_for_send_last/2 :: -( - Host :: mod_pubsub:hostPubsub(), - Owner :: jid()) + ( + Host :: mod_pubsub:hostPubsub(), + Owner :: jid()) -> {result, - [{mod_pubsub:pubsubNode(), - mod_pubsub:subscription(), - mod_pubsub:subId(), - ljid()}] - } -). - + [{mod_pubsub:pubsubNode(), + mod_pubsub:subscription(), + mod_pubsub:subId(), + ljid()}] + } + ). get_entity_subscriptions_for_send_last(Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - H = (?PUBSUB):escape(Host), + H = encode_host(Host), SJ = encode_jid(SubKey), GJ = encode_jid(GenKey), Query = case SubKey of - GenKey -> - [<<"select node, type, i.nodeid, jid, subscriptio" - "ns from pubsub_state i, pubsub_node " - "n, pubsub_node_option o where i.nodeid " - "= n.nodeid and n.nodeid = o.nodeid and " - "name='send_last_published_item' and " - "val='on_sub_and_presence' and jid like " - "'">>, - GJ, <<"%' and host='">>, H, <<"';">>]; - _ -> - [<<"select node, type, i.nodeid, jid, subscriptio" - "ns from pubsub_state i, pubsub_node " - "n, pubsub_node_option o where i.nodeid " - "= n.nodeid and n.nodeid = o.nodeid and " - "name='send_last_published_item' and " - "val='on_sub_and_presence' and jid in " - "('">>, - SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] - end, + GenKey -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n, pubsub_node_option o " + "where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' " + "and val='on_sub_and_presence' and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>]; + _ -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n, pubsub_node_option o " + "where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' " + "and val='on_sub_and_presence' and jid in ('">>, SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] + end, Reply = case catch ejabberd_odbc:sql_query_t(Query) of - {selected, - [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, - <<"subscriptions">>], - RItems} -> - lists:foldl(fun ([N, T, I, J, S], Acc) -> - Node = - nodetree_tree_odbc:raw_to_node(Host, - [N, - <<"">>, - T, - I]), - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> [{Node, none, Jid} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, Jid}| Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> [] - end, + {selected, + [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> + lists:foldl(fun ([N, T, I, J, S], Acc) -> + Node = nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Node, none, Jid} | Acc]; + Subs -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, Jid}| Acc2] + end, + Acc, Subs) + end + end, + [], RItems); + _ -> + [] + end, {result, Reply}. --spec(get_node_subscriptions/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [{ljid(), mod_pubsub:subscription(), mod_pubsub:subId()}]} -). -get_node_subscriptions(NodeIdx) -> +get_node_subscriptions(Nidx) -> Reply = case catch - ejabberd_odbc:sql_query_t([<<"select jid, subscriptions from pubsub_state " - "where nodeid='">>, - NodeIdx, <<"';">>]) - of - {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> - lists:foldl(fun ([J, S], Acc) -> - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> [{Jid, none} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Jid, Sub, SubId} | Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> [] - end, + ejabberd_odbc:sql_query_t([<<"select jid, subscriptions from pubsub_state " + "where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> + lists:foldl(fun ([J, S], Acc) -> + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Jid, none} | Acc]; + Subs -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Jid, Sub, SubId} | Acc2] + end, + Acc, Subs) + end + end, + [], RItems); + _ -> + [] + end, {result, Reply}. --spec(get_subscriptions/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid()) - -> {result, [{mod_pubsub:subscription(), mod_pubsub:subId()}]} -). -get_subscriptions(NodeIdx, Owner) -> +get_subscriptions(Nidx, Owner) -> SubKey = jlib:jid_tolower(Owner), J = encode_jid(SubKey), Reply = case catch - ejabberd_odbc:sql_query_t([<<"select subscriptions from pubsub_state " - "where nodeid='">>, - NodeIdx, <<"' and jid='">>, J, - <<"';">>]) - of - {selected, [<<"subscriptions">>], [[S]]} -> - decode_subscriptions(S); - _ -> [] - end, + ejabberd_odbc:sql_query_t([<<"select subscriptions from pubsub_state where " + "nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {selected, [<<"subscriptions">>], [[S]]} -> + decode_subscriptions(S); + _ -> + [] + end, {result, Reply}. --spec(set_subscriptions/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid(), - Subscription :: mod_pubsub:subscription(), - SubId :: mod_pubsub:subId()) - -> _ - %%% - | {error, xmlel()} -). -set_subscriptions(NodeIdx, Owner, Subscription, SubId) -> +set_subscriptions(Nidx, Owner, Subscription, SubId) -> SubKey = jlib:jid_tolower(Owner), - SubState = get_state_without_itemids(NodeIdx, SubKey), + SubState = get_state_without_itemids(Nidx, SubKey), case {SubId, SubState#pubsub_state.subscriptions} of - {_, []} -> - case Subscription of - none -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), - <<"not-subscribed">>)}; - _ -> - new_subscription(NodeIdx, Owner, Subscription, SubState) - end; - {<<"">>, [{_, SID}]} -> - case Subscription of - none -> unsub_with_subid(NodeIdx, SID, SubState); - _ -> replace_subscription({Subscription, SID}, SubState) - end; - {<<"">>, [_ | _]} -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), - <<"subid-required">>)}; - _ -> - case Subscription of - none -> unsub_with_subid(NodeIdx, SubId, SubState); - _ -> - replace_subscription({Subscription, SubId}, SubState) - end + {_, []} -> + case Subscription of + none -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; + _ -> + new_subscription(Nidx, Owner, Subscription, SubState) + end; + {<<>>, [{_, SID}]} -> + case Subscription of + none -> unsub_with_subid(Nidx, SID, SubState); + _ -> replace_subscription({Subscription, SID}, SubState) + end; + {<<>>, [_ | _]} -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; + _ -> + case Subscription of + none -> unsub_with_subid(Nidx, SubId, SubState); + _ -> replace_subscription({Subscription, SubId}, SubState) + end end. --spec(replace_subscription/2 :: -( - NewSub :: {mod_pubsub:subscription(), mod_pubsub:subId()}, - SubState :: mod_pubsub:pubsubState()) - -> {result, []} -). replace_subscription(NewSub, SubState) -> NewSubs = replace_subscription(NewSub, SubState#pubsub_state.subscriptions, []), set_state(SubState#pubsub_state{subscriptions = NewSubs}). replace_subscription(_, [], Acc) -> Acc; -replace_subscription({Sub, SubId}, [{_, SubID} | T], Acc) -> - replace_subscription({Sub, SubId}, T, [{Sub, SubID} | Acc]). - --spec(new_subscription/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid(), - Subscription :: mod_pubsub:subscription(), - SubState :: mod_pubsub:pubsubState()) - -> {mod_pubsub:subscription(), mod_pubsub:subId()} - %%% - | {error, xmlel()} -). - -new_subscription(NodeIdx, Owner, Subscription, SubState) -> - case pubsub_subscription_odbc:subscribe_node(Owner, NodeIdx, []) of - {result, SubId} -> - Subscriptions = SubState#pubsub_state.subscriptions, - set_state(SubState#pubsub_state{subscriptions = - [{Subscription, SubId} | Subscriptions]}), - {Subscription, SubId}; - _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} - end. - --spec(unsub_with_subid/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - SubId :: mod_pubsub:subId(), - SubState :: mod_pubsub:pubsubState()) - -> ok -). -unsub_with_subid(NodeIdx, SubId, SubState) -> - pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, - NodeIdx, SubId), - NewSubs = lists:filter(fun ({_, SID}) -> SubId =/= SID - end, - SubState#pubsub_state.subscriptions), +replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> + replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). + +new_subscription(Nidx, Owner, Subscription, SubState) -> + {result, SubId} = pubsub_subscription_odbc:subscribe_node(Owner, Nidx, []), + Subscriptions = [{Subscription, SubId} | SubState#pubsub_state.subscriptions], + set_state(SubState#pubsub_state{subscriptions = Subscriptions}), + {Subscription, SubId}. + +unsub_with_subid(Nidx, SubId, SubState) -> + pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, Nidx, SubId), + NewSubs = [{S, Sid} + || {S, Sid} <- SubState#pubsub_state.subscriptions, + SubId =/= Sid], case {NewSubs, SubState#pubsub_state.affiliation} of - {[], none} -> - del_state(NodeIdx, - element(1, SubState#pubsub_state.stateid)); - _ -> - set_state(SubState#pubsub_state{subscriptions = NewSubs}) + {[], none} -> del_state(Nidx, element(1, SubState#pubsub_state.stateid)); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) end. -%% @spec (Host, Owner) -> {result, [Node]} | {error, Reason} -%% Host = host() -%% Owner = jid() -%% Node = pubsubNode() %% @doc

    Returns a list of Owner's nodes on Host with pending %% subscriptions.

    --spec(get_pending_nodes/2 :: -( - Host :: mod_pubsub:hostPubsub(), - Owner :: jid()) - -> {result, [mod_pubsub:nodeId()]} -). get_pending_nodes(Host, Owner) -> GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), - States = mnesia:match_object(#pubsub_state{stateid = - {GenKey, '_'}, - affiliation = owner, _ = '_'}), - NodeIDs = [ID - || #pubsub_state{stateid = {_, ID}} <- States], - NodeTree = case catch - ets:lookup(gen_mod:get_module_proc(Host, config), - nodetree) - of - [{nodetree, N}] -> N; - _ -> nodetree_tree_odbc - end, - Reply = mnesia:foldl(fun (#pubsub_state{stateid = - {_, NID}} = - S, - Acc) -> - case lists:member(NID, NodeIDs) of - true -> - case get_nodes_helper(NodeTree, S) of - {value, Node} -> [Node | Acc]; - false -> Acc - end; - false -> Acc - end - end, - [], pubsub_state), + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, + affiliation = owner, _ = '_'}), + Nidxxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], + NodeTree = mod_pubsub:tree(Host), + Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, Nidx}} = S, Acc) -> + case lists:member(Nidx, Nidxxs) of + true -> + case get_nodes_helper(NodeTree, S) of + {value, Node} -> [Node | Acc]; + false -> Acc + end; + false -> + Acc + end + end, + [], pubsub_state), {result, Reply}. -get_nodes_helper(NodeTree, - #pubsub_state{stateid = {_, N}, - subscriptions = Subs}) -> - HasPending = fun ({pending, _}) -> true; - (pending) -> true; - (_) -> false - end, +get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> + HasPending = fun + ({pending, _}) -> true; + (pending) -> true; + (_) -> false + end, case lists:any(HasPending, Subs) of - true -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {_, Node}} -> {value, Node}; - _ -> false - end; - false -> false + true -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {_, Node}} -> {value, Node}; + _ -> false + end; + false -> + false end. -%% @spec (NodeId) -> [States] | [] -%% NodeId = mod_pubsub:pubsubNodeId() %% @doc Returns the list of stored states for a given node. %%

    For the default PubSub module, states are stored in Mnesia database.

    %%

    We can consider that the pubsub_state table have been created by the main @@ -1080,127 +669,84 @@ get_nodes_helper(NodeTree, %% relational database).

    %%

    If a PubSub plugin wants to delegate the states storage to the default node, %% they can implement this function like this: -%% ```get_states(NodeId) -> -%% node_default:get_states(NodeId).'''

    --spec(get_states/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [mod_pubsub:pubsubState()]} -). -get_states(NodeIdx) -> +%% ```get_states(Nidx) -> +%% node_default:get_states(Nidx).'''

    +get_states(Nidx) -> case catch - ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " - "from pubsub_state where nodeid='">>, - NodeIdx, <<"';">>]) - of - {selected, - [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], - RItems} -> - {result, - lists:map(fun ([SJID, Affiliation, Subscriptions]) -> - #pubsub_state{stateid = {decode_jid(SJID), NodeIdx}, - items = itemids(NodeIdx, SJID), - affiliation = decode_affiliation(Affiliation), - subscriptions = decode_subscriptions(Subscriptions)} - end, - RItems)}; - _ -> {result, []} + ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " + "from pubsub_state where nodeid='">>, Nidx, <<"';">>]) + of + {selected, + [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], RItems} -> + {result, + lists:map(fun ([SJID, Aff, Subs]) -> + #pubsub_state{stateid = {decode_jid(SJID), Nidx}, + items = itemids(Nidx, SJID), + affiliation = decode_affiliation(Aff), + subscriptions = decode_subscriptions(Subs)} + end, + RItems)}; + _ -> + {result, []} end. -%% @spec (NodeId, JID) -> [State] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% JID = mod_pubsub:jid() -%% State = mod_pubsub:pubsubItems() %% @doc

    Returns a state (one state list), given its reference.

    - --spec(get_state/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: ljid()) - -> mod_pubsub:pubsubState() -). -get_state(NodeIdx, JID) -> - State = get_state_without_itemids(NodeIdx, JID), +get_state(Nidx, JID) -> + State = get_state_without_itemids(Nidx, JID), {SJID, _} = State#pubsub_state.stateid, - State#pubsub_state{items = itemids(NodeIdx, SJID)}. + State#pubsub_state{items = itemids(Nidx, SJID)}. -spec(get_state_without_itemids/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: jid()) - -> mod_pubsub:pubsubState() -). -get_state_without_itemids(NodeIdx, JID) -> + (Nidx :: mod_pubsub:nodeIdx(), + Key :: ljid()) -> + mod_pubsub:pubsubState() + ). +get_state_without_itemids(Nidx, JID) -> J = encode_jid(JID), case catch - ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " - "from pubsub_state where jid='">>, - J, <<"' and nodeid='">>, NodeIdx, - <<"';">>]) - of - {selected, - [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], - [[SJID, Affiliation, Subscriptions]]} -> - #pubsub_state{stateid = {decode_jid(SJID), NodeIdx}, - affiliation = decode_affiliation(Affiliation), - subscriptions = decode_subscriptions(Subscriptions)}; - _ -> #pubsub_state{stateid = {JID, NodeIdx}} + ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " + "from pubsub_state where jid='">>, J, <<"' and nodeid='">>, Nidx, <<"';">>]) + of + {selected, + [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], [[SJID, Aff, Subs]]} -> + #pubsub_state{stateid = {decode_jid(SJID), Nidx}, + affiliation = decode_affiliation(Aff), + subscriptions = decode_subscriptions(Subs)}; + _ -> + #pubsub_state{stateid = {JID, Nidx}} end. -%% @spec (State) -> ok | {error, Reason::stanzaError()} -%% State = mod_pubsub:pubsubStates() %% @doc

    Write a state into database.

    - --spec(set_state/1 :: -( - State :: mod_pubsub:pubsubState()) - -> {result, []} -). set_state(State) -> - {_, NodeIdx} = State#pubsub_state.stateid, - set_state(NodeIdx, State). - --spec(set_state/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - State :: mod_pubsub:pubsubState()) - -> {result, []} -). -set_state(NodeIdx, State) -> + {_, Nidx} = State#pubsub_state.stateid, + set_state(Nidx, State). + +set_state(Nidx, State) -> {JID, _} = State#pubsub_state.stateid, J = encode_jid(JID), S = encode_subscriptions(State#pubsub_state.subscriptions), A = encode_affiliation(State#pubsub_state.affiliation), case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, - S, <<"', affiliation='">>, A, - <<"' where nodeid='">>, NodeIdx, - <<"' and jid='">>, J, <<"';">>]) - of - {updated, 1} -> ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, " - "affiliation, subscriptions) values('">>, - NodeIdx, <<"', '">>, J, <<"', '">>, A, - <<"', '">>, S, <<"');">>]) + ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, S, <<"', affiliation='">>, A, + <<"' where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values('">>, + Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '">>, S, <<"');">>]) end, - {result, []}. + ok. -%% @spec (NodeId, JID) -> ok | {error, Reason::stanzaError()} -%% NodeId = mod_pubsub:pubsubNodeId() -%% JID = mod_pubsub:jid() %% @doc

    Delete a state from database.

    -del_state(NodeId, JID) -> +del_state(Nidx, JID) -> J = encode_jid(JID), - catch - ejabberd_odbc:sql_query_t([<<"delete from pubsub_state where jid='">>, - J, <<"' and nodeid='">>, NodeId, <<"';">>]), + catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_state where jid='">>, + J, <<"' and nodeid='">>, Nidx, <<"';">>]), ok. -%% @spec (NodeId, From) -> {[Items],RsmOut} | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% Items = mod_pubsub:pubsubItems() %% @doc Returns the list of stored items for a given node. %%

    For the default PubSub module, items are stored in Mnesia database.

    %%

    We can consider that the pubsub_item table have been created by the main @@ -1209,464 +755,439 @@ del_state(NodeId, JID) -> %% relational database), or they can even decide not to persist any items.

    %%

    If a PubSub plugin wants to delegate the item storage to the default node, %% they can implement this function like this: -%% ```get_items(NodeId, From) -> -%% node_default:get_items(NodeId, From).'''

    -get_items(NodeId, _From) -> +%% ```get_items(Nidx, From) -> +%% node_default:get_items(Nidx, From).'''

    +get_items(Nidx, _From) -> case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " - "modification, payload from pubsub_item " - "where nodeid='">>, - NodeId, - <<"' order by modification desc;">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, - <<"modification">>, <<"payload">>], - RItems} -> - {result, - lists:map(fun (RItem) -> raw_to_item(NodeId, RItem) end, - RItems)}; - _ -> {result, []} + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' order by modification desc;">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; + _ -> + {result, []} end. -get_items(NodeId, From, none) -> +get_items(Nidx, From, none) -> MaxItems = case catch - ejabberd_odbc:sql_query_t([<<"select val from pubsub_node_option where " - "nodeid='">>, - NodeId, - <<"' and name='max_items';">>]) - of - {selected, [<<"val">>], [[Value]]} -> - Tokens = element(2, - erl_scan:string(binary_to_list(<>))), - element(2, erl_parse:parse_term(Tokens)); - _ -> ?MAXITEMS - end, - get_items(NodeId, From, #rsm_in{max = MaxItems}); -get_items(NodeId, _From, - #rsm_in{max = M, direction = Direction, id = I, - index = IncIndex}) -> - Max = (?PUBSUB):escape(jlib:i2l(M)), + ejabberd_odbc:sql_query_t([<<"select val from pubsub_node_option " + "where nodeid='">>, Nidx, <<"' and name='max_items';">>]) + of + {selected, [<<"val">>], [[Value]]} -> + Tokens = element(2, erl_scan:string(binary_to_list(<>))), + element(2, erl_parse:parse_term(Tokens)); + _ -> + ?MAXITEMS + end, + get_items(Nidx, From, #rsm_in{max = MaxItems}); +get_items(Nidx, _From, + #rsm_in{max = M, direction = Direction, id = I, index = IncIndex}) -> + Max = ejabberd_odbc:escape(jlib:i2l(M)), {Way, Order} = case Direction of - aft -> {<<"<">>, <<"desc">>}; - before when I == <<>> -> {<<"is not">>, <<"asc">>}; - before -> {<<">">>, <<"asc">>}; - _ when IncIndex =/= undefined -> - {<<"<">>, <<"desc">>}; % using index - _ -> {<<"is not">>, <<"desc">>}% Can be better - end, + % aft -> {<<"<">>, <<"desc">>}; + % before when I == <<>> -> {<<"is not">>, <<"asc">>}; + % before -> {<<">">>, <<"asc">>}; + % _ when IncIndex =/= undefined -> + % {<<"<">>, <<"desc">>}; % using index + _ -> + {<<"is not">>, <<"desc">>}% Can be better + end, [AttrName, Id] = case I of - undefined when IncIndex =/= undefined -> - case catch - ejabberd_odbc:sql_query_t([<<"select modification from pubsub_item " - "pi where exists ( select count(*) as " - "count1 from pubsub_item where nodeid='">>, - NodeId, - <<"' and modification > pi.modification " - "having count1 = ">>, - (?PUBSUB):escape(jlib:i2l(IncIndex)), - <<" );">>]) - of - {selected, [_], [[O]]} -> - [<<"modification">>, <<"'", O/binary, "'">>]; - _ -> [<<"modification">>, <<"null">>] - end; - undefined -> [<<"modification">>, <<"null">>]; - <<>> -> [<<"modification">>, <<"null">>]; - I -> - [A, B] = str:tokens((?PUBSUB):escape(jlib:i2l(I)), - <<"@">>), - [A, <<"'", B/binary, "'">>] - end, + undefined when IncIndex =/= undefined -> + case catch + ejabberd_odbc:sql_query_t([<<"select modification from pubsub_item pi " + "where exists ( select count(*) as count1 " + "from pubsub_item where nodeid='">>, Nidx, + <<"' and modification > pi.modification having count1 = ">>, + ejabberd_odbc:escape(jlib:i2l(IncIndex)), <<" );">>]) + of + {selected, [_], [[O]]} -> + [<<"modification">>, <<"'", O/binary, "'">>]; + _ -> + [<<"modification">>, <<"null">>] + end; + undefined -> + [<<"modification">>, <<"null">>]; + <<>> -> + [<<"modification">>, <<"null">>]; + I -> + [A, B] = str:tokens(ejabberd_odbc:escape(jlib:i2l(I)), <<"@">>), + [A, <<"'", B/binary, "'">>] + end, Count = case catch - ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item where " - "nodeid='">>, - NodeId, <<"';">>]) - of - {selected, [_], [[C]]} -> C; - _ -> <<"0">> - end, + ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [_], [[C]]} -> C; + _ -> <<"0">> + end, case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " - "modification, payload from pubsub_item " - "where nodeid='">>, - NodeId, <<"' and ">>, AttrName, <<" ">>, - Way, <<" ">>, Id, <<" order by ">>, - AttrName, <<" ">>, Order, <<" limit ">>, - jlib:i2l(Max), <<" ;">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, - <<"modification">>, <<"payload">>], - RItems} -> - case RItems of - [[_, _, _, F, _]|_] -> - Index = case catch - ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item where " - "nodeid='">>, - NodeId, <<"' and ">>, - AttrName, <<" > '">>, - F, <<"';">>]) - of - %{selected, [_], [{C}, {In}]} -> [string:strip(C, both, $"), string:strip(In, both, $")]; - {selected, [_], [[In]]} -> In; - _ -> <<"0">> - end, - [_, _, _, L, _] = lists:last(RItems), - RsmOut = #rsm_out{count = Count, index = Index, - first = <<"modification@", F/binary>>, - last = <<"modification@", (jlib:i2l(L))/binary>>}, - {result, {[raw_to_item(NodeId, RItem) || RItem <- RItems], RsmOut}}; - [] -> {result, {[], #rsm_out{count = Count}}}; - 0 -> {result, {[], #rsm_out{count = Count}}} - end; - _ -> {result, {[], none}} + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, + AttrName, <<" ">>, Order, <<" limit ">>, jlib:i2l(Max), <<" ;">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + case RItems of + [[_, _, _, F, _]|_] -> + Index = case catch + ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item " + "where nodeid='">>, Nidx, <<"' and ">>, + AttrName, <<" > '">>, F, <<"';">>]) + of + %{selected, [_], [{C}, {In}]} -> [string:strip(C, both, $"), string:strip(In, both, $")]; + {selected, [_], [[In]]} -> In; + _ -> <<"0">> + end, + [_, _, _, L, _] = lists:last(RItems), + RsmOut = #rsm_out{count = Count, index = Index, + first = <<"modification@", F/binary>>, + last = <<"modification@", (jlib:i2l(L))/binary>>}, + {result, {[raw_to_item(Nidx, RItem) || RItem <- RItems], RsmOut}}; + [] -> + {result, {[], #rsm_out{count = Count}}} + end; + _ -> + {result, {[], none}} end. -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, none). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, _SubId, RSM) -> +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), - {Affiliation, Subscriptions} = - select_affiliation_subscriptions(NodeId, GenKey, - SubKey), - Whitelisted = can_fetch_item(Affiliation, - Subscriptions), + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Whitelisted = can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and - not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> get_items(NodeId, JID, RSM) + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + Affiliation == outcast -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_items(Nidx, JID, RSM) end. -get_last_items(NodeId, _From, Count) -> +get_last_items(Nidx, _From, Count) -> case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " - "modification, payload from pubsub_item " - "where nodeid='">>, - NodeId, - <<"' order by modification desc limit ">>, - jlib:i2l(Count), <<";">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, - <<"modification">>, <<"payload">>], - RItems} -> - {result, - lists:map(fun (RItem) -> raw_to_item(NodeId, RItem) end, - RItems)}; - _ -> {result, []} + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' order by modification desc limit ">>, jlib:i2l(Count), <<";">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; + _ -> + {result, []} end. -%% @spec (NodeId, ItemId) -> [Item] | [] -%% NodeId = mod_pubsub:pubsubNodeId() -%% ItemId = string() -%% Item = mod_pubsub:pubsubItems() %% @doc

    Returns an item (one item list), given its reference.

    -get_item(NodeId, ItemId) -> - I = (?PUBSUB):escape(ItemId), +get_item(Nidx, ItemId) -> + I = ejabberd_odbc:escape(ItemId), case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " - "modification, payload from pubsub_item " - "where nodeid='">>, - NodeId, <<"' and itemid='">>, I, - <<"';">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, - <<"modification">>, <<"payload">>], - [RItem]} -> - {result, raw_to_item(NodeId, RItem)}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " + "modification, payload from pubsub_item " + "where nodeid='">>, Nidx, <<"' and itemid='">>, I, <<"';">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], [RItem]} -> + {result, raw_to_item(Nidx, RItem)}; + _ -> + {error, ?ERR_ITEM_NOT_FOUND} end. -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, _SubId) -> +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), - {Affiliation, Subscriptions} = - select_affiliation_subscriptions(NodeId, GenKey, - SubKey), - Whitelisted = can_fetch_item(Affiliation, - Subscriptions), + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Whitelisted = can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and - not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), - <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> get_item(NodeId, ItemId) + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + Affiliation == outcast -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_item(Nidx, ItemId) end. -%% @spec (Item) -> ok | {error, Reason::stanzaError()} -%% Item = mod_pubsub:pubsubItems() %% @doc

    Write an item into database.

    set_item(Item) -> - {ItemId, NodeId} = Item#pubsub_item.itemid, - I = (?PUBSUB):escape(ItemId), + {ItemId, Nidx} = Item#pubsub_item.itemid, + I = ejabberd_odbc:escape(ItemId), {C, _} = Item#pubsub_item.creation, {M, JID} = Item#pubsub_item.modification, P = encode_jid(JID), Payload = Item#pubsub_item.payload, - XML = (?PUBSUB):escape(str:join([xml:element_to_binary(X) || X<-Payload], <<>>)), + XML = ejabberd_odbc:escape(str:join([xml:element_to_binary(X) || X<-Payload], <<>>)), S = fun ({T1, T2, T3}) -> - str:join([jlib:i2l(T1, 6), jlib:i2l(T2, 6), jlib:i2l(T3, 6)], <<":">>) - end, + str:join([jlib:i2l(T1, 6), jlib:i2l(T2, 6), jlib:i2l(T3, 6)], <<":">>) + end, case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_item set publisher='">>, - P, <<"', modification='">>, S(M), - <<"', payload='">>, XML, - <<"' where nodeid='">>, NodeId, - <<"' and itemid='">>, I, <<"';">>]) - of - {updated, 1} -> ok; - _ -> - catch + ejabberd_odbc:sql_query_t([<<"update pubsub_item set publisher='">>, P, + <<"', modification='">>, S(M), + <<"', payload='">>, XML, + <<"' where nodeid='">>, Nidx, <<"' and itemid='">>, I, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch ejabberd_odbc:sql_query_t([<<"insert into pubsub_item (nodeid, itemid, " - "publisher, creation, modification, payload) " - "values('">>, - NodeId, <<"', '">>, I, <<"', '">>, P, - <<"', '">>, S(C), <<"', '">>, S(M), - <<"', '">>, XML, <<"');">>]) + "publisher, creation, modification, payload) " + "values('">>, Nidx, <<"', '">>, I, <<"', '">>, P, + <<"', '">>, S(C), <<"', '">>, S(M), + <<"', '">>, XML, <<"');">>]) end, - {result, []}. + ok. -%% @spec (NodeId, ItemId) -> ok | {error, Reason::stanzaError()} -%% NodeId = mod_pubsub:pubsubNodeId() -%% ItemId = string() %% @doc

    Delete an item from database.

    -del_item(NodeId, ItemId) -> - I = (?PUBSUB):escape(ItemId), - catch - ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid='">>, - I, <<"' and nodeid='">>, NodeId, <<"';">>]). - -del_items(_, []) -> ok; -del_items(NodeId, [ItemId]) -> del_item(NodeId, ItemId); -del_items(NodeId, ItemIds) -> - I = str:join([[<<"'">>, (?PUBSUB):escape(X), <<"'">>] - || X <- ItemIds], - <<",">>), +del_item(Nidx, ItemId) -> + I = ejabberd_odbc:escape(ItemId), + catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid='">>, + I, <<"' and nodeid='">>, Nidx, <<"';">>]). + +del_items(_, []) -> + ok; +del_items(Nidx, [ItemId]) -> + del_item(Nidx, ItemId); +del_items(Nidx, ItemIds) -> + I = str:join([[<<"'">>, ejabberd_odbc:escape(X), <<"'">>] || X <- ItemIds], <<",">>), catch - ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid " - "in (">>, - I, <<") and nodeid='">>, NodeId, <<"';">>]). + ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid in (">>, + I, <<") and nodeid='">>, Nidx, <<"';">>]). -get_item_name(_Host, _Node, Id) -> Id. +get_item_name(_Host, _Node, Id) -> + Id. -node_to_path(Node) -> str:tokens((Node), <<"/">>). +node_to_path(Node) -> + node_hometree:node_to_path(Node). -path_to_node([]) -> <<>>; path_to_node(Path) -> - iolist_to_binary(str:join([<<"">> | Path], <<"/">>)). + node_hometree:path_to_node(Path). -%% @spec (Affiliation, Subscription) -> true | false -%% Affiliation = owner | member | publisher | outcast | none -%% Subscription = subscribed | none -%% @doc Determines if the combination of Affiliation and Subscribed -%% are allowed to get items from a node. can_fetch_item(owner, _) -> true; can_fetch_item(member, _) -> true; can_fetch_item(publisher, _) -> true; can_fetch_item(outcast, _) -> false; can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). +%can_fetch_item(_Affiliation, _Subscription) -> false. is_subscribed(Subscriptions) -> - lists:any(fun ({subscribed, _SubId}) -> true; - (_) -> false - end, - Subscriptions). + lists:any(fun + ({subscribed, _SubId}) -> true; + (_) -> false + end, + Subscriptions). -%% Returns the first item where Pred() is true in List -first_in_list(_Pred, []) -> false; +first_in_list(_Pred, []) -> + false; first_in_list(Pred, [H | T]) -> case Pred(H) of - true -> {value, H}; - _ -> first_in_list(Pred, T) + true -> {value, H}; + _ -> first_in_list(Pred, T) end. -itemids(NodeId, {U, S, R}) -> - itemids(NodeId, encode_jid({U, S, R})); -itemids(NodeId, SJID) -> +itemids(Nidx, {U, S, R}) -> + itemids(Nidx, encode_jid({U, S, R})); +itemids(Nidx, SJID) -> case catch - ejabberd_odbc:sql_query_t([<<"select itemid from pubsub_item where " - "nodeid='">>, - NodeId, <<"' and publisher like '">>, - SJID, - <<"%' order by modification desc;">>]) - of - {selected, [<<"itemid">>], RItems} -> - lists:map(fun ([ItemId]) -> ItemId end, RItems); - _ -> [] + ejabberd_odbc:sql_query_t([<<"select itemid from pubsub_item where " + "nodeid='">>, Nidx, <<"' and publisher like '">>, SJID, + <<"%' order by modification desc;">>]) + of + {selected, [<<"itemid">>], RItems} -> + [ItemId || [ItemId] <- RItems]; + _ -> + [] end. -select_affiliation_subscriptions(NodeId, JID) -> +select_affiliation_subscriptions(Nidx, JID) -> J = encode_jid(JID), case catch - ejabberd_odbc:sql_query_t([<<"select affiliation,subscriptions from " - "pubsub_state where nodeid='">>, - NodeId, <<"' and jid='">>, J, <<"';">>]) - of - {selected, [<<"affiliation">>, <<"subscriptions">>], - [[A, S]]} -> - {decode_affiliation(A), decode_subscriptions(S)}; - _ -> {none, []} + ejabberd_odbc:sql_query_t([<<"select affiliation,subscriptions from " + "pubsub_state where nodeid='">>, + Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {selected, [<<"affiliation">>, <<"subscriptions">>], [[A, S]]} -> + {decode_affiliation(A), decode_subscriptions(S)}; + _ -> + {none, []} end. -select_affiliation_subscriptions(NodeId, JID, JID) -> - select_affiliation_subscriptions(NodeId, JID); -select_affiliation_subscriptions(NodeId, GenKey, - SubKey) -> - {result, Affiliation} = get_affiliation(NodeId, GenKey), - {result, Subscriptions} = get_subscriptions(NodeId, - SubKey), +select_affiliation_subscriptions(Nidx, JID, JID) -> + select_affiliation_subscriptions(Nidx, JID); +select_affiliation_subscriptions(Nidx, GenKey, SubKey) -> + {result, Affiliation} = get_affiliation(Nidx, GenKey), + {result, Subscriptions} = get_subscriptions(Nidx, SubKey), {Affiliation, Subscriptions}. -update_affiliation(NodeId, JID, Affiliation) -> +update_affiliation(Nidx, JID, Affiliation) -> J = encode_jid(JID), A = encode_affiliation(Affiliation), case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_state set affiliation='">>, - A, <<"' where nodeid='">>, NodeId, - <<"' and jid='">>, J, <<"';">>]) - of - {updated, 1} -> ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, " - "affiliation, subscriptions) values('">>, - NodeId, <<"', '">>, J, <<"', '">>, A, - <<"', '');">>]) + ejabberd_odbc:sql_query_t([<<"update pubsub_state set affiliation='">>, + A, <<"' where nodeid='">>, Nidx, + <<"' and jid='">>, J, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values('">>, Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '');">>]) end. -update_subscription(NodeId, JID, Subscription) -> +update_subscription(Nidx, JID, Subscription) -> J = encode_jid(JID), S = encode_subscriptions(Subscription), case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, - S, <<"' where nodeid='">>, NodeId, - <<"' and jid='">>, J, <<"';">>]) - of - {updated, 1} -> ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, " - "affiliation, subscriptions) values('">>, - NodeId, <<"', '">>, J, <<"', 'n', '">>, - S, <<"');">>]) + ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, S, + <<"' where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values('">>, Nidx, <<"', '">>, J, <<"', 'n', '">>, S, <<"');">>]) end. -decode_jid(JID) -> - jlib:jid_tolower(jlib:string_to_jid(JID)). - +-spec(decode_jid/1 :: + ( SJID :: binary()) + -> ljid() + ). +decode_jid(SJID) -> + jlib:jid_tolower(jlib:string_to_jid(SJID)). + +-spec(decode_affiliation/1 :: + ( Arg :: binary()) + -> atom() + ). decode_affiliation(<<"o">>) -> owner; decode_affiliation(<<"p">>) -> publisher; decode_affiliation(<<"m">>) -> member; decode_affiliation(<<"c">>) -> outcast; decode_affiliation(_) -> none. +-spec(decode_subscription/1 :: + ( Arg :: binary()) + -> atom() + ). decode_subscription(<<"s">>) -> subscribed; decode_subscription(<<"p">>) -> pending; decode_subscription(<<"u">>) -> unconfigured; decode_subscription(_) -> none. +-spec(decode_subscriptions/1 :: + ( Subscriptions :: binary()) + -> [] | [{atom(), binary()},...] + ). decode_subscriptions(Subscriptions) -> lists:foldl(fun (Subscription, Acc) -> - case str:tokens(Subscription, <<":">>) of - [S, SubId] -> [{decode_subscription(S), SubId} | Acc]; - _ -> Acc - end - end, - [], str:tokens(Subscriptions, <<",">>)). + case str:tokens(Subscription, <<":">>) of + [S, SubId] -> [{decode_subscription(S), SubId} | Acc]; + _ -> Acc + end + end, + [], str:tokens(Subscriptions, <<",">>)). +-spec(encode_jid/1 :: + ( JID :: ljid()) + -> binary() + ). encode_jid(JID) -> - (?PUBSUB):escape(JID). - + ejabberd_odbc:escape(jlib:jid_to_string(JID)). + +-spec(encode_host/1 :: + ( Host :: host()) + -> binary() + ). +encode_host({_U, _S, _R} = LJID) -> encode_jid(LJID); +encode_host(Host) -> ejabberd_odbc:escape(Host). + +-spec(encode_affiliation/1 :: + ( Arg :: atom()) + -> binary() + ). encode_affiliation(owner) -> <<"o">>; encode_affiliation(publisher) -> <<"p">>; encode_affiliation(member) -> <<"m">>; encode_affiliation(outcast) -> <<"c">>; encode_affiliation(_) -> <<"n">>. +-spec(encode_subscription/1 :: + ( Arg :: atom()) + -> binary() + ). encode_subscription(subscribed) -> <<"s">>; encode_subscription(pending) -> <<"p">>; encode_subscription(unconfigured) -> <<"u">>; encode_subscription(_) -> <<"n">>. +-spec(encode_subscriptions/1 :: + ( Subscriptions :: [] | [{atom(), binary()},...]) + -> binary() + ). encode_subscriptions(Subscriptions) -> - str:join(lists:map(fun ({S, SubId}) -> - <<(encode_subscription(S))/binary, ":", - SubId/binary>> - end, - Subscriptions), - <<",">>). + str:join([<<(encode_subscription(S))/binary, ":", SubId/binary>> + || {S, SubId} <- Subscriptions], <<",">>). %%% record getter/setter -state_to_raw(NodeId, State) -> +state_to_raw(Nidx, State) -> {JID, _} = State#pubsub_state.stateid, J = encode_jid(JID), A = encode_affiliation(State#pubsub_state.affiliation), - S = - encode_subscriptions(State#pubsub_state.subscriptions), - [<<"'">>, NodeId, <<"', '">>, J, <<"', '">>, A, - <<"', '">>, S, <<"'">>]. + S = encode_subscriptions(State#pubsub_state.subscriptions), + [<<"'">>, Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '">>, S, <<"'">>]. -raw_to_item(NodeId, - [ItemId, SJID, Creation, Modification, XML]) -> +raw_to_item(Nidx, [ItemId, SJID, Creation, Modification, XML]) -> JID = decode_jid(SJID), ToTime = fun (Str) -> - [T1, T2, T3] = str:tokens(Str, <<":">>), - {jlib:l2i(T1), jlib:l2i(T2), jlib:l2i(T3)} - end, + [T1, T2, T3] = str:tokens(Str, <<":">>), + {jlib:l2i(T1), jlib:l2i(T2), jlib:l2i(T3)} + end, Payload = case xml_stream:parse_element(XML) of - {error, _Reason} -> []; - El -> [El] - end, - #pubsub_item{itemid = {ItemId, NodeId}, - creation = {ToTime(Creation), JID}, - modification = {ToTime(Modification), JID}, - payload = Payload}. + {error, _Reason} -> []; + El -> [El] + end, + #pubsub_item{itemid = {ItemId, Nidx}, + creation = {ToTime(Creation), JID}, + modification = {ToTime(Modification), JID}, + payload = Payload}. diff --git a/src/node_mb.erl b/src/node_mb.erl index efcacf6e8a0..e48fd7967f8 100644 --- a/src/node_mb.erl +++ b/src/node_mb.erl @@ -4,62 +4,54 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne %%% @author Eric Cestari %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -%%% @doc The module {@module} is the pep microblog PubSub plugin. -%%%

    To be used, mod_pubsub must be configured : -%%% {mod_pubsub, [ % requires mod_caps -%%% {access_createnode, pubsub_createnode}, -%%% {plugins, ["default", "pep","mb"]}, -%%% {pep_mapping, [{"urn:xmpp:microblog", "mb"}]} -%%% ]}, -%%%

    -%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    - -module(node_mb). - +-behaviour(gen_pubsub_node). -author('eric@ohmforce.com'). --include("ejabberd.hrl"). --include("logger.hrl"). - -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). +%%% @doc The module {@module} is the pep microblog PubSub plugin. +%%%

    To be used, mod_pubsub must be configured : +%%% {mod_pubsub, [ % requires mod_caps +%%% {access_createnode, pubsub_createnode}, +%%% {plugins, ["default", "pep","mb"]}, +%%% {pep_mapping, [{"urn:xmpp:microblog", "mb"}]} +%%% ]}, +%%%

    +%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_pep:init(Host, ServerHost, Opts). @@ -68,124 +60,127 @@ terminate(Host, ServerHost) -> node_pep:terminate(Host, ServerHost), ok. options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, false}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, presence}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, true}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, false}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, presence}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, on_sub_and_presence}, + {deliver_notifications, true}, + {presence_based_delivery, true}]. features() -> - [<<"create-nodes">>, %* - <<"auto-create">>, %* - <<"auto-subscribe">>, %* - <<"delete-nodes">>, %* - <<"delete-items">>, %* - <<"filtered-notifications">>, %* - <<"modify-affiliations">>, <<"outcast-affiliation">>, - <<"persistent-items">>, - <<"publish">>, %* - <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, - <<"retrieve-items">>, %* - <<"retrieve-subscriptions">>, <<"subscribe">>]. - -create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access) -> - node_pep:create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access). - -create_node(NodeId, Owner) -> - node_pep:create_node(NodeId, Owner). - -delete_node(Removed) -> node_pep:delete_node(Removed). - -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_pep:subscribe_node(NodeId, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). - -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_pep:unsubscribe_node(NodeId, Sender, Subscriber, - SubID). - -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_pep:publish_item(NodeId, Publisher, Model, - MaxItems, ItemId, Payload). - -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_pep:remove_extra_items(NodeId, MaxItems, ItemIds). - -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_pep:delete_item(NodeId, Publisher, PublishModel, - ItemId). - -purge_node(NodeId, Owner) -> - node_pep:purge_node(NodeId, Owner). + [<<"create-nodes">>, + <<"auto-create">>, + <<"auto-subscribe">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"filtered-notifications">>, + <<"modify-affiliations">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_pep:create_node(Nidx, Owner). + +delete_node(Removed) -> + node_pep:delete_node(Removed). + +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_pep:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). + +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_pep:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_pep:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_pep:remove_extra_items(Nidx, MaxItems, ItemIds). + +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_pep:delete_item(Nidx, Publisher, PublishModel, ItemId). + +purge_node(Nidx, Owner) -> + node_pep:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_pep:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_pep:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_pep:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_pep:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_pep:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_pep:set_affiliation(NodeId, Owner, Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_pep:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_pep:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeId) -> - node_pep:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_pep:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_pep:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_pep:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_pep:set_subscriptions(NodeId, Owner, Subscription, - SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_pep:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_pep:get_states(NodeId). +get_states(Nidx) -> + node_pep:get_states(Nidx). -get_state(NodeId, JID) -> - node_pep:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_pep:get_state(Nidx, JID). -set_state(State) -> node_pep:set_state(State). +set_state(State) -> + node_pep:set_state(State). -get_items(NodeId, From) -> - node_pep:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_pep:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_pep:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_pep:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_pep:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_pep:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_pep:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_pep:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_pep:set_item(Item). +set_item(Item) -> + node_pep:set_item(Item). get_item_name(Host, Node, Id) -> node_pep:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_pep:node_to_path(Node). +node_to_path(Node) -> + node_pep:node_to_path(Node). -path_to_node(Path) -> node_pep:path_to_node(Path). +path_to_node(Path) -> + node_pep:path_to_node(Path). diff --git a/src/node_pep.erl b/src/node_pep.erl index f6575dafae8..8eeb28f0e81 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -4,20 +4,19 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne %%% @author Christophe Romain %%% [http://www.process-one.net/] @@ -25,35 +24,29 @@ %%% @end %%% ==================================================================== -%%% @doc The module {@module} is the pep PubSub plugin. -%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    - -module(node_pep). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). --include("ejabberd.hrl"). --include("logger.hrl"). - -include("pubsub.hrl"). - -include("jlib.hrl"). +-include("logger.hrl"). --behaviour(gen_pubsub_node). +%%% @doc The module {@module} is the pep PubSub plugin. +%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts), @@ -63,423 +56,193 @@ init(Host, ServerHost, Opts) -> terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost), ok. --spec(options/0 :: () -> NodeOptions::mod_pubsub:nodeOptions()). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, false}, - {purge_offline, false}, {persist_items, true}, - {max_items, 1}, {subscribe, true}, - {access_model, presence}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, true}]. - --spec(features/0 :: () -> Features::[binary(),...]). + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, false}, + {purge_offline, false}, + {persist_items, false}, + {max_items, 1}, + {subscribe, true}, + {access_model, presence}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, on_sub_and_presence}, + {deliver_notifications, true}, + {presence_based_delivery, true}]. + features() -> - [<<"create-nodes">>, %* - <<"auto-create">>, %* - <<"auto-subscribe">>, %* - <<"delete-nodes">>, %* - <<"delete-items">>, %* - <<"filtered-notifications">>, %* - <<"modify-affiliations">>, <<"outcast-affiliation">>, - <<"persistent-items">>, - <<"publish">>, %* - <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, - <<"retrieve-items">>, %* - <<"retrieve-subscriptions">>, <<"subscribe">>]. - - --spec(create_node_permission/6 :: -( - Host :: mod_pubsub:hostPEP(), - ServerHost :: binary(), - NodeId :: mod_pubsub:nodeId(), - _ParentNodeId :: mod_pubsub:nodeId(), - Owner :: jid(), - Access :: atom()) - -> {result, boolean()} -). + [<<"create-nodes">>, + <<"auto-create">>, + <<"auto-subscribe">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"filtered-notifications">>, + <<"modify-affiliations">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>]. create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> LOwner = jlib:jid_tolower(Owner), {User, Server, _Resource} = LOwner, Allowed = case LOwner of - {<<"">>, Host, <<"">>} -> - true; % pubsub service always allowed + {<<"">>, Host, <<"">>} -> + true; % pubsub service always allowed + _ -> + case acl:match_rule(ServerHost, Access, LOwner) of + allow -> + case Host of + {User, Server, _} -> true; + _ -> false + end; _ -> - case acl:match_rule(ServerHost, Access, LOwner) of - allow -> - case Host of - {User, Server, _} -> true; - _ -> false - end; - E -> ?DEBUG("Create not allowed : ~p~n", [E]), false - end - end, + false + end + end, {result, Allowed}. --spec(create_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} -). -create_node(NodeIdx, Owner) -> - node_hometree:create_node(NodeIdx, Owner). - --spec(delete_node/1 :: -( - Nodes :: [mod_pubsub:pubsubNode(),...]) - -> {result, - {[], - [{mod_pubsub:pubsubNode(), - [{ljid(), [{mod_pubsub:subscription(), mod_pubsub:subId()}]},...]},...] - } - } -). - -delete_node(Removed) -> - case node_hometree:delete_node(Removed) of - {result, {_, _, Result}} -> {result, {[], Result}}; - Error -> Error - end. +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). + +delete_node(Nodes) -> + {result, {_, _, Result}} = node_hometree:delete_node(Nodes), + {result, {[], Result}}. + +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). --spec(subscribe_node/8 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - AccessModel :: mod_pubsub:accessModel(), - SendLast :: 'never' | 'on_sub' | 'on_sub_and_presence', - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - Options :: mod_pubsub:subOptions()) - -> {result, {default, subscribed, mod_pubsub:subId()}} - | {result, {default, subscribed, mod_pubsub:subId(), send_last}} - | {result, {default, pending, mod_pubsub:subId()}} - %%% - | {error, xmlel()} -). -subscribe_node(NodeIdx, Sender, Subscriber, AccessModel, SendLast, - PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeIdx, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options). - --spec(unsubscribe_node/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - SubId :: subId()) - -> {result, default} - % - | {error, xmlel()} -). -unsubscribe_node(NodeIdx, Sender, Subscriber, SubID) -> - case node_hometree:unsubscribe_node(NodeIdx, Sender, Subscriber, SubID) of - {error, Error} -> {error, Error}; - {result, _} -> {result, []} +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + case node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of + {error, Error} -> {error, Error}; + {result, _} -> {result, []} end. --spec(publish_item/6 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - Max_Items :: non_neg_integer(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) - -> {result, {default, broadcast, [mod_pubsub:itemId()]}} - %%% - | {error, xmlel()} -). -publish_item(NodeIdx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(NodeIdx, Publisher, Model, MaxItems, ItemId, Payload). - --spec(remove_extra_items/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Max_Items :: unlimited | non_neg_integer(), - ItemIds :: [mod_pubsub:itemId()]) - -> {result, - {NewItems::[mod_pubsub:itemId()], - OldItems::[mod_pubsub:itemId()]} - } -). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, ItemIds). - - --spec(delete_item/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - ItemId :: <<>> | mod_pubsub:itemId()) - -> {result, {default, broadcast}} - %%% - | {error, xmlel()} -). -delete_item(NodeIdx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeIdx, Publisher, PublishModel, ItemId). - --spec(purge_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} - | {error, xmlel()} -). -purge_node(NodeIdx, Owner) -> - node_hometree:purge_node(NodeIdx, Owner). - --spec(get_entity_affiliations/2 :: -( - Host :: mod_pubsub:hostPEP(), - Owner :: jid()) - -> {result, [{mod_pubsub:pubsubNode(), mod_pubsub:affiliation()}]} -). -get_entity_affiliations(_Host, Owner) -> +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). + +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). + +get_entity_affiliations(Host, Owner) -> {_, D, _} = SubKey = jlib:jid_tolower(Owner), SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - States = mnesia:match_object(#pubsub_state{stateid = - {GenKey, '_'}, - _ = '_'}), - NodeTree = case catch - ets:lookup(gen_mod:get_module_proc(D, config), nodetree) - of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, - affiliation = A}, - Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {{_, D, _}, _}} = - Node -> - [{Node, A} | Acc]; - _ -> Acc - end - end, - [], States), + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), + NodeTree = mod_pubsub:tree(Host), + Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> [{Node, A} | Acc]; + _ -> Acc + end + end, + [], States), {result, Reply}. --spec(get_node_affiliations/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [{ljid(), mod_pubsub:affiliation()}]} -). -get_node_affiliations(NodeIdx) -> - node_hometree:get_node_affiliations(NodeIdx). - --spec(get_affiliation/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, mod_pubsub:affiliation()} -). -get_affiliation(NodeIdx, Owner) -> - node_hometree:get_affiliation(NodeIdx, Owner). - --spec(set_affiliation/3 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid(), - Affiliation :: mod_pubsub:affiliation()) - -> ok -). -set_affiliation(NodeIdx, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeIdx, Owner, Affiliation). - --spec(get_entity_subscriptions/2 :: -( - Host :: mod_pubsub:hostPEP(), - Owner :: jid()) - -> {result, - [{mod_pubsub:pubsubNode(), - mod_pubsub:subscription(), - mod_pubsub:subId(), - ljid()}] - } -). -get_entity_subscriptions(_Host, Owner) -> +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). + +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). + +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). + +get_entity_subscriptions(Host, Owner) -> {U, D, _} = SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), States = case SubKey of - GenKey -> - mnesia:match_object(#pubsub_state{stateid = - {{U, D, '_'}, '_'}, - _ = '_'}); - _ -> - mnesia:match_object(#pubsub_state{stateid = - {GenKey, '_'}, - _ = '_'}) - ++ - mnesia:match_object(#pubsub_state{stateid = - {SubKey, '_'}, - _ = '_'}) - end, - NodeTree = case catch - ets:lookup(gen_mod:get_module_proc(D, config), nodetree) - of - [{nodetree, N}] -> N; - _ -> nodetree_tree - end, - Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, - subscriptions = Ss}, - Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> - lists:foldl(fun - ({subscribed, SubID}, Acc2) -> - [{Node, subscribed, SubID, J} | Acc2]; - ({pending, _SubID}, Acc2) -> - [{Node, pending, J} | Acc2]; - (S, Acc2) -> - [{Node, S, J} | Acc2] - end, Acc, Ss); - _ -> Acc - end - end, - [], States), + GenKey -> + mnesia:match_object(#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); + _ -> + mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) + ++ + mnesia:match_object(#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) + end, + NodeTree = mod_pubsub:tree(Host), + Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {{_, D, _}, _}} = Node -> + lists:foldl(fun + ({subscribed, SubId}, Acc2) -> + [{Node, subscribed, SubId, J} | Acc2]; + ({pending, _SubId}, Acc2) -> + [{Node, pending, J} | Acc2]; + (S, Acc2) -> + [{Node, S, J} | Acc2] + end, + Acc, Ss); + _ -> + Acc + end + end, + [], States), {result, Reply}. --spec(get_node_subscriptions/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, - [{ljid(), mod_pubsub:subscription(), mod_pubsub:subId()}] | - [{ljid(), none},...] - } -). -get_node_subscriptions(NodeIdx) -> - node_hometree:get_node_subscriptions(NodeIdx). - --spec(get_subscriptions/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid()) - -> {result, [{mod_pubsub:subscription(), mod_pubsub:subId()}]} -). -get_subscriptions(NodeIdx, Owner) -> - node_hometree:get_subscriptions(NodeIdx, Owner). - --spec(set_subscriptions/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid(), - Subscription :: mod_pubsub:subscription(), - SubId :: mod_pubsub:subId()) - -> ok - %%% - | {error, xmlel()} -). -set_subscriptions(NodeIdx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeIdx, Owner, Subscription, SubId). - --spec(get_pending_nodes/2 :: -( - Host :: mod_pubsub:hostPubsub(), - Owner :: jid()) - -> {result, [mod_pubsub:nodeId()]} -). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). + +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). + +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). --spec(get_states/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [mod_pubsub:pubsubState()]} -). -get_states(NodeIdx) -> node_hometree:get_states(NodeIdx). - --spec(get_state/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: ljid()) - -> mod_pubsub:pubsubState() -). -get_state(NodeIdx, JID) -> - node_hometree:get_state(NodeIdx, JID). - --spec(set_state/1 :: -( - State::mod_pubsub:pubsubState()) - -> ok -). -set_state(State) -> node_hometree:set_state(State). - --spec(get_items/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - _From :: jid()) - -> {result, [mod_pubsub:pubsubItem()]} -). -get_items(NodeIdx, From) -> - node_hometree:get_items(NodeIdx, From). - --spec(get_items/6 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - JID :: jid(), - AccessModel :: mod_pubsub:accessModel(), - Presence_Subscription :: boolean(), - RosterGroup :: boolean(), - _SubId :: mod_pubsub:subId()) - -> {result, [mod_pubsub:pubsubItem()]} - %%% - | {error, xmlel()} -). -get_items(NodeIdx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeIdx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). - --spec(get_item/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - ItemId :: mod_pubsub:itemId()) - -> {result, mod_pubsub:pubsubItem()} - | {error, xmlel()} -). -get_item(NodeIdx, ItemId) -> - node_hometree:get_item(NodeIdx, ItemId). - --spec(get_item/7 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - ItemId :: mod_pubsub:itemId(), - JID :: jid(), - AccessModel :: mod_pubsub:accessModel(), - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - SubId :: mod_pubsub:subId()) - -> {result, mod_pubsub:pubsubItem()} - | {error, xmlel()} -). -get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, - SubId) -> - node_hometree:get_item(NodeIdx, ItemId, JID, AccessModel, PresenceSubscription, - RosterGroup, SubId). - --spec(set_item/1 :: -( - Item::mod_pubsub:pubsubItem()) - -> ok -). -set_item(Item) -> node_hometree:set_item(Item). +get_states(Nidx) -> + node_hometree:get_states(Nidx). + +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). + +set_state(State) -> + node_hometree:set_state(State). + +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). + +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). + +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). + +set_item(Item) -> + node_hometree:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat:node_to_path(Node). +node_to_path(Node) -> + node_flat:node_to_path(Node). -path_to_node(Path) -> node_flat:path_to_node(Path). +path_to_node(Path) -> + node_flat:path_to_node(Path). %%% %%% Internal @@ -491,10 +254,10 @@ path_to_node(Path) -> node_flat:path_to_node(Path). %% If not, show a warning message in the ejabberd log file. complain_if_modcaps_disabled(ServerHost) -> case gen_mod:is_loaded(ServerHost, mod_caps) of - false -> - ?WARNING_MSG("The PEP plugin is enabled in mod_pubsub " - "of host ~p. This plugin requires mod_caps " - "to be enabled, but it isn't.", - [ServerHost]); - true -> ok + false -> + ?WARNING_MSG("The PEP plugin is enabled in mod_pubsub " + "of host ~p. This plugin requires mod_caps " + "to be enabled, but it isn't.", + [ServerHost]); + true -> ok end. diff --git a/src/node_pep_odbc.erl b/src/node_pep_odbc.erl index 39b936aad20..d80e686fbc7 100644 --- a/src/node_pep_odbc.erl +++ b/src/node_pep_odbc.erl @@ -4,20 +4,19 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne %%% @author Christophe Romain %%% [http://www.process-one.net/] @@ -25,39 +24,30 @@ %%% @end %%% ==================================================================== -%%% @doc The module {@module} is the pep PubSub plugin. -%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    - -module(node_pep_odbc). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). --include("ejabberd.hrl"). --include("logger.hrl"). - -include("pubsub.hrl"). - -include("jlib.hrl"). +-include("logger.hrl"). --define(PUBSUB, mod_pubsub_odbc). - --behaviour(gen_pubsub_node). +%%% @doc The module {@module} is the pep PubSub plugin. +%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, - get_entity_subscriptions_for_send_last/2, - get_node_subscriptions/1, get_subscriptions/2, - set_subscriptions/4, get_pending_nodes/2, get_states/1, - get_state/2, set_state/1, get_items/7, get_items/6, - get_items/3, get_items/2, get_item/7, get_item/2, - set_item/1, get_item_name/3, get_last_items/3, - node_to_path/1, path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1, + get_entity_subscriptions_for_send_last/2, get_last_items/3]). init(Host, ServerHost, Opts) -> node_hometree_odbc:init(Host, ServerHost, Opts), @@ -67,362 +57,183 @@ init(Host, ServerHost, Opts) -> terminate(Host, ServerHost) -> node_hometree_odbc:terminate(Host, ServerHost), ok. --spec(options/0 :: () -> NodeOptions::mod_pubsub:nodeOptions()). options() -> - [{odbc, true}, - {deliver_payloads, true}, - {notify_config, false}, - {notify_delete, false}, - {notify_retract, false}, - {purge_offline, false}, - {persist_items, true}, - {max_items, 1}, - {subscribe, true}, - {access_model, presence}, - {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, true}]. - --spec(features/0 :: () -> Features::[binary(),...]). + [{odbc, true}, {rsm, true} | node_pep:options()]. + features() -> - [<<"create-nodes">>, %* - <<"auto-create">>, %* - <<"auto-subscribe">>, %* - <<"delete-nodes">>, %* - <<"delete-items">>, %* - <<"filtered-notifications">>, %* - <<"modify-affiliations">>, <<"outcast-affiliation">>, - <<"persistent-items">>, - <<"publish">>, %* - <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, - <<"retrieve-items">>, %* - <<"retrieve-subscriptions">>, <<"subscribe">>]. - --spec(create_node_permission/6 :: -( - Host :: mod_pubsub:hostPEP(), - ServerHost :: binary(), - NodeId :: mod_pubsub:nodeId(), - _ParentNodeId :: mod_pubsub:nodeId(), - Owner :: jid(), - Access :: atom()) - -> {result, boolean()} -). - -create_node_permission(Host, ServerHost, _NodeId, _ParentNode, Owner, Access) -> - LOwner = jlib:jid_tolower(Owner), - {User, Server, _Resource} = LOwner, - Allowed = case LOwner of - {<<"">>, Host, <<"">>} -> - true; % pubsub service always allowed - _ -> - case acl:match_rule(ServerHost, Access, LOwner) of - allow -> - case Host of - {User, Server, _} -> true; - _ -> false - end; - E -> ?DEBUG("Create not allowed : ~p~n", [E]), false - end - end, - {result, Allowed}. - --spec(create_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, []} -). -create_node(NodeIdx, Owner) -> - case node_hometree_odbc:create_node(NodeIdx, Owner) of - {result, _} -> {result, []}; - Error -> Error - end. + [<<"rsm">> | node_pep:features()]. --spec(delete_node/1 :: -( - Removed :: [mod_pubsub:pubsubNode(),...]) - -> {result, - {[], - [{mod_pubsub:pubsubNode(), - [{ljid(), [{mod_pubsub:subscription(), mod_pubsub:subId()}]}]}] - } - } -). -delete_node(Removed) -> - case node_hometree_odbc:delete_node(Removed) of - {result, {_, _, Result}} -> {result, {[], Result}}; - Error -> Error - end. +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_hometree_odbc:create_node(Nidx, Owner), + {result, {default, broadcast}}. --spec(subscribe_node/8 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: ljid(), - AccessModel :: mod_pubsub:accessModel(), - SendLast :: 'never' | 'on_sub' | 'on_sub_and_presence', - PresenceSubscription :: boolean(), - RosterGroup :: boolean(), - Options :: mod_pubsub:subOptions()) - -> {result, {default, subscribed, mod_pubsub:subId()}} - | {result, {default, subscribed, mod_pubsub:subId(), send_last}} - | {result, {default, pending, mod_pubsub:subId()}} - %%% - | {error, _} - | {error, _, binary()} -). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree_odbc:subscribe_node(NodeId, Sender, - Subscriber, AccessModel, SendLast, - PresenceSubscription, RosterGroup, - Options). - - --spec(unsubscribe_node/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Sender :: jid(), - Subscriber :: jid(), - SubId :: subId()) - -> {result, []} - % - | {error, _} - | {error, _, binary()} -). -unsubscribe_node(NodeIdx, Sender, Subscriber, SubID) -> - case node_hometree_odbc:unsubscribe_node(NodeIdx, Sender, Subscriber, SubID) of - {error, Error} -> {error, Error}; - {result, _} -> {result, []} +delete_node(Nodes) -> + {result, {_, _, Result}} = node_hometree_odbc:delete_node(Nodes), + {result, {[], Result}}. + +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). + + +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + case node_hometree_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of + {error, Error} -> {error, Error}; + {result, _} -> {result, []} end. --spec(publish_item/6 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - Max_Items :: non_neg_integer(), - ItemId :: <<>> | mod_pubsub:itemId(), - Payload :: mod_pubsub:payload()) - -> {result, {default, broadcast, [mod_pubsub:itemId()]}} - %%% - | {error, _} -). -publish_item(NodeIdx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree_odbc:publish_item(NodeIdx, Publisher, - Model, MaxItems, ItemId, Payload). - -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree_odbc:remove_extra_items(NodeId, MaxItems, - ItemIds). - --spec(delete_item/4 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Publisher :: jid(), - PublishModel :: mod_pubsub:publishModel(), - ItemId :: <<>> | mod_pubsub:itemId()) - -> {result, {default, broadcast}} - %%% - | {error, _} -). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree_odbc:delete_item(NodeId, Publisher, - PublishModel, ItemId). - --spec(purge_node/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: jid()) - -> {result, {default, broadcast}} - | {error, _} -). -purge_node(NodeIdx, Owner) -> - node_hometree_odbc:purge_node(NodeIdx, Owner). - --spec(get_entity_affiliations/2 :: -( - Host :: mod_pubsub:hostPubsub(), - Owner :: jid()) - -> {result, [{mod_pubsub:pubsubNode(), mod_pubsub:affiliation()}]} -). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). + +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). + +purge_node(Nidx, Owner) -> + node_hometree_odbc:purge_node(Nidx, Owner). + get_entity_affiliations(_Host, Owner) -> OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), node_hometree_odbc:get_entity_affiliations(OwnerKey, Owner). --spec(get_node_affiliations/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> {result, [{ljid(), mod_pubsub:affiliation()}]} -). -get_node_affiliations(NodeIdx) -> - node_hometree_odbc:get_node_affiliations(NodeIdx). - --spec(get_affiliation/2 :: -( - NodeIdx :: mod_pubsub:nodeIdx(), - Owner :: ljid()) - -> {result, mod_pubsub:affiliation()} -). -get_affiliation(NodeIdx, Owner) -> - node_hometree_odbc:get_affiliation(NodeIdx, Owner). - -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree_odbc:set_affiliation(NodeId, Owner, Affiliation). +get_node_affiliations(Nidx) -> + node_hometree_odbc:get_node_affiliations(Nidx). + +get_affiliation(Nidx, Owner) -> + node_hometree_odbc:get_affiliation(Nidx, Owner). + +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree_odbc:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(_Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - Host = (?PUBSUB):escape(element(2, SubKey)), + Host = node_hometree_odbc:encode_host(element(2, SubKey)), SJ = node_hometree_odbc:encode_jid(SubKey), GJ = node_hometree_odbc:encode_jid(GenKey), Query = case SubKey of - GenKey -> - [<<"select host, node, type, i.nodeid, jid, " - "subscriptions from pubsub_state i, pubsub_nod" - "e n where i.nodeid = n.nodeid and jid " - "like '">>, - GJ, <<"%' and host like '%@">>, Host, <<"';">>]; - _ -> - [<<"select host, node, type, i.nodeid, jid, " - "subscriptions from pubsub_state i, pubsub_nod" - "e n where i.nodeid = n.nodeid and jid " - "in ('">>, - SJ, <<"', '">>, GJ, <<"') and host like '%@">>, Host, - <<"';">>] - end, + GenKey -> + [<<"select host, node, type, i.nodeid, jid, " + "subscriptions from pubsub_state i, pubsub_node n " + "where i.nodeid = n.nodeid and jid " + "like '">>, GJ, <<"%' and host like '%@">>, Host, <<"';">>]; + _ -> + [<<"select host, node, type, i.nodeid, jid, " + "subscriptions from pubsub_state i, pubsub_node n " + "where i.nodeid = n.nodeid and jid " + "in ('">>, SJ, <<"', '">>, GJ, <<"') and host like '%@">>, Host, <<"';">>] + end, Reply = case catch ejabberd_odbc:sql_query_t(Query) of - {selected, - [<<"host">>, <<"node">>, <<"type">>, <<"nodeid">>, - <<"jid">>, <<"subscriptions">>], - RItems} -> - lists:map(fun ([H, N, T, I, J, S]) -> - O = node_hometree_odbc:decode_jid(H), - Node = nodetree_tree_odbc:raw_to_node(O, - [N, - <<"">>, - T, - I]), - {Node, - node_hometree_odbc:decode_subscriptions(S), - node_hometree_odbc:decode_jid(J)} - end, - RItems); - _ -> [] - end, + {selected, + [<<"host">>, <<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], + RItems} -> + lists:map(fun ([H, N, T, I, J, S]) -> + O = node_hometree_odbc:decode_jid(H), + Node = nodetree_tree_odbc:raw_to_node(O, [N, <<"">>, T, I]), + {Node, + node_hometree_odbc:decode_subscriptions(S), + node_hometree_odbc:decode_jid(J)} + end, + RItems); + _ -> + [] + end, {result, Reply}. get_entity_subscriptions_for_send_last(_Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - Host = (?PUBSUB):escape(element(2, SubKey)), + Host = node_hometree_odbc:encode_host(element(2, SubKey)), SJ = node_hometree_odbc:encode_jid(SubKey), GJ = node_hometree_odbc:encode_jid(GenKey), Query = case SubKey of - GenKey -> - [<<"select host, node, type, i.nodeid, jid, " - "subscriptions from pubsub_state i, pubsub_nod" - "e n, pubsub_node_option o where i.nodeid " - "= n.nodeid and n.nodeid = o.nodeid and " - "name='send_last_published_item' and " - "val='on_sub_and_presence' and jid like " - "'">>, - GJ, <<"%' and host like '%@">>, Host, <<"';">>]; - _ -> - [<<"select host, node, type, i.nodeid, jid, " - "subscriptions from pubsub_state i, pubsub_nod" - "e n, pubsub_node_option o where i.nodeid " - "= n.nodeid and n.nodeid = o.nodeid and " - "name='send_last_published_item' and " - "val='on_sub_and_presence' and jid in " - "('">>, - SJ, <<"', '">>, GJ, <<"') and host like '%@">>, Host, - <<"';">>] - end, + GenKey -> + [<<"select host, node, type, i.nodeid, jid, " + "subscriptions from pubsub_state i, pubsub_node n, " + "pubsub_node_option o where i.nodeid = n.nodeid " + "and n.nodeid = o.nodeid and name='send_last_published_item' and " + "val='on_sub_and_presence' and jid like '">>, + GJ, <<"%' and host like '%@">>, Host, <<"';">>]; + _ -> + [<<"select host, node, type, i.nodeid, jid, " + "subscriptions from pubsub_state i, pubsub_node n, " + "pubsub_node_option o where i.nodeid = n.nodeid " + "and n.nodeid = o.nodeid and name='send_last_published_item' and " + "val='on_sub_and_presence' and jid in ", + "('">>, SJ, <<"', '">>, GJ, <<"') and host like '%@">>, Host, <<"';">>] + end, Reply = case catch ejabberd_odbc:sql_query_t(Query) of - {selected, - [<<"host">>, <<"node">>, <<"type">>, <<"nodeid">>, - <<"jid">>, <<"subscriptions">>], - RItems} -> - lists:map(fun ([H, N, T, I, J, S]) -> - O = node_hometree_odbc:decode_jid(H), - Node = nodetree_tree_odbc:raw_to_node(O, - [N, - <<"">>, - T, - I]), - {Node, - node_hometree_odbc:decode_subscriptions(S), - node_hometree_odbc:decode_jid(J)} - end, - RItems); - _ -> [] - end, + {selected, + [<<"host">>, <<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], + RItems} -> + lists:map(fun ([H, N, T, I, J, S]) -> + O = node_hometree_odbc:decode_jid(H), + Node = nodetree_tree_odbc:raw_to_node(O, [N, <<"">>, T, I]), + {Node, + node_hometree_odbc:decode_subscriptions(S), + node_hometree_odbc:decode_jid(J)} + end, + RItems); + _ -> + [] + end, {result, Reply}. -get_node_subscriptions(NodeId) -> - node_hometree_odbc:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree_odbc:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree_odbc:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree_odbc:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree_odbc:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree_odbc:get_pending_nodes(Host, Owner). -get_states(NodeId) -> - node_hometree_odbc:get_states(NodeId). - -get_state(NodeId, JID) -> - node_hometree_odbc:get_state(NodeId, JID). - -set_state(State) -> node_hometree_odbc:set_state(State). +get_states(Nidx) -> + node_hometree_odbc:get_states(Nidx). -get_items(NodeId, From) -> - node_hometree_odbc:get_items(NodeId, From). +get_state(Nidx, JID) -> + node_hometree_odbc:get_state(Nidx, JID). -get_items(NodeId, From, RSM) -> - node_hometree_odbc:get_items(NodeId, From, RSM). +set_state(State) -> + node_hometree_odbc:set_state(State). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, none). +get_items(Nidx, From, RSM) -> + node_hometree_odbc:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree_odbc:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, RSM). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree_odbc:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_last_items(NodeId, JID, Count) -> - node_hometree_odbc:get_last_items(NodeId, JID, Count). +get_last_items(Nidx, JID, Count) -> + node_hometree_odbc:get_last_items(Nidx, JID, Count). -get_item(NodeId, ItemId) -> - node_hometree_odbc:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree_odbc:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree_odbc:get_item(NodeId, ItemId, JID, - AccessModel, PresenceSubscription, RosterGroup, - SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree_odbc:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree_odbc:set_item(Item). +set_item(Item) -> + node_hometree_odbc:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree_odbc:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat_odbc:node_to_path(Node). +node_to_path(Node) -> + node_flat_odbc:node_to_path(Node). -path_to_node(Path) -> node_flat_odbc:path_to_node(Path). +path_to_node(Path) -> + node_flat_odbc:path_to_node(Path). %%% %%% Internal @@ -433,16 +244,11 @@ path_to_node(Path) -> node_flat_odbc:path_to_node(Path). %% Check that the mod_caps module is enabled in that Jabber Host %% If not, show a warning message in the ejabberd log file. complain_if_modcaps_disabled(ServerHost) -> - Modules = ejabberd_config:get_option({modules, - ServerHost}, - fun(Ms) when is_list(Ms) -> Ms end), - ModCaps = [mod_caps_enabled - || {mod_caps, _Opts} <- Modules], - case ModCaps of - [] -> - ?WARNING_MSG("The PEP plugin is enabled in mod_pubsub " - "of host ~p. This plugin requires mod_caps " - "to be enabled, but it isn't.", - [ServerHost]); - _ -> ok + case gen_mod:is_loaded(ServerHost, mod_caps) of + false -> + ?WARNING_MSG("The PEP plugin is enabled in mod_pubsub " + "of host ~p. This plugin requires mod_caps " + "to be enabled, but it isn't.", + [ServerHost]); + true -> ok end. diff --git a/src/node_private.erl b/src/node_private.erl index 12459e595e1..eab06d56209 100644 --- a/src/node_private.erl +++ b/src/node_private.erl @@ -4,58 +4,45 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne -%%% @author Christophe romain +%%% @author Christophe Romain %%% [http://www.process-one.net/] %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -module(node_private). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% Note on function definition -%% included is all defined plugin function -%% it's possible not to define some function at all -%% in that case, warning will be generated at compilation -%% and function call will fail, -%% then mod_pubsub will call function from node_hometree -%% (this makes code cleaner, but execution a little bit longer) - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). @@ -64,121 +51,126 @@ terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, whitelist}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, never}, - {deliver_notifications, false}, - {presence_based_delivery, false}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, whitelist}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, false}, + {presence_based_delivery, false}]. features() -> - [<<"create-nodes">>, <<"delete-nodes">>, - <<"delete-items">>, <<"instant-nodes">>, - <<"outcast-affiliation">>, <<"persistent-items">>, - <<"publish">>, <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, <<"retrieve-items">>, - <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>]. - -create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, - Node, ParentNode, Owner, Access). - -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"instant-nodes">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeId, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeId, Sender, - Subscriber, SubID). +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_hometree:publish_item(NodeId, Publisher, Model, - MaxItems, ItemId, Payload). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, - ItemIds). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeId, Publisher, - PublishModel, ItemId). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeId, Owner) -> - node_hometree:purge_node(NodeId, Owner). +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_hometree:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_hometree:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_hometree:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_hometree:get_states(NodeId). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat:node_to_path(Node). +node_to_path(Node) -> + node_flat:node_to_path(Node). -path_to_node(Path) -> node_flat:path_to_node(Path). +path_to_node(Path) -> + node_flat:path_to_node(Path). diff --git a/src/node_public.erl b/src/node_public.erl index cbb7baffb7e..efefd67fe45 100644 --- a/src/node_public.erl +++ b/src/node_public.erl @@ -4,58 +4,45 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %%% The Initial Developer of the Original Code is ProcessOne. %%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne %%% All Rights Reserved.'' %%% This software is copyright 2006-2015, ProcessOne. %%% -%%% %%% @copyright 2006-2015 ProcessOne -%%% @author Christophe romain +%%% @author Christophe Romain %%% [http://www.process-one.net/] %%% @version {@vsn}, {@date} {@time} %%% @end %%% ==================================================================== -module(node_public). - +-behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_node). - -%% Note on function definition -%% included is all defined plugin function -%% it's possible not to define some function at all -%% in that case, warning will be generated at compilation -%% and function call will fail, -%% then mod_pubsub will call function from node_hometree -%% (this makes code cleaner, but execution a little bit longer) - -%% API definition -export([init/3, terminate/2, options/0, features/0, - create_node_permission/6, create_node/2, delete_node/1, - purge_node/2, subscribe_node/8, unsubscribe_node/4, - publish_item/6, delete_item/4, remove_extra_items/3, - get_entity_affiliations/2, get_node_affiliations/1, - get_affiliation/2, set_affiliation/3, - get_entity_subscriptions/2, get_node_subscriptions/1, - get_subscriptions/2, set_subscriptions/4, - get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, get_item/7, - get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). init(Host, ServerHost, Opts) -> node_hometree:init(Host, ServerHost, Opts). @@ -64,123 +51,126 @@ terminate(Host, ServerHost) -> node_hometree:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, {notify_config, false}, - {notify_delete, false}, {notify_retract, true}, - {purge_offline, false}, {persist_items, true}, - {max_items, ?MAXITEMS}, {subscribe, true}, - {access_model, open}, {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, never}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, open}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, true}, + {presence_based_delivery, false}]. features() -> - [<<"create-nodes">>, <<"delete-nodes">>, - <<"delete-items">>, <<"instant-nodes">>, - <<"outcast-affiliation">>, <<"persistent-items">>, - <<"publish">>, <<"purge-nodes">>, <<"retract-items">>, - <<"retrieve-affiliations">>, <<"retrieve-items">>, - <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>]. - -create_node_permission(Host, ServerHost, Node, - ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, - Node, ParentNode, Owner, Access). - -create_node(NodeId, Owner) -> - node_hometree:create_node(NodeId, Owner). + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"instant-nodes">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_hometree:create_node(Nidx, Owner). delete_node(Removed) -> node_hometree:delete_node(Removed). -subscribe_node(NodeId, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(NodeId, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). -unsubscribe_node(NodeId, Sender, Subscriber, SubID) -> - node_hometree:unsubscribe_node(NodeId, Sender, - Subscriber, SubID). +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -publish_item(NodeId, Publisher, Model, MaxItems, ItemId, - Payload) -> - node_hometree:publish_item(NodeId, Publisher, Model, - MaxItems, ItemId, Payload). +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -remove_extra_items(NodeId, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(NodeId, MaxItems, - ItemIds). +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). -delete_item(NodeId, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(NodeId, Publisher, - PublishModel, ItemId). +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). -purge_node(NodeId, Owner) -> - node_hometree:purge_node(NodeId, Owner). +purge_node(Nidx, Owner) -> + node_hometree:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> node_hometree:get_entity_affiliations(Host, Owner). -get_node_affiliations(NodeId) -> - node_hometree:get_node_affiliations(NodeId). +get_node_affiliations(Nidx) -> + node_hometree:get_node_affiliations(Nidx). -get_affiliation(NodeId, Owner) -> - node_hometree:get_affiliation(NodeId, Owner). +get_affiliation(Nidx, Owner) -> + node_hometree:get_affiliation(Nidx, Owner). -set_affiliation(NodeId, Owner, Affiliation) -> - node_hometree:set_affiliation(NodeId, Owner, - Affiliation). +set_affiliation(Nidx, Owner, Affiliation) -> + node_hometree:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> node_hometree:get_entity_subscriptions(Host, Owner). -get_node_subscriptions(NodeId) -> - node_hometree:get_node_subscriptions(NodeId). +get_node_subscriptions(Nidx) -> + node_hometree:get_node_subscriptions(Nidx). -get_subscriptions(NodeId, Owner) -> - node_hometree:get_subscriptions(NodeId, Owner). +get_subscriptions(Nidx, Owner) -> + node_hometree:get_subscriptions(Nidx, Owner). -set_subscriptions(NodeId, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(NodeId, Owner, - Subscription, SubId). +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> node_hometree:get_pending_nodes(Host, Owner). -get_states(NodeId) -> node_hometree:get_states(NodeId). +get_states(Nidx) -> + node_hometree:get_states(Nidx). -get_state(NodeId, JID) -> - node_hometree:get_state(NodeId, JID). +get_state(Nidx, JID) -> + node_hometree:get_state(Nidx, JID). -set_state(State) -> node_hometree:set_state(State). +set_state(State) -> + node_hometree:set_state(State). -get_items(NodeId, From) -> - node_hometree:get_items(NodeId, From). +get_items(Nidx, From, RSM) -> + node_hometree:get_items(Nidx, From, RSM). -get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_items(NodeId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_hometree:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_item(NodeId, ItemId) -> - node_hometree:get_item(NodeId, ItemId). +get_item(Nidx, ItemId) -> + node_hometree:get_item(Nidx, ItemId). -get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(NodeId, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). -set_item(Item) -> node_hometree:set_item(Item). +set_item(Item) -> + node_hometree:set_item(Item). -%% @doc

    Return the name of the node if known: Default is to return -%% node id.

    get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). -node_to_path(Node) -> node_flat:node_to_path(Node). +node_to_path(Node) -> + node_flat:node_to_path(Node). -path_to_node(Path) -> node_flat:path_to_node(Path). +path_to_node(Path) -> + node_flat:path_to_node(Path). diff --git a/src/nodetree_dag.erl b/src/nodetree_dag.erl index e8ad8b14195..b2d4fade06a 100644 --- a/src/nodetree_dag.erl +++ b/src/nodetree_dag.erl @@ -4,11 +4,13 @@ %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved via the world wide web at http://www.erlang.org/. +%%% %%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. +%%% %%% %%% @author Brian Cully %%% @version {@vsn}, {@date} {@time} @@ -16,219 +18,141 @@ %%% ==================================================================== -module(nodetree_dag). - +-behaviour(gen_pubsub_nodetree). -author('bjc@kublai.com'). -%% API --export([init/3, terminate/2, options/0, set_node/1, - get_node/3, get_node/2, get_node/1, get_nodes/2, - get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, - get_subnodes/3, get_subnodes_tree/3, create_node/6, - delete_node/2]). - -include_lib("stdlib/include/qlc.hrl"). --include("ejabberd.hrl"). --include("logger.hrl"). - -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_nodetree). +-export([init/3, terminate/2, options/0, set_node/1, + get_node/3, get_node/2, get_node/1, get_nodes/2, + get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, + get_subnodes/3, get_subnodes_tree/3, create_node/6, + delete_node/2]). --define(DEFAULT_NODETYPE, leaf). +-define(DEFAULT_NODETYPE, leaf). -define(DEFAULT_PARENTS, []). - -define(DEFAULT_CHILDREN, []). --compile(export_all). - -%%==================================================================== -%% API -%%==================================================================== init(Host, ServerHost, Opts) -> nodetree_tree:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> nodetree_tree:terminate(Host, ServerHost). --spec(create_node/6 :: -( - Key :: mod_pubsub:hostPubsub(), - NodeID :: mod_pubsub:nodeId(), - Type :: binary(), - Owner :: jid(), - Options :: mod_pubsub:nodeOptions(), - Parents :: [mod_pubsub:nodeId()]) - -> {ok, NodeIdx::mod_pubsub:nodeIdx()} - | {error, xmlel()} -). -create_node(Key, NodeID, Type, Owner, Options, Parents) -> - OwnerJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - case find_node(Key, NodeID) of - false -> - NodeIdx = pubsub_index:new(node), - N = #pubsub_node{nodeid = oid(Key, NodeID), id = NodeIdx, - type = Type, parents = Parents, owners = [OwnerJID], - options = Options}, - case set_node(N) of - ok -> {ok, NodeIdx}; - Other -> Other - end; - _ -> {error, ?ERR_CONFLICT} - end. - --spec(set_node/1 :: -( - PubsubNode::mod_pubsub:pubsubNode()) - -> ok - %%% - | {error, xmlel()} -). -set_node(#pubsub_node{nodeid = {Key, _}, owners = Owners, options = Options} = - Node) -> +set_node(#pubsub_node{nodeid = {Key, _}, owners = Owners, options = Options} = Node) -> Parents = find_opt(collection, ?DEFAULT_PARENTS, Options), case validate_parentage(Key, Owners, Parents) of - true -> - mnesia:write(Node#pubsub_node{parents = Parents}); - Other -> Other + true -> mnesia:write(Node#pubsub_node{parents = Parents}); + Other -> Other end. --spec(delete_node/2 :: -( - Key :: mod_pubsub:hostPubsub(), - NodeID :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode(),...] - %%% - | {error, xmlel()} -). -delete_node(Key, NodeID) -> - case find_node(Key, NodeID) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; - Node -> - lists:foreach(fun (#pubsub_node{options = Opts} = - Child) -> - NewOpts = remove_config_parent(NodeID, Opts), - Parents = find_opt(collection, ?DEFAULT_PARENTS, - NewOpts), - ok = mnesia:write(pubsub_node, - Child#pubsub_node{parents = - Parents, - options = - NewOpts}, - write) - end, - get_subnodes(Key, NodeID)), - pubsub_index:free(node, Node#pubsub_node.id), - mnesia:delete_object(pubsub_node, Node, write), - [Node] +create_node(Key, Node, Type, Owner, Options, Parents) -> + OwnerJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + case find_node(Key, Node) of + false -> + Nidx = pubsub_index:new(node), + N = #pubsub_node{nodeid = oid(Key, Node), id = Nidx, + type = Type, parents = Parents, owners = [OwnerJID], + options = Options}, + case set_node(N) of + ok -> {ok, Nidx}; + Other -> Other + end; + _ -> + {error, ?ERR_CONFLICT} end. -options() -> nodetree_tree:options(). +delete_node(Key, Node) -> + case find_node(Key, Node) of + false -> + {error, ?ERR_ITEM_NOT_FOUND}; + Record -> + lists:foreach(fun (#pubsub_node{options = Opts} = Child) -> + NewOpts = remove_config_parent(Node, Opts), + Parents = find_opt(collection, ?DEFAULT_PARENTS, NewOpts), + ok = mnesia:write(pubsub_node, + Child#pubsub_node{parents = Parents, + options = NewOpts}, + write) + end, + get_subnodes(Key, Node)), + pubsub_index:free(node, Record#pubsub_node.id), + mnesia:delete_object(pubsub_node, Record, write), + [Record] + end. -get_node(Host, NodeID, _From) -> get_node(Host, NodeID). +options() -> + nodetree_tree:options(). --spec(get_node/2 :: -( - Host :: mod_pubsub:hostPubsub(), - NodeID :: mod_pubsub:nodeId()) - -> mod_pubsub:pubsubNode() - %%% - | {error, xmlel} -). -get_node(Host, NodeID) -> - case find_node(Host, NodeID) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; - Node -> Node +get_node(Host, Node, _From) -> + get_node(Host, Node). + +get_node(Host, Node) -> + case find_node(Host, Node) of + false -> {error, ?ERR_ITEM_NOT_FOUND}; + Record -> Record end. --spec(get_node/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> mod_pubsub:pubsubNode() - | {error, xmlel()} -). -get_node(NodeId) -> nodetree_tree:get_node(NodeId). +get_node(Node) -> + nodetree_tree:get_node(Node). get_nodes(Key, From) -> nodetree_tree:get_nodes(Key, From). --spec(get_nodes/1 :: -( - Host::mod_pubsub:host()) - -> [mod_pubsub:pubsubNode()] -). -get_nodes(Key) -> nodetree_tree:get_nodes(Key). +get_nodes(Key) -> + nodetree_tree:get_nodes(Key). --spec(get_parentnodes/3 :: -( - Host :: mod_pubsub:hostPubsub(), - NodeID :: mod_pubsub:nodeId(), - _From :: _) - -> [mod_pubsub:pubsubNode()] - %%% - | {error, xmlel()} -). -get_parentnodes(Host, NodeID, _From) -> - case find_node(Host, NodeID) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; - #pubsub_node{parents = Parents} -> - Q = qlc:q([N - || #pubsub_node{nodeid = {NHost, NNode}} = N +get_parentnodes(Host, Node, _From) -> + case find_node(Host, Node) of + false -> + {error, ?ERR_ITEM_NOT_FOUND}; + #pubsub_node{parents = Parents} -> + Q = qlc:q([N + || #pubsub_node{nodeid = {NHost, NNode}} = N <- mnesia:table(pubsub_node), - Parent <- Parents, Host == NHost, Parent == NNode]), - qlc:e(Q) + Parent <- Parents, Host == NHost, Parent == NNode]), + qlc:e(Q) end. -get_parentnodes_tree(Host, NodeID, _From) -> - Pred = fun (NID, #pubsub_node{nodeid = {_, NNodeID}}) -> - NID == NNodeID - end, +get_parentnodes_tree(Host, Node, _From) -> + Pred = fun (NID, #pubsub_node{nodeid = {_, NNode}}) -> + NID == NNode + end, Tr = fun (#pubsub_node{parents = Parents}) -> Parents - end, - traversal_helper(Pred, Tr, Host, [NodeID]). + end, + traversal_helper(Pred, Tr, Host, [Node]). -get_subnodes(Host, NodeID, _From) -> - get_subnodes(Host, NodeID). +get_subnodes(Host, Node, _From) -> + get_subnodes(Host, Node). --spec(get_subnodes/2 :: -( - Host :: mod_pubsub:hostPubsub(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). get_subnodes(Host, <<>>) -> get_subnodes_helper(Host, <<>>); -get_subnodes(Host, NodeID) -> - case find_node(Host, NodeID) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; - _ -> get_subnodes_helper(Host, NodeID) +get_subnodes(Host, Node) -> + case find_node(Host, Node) of + false -> {error, ?ERR_ITEM_NOT_FOUND}; + _ -> get_subnodes_helper(Host, Node) end. --spec(get_subnodes_helper/2 :: -( - Host :: mod_pubsub:hostPubsub(), - NodeID :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). -get_subnodes_helper(Host, NodeID) -> - Q = qlc:q([Node - || #pubsub_node{nodeid = {NHost, _}, - parents = Parents} = - Node - <- mnesia:table(pubsub_node), - Host == NHost, lists:member(NodeID, Parents)]), +get_subnodes_helper(Host, Node) -> + Q = qlc:q([N + || #pubsub_node{nodeid = {NHost, _}, + parents = Parents} = + N + <- mnesia:table(pubsub_node), + Host == NHost, lists:member(Node, Parents)]), qlc:e(Q). -get_subnodes_tree(Host, NodeID, From) -> +get_subnodes_tree(Host, Node, From) -> Pred = fun (NID, #pubsub_node{parents = Parents}) -> - lists:member(NID, Parents) - end, + lists:member(NID, Parents) + end, Tr = fun (#pubsub_node{nodeid = {_, N}}) -> [N] end, - traversal_helper(Pred, Tr, 1, Host, [NodeID], - [{0, [get_node(Host, NodeID, From)]}]). + traversal_helper(Pred, Tr, 1, Host, [Node], + [{0, [get_node(Host, Node, From)]}]). %%==================================================================== %% Internal functions @@ -236,17 +160,17 @@ get_subnodes_tree(Host, NodeID, From) -> oid(Key, Name) -> {Key, Name}. %% Key = jlib:jid() | host() -%% NodeID = string() +%% Node = string() -spec(find_node/2 :: -( - Key :: mod_pubsub:hostPubsub(), - NodeID :: mod_pubsub:nodeId()) + ( + Key :: mod_pubsub:hostPubsub(), + Node :: mod_pubsub:nodeId()) -> mod_pubsub:pubsubNode() | false -). -find_node(Key, NodeID) -> - case mnesia:read(pubsub_node, oid(Key, NodeID), read) of - [] -> false; - [Node] -> Node + ). +find_node(Key, Node) -> + case mnesia:read(pubsub_node, oid(Key, Node), read) of + [] -> false; + [Node] -> Node end. %% Key = jlib:jid() | host() @@ -254,77 +178,67 @@ find_node(Key, NodeID) -> %% Options = [{Key = atom(), Value = term()}] find_opt(Key, Default, Options) -> case lists:keysearch(Key, 1, Options) of - {value, {Key, Val}} -> Val; - _ -> Default + {value, {Key, Val}} -> Val; + _ -> Default end. -spec(traversal_helper/4 :: -( - Pred :: fun(), - Tr :: fun(), - Host :: mod_pubsub:hostPubsub(), - NodeId :: [mod_pubsub:pubsubNode(),...]) - -> [{Depth::non_neg_integer(), Nodes::[mod_pubsub:pubsubNode(),...]}] -). - -traversal_helper(Pred, Tr, Host, NodeIDs) -> - traversal_helper(Pred, Tr, 0, Host, NodeIDs, []). + ( + Pred :: fun(), + Tr :: fun(), + Host :: mod_pubsub:hostPubsub(), + Nodes :: [mod_pubsub:nodeId(),...]) + -> [{Depth::non_neg_integer(), Nodes::[mod_pubsub:pubsubNode(),...]}] + ). +traversal_helper(Pred, Tr, Host, Nodes) -> + traversal_helper(Pred, Tr, 0, Host, Nodes, []). traversal_helper(_Pred, _Tr, _Depth, _Host, [], Acc) -> Acc; -traversal_helper(Pred, Tr, Depth, Host, NodeIDs, Acc) -> - Q = qlc:q([Node - || #pubsub_node{nodeid = {NHost, _}} = Node - <- mnesia:table(pubsub_node), - NodeID <- NodeIDs, Host == NHost, Pred(NodeID, Node)]), +traversal_helper(Pred, Tr, Depth, Host, Nodes, Acc) -> + Q = qlc:q([N + || #pubsub_node{nodeid = {NHost, _}} = N + <- mnesia:table(pubsub_node), + Node <- Nodes, Host == NHost, Pred(Node, N)]), Nodes = qlc:e(Q), IDs = lists:flatmap(Tr, Nodes), - traversal_helper(Pred, Tr, Depth + 1, Host, IDs, - [{Depth, Nodes} | Acc]). + traversal_helper(Pred, Tr, Depth + 1, Host, IDs, [{Depth, Nodes} | Acc]). -remove_config_parent(NodeID, Options) -> - remove_config_parent(NodeID, Options, []). +remove_config_parent(Node, Options) -> + remove_config_parent(Node, Options, []). -remove_config_parent(_NodeID, [], Acc) -> +remove_config_parent(_Node, [], Acc) -> lists:reverse(Acc); -remove_config_parent(NodeID, [{collection, Parents} | T], Acc) -> - remove_config_parent(NodeID, T, - [{collection, lists:delete(NodeID, Parents)} | Acc]); -remove_config_parent(NodeID, [H | T], Acc) -> - remove_config_parent(NodeID, T, [H | Acc]). +remove_config_parent(Node, [{collection, Parents} | T], Acc) -> + remove_config_parent(Node, T, [{collection, lists:delete(Node, Parents)} | Acc]); +remove_config_parent(Node, [H | T], Acc) -> + remove_config_parent(Node, T, [H | Acc]). -spec(validate_parentage/3 :: -( - Key :: mod_pubsub:hostPubsub(), - Owners :: [ljid(),...], - Parent_NodeIds :: [mod_pubsub:nodeId()]) + ( + Key :: mod_pubsub:hostPubsub(), + Owners :: [ljid(),...], + Parent_Nodes :: [mod_pubsub:nodeId()]) -> true %%% - | {error, xmlel()} -). -validate_parentage(_Key, _Owners, []) -> true; + | {error, xmlel()} + ). +validate_parentage(_Key, _Owners, []) -> + true; validate_parentage(Key, Owners, [[] | T]) -> validate_parentage(Key, Owners, T); validate_parentage(Key, Owners, [<<>> | T]) -> validate_parentage(Key, Owners, T); validate_parentage(Key, Owners, [ParentID | T]) -> case find_node(Key, ParentID) of - false -> {error, ?ERR_ITEM_NOT_FOUND}; - #pubsub_node{owners = POwners, options = POptions} -> - NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions), - MutualOwners = [O || O <- Owners, PO <- POwners, O == PO], - case {MutualOwners, NodeType} of - {[], _} -> {error, ?ERR_FORBIDDEN}; - {_, collection} -> validate_parentage(Key, Owners, T); - {_, _} -> {error, ?ERR_NOT_ALLOWED} - end - end. - -%% @spec (Host) -> jid() -%% Host = host() -%% @doc

    Generate pubsub service JID.

    -service_jid(Host) -> - case Host of - {U, S, _} -> jlib:make_jid(U, S, <<>>); - _ -> jlib:make_jid(<<>>, Host, <<>>) + false -> + {error, ?ERR_ITEM_NOT_FOUND}; + #pubsub_node{owners = POwners, options = POptions} -> + NodeType = find_opt(node_type, ?DEFAULT_NODETYPE, POptions), + MutualOwners = [O || O <- Owners, PO <- POwners, O == PO], + case {MutualOwners, NodeType} of + {[], _} -> {error, ?ERR_FORBIDDEN}; + {_, collection} -> validate_parentage(Key, Owners, T); + {_, _} -> {error, ?ERR_NOT_ALLOWED} + end end. diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl index 7a9b46bcc96..e34eabf307a 100644 --- a/src/nodetree_tree.erl +++ b/src/nodetree_tree.erl @@ -36,287 +36,163 @@ %%% improvements.

    -module(nodetree_tree). - +-behaviour(gen_pubsub_nodetree). -author('christophe.romain@process-one.net'). -include_lib("stdlib/include/qlc.hrl"). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_nodetree). - -export([init/3, terminate/2, options/0, set_node/1, - get_node/3, get_node/2, get_node/1, get_nodes/2, - get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, - get_subnodes/3, get_subnodes_tree/3, create_node/6, - delete_node/2]). - -%% ================ -%% API definition -%% ================ + get_node/3, get_node/2, get_node/1, get_nodes/2, + get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, + get_subnodes/3, get_subnodes_tree/3, create_node/6, + delete_node/2]). -%% @spec (Host, ServerHost, Options) -> ok -%% Host = string() -%% ServerHost = string() -%% Options = [{atom(), term()}] -%% @doc

    Called during pubsub modules initialisation. Any pubsub plugin must -%% implement this function. It can return anything.

    -%%

    This function is mainly used to trigger the setup task necessary for the -%% plugin. It can be used for example by the developer to create the specific -%% module database schema if it does not exists yet.

    init(_Host, _ServerHost, _Options) -> mnesia:create_table(pubsub_node, - [{disc_copies, [node()]}, - {attributes, record_info(fields, pubsub_node)}]), + [{disc_copies, [node()]}, + {attributes, record_info(fields, pubsub_node)}]), mnesia:add_table_index(pubsub_node, id), NodesFields = record_info(fields, pubsub_node), case mnesia:table_info(pubsub_node, attributes) of - NodesFields -> ok; - _ -> ok + NodesFields -> ok; + _ -> ok end, %% mnesia:transform_table(pubsub_state, ignore, StatesFields) ok. -%% @spec (Host, ServerHost) -> ok -%% Host = string() -%% ServerHost = string() -%% @spec () -> Options -%% Options = [mod_pubsub:nodeOption()] -%% @doc Returns the default pubsub node tree options. -terminate(_Host, _ServerHost) -> ok. +terminate(_Host, _ServerHost) -> + ok. -options() -> [{virtual_tree, false}]. +options() -> + [{virtual_tree, false}]. -%% @spec (Node) -> ok | {error, Reason} -%% Node = mod_pubsub:pubsubNode() -%% Reason = mod_pubsub:stanzaError() --spec(set_node/1 :: -( - Node::mod_pubsub:pubsubNode()) - -> ok -). set_node(Node) when is_record(Node, pubsub_node) -> mnesia:write(Node). -%set_node(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. -get_node(Host, Node, _From) -> get_node(Host, Node). +get_node(Host, Node, _From) -> + get_node(Host, Node). -%% @spec (Host, NodeId) -> Node | {error, Reason} -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% Node = mod_pubsub:pubsubNode() -%% Reason = mod_pubsub:stanzaError() --spec(get_node/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> mod_pubsub:pubsubNode() - | {error, xmlel()} -). -get_node(Host, NodeId) -> - case catch mnesia:read({pubsub_node, {Host, NodeId}}) of - [Record] when is_record(Record, pubsub_node) -> Record; - [] -> {error, ?ERR_ITEM_NOT_FOUND} -% Error -> Error +get_node(Host, Node) -> + case catch mnesia:read({pubsub_node, {Host, Node}}) of + [Record] when is_record(Record, pubsub_node) -> Record; + _ -> {error, ?ERR_ITEM_NOT_FOUND} end. --spec(get_node/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> mod_pubsub:pubsubNode() - | {error, xmlel()} -). -get_node(NodeIdx) -> - case catch mnesia:index_read(pubsub_node, NodeIdx, #pubsub_node.id) of - [Record] when is_record(Record, pubsub_node) -> Record; - [] -> {error, ?ERR_ITEM_NOT_FOUND} -% Error -> Error +get_node(Nidx) -> + case catch mnesia:index_read(pubsub_node, Nidx, #pubsub_node.id) of + [Record] when is_record(Record, pubsub_node) -> Record; + _ -> {error, ?ERR_ITEM_NOT_FOUND} end. -get_nodes(Host, _From) -> get_nodes(Host). +get_nodes(Host, _From) -> + get_nodes(Host). -%% @spec (Host) -> Nodes | {error, Reason} -%% Host = mod_pubsub:host() -%% Nodes = [mod_pubsub:pubsubNode()] -%% Reason = {aborted, atom()} --spec(get_nodes/1 :: -( - Host::mod_pubsub:host()) - -> [mod_pubsub:pubsubNode()] -). get_nodes(Host) -> mnesia:match_object(#pubsub_node{nodeid = {Host, '_'}, _ = '_'}). -%% @spec (Host, Node, From) -> [] -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% From = mod_pubsub:jid() -%% @doc

    Default node tree does not handle parents, return empty list.

    -get_parentnodes(_Host, _NodeId, _From) -> []. +get_parentnodes(_Host, _Node, _From) -> + []. -%% @spec (Host, NodeId, From) -> [{Depth, Node}] | [] -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% From = mod_pubsub:jid() -%% Depth = integer() -%% Node = mod_pubsub:pubsubNode() %% @doc

    Default node tree does not handle parents, return a list %% containing just this node.

    --spec(get_parentnodes_tree/3 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId(), - From :: jid()) - -> [{0, [mod_pubsub:pubsubNode(),...]}] -). -get_parentnodes_tree(Host, NodeId, From) -> - case get_node(Host, NodeId, From) of - Node when is_record(Node, pubsub_node) -> [{0, [Node]}]; - _Error -> [] +get_parentnodes_tree(Host, Node, _From) -> + case catch mnesia:read({pubsub_node, {Host, Node}}) of + [Record] when is_record(Record, pubsub_node) -> [{0, [Record]}]; + _ -> [] end. -%% @spec (Host, NodeId, From) -> Nodes -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% From = mod_pubsub:jid() -%% Nodes = [mod_pubsub:pubsubNode()] -get_subnodes(Host, NodeId, _From) -> - get_subnodes(Host, NodeId). +get_subnodes(Host, Node, _From) -> + get_subnodes(Host, Node). --spec(get_subnodes/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). get_subnodes(Host, <<>>) -> Q = qlc:q([N - || #pubsub_node{nodeid = {NHost, _}, - parents = Parents} = - N - <- mnesia:table(pubsub_node), - Host == NHost, Parents == []]), + || #pubsub_node{nodeid = {NHost, _}, + parents = Parents} = + N + <- mnesia:table(pubsub_node), + Host == NHost, Parents == []]), qlc:e(Q); get_subnodes(Host, Node) -> Q = qlc:q([N - || #pubsub_node{nodeid = {NHost, _}, - parents = Parents} = - N - <- mnesia:table(pubsub_node), - Host == NHost, lists:member(Node, Parents)]), + || #pubsub_node{nodeid = {NHost, _}, + parents = Parents} = + N + <- mnesia:table(pubsub_node), + Host == NHost, lists:member(Node, Parents)]), qlc:e(Q). get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). -%% @spec (Host, NodeId) -> Nodes -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% Nodes = [] | [mod_pubsub:pubsubNode()] --spec(get_subnodes_tree/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). -get_subnodes_tree(Host, NodeId) -> - case get_node(Host, NodeId) of - {error, _} -> []; - Rec -> - BasePlugin = jlib:binary_to_atom(<<"node_", - (Rec#pubsub_node.type)/binary>>), - BasePath = BasePlugin:node_to_path(NodeId), - mnesia:foldl(fun (#pubsub_node{nodeid = {H, N}} = R, - Acc) -> - Plugin = jlib:binary_to_atom(<<"node_", - (R#pubsub_node.type)/binary>>), - Path = Plugin:node_to_path(N), - case lists:prefix(BasePath, Path) and (H == Host) of - true -> [R | Acc]; - false -> Acc - end - end, - [], pubsub_node) +get_subnodes_tree(Host, Node) -> + case get_node(Host, Node) of + {error, _} -> + []; + Rec -> + BasePlugin = jlib:binary_to_atom(<<"node_", + (Rec#pubsub_node.type)/binary>>), + BasePath = BasePlugin:node_to_path(Node), + mnesia:foldl(fun (#pubsub_node{nodeid = {H, N}} = R, Acc) -> + Plugin = jlib:binary_to_atom(<<"node_", + (R#pubsub_node.type)/binary>>), + Path = Plugin:node_to_path(N), + case lists:prefix(BasePath, Path) and (H == Host) of + true -> [R | Acc]; + false -> Acc + end + end, + [], pubsub_node) end. -%% @spec (Host, NodeId, Type, Owner, Options, Parents) -> -%% {ok, NodeIdx} | {error, Reason} -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% Type = mod_pubsub:nodeType() -%% Owner = mod_pubsub:jid() -%% Options = [mod_pubsub:nodeOption()] -%% Parents = [] | [mod_pubsub:nodeId()] -%% NodeIdx = mod_pubsub:nodeIdx() -%% Reason = mod_pubsub:stanzaError() --spec(create_node/6 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId(), - Type :: binary(), - Owner :: jid(), - Options :: mod_pubsub:nodeOptions(), - Parents :: [mod_pubsub:nodeId()]) - -> {ok, NodeIdx::mod_pubsub:nodeIdx()} - %%% - | {error, xmlel()} -). -create_node(Host, NodeId, Type, Owner, Options, Parents) -> +create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - case catch mnesia:read({pubsub_node, {Host, NodeId}}) of - [] -> - ParentExists = case Host of - {_U, _S, _R} -> - %% This is special case for PEP handling - %% PEP does not uses hierarchy - true; - _ -> - case Parents of - [] -> true; - [Parent | _] -> - case catch mnesia:read({pubsub_node, - {Host, Parent}}) - of - [#pubsub_node{owners = - [{[], Host, []}]}] -> - true; - [#pubsub_node{owners = Owners}] -> - lists:member(BJID, Owners); - _ -> false - end; - _ -> false - end - end, - case ParentExists of - true -> - NodeIdx = pubsub_index:new(node), - mnesia:write(#pubsub_node{nodeid = {Host, NodeId}, - id = NodeIdx, parents = Parents, - type = Type, owners = [BJID], - options = Options}), - {ok, NodeIdx}; - false -> {error, ?ERR_FORBIDDEN} - end; - _ -> {error, ?ERR_CONFLICT} + case catch mnesia:read({pubsub_node, {Host, Node}}) of + [] -> + ParentExists = case Host of + {_U, _S, _R} -> + %% This is special case for PEP handling + %% PEP does not uses hierarchy + true; + _ -> + case Parents of + [] -> + true; + [Parent | _] -> + case catch mnesia:read({pubsub_node, {Host, Parent}}) of + [#pubsub_node{owners = [{[], Host, []}]}] -> + true; + [#pubsub_node{owners = Owners}] -> + lists:member(BJID, Owners); + _ -> + false + end; + _ -> + false + end + end, + case ParentExists of + true -> + Nidx = pubsub_index:new(node), + mnesia:write(#pubsub_node{nodeid = {Host, Node}, + id = Nidx, parents = Parents, + type = Type, owners = [BJID], + options = Options}), + {ok, Nidx}; + false -> + {error, ?ERR_FORBIDDEN} + end; + _ -> + {error, ?ERR_CONFLICT} end. -%% @spec (Host, NodeId) -> Removed -%% Host = mod_pubsub:host() -%% NodeId = mod_pubsub:nodeId() -%% Removed = [mod_pubsub:pubsubNode()] --spec(delete_node/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode(),...] -). -delete_node(Host, NodeId) -> - Removed = get_subnodes_tree(Host, NodeId), - lists:foreach(fun (#pubsub_node{nodeid = {_, SubNodeId}, id = SubNodeIdx}) -> - pubsub_index:free(node, SubNodeIdx), - mnesia:delete({pubsub_node, {Host, SubNodeId}}) - end, - Removed), +delete_node(Host, Node) -> + Removed = get_subnodes_tree(Host, Node), + lists:foreach(fun (#pubsub_node{nodeid = {_, SubNode}, id = SubNidx}) -> + pubsub_index:free(node, SubNidx), + mnesia:delete({pubsub_node, {Host, SubNode}}) + end, + Removed), Removed. diff --git a/src/nodetree_tree_odbc.erl b/src/nodetree_tree_odbc.erl index eb966109b47..38fb51c2afd 100644 --- a/src/nodetree_tree_odbc.erl +++ b/src/nodetree_tree_odbc.erl @@ -36,437 +36,280 @@ %%% improvements.

    -module(nodetree_tree_odbc). - +-behaviour(gen_pubsub_nodetree). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --define(PUBSUB, mod_pubsub_odbc). - --define(PLUGIN_PREFIX, <<"node_">>). --define(ODBC_SUFFIX, <<"_odbc">>). - --behaviour(gen_pubsub_nodetree). - -export([init/3, terminate/2, options/0, set_node/1, - get_node/3, get_node/2, get_node/1, get_nodes/2, - get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, - get_subnodes/3, get_subnodes_tree/3, create_node/6, - delete_node/2]). + get_node/3, get_node/2, get_node/1, get_nodes/2, + get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, + get_subnodes/3, get_subnodes_tree/3, create_node/6, + delete_node/2]). -export([raw_to_node/2]). -%% ================ -%% API definition -%% ================ +init(_Host, _ServerHost, _Opts) -> + ok. -%% @spec (Host, ServerHost, Opts) -> any() -%% Host = mod_pubsub:host() -%% ServerHost = host() -%% Opts = list() -%% @doc

    Called during pubsub modules initialisation. Any pubsub plugin must -%% implement this function. It can return anything.

    -%%

    This function is mainly used to trigger the setup task necessary for the -%% plugin. It can be used for example by the developer to create the specific -%% module database schema if it does not exists yet.

    -%% @spec () -> [Option] -%% Option = mod_pubsub:nodetreeOption() -%% @doc Returns the default pubsub node tree options. -%% @spec (Host, Node, From) -> pubsubNode() | {error, Reason} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -init(_Host, _ServerHost, _Opts) -> ok. +terminate(_Host, _ServerHost) -> + ok. -terminate(_Host, _ServerHost) -> ok. +options() -> + [{odbc, true} | nodetree_tree:options()]. -options() -> [{virtual_tree, false}, {odbc, true}]. +set_node(Record) when is_record(Record, pubsub_node) -> + {Host, Node} = Record#pubsub_node.nodeid, + Parent = case Record#pubsub_node.parents of + [] -> <<>>; + [First | _] -> First + end, + Type = Record#pubsub_node.type, + H = node_hometree_odbc:encode_host(Host), + N = ejabberd_odbc:escape(Node), + P = ejabberd_odbc:escape(Parent), + Nidx = case nodeidx(Host, Node) of + {result, OldNidx} -> + catch + ejabberd_odbc:sql_query_t([<<"delete from pubsub_node_option where " + "nodeid='">>, OldNidx, <<"';">>]), + catch + ejabberd_odbc:sql_query_t([<<"update pubsub_node set host='">>, + H, <<"' node='">>, N, + <<"' parent='">>, P, + <<"' type='">>, Type, + <<"' where nodeid='">>, + OldNidx, <<"';">>]), + OldNidx; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_node(host, node, " + "parent, type) values('">>, + H, <<"', '">>, N, <<"', '">>, P, + <<"', '">>, Type, <<"');">>]), + case nodeidx(Host, Node) of + {result, NewNidx} -> NewNidx; + _ -> none % this should not happen + end + end, + case Nidx of + none -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> + lists:foreach(fun ({Key, Value}) -> + SKey = iolist_to_binary(atom_to_list(Key)), + SValue = ejabberd_odbc:escape( + list_to_binary( + lists:flatten(io_lib:fwrite("~p", [Value])))), + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_node_option(nodeid, " + "name, val) values('">>, + Nidx, <<"', '">>, + SKey, <<"', '">>, SValue, <<"');">>]) + end, + Record#pubsub_node.options), + {result, Nidx} + end. -get_node(Host, Node, _From) -> get_node(Host, Node). +get_node(Host, Node, _From) -> + get_node(Host, Node). --spec(get_node/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> mod_pubsub:pubsubNode() - | {error, _} -). get_node(Host, Node) -> - H = (?PUBSUB):escape(Host), - N = (?PUBSUB):escape(Node), + H = node_hometree_odbc:encode_host(Host), + N = ejabberd_odbc:escape(Node), case catch - ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " - "pubsub_node where host='">>, - H, <<"' and node='">>, N, <<"';">>]) - of - {selected, - [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], - [RItem]} -> - raw_to_node(Host, RItem); - {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"' and node='">>, N, <<"';">>]) + of + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], [RItem]} -> + raw_to_node(Host, RItem); + {'EXIT', _Reason} -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> + {error, ?ERR_ITEM_NOT_FOUND} end. --spec(get_node/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> mod_pubsub:pubsubNode() - | {error, _} -). -get_node(NodeIdx) -> +get_node(Nidx) -> case catch - ejabberd_odbc:sql_query_t([<<"select host, node, parent, type from " - "pubsub_node where nodeid='">>, - NodeIdx, <<"';">>]) - of - {selected, - [<<"host">>, <<"node">>, <<"parent">>, <<"type">>], - [[Host, Node, Parent, Type]]} -> - raw_to_node(Host, [Node, Parent, Type, NodeIdx]); - {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + ejabberd_odbc:sql_query_t([<<"select host, node, parent, type from " + "pubsub_node where nodeid='">>, + Nidx, <<"';">>]) + of + {selected, + [<<"host">>, <<"node">>, <<"parent">>, <<"type">>], [[Host, Node, Parent, Type]]} -> + raw_to_node(Host, [Node, Parent, Type, Nidx]); + {'EXIT', _Reason} -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> + {error, ?ERR_ITEM_NOT_FOUND} end. -%% @spec (Host, From) -> [pubsubNode()] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -get_nodes(Host, _From) -> get_nodes(Host). +get_nodes(Host, _From) -> + get_nodes(Host). --spec(get_nodes/1 :: -( - Host::mod_pubsub:host()) - -> [mod_pubsub:pubsubNode()] -). get_nodes(Host) -> - H = (?PUBSUB):escape(Host), + H = node_hometree_odbc:encode_host(Host), case catch - ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " - "pubsub_node where host='">>, - H, <<"';">>]) - of - {selected, - [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], - RItems} -> - lists:map(fun (Item) -> raw_to_node(Host, Item) end, - RItems); - _ -> [] + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, H, <<"';">>]) + of + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], RItems} -> + [raw_to_node(Host, Item) || Item <- RItems]; + _ -> + [] end. -%% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% Depth = integer() -%% Record = pubsubNode() -%% @doc

    Default node tree does not handle parents, return empty list.

    -%% @spec (Host, Node, From) -> [{Depth, Record}] | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% Depth = integer() -%% Record = pubsubNode() +get_parentnodes(_Host, _Node, _From) -> + []. + %% @doc

    Default node tree does not handle parents, return a list %% containing just this node.

    -get_parentnodes(_Host, _Node, _From) -> []. - --spec(get_parentnodes_tree/3 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId(), - From :: jid()) - -> [{0, [mod_pubsub:pubsubNode(),...]}] -). - get_parentnodes_tree(Host, Node, From) -> case get_node(Host, Node, From) of - N when is_record(N, pubsub_node) -> [{0, [N]}]; - _Error -> [] + {error, _} -> []; + Record -> [{0, [Record]}] end. get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). -%% @spec (Host, Index) -> [pubsubNode()] | {error, Reason} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() --spec(get_subnodes/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). get_subnodes(Host, Node) -> - H = (?PUBSUB):escape(Host), - N = (?PUBSUB):escape(Node), + H = node_hometree_odbc:encode_host(Host), + N = ejabberd_odbc:escape(Node), case catch - ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " - "pubsub_node where host='">>, - H, <<"' and parent='">>, N, <<"';">>]) - of - {selected, - [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], - RItems} -> - lists:map(fun (Item) -> raw_to_node(Host, Item) end, - RItems); - _ -> [] + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"' and parent='">>, N, <<"';">>]) + of + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], RItems} -> + [raw_to_node(Host, Item) || Item <- RItems]; + _ -> + [] end. get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). -%% @spec (Host, Index) -> [pubsubNode()] | {error, Reason} -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() --spec(get_subnodes_tree/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). - get_subnodes_tree(Host, Node) -> - H = (?PUBSUB):escape(Host), - N = (?PUBSUB):escape(Node), + H = node_hometree_odbc:encode_host(Host), + N = ejabberd_odbc:escape(Node), case catch - ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " - "pubsub_node where host='">>, - H, <<"' and node like '">>, N, <<"%';">>]) - of - {selected, - [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], - RItems} -> - lists:map(fun (Item) -> raw_to_node(Host, Item) end, - RItems); - _ -> [] + ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " + "pubsub_node where host='">>, + H, <<"' and node like '">>, N, <<"%';">>]) + of + {selected, + [<<"node">>, <<"parent">>, <<"type">>, <<"nodeid">>], RItems} -> + [raw_to_node(Host, Item) || Item <- RItems]; + _ -> + [] end. -%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok | {error, Reason} -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() -%% NodeType = mod_pubsub:nodeType() -%% Owner = mod_pubsub:jid() -%% Options = list() -%% Parents = list() - --spec(create_node/6 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId(), - Type :: binary(), - Owner :: jid(), - Options :: mod_pubsub:nodeOptions(), - Parents :: [mod_pubsub:nodeId()]) - -> {ok, NodeIdx::mod_pubsub:nodeIdx()} - %%% - | {error, _} -). - create_node(Host, Node, Type, Owner, Options, Parents) -> BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - case nodeid(Host, Node) of - {error, ?ERR_ITEM_NOT_FOUND} -> - ParentExists = case Host of - {_U, _S, _R} -> - %% This is special case for PEP handling - %% PEP does not uses hierarchy - true; - _ -> - case Parents of - [] -> true; - [Parent | _] -> - case nodeid(Host, Parent) of - {result, PNodeId} -> - case nodeowners(PNodeId) of - [{<<>>, Host, <<>>}] -> true; - Owners -> - lists:member(BJID, Owners) - end; - _ -> false - end; - _ -> false - end - end, - case ParentExists of - true -> - case set_node(#pubsub_node{nodeid = {Host, Node}, - parents = Parents, type = Type, - options = Options}) + case nodeidx(Host, Node) of + {error, ?ERR_ITEM_NOT_FOUND} -> + ParentExists = case Host of + {_U, _S, _R} -> + %% This is special case for PEP handling + %% PEP does not uses hierarchy + true; + _ -> + case Parents of + [] -> + true; + [Parent | _] -> + case nodeidx(Host, Parent) of + {result, PNode} -> + case nodeowners(PNode) of + [{<<>>, Host, <<>>}] -> true; + Owners -> lists:member(BJID, Owners) + end; + _ -> + false + end; + _ -> + false + end + end, + case ParentExists of + true -> + case set_node(#pubsub_node{nodeid = {Host, Node}, + parents = Parents, type = Type, + options = Options}) of - {result, NodeId} -> {ok, NodeId}; - Other -> Other - end; - false -> {error, ?ERR_FORBIDDEN} - end; - {result, _} -> {error, ?ERR_CONFLICT}; - Error -> Error + {result, Nidx} -> {ok, Nidx}; + Other -> Other + end; + false -> + {error, ?ERR_FORBIDDEN} + end; + {result, _} -> + {error, ?ERR_CONFLICT}; + Error -> + Error end. -%% @spec (Host, Node) -> [mod_pubsub:node()] -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% Node = mod_pubsub:pubsubNode() --spec(delete_node/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> [mod_pubsub:pubsubNode()] -). - delete_node(Host, Node) -> - H = (?PUBSUB):escape(Host), - N = (?PUBSUB):escape(Node), + H = node_hometree_odbc:encode_host(Host), + N = ejabberd_odbc:escape(Node), Removed = get_subnodes_tree(Host, Node), - catch - ejabberd_odbc:sql_query_t([<<"delete from pubsub_node where host='">>, - H, <<"' and node like '">>, N, <<"%';">>]), + catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_node where host='">>, + H, <<"' and node like '">>, N, <<"%';">>]), Removed. %% helpers --spec(raw_to_node/2 :: -( - Host :: mod_pubsub:host(), - _ :: {NodeId::mod_pubsub:nodeId(), - Parent::mod_pubsub:nodeId(), - Type::binary(), - NodeIdx::mod_pubsub:nodeIdx()}) - -> mod_pubsub:pubsubNode() -). -raw_to_node(Host, [Node, Parent, Type, NodeIdx]) -> +raw_to_node(Host, [Node, Parent, Type, Nidx]) -> Options = case catch - ejabberd_odbc:sql_query_t([<<"select name,val from pubsub_node_option " - "where nodeid='">>, - NodeIdx, <<"';">>]) - of - {selected, [<<"name">>, <<"val">>], ROptions} -> - DbOpts = lists:map(fun ([Key, Value]) -> - RKey = - jlib:binary_to_atom(Key), - Tokens = element(2, - erl_scan:string( - binary_to_list(<>))), - RValue = element(2, - erl_parse:parse_term(Tokens)), - {RKey, RValue} - end, - ROptions), - Module = - jlib:binary_to_atom(<<(?PLUGIN_PREFIX)/binary, - Type/binary, - (?ODBC_SUFFIX)/binary>>), - StdOpts = Module:options(), - lists:foldl(fun ({Key, Value}, Acc) -> - lists:keyreplace(Key, 1, Acc, - {Key, Value}) - end, - StdOpts, DbOpts); - _ -> [] - end, + ejabberd_odbc:sql_query_t([<<"select name,val from pubsub_node_option " + "where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"name">>, <<"val">>], ROptions} -> + DbOpts = lists:map(fun ([Key, Value]) -> + RKey = jlib:binary_to_atom(Key), + Tokens = element(2, erl_scan:string(binary_to_list(<>))), + RValue = element(2, erl_parse:parse_term(Tokens)), + {RKey, RValue} + end, + ROptions), + Module = jlib:binary_to_atom(<<"node_", Type/binary, "_odbc">>), + StdOpts = Module:options(), + lists:foldl(fun ({Key, Value}, Acc) -> + lists:keyreplace(Key, 1, Acc, {Key, Value}) + end, + StdOpts, DbOpts); + _ -> + [] + end, Parents = case Parent of - <<>> -> []; - _ -> [Parent] - end, - #pubsub_node{nodeid = - {Host, Node}, - parents = Parents, - id = NodeIdx, type = Type, options = Options}. - -% @spec (NodeRecord) -> ok | {error, Reason} -%% Record = mod_pubsub:pubsub_node() --spec(set_node/1 :: -( - Record::mod_pubsub:pubsubNode()) - -> {result, NodeIdx::mod_pubsub:nodeIdx()} - %%% - | {error, _} -). -set_node(Record) -> - {Host, Node} = Record#pubsub_node.nodeid, - Parent = case Record#pubsub_node.parents of - [] -> <<>>; - [First | _] -> First - end, - Type = Record#pubsub_node.type, - H = (?PUBSUB):escape(Host), - N = (?PUBSUB):escape(Node), - P = (?PUBSUB):escape(Parent), - NodeIdx = case nodeid(Host, Node) of - {result, OldNodeIdx} -> - catch - ejabberd_odbc:sql_query_t([<<"delete from pubsub_node_option where " - "nodeid='">>, - OldNodeIdx, <<"';">>]), - catch - ejabberd_odbc:sql_query_t([<<"update pubsub_node set host='">>, - H, <<"' node='">>, N, - <<"' parent='">>, P, - <<"' type='">>, Type, - <<"' where nodeid='">>, - OldNodeIdx, <<"';">>]), - OldNodeIdx; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_node(host, node, " - "parent, type) values('">>, - H, <<"', '">>, N, <<"', '">>, P, - <<"', '">>, Type, <<"');">>]), - case nodeid(Host, Node) of - {result, NewNodeIdx} -> NewNodeIdx; - _ -> none % this should not happen - end - end, - case NodeIdx of - none -> {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> - lists:foreach(fun ({Key, Value}) -> - SKey = iolist_to_binary(atom_to_list(Key)), - SValue = - (?PUBSUB):escape(list_to_binary(lists:flatten(io_lib:fwrite("~p", - [Value])))), - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_node_option(nodeid, " - "name, val) values('">>, - NodeIdx, <<"', '">>, - SKey, <<"', '">>, - SValue, <<"');">>]) - end, - Record#pubsub_node.options), - {result, NodeIdx} - end. - --spec(nodeid/2 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId()) - -> {result, NodeIdx::mod_pubsub:nodeIdx()} - %%% - | {error, _} -). - -nodeid(Host, NodeId) -> - H = (?PUBSUB):escape(Host), - N = (?PUBSUB):escape(NodeId), + <<>> -> []; + _ -> [Parent] + end, + #pubsub_node{nodeid = {Host, Node}, + parents = Parents, + id = Nidx, type = Type, options = Options}. + +nodeidx(Host, Node) -> + H = node_hometree_odbc:encode_host(Host), + N = ejabberd_odbc:escape(Node), case catch - ejabberd_odbc:sql_query_t([<<"select nodeid from pubsub_node where " - "host='">>, - H, <<"' and node='">>, N, <<"';">>]) - of - {selected, [<<"nodeid">>], [[NodeIdx]]} -> - {result, NodeIdx}; - {'EXIT', _Reason} -> - {error, ?ERR_INTERNAL_SERVER_ERROR}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} + ejabberd_odbc:sql_query_t([<<"select nodeid from pubsub_node where " + "host='">>, + H, <<"' and node='">>, N, <<"';">>]) + of + {selected, [<<"nodeid">>], [[Nidx]]} -> + {result, Nidx}; + {'EXIT', _Reason} -> + {error, ?ERR_INTERNAL_SERVER_ERROR}; + _ -> + {error, ?ERR_ITEM_NOT_FOUND} end. --spec(nodeowners/1 :: -( - NodeIdx::mod_pubsub:nodeIdx()) - -> Node_Owners::[ljid()] -). - -nodeowners(NodeIdx) -> - {result, Res} = node_hometree_odbc:get_node_affiliations(NodeIdx), - lists:foldl(fun ({LJID, owner}, Acc) -> [LJID | Acc]; - (_, Acc) -> Acc - end, - [], Res). +nodeowners(Nidx) -> + {result, Res} = node_hometree_odbc:get_node_affiliations(Nidx), + [LJID || {LJID, Aff} <- Res, Aff =:= owner]. diff --git a/src/nodetree_virtual.erl b/src/nodetree_virtual.erl index abe88560fca..d56be860fc1 100644 --- a/src/nodetree_virtual.erl +++ b/src/nodetree_virtual.erl @@ -26,143 +26,84 @@ %%% ==================================================================== %%% @doc The module {@module} is the PubSub node tree plugin that -%%% allow virtual nodes handling. +%%% allow virtual nodes handling. This prevent storage of nodes. %%%

    PubSub node tree plugins are using the {@link gen_nodetree} behaviour.

    %%%

    This plugin development is still a work in progress. Due to optimizations in %%% mod_pubsub, this plugin can not work anymore without altering functioning. %%% Please, send us comments, feedback and improvements.

    -module(nodetree_virtual). - +-behaviour(gen_pubsub_nodetree). -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). - -include("jlib.hrl"). --behaviour(gen_pubsub_nodetree). - -export([init/3, terminate/2, options/0, set_node/1, - get_node/3, get_node/2, get_node/1, get_nodes/2, - get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, - get_subnodes/3, get_subnodes_tree/3, create_node/6, - delete_node/2]). - -%% ================ -%% API definition -%% ================ - -%% @spec (Host, ServerHost, Opts) -> any() -%% Host = mod_pubsub:host() -%% ServerHost = host() -%% Opts = list() -%% @doc

    Called during pubsub modules initialisation. Any pubsub plugin must -%% implement this function. It can return anything.

    -%%

    This function is mainly used to trigger the setup task necessary for the -%% plugin. It can be used for example by the developer to create the specific -%% module database schema if it does not exists yet.

    -%% @spec () -> [Option] -%% Option = mod_pubsub:nodetreeOption() -%% @doc

    Returns the default pubsub node tree options.

    -%% @spec (NodeRecord) -> ok | {error, Reason} -%% NodeRecord = mod_pubsub:pubsub_node() -%% @doc

    No node record is stored on database. Just do nothing.

    -%% @spec (Host, Node, From) -> pubsubNode() -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% @doc

    Virtual node tree does not handle a node database. Any node is considered -%% as existing. Node record contains default values.

    -init(_Host, _ServerHost, _Opts) -> ok. - -terminate(_Host, _ServerHost) -> ok. - -options() -> [{virtual_tree, true}]. - -set_node(_NodeRecord) -> ok. - -get_node(Host, Node, _From) -> get_node(Host, Node). - -get_node(Host, Node) -> get_node({Host, Node}). - -get_node({Host, _} = NodeId) -> - Record = #pubsub_node{nodeid = NodeId, id = NodeId}, - Module = jlib:binary_to_atom(<<"node_", - (Record#pubsub_node.type)/binary>>), - Options = Module:options(), - Owners = [{<<"">>, Host, <<"">>}], - Record#pubsub_node{owners = Owners, options = Options}. - -%% @spec (Host, From) -> [pubsubNode()] -%% Host = mod_pubsub:host() | mod_pubsub:jid() -%% From = mod_pubsub:jid() -%% @doc

    Virtual node tree does not handle a node database. Any node is considered -%% as existing. Nodes list can not be determined.

    -%% @spec (Host, Node, From) -> [pubsubNode()] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% @doc

    Virtual node tree does not handle parent/child. Child list is empty.

    -%% @spec (Host, Node, From) -> [pubsubNode()] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% @doc

    Virtual node tree does not handle parent/child. Child list is empty.

    -%% @spec (Host, Node, From) -> [pubsubNode()] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% @doc

    Virtual node tree does not handle parent/child. Child list is empty.

    -get_nodes(Host, _From) -> get_nodes(Host). - -get_nodes(_Host) -> []. - -get_parentnodes(_Host, _Node, _From) -> []. - --spec(get_parentnodes_tree/3 :: -( - Host :: mod_pubsub:host(), - NodeId :: mod_pubsub:nodeId(), - From :: jid()) - -> [{0, [mod_pubsub:pubsubNode(),...]}] -). -get_parentnodes_tree(Host, NodeId, From) -> - case get_node(Host, NodeId, From) of - Node when is_record(Node, pubsub_node) -> [{0, [Node]}]; - _Error -> [] + get_node/3, get_node/2, get_node/1, get_nodes/2, + get_nodes/1, get_parentnodes/3, get_parentnodes_tree/3, + get_subnodes/3, get_subnodes_tree/3, create_node/6, + delete_node/2]). + +init(_Host, _ServerHost, _Opts) -> + ok. + +terminate(_Host, _ServerHost) -> + ok. + +options() -> + [{virtual_tree, true}]. + +set_node(_Node) -> + ok. + +get_node(Host, Node, _From) -> + get_node(Host, Node). + +get_node(Host, Node) -> + get_node(nodeidx(Host, Node)). + +get_node(Nidx) -> + {Host, Node} = nodeid(Nidx), + Record = #pubsub_node{nodeid = Node, id = Nidx}, + Module = jlib:binary_to_atom(<<"node_", (Record#pubsub_node.type)/binary>>), + Record#pubsub_node{owners = [{<<"">>, Host, <<"">>}], + options = Module:options()}. + +get_nodes(Host, _From) -> + get_nodes(Host). + +get_nodes(_Host) -> + []. + +get_parentnodes(_Host, _Node, _From) -> + []. + +get_parentnodes_tree(Host, Node, From) -> + case get_node(Host, Node, From) of + Node when is_record(Node, pubsub_node) -> [{0, [Node]}]; + _Error -> [] end. get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). -%% @spec (Host, Node, From) -> [pubsubNode()] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% From = mod_pubsub:jid() -%% @doc

    Virtual node tree does not handle parent/child. Child list is empty.

    -get_subnodes(_Host, _Node) -> []. +get_subnodes(_Host, _Node) -> + []. get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). -%% @spec (Host, Node, Type, Owner, Options, Parents) -> ok -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% Type = mod_pubsub:nodeType() -%% Owner = mod_pubsub:jid() -%% Options = list() -%% @doc

    No node record is stored on database. Any valid node -%% is considered as already created.

    -%%

    default allowed nodes: /home/host/user/any/node/name

    -%% @spec (Host, Node) -> [mod_pubsub:node()] -%% Host = mod_pubsub:host() -%% Node = mod_pubsub:pubsubNode() -%% @doc

    Virtual node tree does not handle parent/child. -%% node deletion just affects the corresponding node.

    - -get_subnodes_tree(_Host, _Node) -> []. - -create_node(Host, Node, _Type, _Owner, _Options, - _Parents) -> + +get_subnodes_tree(_Host, _Node) -> + []. + +create_node(Host, Node, _Type, _Owner, _Options, _Parents) -> {error, {virtual, {Host, Node}}}. -delete_node(Host, Node) -> [get_node(Host, Node)]. +delete_node(Host, Node) -> + [get_node(Host, Node)]. + +%% internal helper + +nodeidx(Host, Node) -> term_to_binary({Host, Node}). +nodeid(Nidx) -> binary_to_term(Nidx). diff --git a/src/pubsub_db_odbc.erl b/src/pubsub_db_odbc.erl index f22ee196830..56a500ebbfc 100644 --- a/src/pubsub_db_odbc.erl +++ b/src/pubsub_db_odbc.erl @@ -26,89 +26,77 @@ -include("pubsub.hrl"). -export([add_subscription/1, read_subscription/1, - delete_subscription/1, update_subscription/1]). + delete_subscription/1, update_subscription/1]). %% TODO: Those -spec lines produce errors in old Erlang versions. %% They can be enabled again in ejabberd 3.0 because it uses R12B or higher. %% -spec read_subscription(SubID :: string()) -> {ok, #pubsub_subscription{}} | notfound. read_subscription(SubID) -> case - ejabberd_odbc:sql_query_t([<<"select opt_name, opt_value from pubsub_subscr" - "iption_opt where subid = '">>, - ejabberd_odbc:escape(SubID), <<"'">>]) - of - {selected, [<<"opt_name">>, <<"opt_value">>], []} -> - notfound; - {selected, [<<"opt_name">>, <<"opt_value">>], - Options} -> - {ok, - #pubsub_subscription{subid = SubID, - options = - lists:map(fun subscription_opt_from_odbc/1, - Options)}} + ejabberd_odbc:sql_query_t([<<"select opt_name, opt_value from pubsub_subscr" + "iption_opt where subid = '">>, + ejabberd_odbc:escape(SubID), <<"'">>]) + of + {selected, [<<"opt_name">>, <<"opt_value">>], []} -> + notfound; + {selected, [<<"opt_name">>, <<"opt_value">>], Options} -> + {ok, + #pubsub_subscription{subid = SubID, + options = lists:map(fun subscription_opt_from_odbc/1, Options)}} end. %% -spec delete_subscription(SubID :: string()) -> ok. delete_subscription(SubID) -> -%% -spec update_subscription(#pubsub_subscription{}) -> ok . -%% -spec add_subscription(#pubsub_subscription{}) -> ok. -%% -------------- Internal utilities ----------------------- + %% -spec update_subscription(#pubsub_subscription{}) -> ok . + %% -spec add_subscription(#pubsub_subscription{}) -> ok. + %% -------------- Internal utilities ----------------------- ejabberd_odbc:sql_query_t([<<"delete from pubsub_subscription_opt " - "where subid = '">>, - ejabberd_odbc:escape(SubID), <<"'">>]), + "where subid = '">>, + ejabberd_odbc:escape(SubID), <<"'">>]), ok. -update_subscription(#pubsub_subscription{subid = - SubId} = - Sub) -> +update_subscription(#pubsub_subscription{subid = SubId} = Sub) -> delete_subscription(SubId), add_subscription(Sub). -add_subscription(#pubsub_subscription{subid = SubId, - options = Opts}) -> +add_subscription(#pubsub_subscription{subid = SubId, options = Opts}) -> EscapedSubId = ejabberd_odbc:escape(SubId), lists:foreach(fun (Opt) -> - {OdbcOptName, OdbcOptValue} = - subscription_opt_to_odbc(Opt), - ejabberd_odbc:sql_query_t([<<"insert into pubsub_subscription_opt(subid, " - "opt_name, opt_value)values ('">>, - EscapedSubId, <<"','">>, - OdbcOptName, <<"','">>, - OdbcOptValue, <<"')">>]) - end, - Opts), + {OdbcOptName, OdbcOptValue} = subscription_opt_to_odbc(Opt), + ejabberd_odbc:sql_query_t([<<"insert into pubsub_subscription_opt(subid, " + "opt_name, opt_value)values ('">>, + EscapedSubId, <<"','">>, + OdbcOptName, <<"','">>, + OdbcOptValue, <<"')">>]) + end, + Opts), ok. subscription_opt_from_odbc({<<"DELIVER">>, Value}) -> {deliver, odbc_to_boolean(Value)}; subscription_opt_from_odbc({<<"DIGEST">>, Value}) -> {digest, odbc_to_boolean(Value)}; -subscription_opt_from_odbc({<<"DIGEST_FREQUENCY">>, - Value}) -> +subscription_opt_from_odbc({<<"DIGEST_FREQUENCY">>, Value}) -> {digest_frequency, odbc_to_integer(Value)}; subscription_opt_from_odbc({<<"EXPIRE">>, Value}) -> {expire, odbc_to_timestamp(Value)}; -subscription_opt_from_odbc({<<"INCLUDE_BODY">>, - Value}) -> +subscription_opt_from_odbc({<<"INCLUDE_BODY">>, Value}) -> {include_body, odbc_to_boolean(Value)}; %%TODO: might be > than 1 show_values value??. %% need to use compact all in only 1 opt. -subscription_opt_from_odbc({<<"SHOW_VALUES">>, - Value}) -> +subscription_opt_from_odbc({<<"SHOW_VALUES">>, Value}) -> {show_values, Value}; -subscription_opt_from_odbc({<<"SUBSCRIPTION_TYPE">>, - Value}) -> +subscription_opt_from_odbc({<<"SUBSCRIPTION_TYPE">>, Value}) -> {subscription_type, - case Value of - <<"items">> -> items; - <<"nodes">> -> nodes - end}; -subscription_opt_from_odbc({<<"SUBSCRIPTION_DEPTH">>, - Value}) -> + case Value of + <<"items">> -> items; + <<"nodes">> -> nodes + end}; +subscription_opt_from_odbc({<<"SUBSCRIPTION_DEPTH">>, Value}) -> {subscription_depth, - case Value of - <<"all">> -> all; - N -> odbc_to_integer(N) - end}. + case Value of + <<"all">> -> all; + N -> odbc_to_integer(N) + end}. subscription_opt_to_odbc({deliver, Bool}) -> {<<"DELIVER">>, boolean_to_odbc(Bool)}; @@ -124,19 +112,18 @@ subscription_opt_to_odbc({show_values, Values}) -> {<<"SHOW_VALUES">>, Values}; subscription_opt_to_odbc({subscription_type, Type}) -> {<<"SUBSCRIPTION_TYPE">>, - case Type of - items -> <<"items">>; - nodes -> <<"nodes">> - end}; + case Type of + items -> <<"items">>; + nodes -> <<"nodes">> + end}; subscription_opt_to_odbc({subscription_depth, Depth}) -> {<<"SUBSCRIPTION_DEPTH">>, - case Depth of - all -> <<"all">>; - N -> integer_to_odbc(N) - end}. + case Depth of + all -> <<"all">>; + N -> integer_to_odbc(N) + end}. -integer_to_odbc(N) -> - iolist_to_binary(integer_to_list(N)). +integer_to_odbc(N) -> iolist_to_binary(integer_to_list(N)). boolean_to_odbc(true) -> <<"1">>; boolean_to_odbc(false) -> <<"0">>. @@ -147,5 +134,4 @@ odbc_to_integer(N) -> jlib:binary_to_integer(N). odbc_to_boolean(B) -> B == <<"1">>. -odbc_to_timestamp(T) -> - jlib:datetime_string_to_timestamp(T). +odbc_to_timestamp(T) -> jlib:datetime_string_to_timestamp(T). diff --git a/src/pubsub_index.erl b/src/pubsub_index.erl index 94efa0e963c..c9ec94a6252 100644 --- a/src/pubsub_index.erl +++ b/src/pubsub_index.erl @@ -29,7 +29,6 @@ %% new/1 and free/2 MUST be called inside a transaction bloc -module(pubsub_index). - -author('christophe.romain@process-one.net'). -include("pubsub.hrl"). @@ -38,30 +37,30 @@ init(_Host, _ServerHost, _Opts) -> mnesia:create_table(pubsub_index, - [{disc_copies, [node()]}, - {attributes, record_info(fields, pubsub_index)}]). + [{disc_copies, [node()]}, + {attributes, record_info(fields, pubsub_index)}]). new(Index) -> case mnesia:read({pubsub_index, Index}) of - [I] -> - case I#pubsub_index.free of - [] -> - Id = I#pubsub_index.last + 1, - mnesia:write(I#pubsub_index{last = Id}), - Id; - [Id | Free] -> - mnesia:write(I#pubsub_index{free = Free}), Id - end; - _ -> - mnesia:write(#pubsub_index{index = Index, last = 1, - free = []}), - 1 + [I] -> + case I#pubsub_index.free of + [] -> + Id = I#pubsub_index.last + 1, + mnesia:write(I#pubsub_index{last = Id}), + Id; + [Id | Free] -> + mnesia:write(I#pubsub_index{free = Free}), Id + end; + _ -> + mnesia:write(#pubsub_index{index = Index, last = 1, free = []}), + 1 end. free(Index, Id) -> case mnesia:read({pubsub_index, Index}) of - [I] -> - Free = I#pubsub_index.free, - mnesia:write(I#pubsub_index{free = [Id | Free]}); - _ -> ok + [I] -> + Free = I#pubsub_index.free, + mnesia:write(I#pubsub_index{free = [Id | Free]}); + _ -> + ok end. diff --git a/src/pubsub_migrate.erl b/src/pubsub_migrate.erl new file mode 100644 index 00000000000..e48efcd494d --- /dev/null +++ b/src/pubsub_migrate.erl @@ -0,0 +1,422 @@ +%%%---------------------------------------------------------------------- +%%% File : pubsub_migrate.erl +%%% Author : Christophe Romain +%%% Purpose : Migration/Upgrade code put out of mod_pubsub +%%% Created : 26 Jul 2014 by Christophe Romain +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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(pubsub_migrate). + +-include("pubsub.hrl"). +-include("logger.hrl"). + +-export([update_node_database/2, update_state_database/2, update_lastitem_database/2]). + +update_item_database_binary() -> + F = fun () -> + case catch mnesia:read({pubsub_last_item, mnesia:first(pubsub_last_item)}) of + [First] when is_list(First#pubsub_last_item.itemid) -> + ?INFO_MSG("Binarization of pubsub items table...", []), + lists:foreach(fun (Id) -> + [Node] = mnesia:read({pubsub_last_item, Id}), + + ItemId = iolist_to_binary(Node#pubsub_last_item.itemid), + + ok = mnesia:delete({pubsub_last_item, Id}), + ok = mnesia:write(Node#pubsub_last_item{itemid=ItemId}) + end, + mnesia:all_keys(pubsub_last_item)); + _-> no_need + end + end, + case mnesia:transaction(F) of + {aborted, Reason} -> + ?ERROR_MSG("Failed to binarize pubsub items table: ~p", [Reason]); + {atomic, no_need} -> + ok; + {atomic, Result} -> + ?INFO_MSG("Pubsub items table has been binarized: ~p", [Result]) + end. + + +update_node_database_binary() -> + F = fun () -> + case catch mnesia:read({pubsub_node, mnesia:first(pubsub_node)}) of + [First] when is_list(First#pubsub_node.type) -> + ?INFO_MSG("Binarization of pubsub nodes table...", []), + lists:foreach(fun ({H, N}) -> + [Node] = mnesia:read({pubsub_node, {H, N}}), + + Type = iolist_to_binary(Node#pubsub_node.type), + BN = case N of + Binary when is_binary(Binary) -> + N; + _ -> + {result, BN1} = mod_pubsub:node_call(H, Type, path_to_node, [N]), + BN1 + end, + BP = case [case P of + Binary2 when is_binary(Binary2) -> P; + _ -> element(2, mod_pubsub:node_call(H, Type, path_to_node, [P])) + end + || P <- Node#pubsub_node.parents] of + [<<>>] -> []; + Parents -> Parents + end, + + BH = case H of + {U, S, R} -> {iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)}; + String -> iolist_to_binary(String) + end, + + Owners = [{iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)} || + {U, S, R} <- Node#pubsub_node.owners], + + ok = mnesia:delete({pubsub_node, {H, N}}), + ok = mnesia:write(Node#pubsub_node{nodeid = {BH, BN}, + parents = BP, + type = Type, + owners = Owners}); + (_) -> ok + end, + mnesia:all_keys(pubsub_node)); + _-> no_need + end + end, + case mnesia:transaction(F) of + {aborted, Reason} -> + ?ERROR_MSG("Failed to binarize pubsub node table: ~p", [Reason]); + {atomic, no_need} -> + ok; + {atomic, Result} -> + ?INFO_MSG("Pubsub nodes table has been binarized: ~p", [Result]) + end. + +update_node_database(Host, ServerHost) -> + mnesia:del_table_index(pubsub_node, type), + mnesia:del_table_index(pubsub_node, parentid), + case catch mnesia:table_info(pubsub_node, attributes) of + [host_node, host_parent, info] -> + ?INFO_MSG("Upgrading pubsub nodes table...", []), + F = fun () -> + {Result, LastIdx} = lists:foldl(fun ({pubsub_node, + NodeId, ParentId, + {nodeinfo, Items, + Options, + Entities}}, + {RecList, + NodeIdx}) -> + ItemsList = + lists:foldl(fun + ({item, + IID, + Publisher, + Payload}, + Acc) -> + C = + {unknown, + Publisher}, + M = + {now(), + Publisher}, + mnesia:write(#pubsub_item{itemid + = + {IID, + NodeIdx}, + creation + = + C, + modification + = + M, + payload + = + Payload}), + [{Publisher, + IID} + | Acc] + end, + [], + Items), + Owners = + dict:fold(fun + (JID, + {entity, + Aff, + Sub}, + Acc) -> + UsrItems = + lists:foldl(fun + ({P, + I}, + IAcc) -> + case + P + of + JID -> + [I + | IAcc]; + _ -> + IAcc + end + end, + [], + ItemsList), + mnesia:write({pubsub_state, + {JID, + NodeIdx}, + UsrItems, + Aff, + Sub}), + case + Aff + of + owner -> + [JID + | Acc]; + _ -> + Acc + end + end, + [], + Entities), + mnesia:delete({pubsub_node, + NodeId}), + {[#pubsub_node{nodeid + = + NodeId, + id + = + NodeIdx, + parents + = + [element(2, + ParentId)], + owners + = + Owners, + options + = + Options} + | RecList], + NodeIdx + 1} + end, + {[], 1}, + mnesia:match_object({pubsub_node, + {Host, + '_'}, + '_', + '_'})), + mnesia:write(#pubsub_index{index = node, last = LastIdx, + free = []}), + Result + end, + {atomic, NewRecords} = mnesia:transaction(F), + {atomic, ok} = mnesia:delete_table(pubsub_node), + {atomic, ok} = mnesia:create_table(pubsub_node, + [{disc_copies, [node()]}, + {attributes, + record_info(fields, + pubsub_node)}]), + FNew = fun () -> + lists:foreach(fun (Record) -> mnesia:write(Record) end, + NewRecords) + end, + case mnesia:transaction(FNew) of + {atomic, Result} -> + ?INFO_MSG("Pubsub nodes table upgraded: ~p", + [Result]); + {aborted, Reason} -> + ?ERROR_MSG("Problem upgrading Pubsub nodes table:~n~p", + [Reason]) + end; + [nodeid, parentid, type, owners, options] -> + F = fun ({pubsub_node, NodeId, {_, Parent}, Type, + Owners, Options}) -> + #pubsub_node{nodeid = NodeId, id = 0, + parents = [Parent], type = Type, + owners = Owners, options = Options} + end, + mnesia:transform_table(pubsub_node, F, + [nodeid, id, parents, type, owners, options]), + FNew = fun () -> + LastIdx = lists:foldl(fun (#pubsub_node{nodeid = + NodeId} = + PubsubNode, + NodeIdx) -> + mnesia:write(PubsubNode#pubsub_node{id + = + NodeIdx}), + lists:foreach(fun + (#pubsub_state{stateid + = + StateId} = + State) -> + {JID, + _} = + StateId, + mnesia:delete({pubsub_state, + StateId}), + mnesia:write(State#pubsub_state{stateid + = + {JID, + NodeIdx}}) + end, + mnesia:match_object(#pubsub_state{stateid + = + {'_', + NodeId}, + _ + = + '_'})), + lists:foreach(fun + (#pubsub_item{itemid + = + ItemId} = + Item) -> + {IID, + _} = + ItemId, + {M1, + M2} = + Item#pubsub_item.modification, + {C1, + C2} = + Item#pubsub_item.creation, + mnesia:delete({pubsub_item, + ItemId}), + mnesia:write(Item#pubsub_item{itemid + = + {IID, + NodeIdx}, + modification + = + {M2, + M1}, + creation + = + {C2, + C1}}) + end, + mnesia:match_object(#pubsub_item{itemid + = + {'_', + NodeId}, + _ + = + '_'})), + NodeIdx + 1 + end, + 1, + mnesia:match_object({pubsub_node, + {Host, '_'}, + '_', '_', + '_', '_', + '_'}) + ++ + mnesia:match_object({pubsub_node, + {{'_', + ServerHost, + '_'}, + '_'}, + '_', '_', + '_', '_', + '_'})), + mnesia:write(#pubsub_index{index = node, + last = LastIdx, free = []}) + end, + case mnesia:transaction(FNew) of + {atomic, Result} -> + rename_default_nodeplugin(), + ?INFO_MSG("Pubsub nodes table upgraded: ~p", + [Result]); + {aborted, Reason} -> + ?ERROR_MSG("Problem upgrading Pubsub nodes table:~n~p", + [Reason]) + end; + [nodeid, id, parent, type, owners, options] -> + F = fun ({pubsub_node, NodeId, Id, Parent, Type, Owners, + Options}) -> + #pubsub_node{nodeid = NodeId, id = Id, + parents = [Parent], type = Type, + owners = Owners, options = Options} + end, + mnesia:transform_table(pubsub_node, F, + [nodeid, id, parents, type, owners, options]), + rename_default_nodeplugin(); + _ -> ok + end, + update_node_database_binary(). + +rename_default_nodeplugin() -> + lists:foreach(fun (Node) -> + mnesia:dirty_write(Node#pubsub_node{type = + <<"hometree">>}) + end, + mnesia:dirty_match_object(#pubsub_node{type = + <<"default">>, + _ = '_'})). + +update_state_database(_Host, _ServerHost) -> + case catch mnesia:table_info(pubsub_state, attributes) of + [stateid, nodeidx, items, affiliation, subscriptions] -> + ?INFO_MSG("Upgrading pubsub states table...", []), + F = fun ({pubsub_state, {{U,S,R}, NodeID}, _NodeIdx, Items, Aff, Sub}, Acc) -> + JID = {iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(R)}, + Subs = case Sub of + none -> + []; + [] -> + []; + _ -> + {result, SubID} = pubsub_subscription:subscribe_node(JID, NodeID, []), + [{Sub, SubID}] + end, + NewState = #pubsub_state{stateid = {JID, NodeID}, + items = Items, + affiliation = Aff, + subscriptions = Subs}, + [NewState | Acc] + end, + {atomic, NewRecs} = mnesia:transaction(fun mnesia:foldl/3, + [F, [], pubsub_state]), + {atomic, ok} = mnesia:delete_table(pubsub_state), + {atomic, ok} = mnesia:create_table(pubsub_state, + [{disc_copies, [node()]}, + {attributes, record_info(fields, pubsub_state)}]), + FNew = fun () -> + lists:foreach(fun mnesia:write/1, NewRecs) + end, + case mnesia:transaction(FNew) of + {atomic, Result} -> + ?INFO_MSG("Pubsub states table upgraded: ~p", + [Result]); + {aborted, Reason} -> + ?ERROR_MSG("Problem upgrading Pubsub states table:~n~p", + [Reason]) + end; + _ -> + ok + end. + +update_lastitem_database(_Host, _ServerHost) -> + update_item_database_binary(). diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index 1e3f18e7bc6..df1560005c7 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -26,169 +26,111 @@ %% API -export([init/0, subscribe_node/3, unsubscribe_node/3, - get_subscription/3, set_subscription/4, - get_options_xform/2, parse_options_xform/1]). + get_subscription/3, set_subscription/4, + get_options_xform/2, parse_options_xform/1]). % Internal function also exported for use in transactional bloc from pubsub plugins -export([add_subscription/3, delete_subscription/3, - read_subscription/3, write_subscription/4]). + read_subscription/3, write_subscription/4]). -include("pubsub.hrl"). -include("jlib.hrl"). -define(PUBSUB_DELIVER, <<"pubsub#deliver">>). - -define(PUBSUB_DIGEST, <<"pubsub#digest">>). - --define(PUBSUB_DIGEST_FREQUENCY, - <<"pubsub#digest_frequency">>). - +-define(PUBSUB_DIGEST_FREQUENCY, <<"pubsub#digest_frequency">>). -define(PUBSUB_EXPIRE, <<"pubsub#expire">>). - -define(PUBSUB_INCLUDE_BODY, <<"pubsub#include_body">>). - -define(PUBSUB_SHOW_VALUES, <<"pubsub#show-values">>). - --define(PUBSUB_SUBSCRIPTION_TYPE, - <<"pubsub#subscription_type">>). - --define(PUBSUB_SUBSCRIPTION_DEPTH, - <<"pubsub#subscription_depth">>). - --define(DELIVER_LABEL, - <<"Whether an entity wants to receive or " - "disable notifications">>). - --define(DIGEST_LABEL, - <<"Whether an entity wants to receive digests " - "(aggregations) of notifications or all " - "notifications individually">>). - --define(DIGEST_FREQUENCY_LABEL, - <<"The minimum number of milliseconds between " - "sending any two notification digests">>). - --define(EXPIRE_LABEL, - <<"The DateTime at which a leased subscription " - "will end or has ended">>). - --define(INCLUDE_BODY_LABEL, - <<"Whether an entity wants to receive an " - "XMPP message body in addition to the " - "payload format">>). - --define(SHOW_VALUES_LABEL, - <<"The presence states for which an entity " - "wants to receive notifications">>). - --define(SUBSCRIPTION_TYPE_LABEL, - <<"Type of notification to receive">>). - --define(SUBSCRIPTION_DEPTH_LABEL, - <<"Depth from subscription for which to " - "receive notifications">>). - --define(SHOW_VALUE_AWAY_LABEL, - <<"XMPP Show Value of Away">>). - --define(SHOW_VALUE_CHAT_LABEL, - <<"XMPP Show Value of Chat">>). - --define(SHOW_VALUE_DND_LABEL, - <<"XMPP Show Value of DND (Do Not Disturb)">>). - --define(SHOW_VALUE_ONLINE_LABEL, - <<"Mere Availability in XMPP (No Show Value)">>). - --define(SHOW_VALUE_XA_LABEL, - <<"XMPP Show Value of XA (Extended Away)">>). - --define(SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL, - <<"Receive notification of new items only">>). - --define(SUBSCRIPTION_TYPE_VALUE_NODES_LABEL, - <<"Receive notification of new nodes only">>). - --define(SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL, - <<"Receive notification from direct child " - "nodes only">>). - --define(SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL, - <<"Receive notification from all descendent " - "nodes">>). +-define(PUBSUB_SUBSCRIPTION_TYPE, <<"pubsub#subscription_type">>). +-define(PUBSUB_SUBSCRIPTION_DEPTH, <<"pubsub#subscription_depth">>). +-define(DELIVER_LABEL, <<"Whether an entity wants to receive or disable notifications">>). +-define(DIGEST_LABEL, <<"Whether an entity wants to receive digests " + "(aggregations) of notifications or all notifications individually">>). +-define(DIGEST_FREQUENCY_LABEL, <<"The minimum number of milliseconds between " + "sending any two notification digests">>). +-define(EXPIRE_LABEL, <<"The DateTime at which a leased subscription will end or has ended">>). +-define(INCLUDE_BODY_LABEL, <<"Whether an entity wants to receive an " + "XMPP message body in addition to the payload format">>). +-define(SHOW_VALUES_LABEL, <<"The presence states for which an entity wants to receive notifications">>). +-define(SUBSCRIPTION_TYPE_LABEL, <<"Type of notification to receive">>). +-define(SUBSCRIPTION_DEPTH_LABEL, <<"Depth from subscription for which to receive notifications">>). +-define(SHOW_VALUE_AWAY_LABEL, <<"XMPP Show Value of Away">>). +-define(SHOW_VALUE_CHAT_LABEL, <<"XMPP Show Value of Chat">>). +-define(SHOW_VALUE_DND_LABEL, <<"XMPP Show Value of DND (Do Not Disturb)">>). +-define(SHOW_VALUE_ONLINE_LABEL, <<"Mere Availability in XMPP (No Show Value)">>). +-define(SHOW_VALUE_XA_LABEL, <<"XMPP Show Value of XA (Extended Away)">>). +-define(SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL, <<"Receive notification of new items only">>). +-define(SUBSCRIPTION_TYPE_VALUE_NODES_LABEL, <<"Receive notification of new nodes only">>). +-define(SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL, <<"Receive notification from direct child nodes only">>). +-define(SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL, <<"Receive notification from all descendent nodes">>). %%==================================================================== %% API %%==================================================================== init() -> ok = create_table(). -subscribe_node(JID, NodeID, Options) -> - case catch mnesia:sync_dirty(fun add_subscription/3, - [JID, NodeID, Options]) - of - {'EXIT', {aborted, Error}} -> Error; - {error, Error} -> {error, Error}; - Result -> {result, Result} +subscribe_node(JID, NodeId, Options) -> + case catch mnesia:sync_dirty(fun add_subscription/3, [JID, NodeId, Options]) + of + {'EXIT', {aborted, Error}} -> Error; + {error, Error} -> {error, Error}; + Result -> {result, Result} end. -unsubscribe_node(JID, NodeID, SubID) -> - case catch mnesia:sync_dirty(fun delete_subscription/3, - [JID, NodeID, SubID]) - of - {'EXIT', {aborted, Error}} -> Error; - {error, Error} -> {error, Error}; - Result -> {result, Result} +unsubscribe_node(JID, NodeId, SubID) -> + case catch mnesia:sync_dirty(fun delete_subscription/3, [JID, NodeId, SubID]) + of + {'EXIT', {aborted, Error}} -> Error; + {error, Error} -> {error, Error}; + Result -> {result, Result} end. -get_subscription(JID, NodeID, SubID) -> - case catch mnesia:sync_dirty(fun read_subscription/3, - [JID, NodeID, SubID]) - of - {'EXIT', {aborted, Error}} -> Error; - {error, Error} -> {error, Error}; - Result -> {result, Result} +get_subscription(JID, NodeId, SubID) -> + case catch mnesia:sync_dirty(fun read_subscription/3, [JID, NodeId, SubID]) + of + {'EXIT', {aborted, Error}} -> Error; + {error, Error} -> {error, Error}; + Result -> {result, Result} end. -set_subscription(JID, NodeID, SubID, Options) -> - case catch mnesia:sync_dirty(fun write_subscription/4, - [JID, NodeID, SubID, Options]) - of - {'EXIT', {aborted, Error}} -> Error; - {error, Error} -> {error, Error}; - Result -> {result, Result} +set_subscription(JID, NodeId, SubID, Options) -> + case catch mnesia:sync_dirty(fun write_subscription/4, [JID, NodeId, SubID, Options]) + of + {'EXIT', {aborted, Error}} -> Error; + {error, Error} -> {error, Error}; + Result -> {result, Result} end. get_options_xform(Lang, Options) -> - Keys = [deliver, show_values, subscription_type, - subscription_depth], - XFields = [get_option_xfield(Lang, Key, Options) - || Key <- Keys], + Keys = [deliver, show_values, subscription_type, subscription_depth], + XFields = [get_option_xfield(Lang, Key, Options) || Key <- Keys], {result, - #xmlel{name = <<"x">>, + #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = - [#xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"FORM_TYPE">>}, - {<<"type">>, <<"hidden">>}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = - [{xmlcdata, ?NS_PUBSUB_SUB_OPTIONS}]}]}] - ++ XFields}}. + [#xmlel{name = <<"field">>, + attrs = + [{<<"var">>, <<"FORM_TYPE">>}, + {<<"type">>, <<"hidden">>}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, ?NS_PUBSUB_SUB_OPTIONS}]}]}] + ++ XFields}}. parse_options_xform(XFields) -> case xml:remove_cdata(XFields) of - [#xmlel{name = <<"x">>} = XEl] -> - case jlib:parse_xdata_submit(XEl) of - XData when is_list(XData) -> - Opts = set_xoption(XData, []), - {result, Opts}; - Other -> Other - end; - _ -> {result, []} + [#xmlel{name = <<"x">>} = XEl] -> + case jlib:parse_xdata_submit(XEl) of + XData when is_list(XData) -> + Opts = set_xoption(XData, []), + {result, Opts}; + Other -> Other + end; + _ -> {result, []} end. %%==================================================================== @@ -196,69 +138,67 @@ parse_options_xform(XFields) -> %%==================================================================== create_table() -> case mnesia:create_table(pubsub_subscription, - [{disc_copies, [node()]}, - {attributes, - record_info(fields, pubsub_subscription)}, - {type, set}]) - of - {atomic, ok} -> ok; - {aborted, {already_exists, _}} -> ok; - Other -> Other + [{disc_copies, [node()]}, + {attributes, + record_info(fields, pubsub_subscription)}, + {type, set}]) + of + {atomic, ok} -> ok; + {aborted, {already_exists, _}} -> ok; + Other -> Other end. -spec(add_subscription/3 :: -( - _JID :: ljid(), - _NodeID :: mod_pubsub:nodeIdx(), - Options :: [] | mod_pubsub:subOptions()) + ( + _JID :: ljid(), + _NodeId :: mod_pubsub:nodeIdx(), + Options :: [] | mod_pubsub:subOptions()) -> SubId :: mod_pubsub:subId() -). + ). -add_subscription(_JID, _NodeID, []) -> make_subid(); -add_subscription(_JID, _NodeID, Options) -> +add_subscription(_JID, _NodeId, []) -> make_subid(); +add_subscription(_JID, _NodeId, Options) -> SubID = make_subid(), - mnesia:write(#pubsub_subscription{subid = SubID, - options = Options}), + mnesia:write(#pubsub_subscription{subid = SubID, options = Options}), SubID. -spec(delete_subscription/3 :: -( - _JID :: _, - _NodeID :: _, - SubId :: mod_pubsub:subId()) + ( + _JID :: _, + _NodeId :: _, + SubId :: mod_pubsub:subId()) -> ok -). + ). -delete_subscription(_JID, _NodeID, SubID) -> +delete_subscription(_JID, _NodeId, SubID) -> mnesia:delete({pubsub_subscription, SubID}). -spec(read_subscription/3 :: -( - _JID :: ljid(), - _NodeID :: _, - SubID :: mod_pubsub:subId()) + ( + _JID :: ljid(), + _NodeId :: _, + SubID :: mod_pubsub:subId()) -> mod_pubsub:pubsubSubscription() - | {error, notfound} -). + | {error, notfound} + ). -read_subscription(_JID, _NodeID, SubID) -> +read_subscription(_JID, _NodeId, SubID) -> case mnesia:read({pubsub_subscription, SubID}) of - [Sub] -> Sub; - _ -> {error, notfound} + [Sub] -> Sub; + _ -> {error, notfound} end. -spec(write_subscription/4 :: -( - _JID :: ljid(), - _NodeID :: _, - SubID :: mod_pubsub:subId(), - Options :: mod_pubsub:subOptions()) + ( + _JID :: ljid(), + _NodeId :: _, + SubID :: mod_pubsub:subId(), + Options :: mod_pubsub:subOptions()) -> ok -). + ). -write_subscription(_JID, _NodeID, SubID, Options) -> - mnesia:write(#pubsub_subscription{subid = SubID, - options = Options}). +write_subscription(_JID, _NodeId, SubID, Options) -> + mnesia:write(#pubsub_subscription{subid = SubID, options = Options}). -spec(make_subid/0 :: () -> SubId::mod_pubsub:subId()). make_subid() -> @@ -274,43 +214,42 @@ make_subid() -> set_xoption([], Opts) -> Opts; set_xoption([{Var, Value} | T], Opts) -> NewOpts = case var_xfield(Var) of - {error, _} -> Opts; - Key -> - Val = val_xfield(Key, Value), - lists:keystore(Key, 1, Opts, {Key, Val}) - end, + {error, _} -> Opts; + Key -> + Val = val_xfield(Key, Value), + lists:keystore(Key, 1, Opts, {Key, Val}) + end, set_xoption(T, NewOpts). %% Return the options list's key for an XForm var. %% Convert Values for option list's Key. var_xfield(?PUBSUB_DELIVER) -> deliver; var_xfield(?PUBSUB_DIGEST) -> digest; -var_xfield(?PUBSUB_DIGEST_FREQUENCY) -> - digest_frequency; +var_xfield(?PUBSUB_DIGEST_FREQUENCY) -> digest_frequency; var_xfield(?PUBSUB_EXPIRE) -> expire; var_xfield(?PUBSUB_INCLUDE_BODY) -> include_body; var_xfield(?PUBSUB_SHOW_VALUES) -> show_values; -var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> - subscription_type; -var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> - subscription_depth; +var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> subscription_type; +var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> subscription_depth; var_xfield(_) -> {error, badarg}. val_xfield(deliver, [Val]) -> xopt_to_bool(Val); -%val_xfield(digest, [Val]) -> xopt_to_bool(Val); -%val_xfield(digest_frequency, [Val]) -> -% jlib:binary_to_integer(Val); -%val_xfield(expire, [Val]) -> -% jlib:datetime_string_to_timestamp(Val); -%val_xfield(include_body, [Val]) -> xopt_to_bool(Val); +val_xfield(digest, [Val]) -> xopt_to_bool(Val); +val_xfield(digest_frequency, [Val]) -> + case catch jlib:binary_to_integer(Val) of + N when is_integer(N) -> N; + _ -> {error, ?ERR_NOT_ACCEPTABLE} + end; +val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val); +val_xfield(include_body, [Val]) -> xopt_to_bool(Val); val_xfield(show_values, Vals) -> Vals; val_xfield(subscription_type, [<<"items">>]) -> items; val_xfield(subscription_type, [<<"nodes">>]) -> nodes; val_xfield(subscription_depth, [<<"all">>]) -> all; val_xfield(subscription_depth, [Depth]) -> case catch jlib:binary_to_integer(Depth) of - N when is_integer(N) -> N; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + N when is_integer(N) -> N; + _ -> {error, ?ERR_NOT_ACCEPTABLE} end. %% Convert XForm booleans to Erlang booleans. @@ -321,31 +260,30 @@ xopt_to_bool(<<"true">>) -> true; xopt_to_bool(_) -> {error, ?ERR_NOT_ACCEPTABLE}. -spec(get_option_xfield/3 :: -( - Lang :: binary(), - Key :: atom(), - Options :: mod_pubsub:subOptions()) + ( + Lang :: binary(), + Key :: atom(), + Options :: mod_pubsub:subOptions()) -> xmlel() -). + ). %% Return a field for an XForm for Key, with data filled in, if %% applicable, from Options. get_option_xfield(Lang, Key, Options) -> Var = xfield_var(Key), Label = xfield_label(Key), - {Type, OptEls} = type_and_options(xfield_type(Key), - Lang), + {Type, OptEls} = type_and_options(xfield_type(Key), Lang), Vals = case lists:keysearch(Key, 1, Options) of - {value, {_, Val}} -> - [tr_xfield_values(Vals) - || Vals <- xfield_val(Key, Val)]; - false -> [] - end, + {value, {_, Val}} -> + [tr_xfield_values(Vals) + || Vals <- xfield_val(Key, Val)]; + false -> [] + end, #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, Var}, {<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}], - children = OptEls ++ Vals}. + attrs = + [{<<"var">>, Var}, {<<"type">>, Type}, + {<<"label">>, translate:translate(Lang, Label)}], + children = OptEls ++ Vals}. type_and_options({Type, Options}, Lang) -> {Type, [tr_xfield_options(O, Lang) || O <- Options]}; @@ -353,42 +291,26 @@ type_and_options(Type, _Lang) -> {Type, []}. tr_xfield_options({Value, Label}, Lang) -> #xmlel{name = <<"option">>, - attrs = - [{<<"label">>, translate:translate(Lang, Label)}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Value}]}]}. + attrs = + [{<<"label">>, translate:translate(Lang, Label)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = [{xmlcdata, Value}]}]}. tr_xfield_values(Value) -> -%% Return the XForm variable name for a subscription option key. -%% Return the XForm variable type for a subscription option key. + %% Return the XForm variable name for a subscription option key. + %% Return the XForm variable type for a subscription option key. #xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Value}]}. - --spec(xfield_var/1 :: -( - Var :: 'deliver' -% | 'digest' -% | 'digest_frequency' -% | 'expire' -% | 'include_body' - | 'show_values' - | 'subscription_type' - | 'subscription_depth') - -> binary() -). + children = [{xmlcdata, Value}]}. xfield_var(deliver) -> ?PUBSUB_DELIVER; %xfield_var(digest) -> ?PUBSUB_DIGEST; -%xfield_var(digest_frequency) -> -% ?PUBSUB_DIGEST_FREQUENCY; +%xfield_var(digest_frequency) -> ?PUBSUB_DIGEST_FREQUENCY; %xfield_var(expire) -> ?PUBSUB_EXPIRE; %xfield_var(include_body) -> ?PUBSUB_INCLUDE_BODY; xfield_var(show_values) -> ?PUBSUB_SHOW_VALUES; -xfield_var(subscription_type) -> - ?PUBSUB_SUBSCRIPTION_TYPE; -xfield_var(subscription_depth) -> - ?PUBSUB_SUBSCRIPTION_DEPTH. +xfield_var(subscription_type) -> ?PUBSUB_SUBSCRIPTION_TYPE; +xfield_var(subscription_depth) -> ?PUBSUB_SUBSCRIPTION_DEPTH. xfield_type(deliver) -> <<"boolean">>; %xfield_type(digest) -> <<"boolean">>; @@ -397,52 +319,31 @@ xfield_type(deliver) -> <<"boolean">>; %xfield_type(include_body) -> <<"boolean">>; xfield_type(show_values) -> {<<"list-multi">>, - [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL}, - {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL}, - {<<"dnd">>, ?SHOW_VALUE_DND_LABEL}, - {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL}, - {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]}; + [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL}, + {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL}, + {<<"dnd">>, ?SHOW_VALUE_DND_LABEL}, + {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL}, + {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]}; xfield_type(subscription_type) -> {<<"list-single">>, - [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL}, - {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]}; + [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL}, + {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]}; xfield_type(subscription_depth) -> {<<"list-single">>, - [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL}, - {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}. + [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL}, + {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}. %% Return the XForm variable label for a subscription option key. xfield_label(deliver) -> ?DELIVER_LABEL; %xfield_label(digest) -> ?DIGEST_LABEL; -%xfield_label(digest_frequency) -> -% ?DIGEST_FREQUENCY_LABEL; +%xfield_label(digest_frequency) -> ?DIGEST_FREQUENCY_LABEL; %xfield_label(expire) -> ?EXPIRE_LABEL; %xfield_label(include_body) -> ?INCLUDE_BODY_LABEL; xfield_label(show_values) -> ?SHOW_VALUES_LABEL; %% Return the XForm value for a subscription option key. %% Convert erlang booleans to XForms. -xfield_label(subscription_type) -> - ?SUBSCRIPTION_TYPE_LABEL; -xfield_label(subscription_depth) -> - ?SUBSCRIPTION_DEPTH_LABEL. - --spec(xfield_val/2 :: -( - Field :: 'deliver' -% | 'digest' -% | 'digest_frequency' -% | 'expire' -% | 'include_body' - | 'show_values' - | 'subscription_type' - | 'subscription_depth', - Val :: boolean() - | binary() - | integer() - | [binary()]) -% | erlang:timestamp()) - -> [binary()] -). +xfield_label(subscription_type) -> ?SUBSCRIPTION_TYPE_LABEL; +xfield_label(subscription_depth) -> ?SUBSCRIPTION_DEPTH_LABEL. xfield_val(deliver, Val) -> [bool_to_xopt(Val)]; %xfield_val(digest, Val) -> [bool_to_xopt(Val)]; @@ -450,7 +351,7 @@ xfield_val(deliver, Val) -> [bool_to_xopt(Val)]; % [iolist_to_binary(integer_to_list(Val))]; %xfield_val(expire, Val) -> % [jlib:now_to_utc_string(Val)]; -%%xfield_val(include_body, Val) -> [bool_to_xopt(Val)]; +%xfield_val(include_body, Val) -> [bool_to_xopt(Val)]; xfield_val(show_values, Val) -> Val; xfield_val(subscription_type, items) -> [<<"items">>]; xfield_val(subscription_type, nodes) -> [<<"nodes">>]; diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index b54733aaadf..6c99b155dd5 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -22,98 +22,45 @@ %%% ==================================================================== -module(pubsub_subscription_odbc). - -author("pablo.polvorin@process-one.net"). %% API -export([init/0, subscribe_node/3, unsubscribe_node/3, - get_subscription/3, set_subscription/4, - get_options_xform/2, parse_options_xform/1]). + get_subscription/3, set_subscription/4, + get_options_xform/2, parse_options_xform/1]). -include("pubsub.hrl"). -include("jlib.hrl"). -define(PUBSUB_DELIVER, <<"pubsub#deliver">>). - -define(PUBSUB_DIGEST, <<"pubsub#digest">>). - --define(PUBSUB_DIGEST_FREQUENCY, - <<"pubsub#digest_frequency">>). - +-define(PUBSUB_DIGEST_FREQUENCY, <<"pubsub#digest_frequency">>). -define(PUBSUB_EXPIRE, <<"pubsub#expire">>). - -define(PUBSUB_INCLUDE_BODY, <<"pubsub#include_body">>). - -define(PUBSUB_SHOW_VALUES, <<"pubsub#show-values">>). - --define(PUBSUB_SUBSCRIPTION_TYPE, - <<"pubsub#subscription_type">>). - --define(PUBSUB_SUBSCRIPTION_DEPTH, - <<"pubsub#subscription_depth">>). - --define(DELIVER_LABEL, - <<"Whether an entity wants to receive or " - "disable notifications">>). - --define(DIGEST_LABEL, - <<"Whether an entity wants to receive digests " - "(aggregations) of notifications or all " - "notifications individually">>). - --define(DIGEST_FREQUENCY_LABEL, - <<"The minimum number of milliseconds between " - "sending any two notification digests">>). - --define(EXPIRE_LABEL, - <<"The DateTime at which a leased subscription " - "will end or has ended">>). - --define(INCLUDE_BODY_LABEL, - <<"Whether an entity wants to receive an " - "XMPP message body in addition to the " - "payload format">>). - --define(SHOW_VALUES_LABEL, - <<"The presence states for which an entity " - "wants to receive notifications">>). - --define(SUBSCRIPTION_TYPE_LABEL, - <<"Type of notification to receive">>). - --define(SUBSCRIPTION_DEPTH_LABEL, - <<"Depth from subscription for which to " - "receive notifications">>). - --define(SHOW_VALUE_AWAY_LABEL, - <<"XMPP Show Value of Away">>). - --define(SHOW_VALUE_CHAT_LABEL, - <<"XMPP Show Value of Chat">>). - --define(SHOW_VALUE_DND_LABEL, - <<"XMPP Show Value of DND (Do Not Disturb)">>). - --define(SHOW_VALUE_ONLINE_LABEL, - <<"Mere Availability in XMPP (No Show Value)">>). - --define(SHOW_VALUE_XA_LABEL, - <<"XMPP Show Value of XA (Extended Away)">>). - --define(SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL, - <<"Receive notification of new items only">>). - --define(SUBSCRIPTION_TYPE_VALUE_NODES_LABEL, - <<"Receive notification of new nodes only">>). - --define(SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL, - <<"Receive notification from direct child " - "nodes only">>). - --define(SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL, - <<"Receive notification from all descendent " - "nodes">>). +-define(PUBSUB_SUBSCRIPTION_TYPE, <<"pubsub#subscription_type">>). +-define(PUBSUB_SUBSCRIPTION_DEPTH, <<"pubsub#subscription_depth">>). +-define(DELIVER_LABEL, <<"Whether an entity wants to receive or disable notifications">>). +-define(DIGEST_LABEL, <<"Whether an entity wants to receive digests " + "(aggregations) of notifications or all notifications individually">>). +-define(DIGEST_FREQUENCY_LABEL, <<"The minimum number of milliseconds between " + "sending any two notification digests">>). +-define(EXPIRE_LABEL, <<"The DateTime at which a leased subscription will end or has ended">>). +-define(INCLUDE_BODY_LABEL, <<"Whether an entity wants to receive an " + "XMPP message body in addition to the payload format">>). +-define(SHOW_VALUES_LABEL, <<"The presence states for which an entity wants to receive notifications">>). +-define(SUBSCRIPTION_TYPE_LABEL, <<"Type of notification to receive">>). +-define(SUBSCRIPTION_DEPTH_LABEL, <<"Depth from subscription for which to receive notifications">>). +-define(SHOW_VALUE_AWAY_LABEL, <<"XMPP Show Value of Away">>). +-define(SHOW_VALUE_CHAT_LABEL, <<"XMPP Show Value of Chat">>). +-define(SHOW_VALUE_DND_LABEL, <<"XMPP Show Value of DND (Do Not Disturb)">>). +-define(SHOW_VALUE_ONLINE_LABEL, <<"Mere Availability in XMPP (No Show Value)">>). +-define(SHOW_VALUE_XA_LABEL, <<"XMPP Show Value of XA (Extended Away)">>). +-define(SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL, <<"Receive notification of new items only">>). +-define(SUBSCRIPTION_TYPE_VALUE_NODES_LABEL, <<"Receive notification of new nodes only">>). +-define(SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL, <<"Receive notification from direct child nodes only">>). +-define(SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL, <<"Receive notification from all descendent nodes">>). -define(DB_MOD, pubsub_db_odbc). %%==================================================================== @@ -123,99 +70,92 @@ init() -> ok = create_table(). -spec(subscribe_node/3 :: -( - _JID :: _, - _NodeID :: _, - Options :: mod_pubsub:subOptions()) + ( + _JID :: _, + _NodeId :: _, + Options :: [] | mod_pubsub:subOptions()) -> {result, mod_pubsub:subId()} -). -subscribe_node(_JID, _NodeID, Options) -> + ). +subscribe_node(_JID, _NodeId, Options) -> SubID = make_subid(), - (?DB_MOD):add_subscription(#pubsub_subscription{subid = - SubID, - options = Options}), + (?DB_MOD):add_subscription(#pubsub_subscription{subid = SubID, options = Options}), {result, SubID}. -spec(unsubscribe_node/3 :: -( - _JID :: _, - _NodeID :: _, - SubID :: mod_pubsub:subId()) + ( + _JID :: _, + _NodeId :: _, + SubID :: mod_pubsub:subId()) -> {result, mod_pubsub:subscription()} - | {error, notfound} -). -unsubscribe_node(_JID, _NodeID, SubID) -> + | {error, notfound} + ). +unsubscribe_node(_JID, _NodeId, SubID) -> case (?DB_MOD):read_subscription(SubID) of - {ok, Sub} -> - (?DB_MOD):delete_subscription(SubID), {result, Sub}; - notfound -> {error, notfound} + {ok, Sub} -> (?DB_MOD):delete_subscription(SubID), {result, Sub}; + notfound -> {error, notfound} end. -spec(get_subscription/3 :: -( - _JID :: _, - _NodeID :: _, - SubId :: mod_pubsub:subId()) + ( + _JID :: _, + _NodeId :: _, + SubId :: mod_pubsub:subId()) -> {result, mod_pubsub:subscription()} - | {error, notfound} -). -get_subscription(_JID, _NodeID, SubID) -> + | {error, notfound} + ). +get_subscription(_JID, _NodeId, SubID) -> case (?DB_MOD):read_subscription(SubID) of - {ok, Sub} -> {result, Sub}; - notfound -> {error, notfound} + {ok, Sub} -> {result, Sub}; + notfound -> {error, notfound} end. -spec(set_subscription/4 :: -( - _JID :: _, - _NodeID :: _, - SubId :: mod_pubsub:subId(), - Options :: mod_pubsub:subOptions()) + ( + _JID :: _, + _NodeId :: _, + SubId :: mod_pubsub:subId(), + Options :: mod_pubsub:subOptions()) -> {result, ok} -). -set_subscription(_JID, _NodeID, SubID, Options) -> + ). +set_subscription(_JID, _NodeId, SubID, Options) -> case (?DB_MOD):read_subscription(SubID) of - {ok, _} -> - (?DB_MOD):update_subscription(#pubsub_subscription{subid - = SubID, - options = - Options}), - {result, ok}; - notfound -> - (?DB_MOD):add_subscription(#pubsub_subscription{subid = - SubID, - options = Options}), - {result, ok} + {ok, _} -> + (?DB_MOD):update_subscription(#pubsub_subscription{subid = SubID, + options = Options}), + {result, ok}; + notfound -> + (?DB_MOD):add_subscription(#pubsub_subscription{subid = SubID, + options = Options}), + {result, ok} end. get_options_xform(Lang, Options) -> Keys = [deliver, show_values, subscription_type, subscription_depth], - XFields = [get_option_xfield(Lang, Key, Options) - || Key <- Keys], + XFields = [get_option_xfield(Lang, Key, Options) || Key <- Keys], {result, - #xmlel{name = <<"x">>, + #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}], children = - [#xmlel{name = <<"field">>, - attrs = - [{<<"var">>, <<"FORM_TYPE">>}, - {<<"type">>, <<"hidden">>}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = - [{xmlcdata, ?NS_PUBSUB_SUB_OPTIONS}]}]}] - ++ XFields}}. + [#xmlel{name = <<"field">>, + attrs = + [{<<"var">>, <<"FORM_TYPE">>}, + {<<"type">>, <<"hidden">>}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, ?NS_PUBSUB_SUB_OPTIONS}]}]}] + ++ XFields}}. parse_options_xform(XFields) -> case xml:remove_cdata(XFields) of - [#xmlel{name = <<"x">>} = XEl] -> - case jlib:parse_xdata_submit(XEl) of - XData when is_list(XData) -> - Opts = set_xoption(XData, []), - {result, Opts}; - Other -> Other - end; - _ -> {result, []} + [#xmlel{name = <<"x">>} = XEl] -> + case jlib:parse_xdata_submit(XEl) of + XData when is_list(XData) -> + Opts = set_xoption(XData, []), + {result, Opts}; + Other -> Other + end; + _ -> {result, []} end. %%==================================================================== @@ -237,43 +177,42 @@ make_subid() -> set_xoption([], Opts) -> Opts; set_xoption([{Var, Value} | T], Opts) -> NewOpts = case var_xfield(Var) of - {error, _} -> Opts; - Key -> - Val = val_xfield(Key, Value), - lists:keystore(Key, 1, Opts, {Key, Val}) - end, + {error, _} -> Opts; + Key -> + Val = val_xfield(Key, Value), + lists:keystore(Key, 1, Opts, {Key, Val}) + end, set_xoption(T, NewOpts). %% Return the options list's key for an XForm var. %% Convert Values for option list's Key. var_xfield(?PUBSUB_DELIVER) -> deliver; -%var_xfield(?PUBSUB_DIGEST) -> digest; -%var_xfield(?PUBSUB_DIGEST_FREQUENCY) -> -% digest_frequency; -%var_xfield(?PUBSUB_EXPIRE) -> expire; -%var_xfield(?PUBSUB_INCLUDE_BODY) -> include_body; +var_xfield(?PUBSUB_DIGEST) -> digest; +var_xfield(?PUBSUB_DIGEST_FREQUENCY) -> digest_frequency; +var_xfield(?PUBSUB_EXPIRE) -> expire; +var_xfield(?PUBSUB_INCLUDE_BODY) -> include_body; var_xfield(?PUBSUB_SHOW_VALUES) -> show_values; -var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> - subscription_type; -var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> - subscription_depth; +var_xfield(?PUBSUB_SUBSCRIPTION_TYPE) -> subscription_type; +var_xfield(?PUBSUB_SUBSCRIPTION_DEPTH) -> subscription_depth; var_xfield(_) -> {error, badarg}. val_xfield(deliver, [Val]) -> xopt_to_bool(Val); -%val_xfield(digest, [Val]) -> xopt_to_bool(Val); -%val_xfield(digest_frequency, [Val]) -> -% jlib:binary_to_integer(Val); -%val_xfield(expire, [Val]) -> -% jlib:datetime_string_to_timestamp(Val); -%val_xfield(include_body, [Val]) -> xopt_to_bool(Val); +val_xfield(digest, [Val]) -> xopt_to_bool(Val); +val_xfield(digest_frequency, [Val]) -> + case catch jlib:binary_to_integer(Val) of + N when is_integer(N) -> N; + _ -> {error, ?ERR_NOT_ACCEPTABLE} + end; +val_xfield(expire, [Val]) -> jlib:datetime_string_to_timestamp(Val); +val_xfield(include_body, [Val]) -> xopt_to_bool(Val); val_xfield(show_values, Vals) -> Vals; val_xfield(subscription_type, [<<"items">>]) -> items; val_xfield(subscription_type, [<<"nodes">>]) -> nodes; val_xfield(subscription_depth, [<<"all">>]) -> all; val_xfield(subscription_depth, [Depth]) -> case catch jlib:binary_to_integer(Depth) of - N when is_integer(N) -> N; - _ -> {error, ?ERR_NOT_ACCEPTABLE} + N when is_integer(N) -> N; + _ -> {error, ?ERR_NOT_ACCEPTABLE} end. %% Convert XForm booleans to Erlang booleans. @@ -288,19 +227,18 @@ xopt_to_bool(_) -> {error, ?ERR_NOT_ACCEPTABLE}. get_option_xfield(Lang, Key, Options) -> Var = xfield_var(Key), Label = xfield_label(Key), - {Type, OptEls} = type_and_options(xfield_type(Key), - Lang), + {Type, OptEls} = type_and_options(xfield_type(Key), Lang), Vals = case lists:keysearch(Key, 1, Options) of - {value, {_, Val}} -> - [tr_xfield_values(Vals) - || Vals <- xfield_val(Key, Val)]; - false -> [] - end, + {value, {_, Val}} -> + [tr_xfield_values(Vals) + || Vals <- xfield_val(Key, Val)]; + false -> [] + end, #xmlel{name = <<"field">>, - attrs = - [{<<"var">>, Var}, {<<"type">>, Type}, - {<<"label">>, translate:translate(Lang, Label)}], - children = OptEls ++ Vals}. + attrs = + [{<<"var">>, Var}, {<<"type">>, Type}, + {<<"label">>, translate:translate(Lang, Label)}], + children = OptEls ++ Vals}. type_and_options({Type, Options}, Lang) -> {Type, [tr_xfield_options(O, Lang) || O <- Options]}; @@ -308,29 +246,26 @@ type_and_options(Type, _Lang) -> {Type, []}. tr_xfield_options({Value, Label}, Lang) -> #xmlel{name = <<"option">>, - attrs = - [{<<"label">>, translate:translate(Lang, Label)}], - children = - [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Value}]}]}. + attrs = + [{<<"label">>, translate:translate(Lang, Label)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = [{xmlcdata, Value}]}]}. tr_xfield_values(Value) -> -%% Return the XForm variable name for a subscription option key. -%% Return the XForm variable type for a subscription option key. + %% Return the XForm variable name for a subscription option key. + %% Return the XForm variable type for a subscription option key. #xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, Value}]}. + children = [{xmlcdata, Value}]}. xfield_var(deliver) -> ?PUBSUB_DELIVER; %xfield_var(digest) -> ?PUBSUB_DIGEST; -%xfield_var(digest_frequency) -> -% ?PUBSUB_DIGEST_FREQUENCY; +%xfield_var(digest_frequency) -> ?PUBSUB_DIGEST_FREQUENCY; %xfield_var(expire) -> ?PUBSUB_EXPIRE; %xfield_var(include_body) -> ?PUBSUB_INCLUDE_BODY; xfield_var(show_values) -> ?PUBSUB_SHOW_VALUES; -xfield_var(subscription_type) -> - ?PUBSUB_SUBSCRIPTION_TYPE; -xfield_var(subscription_depth) -> - ?PUBSUB_SUBSCRIPTION_DEPTH. +xfield_var(subscription_type) -> ?PUBSUB_SUBSCRIPTION_TYPE; +xfield_var(subscription_depth) -> ?PUBSUB_SUBSCRIPTION_DEPTH. xfield_type(deliver) -> <<"boolean">>; %xfield_type(digest) -> <<"boolean">>; @@ -339,34 +274,31 @@ xfield_type(deliver) -> <<"boolean">>; %xfield_type(include_body) -> <<"boolean">>; xfield_type(show_values) -> {<<"list-multi">>, - [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL}, - {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL}, - {<<"dnd">>, ?SHOW_VALUE_DND_LABEL}, - {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL}, - {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]}; + [{<<"away">>, ?SHOW_VALUE_AWAY_LABEL}, + {<<"chat">>, ?SHOW_VALUE_CHAT_LABEL}, + {<<"dnd">>, ?SHOW_VALUE_DND_LABEL}, + {<<"online">>, ?SHOW_VALUE_ONLINE_LABEL}, + {<<"xa">>, ?SHOW_VALUE_XA_LABEL}]}; xfield_type(subscription_type) -> {<<"list-single">>, - [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL}, - {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]}; + [{<<"items">>, ?SUBSCRIPTION_TYPE_VALUE_ITEMS_LABEL}, + {<<"nodes">>, ?SUBSCRIPTION_TYPE_VALUE_NODES_LABEL}]}; xfield_type(subscription_depth) -> {<<"list-single">>, - [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL}, - {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}. + [{<<"1">>, ?SUBSCRIPTION_DEPTH_VALUE_ONE_LABEL}, + {<<"all">>, ?SUBSCRIPTION_DEPTH_VALUE_ALL_LABEL}]}. %% Return the XForm variable label for a subscription option key. xfield_label(deliver) -> ?DELIVER_LABEL; %xfield_label(digest) -> ?DIGEST_LABEL; -%xfield_label(digest_frequency) -> -% ?DIGEST_FREQUENCY_LABEL; +%xfield_label(digest_frequency) -> ?DIGEST_FREQUENCY_LABEL; %xfield_label(expire) -> ?EXPIRE_LABEL; %xfield_label(include_body) -> ?INCLUDE_BODY_LABEL; xfield_label(show_values) -> ?SHOW_VALUES_LABEL; %% Return the XForm value for a subscription option key. %% Convert erlang booleans to XForms. -xfield_label(subscription_type) -> - ?SUBSCRIPTION_TYPE_LABEL; -xfield_label(subscription_depth) -> - ?SUBSCRIPTION_DEPTH_LABEL. +xfield_label(subscription_type) -> ?SUBSCRIPTION_TYPE_LABEL; +xfield_label(subscription_depth) -> ?SUBSCRIPTION_DEPTH_LABEL. xfield_val(deliver, Val) -> [bool_to_xopt(Val)]; %xfield_val(digest, Val) -> [bool_to_xopt(Val)]; diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 4606ae0fd79..a827a9174f0 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -813,7 +813,7 @@ pubsub(Config) -> node = Node, jid = my_jid(Config)}}]}), ?recv2( - #message{sub_els = [#pubsub_event{}, #delay{}, #legacy_delay{}]}, + #message{sub_els = [#pubsub_event{}, #delay{}]}, #iq{type = result, id = I1}), %% Get subscriptions true = lists:member(?PUBSUB("retrieve-subscriptions"), Features), @@ -860,8 +860,7 @@ pubsub(Config) -> #message{sub_els = [#pubsub_event{ items = [#pubsub_event_items{ node = Node, - retract = [ItemID]}]}, - #shim{headers = [{<<"Collection">>, Node}]}]}), + retract = [ItemID]}]}]}), %% Unsubscribe from node "presence" #iq{type = result, sub_els = []} = send_recv(Config, diff --git a/test/ejabberd_SUITE_data/ejabberd.cfg b/test/ejabberd_SUITE_data/ejabberd.cfg index cb321661e68..a92608b6061 100644 --- a/test/ejabberd_SUITE_data/ejabberd.cfg +++ b/test/ejabberd_SUITE_data/ejabberd.cfg @@ -94,7 +94,8 @@ {mod_offline, [{db_type, odbc}]}, {mod_privacy, [{db_type, odbc}]}, {mod_private, [{db_type, odbc}]}, - {mod_pubsub_odbc, [{access_createnode, pubsub_createnode}, + {mod_pubsub, [{db_type, odbc}, + {access_createnode, pubsub_createnode}, {ignore_pep_from_offline, true}, {last_item_cache, false}, {plugins, ["flat", "hometree", "pep"]}]}, @@ -114,7 +115,8 @@ {mod_offline, [{db_type, odbc}]}, {mod_privacy, [{db_type, odbc}]}, {mod_private, [{db_type, odbc}]}, - {mod_pubsub_odbc, [{access_createnode, pubsub_createnode}, + {mod_pubsub, [{db_type, odbc}, + {access_createnode, pubsub_createnode}, {ignore_pep_from_offline, true}, {last_item_cache, false}, {plugins, ["flat", "hometree", "pep"]}]}, @@ -133,7 +135,8 @@ {mod_offline, [{db_type, odbc}]}, {mod_privacy, [{db_type, odbc}]}, {mod_private, [{db_type, odbc}]}, - {mod_pubsub_odbc, [{access_createnode, pubsub_createnode}, + {mod_pubsub, [{db_type, odbc}, + {access_createnode, pubsub_createnode}, {ignore_pep_from_offline, true}, {last_item_cache, false}, {plugins, ["flat", "hometree", "pep"]}]}, diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index c19e2244177..0a836b8051e 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -26,7 +26,8 @@ host_config: db_type: odbc mod_private: db_type: odbc - mod_pubsub_odbc: + mod_pubsub: + db_type: odbc access_createnode: pubsub_createnode ignore_pep_from_offline: true last_item_cache: false @@ -76,7 +77,8 @@ Welcome to this XMPP server." db_type: odbc mod_private: db_type: odbc - mod_pubsub_odbc: + mod_pubsub: + db_type: odbc access_createnode: pubsub_createnode ignore_pep_from_offline: true last_item_cache: false @@ -132,7 +134,8 @@ Welcome to this XMPP server." db_type: odbc mod_private: db_type: odbc - mod_pubsub_odbc: + mod_pubsub: + db_type: odbc access_createnode: pubsub_createnode ignore_pep_from_offline: true last_item_cache: false From 747d25b4adc50570f4d073c50ca8a5aa9aaa0d65 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 21 Apr 2015 15:02:20 +0200 Subject: [PATCH 028/695] Fixed node type (thanks to saczawap) (#435) --- src/mod_pubsub.erl | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 8fbdfbb6fd7..d5398fadf43 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -1057,27 +1057,21 @@ command_disco_info(_Host, ?NS_PUBSUB_GET_PENDING, _From) -> node_disco_info(Host, Node, From) -> node_disco_info(Host, Node, From, true, true). -node_disco_info(Host, Node, From, _Identity, _Features) -> - Action = fun (#pubsub_node{type = Type, id = Nidx}) -> - Types = case tree_call(Host, get_subnodes, [Host, Node, From]) of - [] -> - [<<"leaf">>]; - _ -> - case node_call(Host, Type, get_items, [Nidx, From, none]) of - {result, {[], _}} -> [<<"collection">>]; - {result, _} -> [<<"leaf">>, <<"collection">>]; - _ -> [] - end +node_disco_info(Host, Node, _From, _Identity, _Features) -> + Action = fun (#pubsub_node{type = Type, options = Options}) -> + NodeType = case get_option(Options, node_type) of + collection -> <<"collection">>; + _ -> <<"leaf">> end, - I = [#xmlel{name = <<"identity">>, - attrs = [{<<"category">>, <<"pubsub">>}, {<<"type">>, T}]} - || T <- Types], + I = #xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"pubsub">>}, + {<<"type">>, NodeType}]}, F = [#xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_PUBSUB}]} | [#xmlel{name = <<"feature">>, attrs = [{<<"var">>, feature(F)}]} || F <- plugin_features(Host, Type)]], - {result, I ++ F} + {result, [I | F]} end, case transaction(Host, Node, Action, sync_dirty) of {result, {_, Result}} -> {result, Result}; From cbd45974e22e940b974d8668eb5f4bc2350bb5c3 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 21 Apr 2015 15:14:39 +0200 Subject: [PATCH 029/695] Owner can subscribe to its node (#454) --- src/node_hometree.erl | 7 ++++--- src/node_hometree_odbc.erl | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/node_hometree.erl b/src/node_hometree.erl index 2840c1850b1..f2e592aaaed 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -217,6 +217,7 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, (_) -> false end, Subscriptions), + Owner = Affiliation == owner, if not Authorized -> {error, ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; @@ -225,13 +226,13 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, PendingSubscription -> {error, ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; - (AccessModel == presence) and not PresenceSubscription -> + (AccessModel == presence) and (not PresenceSubscription) and (not Owner) -> {error, ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> + (AccessModel == roster) and (not RosterGroup) and (not Owner) -> {error, ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> + (AccessModel == whitelist) and (not Whitelisted) and (not Owner) -> {error, ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; %%MustPay -> diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index d0cfad0f1ea..6207e0fbc5b 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -158,6 +158,7 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, (_) -> false end, Subscriptions), + Owner = Affiliation == owner, if not Authorized -> {error, ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; @@ -166,13 +167,13 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, PendingSubscription -> {error, ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; - (AccessModel == presence) and not PresenceSubscription -> + (AccessModel == presence) and (not PresenceSubscription) and (not Owner) -> {error, ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> + (AccessModel == roster) and (not RosterGroup) and (not Owner) -> {error, ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> + (AccessModel == whitelist) and (not Whitelisted) and (not Owner) -> {error, ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; %%MustPay -> From 61f80396dac63e47f440ad39212c9e4adeb69e21 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 21 Apr 2015 16:11:00 +0200 Subject: [PATCH 030/695] remove deferred Collection shim header --- src/mod_pubsub.erl | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index d5398fadf43..e266e89be19 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3427,9 +3427,9 @@ broadcast_stanza(Host, _Node, _Nidx, _Type, NodeOptions, SubsByDepth, NotifyType Stanza; %% If there's only one SubID, don't add it {true, [_]} -> - add_shim_headers(Stanza, collection_shim(NodeName)); + Stnza; {true, SubIDs} -> - add_shim_headers(Stanza, lists:append(collection_shim(NodeName), subid_shim(SubIDs))) + add_shim_headers(Stanza, subid_shim(SubIDs)) end, lists:foreach(fun(To) -> ejabberd_router:route(From, jlib:make_jid(To), StanzaToSend) @@ -4244,11 +4244,6 @@ add_headers(#xmlel{name = Name, attrs = Attrs, children = Els}, HeaderName, Head #xmlel{name = Name, attrs = Attrs, children = lists:append(Els, [HeaderEl])}. -collection_shim(Node) -> - [#xmlel{name = <<"header">>, - attrs = [{<<"name">>, <<"Collection">>}], - children = [{xmlcdata, Node}]}]. - subid_shim(SubIds) -> [#xmlel{name = <<"header">>, attrs = [{<<"name">>, <<"SubId">>}], From cf37f3977af7bd119883259fbf451f789455f5e7 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 21 Apr 2015 16:13:23 +0200 Subject: [PATCH 031/695] Fix typo, oups... --- src/mod_pubsub.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index e266e89be19..75a64e1a6f2 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3413,7 +3413,7 @@ broadcast_stanza(Host, _Node, _Nidx, _Type, NodeOptions, SubsByDepth, NotifyType Stanza = add_message_type(BaseStanza, NotificationType), %% Handles explicit subscriptions SubIDsByJID = subscribed_nodes_by_jid(NotifyType, SubsByDepth), - lists:foreach(fun ({LJID, NodeName, SubIDs}) -> + lists:foreach(fun ({LJID, _NodeName, SubIDs}) -> LJIDs = case BroadcastAll of true -> {U, S, _} = LJID, @@ -3427,7 +3427,7 @@ broadcast_stanza(Host, _Node, _Nidx, _Type, NodeOptions, SubsByDepth, NotifyType Stanza; %% If there's only one SubID, don't add it {true, [_]} -> - Stnza; + Stanza; {true, SubIDs} -> add_shim_headers(Stanza, subid_shim(SubIDs)) end, From 6e4d6caebf19584200b6478d170bda5090ef2a2b Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 21 Apr 2015 17:23:59 +0200 Subject: [PATCH 032/695] Add support for publish-only (#30) --- src/mod_pubsub.erl | 3 +++ src/node_hometree.erl | 12 ++++++++---- src/node_hometree_odbc.erl | 11 +++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 75a64e1a6f2..a8b7b0ecb0d 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3069,6 +3069,7 @@ get_roster_info(OwnerUser, OwnerServer, JID, AllowedGroups) -> string_to_affiliation(<<"owner">>) -> owner; string_to_affiliation(<<"publisher">>) -> publisher; +string_to_affiliation(<<"publish-only">>) -> publish_only; string_to_affiliation(<<"member">>) -> member; string_to_affiliation(<<"outcast">>) -> outcast; string_to_affiliation(<<"none">>) -> none; @@ -3082,6 +3083,7 @@ string_to_subscription(_) -> false. affiliation_to_string(owner) -> <<"owner">>; affiliation_to_string(publisher) -> <<"publisher">>; +affiliation_to_string(publish_only) -> <<"publish-only">>; affiliation_to_string(member) -> <<"member">>; affiliation_to_string(outcast) -> <<"outcast">>; affiliation_to_string(_) -> <<"none">>. @@ -4023,6 +4025,7 @@ features() -> <<"presence-notifications">>, % OPTIONAL <<"presence-subscribe">>, % RECOMMENDED <<"publisher-affiliation">>, % RECOMMENDED + <<"publish-only-affiliation">>, % OPTIONAL <<"retrieve-default">>, <<"shim">>]. % RECOMMENDED diff --git a/src/node_hometree.erl b/src/node_hometree.erl index f2e592aaaed..296fbdde7a8 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -114,6 +114,7 @@ features() -> <<"outcast-affiliation">>, <<"persistent-items">>, <<"publish">>, + <<"publish-only-affiliation">>, <<"purge-nodes">>, <<"retract-items">>, <<"retrieve-affiliations">>, @@ -221,7 +222,7 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, if not Authorized -> {error, ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; - Affiliation == outcast -> + (Affiliation == outcast) or (Affiliation == publish_only) -> {error, ?ERR_FORBIDDEN}; PendingSubscription -> {error, @@ -377,7 +378,9 @@ publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> end, if not ((PublishModel == open) or (PublishModel == publishers) and - ((Affiliation == owner) or (Affiliation == publisher)) + ((Affiliation == owner) + or (Affiliation == publisher) + or (Affiliation == publish_only)) or (Subscribed == true)) -> {error, ?ERR_FORBIDDEN}; true -> @@ -743,7 +746,7 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RS %%InvalidSubId -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> + (Affiliation == outcast) or (Affiliation == publish_only) -> {error, ?ERR_FORBIDDEN}; (AccessModel == presence) and not PresenceSubscription -> {error, @@ -784,7 +787,7 @@ get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _Sub %%InvalidSubId -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> + (Affiliation == outcast) or (Affiliation == publish_only) -> {error, ?ERR_FORBIDDEN}; (AccessModel == presence) and not PresenceSubscription -> {error, @@ -832,6 +835,7 @@ path_to_node(Path) -> iolist_to_binary(str:join([<<"">> | Path], <<"/">>)). can_fetch_item(owner, _) -> true; can_fetch_item(member, _) -> true; can_fetch_item(publisher, _) -> true; +can_fetch_item(publish_only, _) -> false; can_fetch_item(outcast, _) -> false; can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). %can_fetch_item(_Affiliation, _Subscription) -> false. diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index 6207e0fbc5b..b9abac20336 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -162,7 +162,7 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, if not Authorized -> {error, ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; - Affiliation == outcast -> + (Affiliation == outcast) or (Affiliation == publish_only) -> {error, ?ERR_FORBIDDEN}; PendingSubscription -> {error, @@ -299,7 +299,9 @@ publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> end, if not ((PublishModel == open) or (PublishModel == publishers) and - ((Affiliation == owner) or (Affiliation == publisher)) + ((Affiliation == owner) + or (Affiliation == publisher) + or (Affiliation == publish_only)) or (Subscribed == true)) -> {error, ?ERR_FORBIDDEN}; true -> @@ -868,7 +870,7 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM %%InvalidSubId -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> + (Affiliation == outcast) or (Affiliation == publish_only) -> {error, ?ERR_FORBIDDEN}; (AccessModel == presence) and not PresenceSubscription -> {error, @@ -927,7 +929,7 @@ get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _Sub %%InvalidSubId -> %% Entity is subscribed but specifies an invalid subscription ID %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - Affiliation == outcast -> + (Affiliation == outcast) or (Affiliation == publish_only) -> {error, ?ERR_FORBIDDEN}; (AccessModel == presence) and not PresenceSubscription -> {error, @@ -1005,6 +1007,7 @@ path_to_node(Path) -> can_fetch_item(owner, _) -> true; can_fetch_item(member, _) -> true; can_fetch_item(publisher, _) -> true; +can_fetch_item(publish_only, _) -> false; can_fetch_item(outcast, _) -> false; can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). %can_fetch_item(_Affiliation, _Subscription) -> false. From e280de8452941115bf086f829854ab9bd72897fc Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 22 Apr 2015 11:01:13 +0200 Subject: [PATCH 033/695] Allow to modify host when registering account in web (#291) --- src/mod_register_web.erl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index fb94923f6bd..b9f799b41b9 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -97,8 +97,8 @@ process([<<"change_password">>], form_changepass_get(Host, Lang); process([<<"new">>], #request{method = 'POST', q = Q, ip = {Ip, _Port}, - lang = Lang, host = Host}) -> - case form_new_post(Q, Host) of + lang = Lang, host = _HTTPHost}) -> + case form_new_post(Q) of {success, ok, {Username, Host, _Password}} -> Jid = jlib:make_jid(Username, Host, <<"">>), mod_register:send_registration_notifications(?MODULE, Jid, Ip), @@ -233,7 +233,8 @@ form_new_get(Host, Lang, IP) -> <<(?T(<<"Characters not allowed:">>))/binary, " \" & ' / : < > @ ">>)])]), ?XE(<<"li">>, - [?CT(<<"Server:">>), ?C(<<" ">>), ?C(Host)]), + [?CT(<<"Server:">>), ?C(<<" ">>), + ?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password">>, <<"">>, @@ -277,9 +278,9 @@ form_new_get(Host, Lang, IP) -> %%% Formulary new POST %%%---------------------------------------------------------------------- -form_new_post(Q, Host) -> +form_new_post(Q) -> case catch get_register_parameters(Q) of - [Username, Password, Password, Id, Key] -> + [Username, Host, Password, Password, Id, Key] -> form_new_post(Username, Host, Password, {Id, Key}); [_Username, _Password, _Password2, false, false] -> {error, passwords_not_identical}; @@ -296,7 +297,7 @@ get_register_parameters(Q) -> false -> false end end, - [<<"username">>, <<"password">>, <<"password2">>, + [<<"username">>, <<"host">>, <<"password">>, <<"password2">>, <<"id">>, <<"key">>]). form_new_post(Username, Host, Password, From 43f2064daa1b2613610f338824d9636dd723f336 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Apr 2015 12:21:48 +0200 Subject: [PATCH 034/695] Remove obsolete release notes --- doc/release_notes_0.9.1.txt | 62 -------- doc/release_notes_0.9.8.txt | 99 ------------ doc/release_notes_0.9.txt | 88 ----------- doc/release_notes_1.0.0.txt | 120 --------------- doc/release_notes_1.1.0.txt | 115 -------------- doc/release_notes_1.1.1.txt | 119 --------------- doc/release_notes_1.1.2.txt | 119 --------------- doc/release_notes_1.1.3.txt | 14 -- doc/release_notes_1.1.4.txt | 31 ---- doc/release_notes_2.0.0.txt | 208 -------------------------- doc/release_notes_2.0.1.txt | 30 ---- doc/release_notes_2.0.2.txt | 34 ----- doc/release_notes_2.0.3.txt | 35 ----- doc/release_notes_2.0.4.txt | 44 ------ doc/release_notes_2.0.5.txt | 33 ---- doc/release_notes_2.1.0.txt | 281 ----------------------------------- doc/release_notes_2.1.1.txt | 47 ------ doc/release_notes_2.1.10.txt | 39 ----- doc/release_notes_2.1.11.txt | 58 -------- doc/release_notes_2.1.12.txt | 67 --------- doc/release_notes_2.1.2.txt | 51 ------- doc/release_notes_2.1.3.txt | 91 ------------ doc/release_notes_2.1.4.txt | 80 ---------- doc/release_notes_2.1.5.txt | 70 --------- doc/release_notes_2.1.6.txt | 67 --------- doc/release_notes_2.1.7.txt | 97 ------------ doc/release_notes_2.1.8.txt | 21 --- doc/release_notes_2.1.9.txt | 56 ------- 28 files changed, 2176 deletions(-) delete mode 100644 doc/release_notes_0.9.1.txt delete mode 100644 doc/release_notes_0.9.8.txt delete mode 100644 doc/release_notes_0.9.txt delete mode 100644 doc/release_notes_1.0.0.txt delete mode 100644 doc/release_notes_1.1.0.txt delete mode 100644 doc/release_notes_1.1.1.txt delete mode 100644 doc/release_notes_1.1.2.txt delete mode 100644 doc/release_notes_1.1.3.txt delete mode 100644 doc/release_notes_1.1.4.txt delete mode 100644 doc/release_notes_2.0.0.txt delete mode 100644 doc/release_notes_2.0.1.txt delete mode 100644 doc/release_notes_2.0.2.txt delete mode 100644 doc/release_notes_2.0.3.txt delete mode 100644 doc/release_notes_2.0.4.txt delete mode 100644 doc/release_notes_2.0.5.txt delete mode 100644 doc/release_notes_2.1.0.txt delete mode 100644 doc/release_notes_2.1.1.txt delete mode 100644 doc/release_notes_2.1.10.txt delete mode 100644 doc/release_notes_2.1.11.txt delete mode 100644 doc/release_notes_2.1.12.txt delete mode 100644 doc/release_notes_2.1.2.txt delete mode 100644 doc/release_notes_2.1.3.txt delete mode 100644 doc/release_notes_2.1.4.txt delete mode 100644 doc/release_notes_2.1.5.txt delete mode 100644 doc/release_notes_2.1.6.txt delete mode 100644 doc/release_notes_2.1.7.txt delete mode 100644 doc/release_notes_2.1.8.txt delete mode 100644 doc/release_notes_2.1.9.txt diff --git a/doc/release_notes_0.9.1.txt b/doc/release_notes_0.9.1.txt deleted file mode 100644 index 39637e4fbe2..00000000000 --- a/doc/release_notes_0.9.1.txt +++ /dev/null @@ -1,62 +0,0 @@ - Release notes - ejabberd 0.9.1 - - This document describes the main changes from [25]ejabberd 0.9. - - The code can be downloaded from the [26]download page. - - For more detailed information, please refer to ejabberd [27]User Guide. - - -Groupchat (Multi-user chat and IRC) improvements - - The multi-user chat code has been improved to comply with the latest version - of Jabber Enhancement Proposal 0045. - - The IRC (Internet Relay Chat) features now support WHOIS and USERINFO - requests. - - -Web interface - - ejabberd modules management features have been added to the web interface. - They now allow to start or stop extension module without restarting the - ejabberd server. - - -Publish and subscribe - - It is now possible to a subscribe node with a JabberID that includes a - resource. - - -Translations - - A new script has been included to help translate ejabberd into new languages - and maintain existing translations. - - As a result, ejabberd is now translating into 10 languages: - * Dutch - * English - * French - * German - * Polish - * Portuguese - * Russian - * Spanish - * Swedish - * Ukrainian - - -Migration - - No changes have been made to the database. No particular conversion steps - are needed. However, you should backup your database before upgrading to a - new ejabberd version. - - -Bugfixes - - This release contains several bugfixes and architectural changes. Please - refer to the Changelog file supplied with this release for details of all - improvements in the ejabberd code. diff --git a/doc/release_notes_0.9.8.txt b/doc/release_notes_0.9.8.txt deleted file mode 100644 index b9b65b63b3e..00000000000 --- a/doc/release_notes_0.9.8.txt +++ /dev/null @@ -1,99 +0,0 @@ - Release notes - ejabberd 0.9.8 - 2005-08-01 - - This document describes the main changes in ejabberd 0.9.8. This - version prepares the way for the release of ejabberd 1.0, which - is due later this year. - - The code can be downloaded from the Process-one website: - http://www.process-one.net/en/projects/ejabberd/ - - For more detailed information, please refer to ejabberd User Guide - on the Process-one website: - http://www.process-one.net/en/projects/ejabberd/docs.html - - - Recent changes include.... - - -Enhanced virtual hosting - - Virtual hosting applies to many more setting options and - features and is transparent. Virtual hosting accepts different - parameters for different virtual hosts regarding the following - features: authentication method, access control lists and access - rules, users management, statistics, and shared roster. The web - interface gives access to each virtual host's parameters. - - -Enhanced Publish-Subscribe module - - ejabberd's Publish-Subscribe module integrates enhancements - coming from J-EAI, an XMPP-based integration server built on - ejabberd. ejabberd thus supports Publish-Subscribe node - configuration. It is possible to define nodes that should be - persistent, and the number of items to persist. Besides that, it - is also possible to define various notification parameters, such - as the delivery of the payload with the notifications, and the - notification of subscribers when some changes occur on items. - Other examples are: the maximum size of the items payload, the - subscription approvers, the limitation of the notification to - online users only, etc. - - -Code reorganisation and update - - - The mod_register module has been cleaned up. - - ODBC support has been updated and several bugs have been fixed. - - -Development API - - To ease the work of Jabber/XMPP developers, a filter_packet hook - has been added. As a result it is possible to develop plugins to - filter or modify packets flowing through ejabberd. - - -Translations - - - Translations have been updated to support the new Publish-Subscribe features. - - A new Brazilian Portuguese translation has been contributed. - - -Web interface - - - The CSS stylesheet from the web interface is W3C compliant. - - -Installers - - Installers are provided for Microsoft Windows and Linux/x86. The - Linux installer includes Erlang ASN.1 modules for LDAP - authentication support. - - -Bugfixes - - - This release contains several bugfixes and architectural - changes. Among other bugfixes include improvements in LDAP - authentication. Please refer to the ChangeLog file supplied - with this release regarding all improvements in ejabberd. - - -References - - The ejabberd feature sheet helps comparing with other Jabber/XMPP - servers: - http://www.process-one.net/en/projects/ejabberd/docs/features.pdf - - Contributed tutorials of interest are: - - Migration from Jabberd1.4 to ejabberd: - http://ejabberd.jabber.ru/jabberd1-to-ejabberd - - Migration from Jabberd2 to ejabberd: - http://ejabberd.jabber.ru/jabberd2-to-ejabberd - - Transport configuration for connecting to other networks: - http://ejabberd.jabber.ru/tutorials-transports - -END - diff --git a/doc/release_notes_0.9.txt b/doc/release_notes_0.9.txt deleted file mode 100644 index 6bdce830f37..00000000000 --- a/doc/release_notes_0.9.txt +++ /dev/null @@ -1,88 +0,0 @@ - Release notes - ejabberd 0.9 - - This document describes the major new features of and changes to - ejabberd 0.9, compared to latest public release ejabber 0.7.5. - - For more detailed information, please refer to ejabberd User - Guide. - - -Virtual Hosting - - ejabberd now can host several domain on the same instance. - This option is enabled by using: - - {hosts, ["erlang-projects.org", "erlang-fr.org"]}. - - instead of the previous host directive. - - Note that you are now using a list of hosts. The main one should - be the first listed. See migration section further in this release - note for details. - - -Shared Roster - - Shared roster is a new feature that allow the ejabberd - administrator to add jabber user that will be present in the - roster of every users on the server. - Shared roster are enabled by adding: - - {mod_shared_roster, []} - - at the end of your module list in your ejabberd.cfg file. - - -PostgreSQL (ODBC) support - - This feature is experimental and not yet properly documented. This - feature is released for testing purpose. - - You need to have Erlang/OTP R10 to compile with ODBC on various - flavour of *nix. You should use Erlang/OTP R10B-4, as this task - has became easier with this release. It comes already build in - Erlang/OTP Microsoft Windows binary. - - PostgreSQL support is enabled by using the following module in - ejabberd.cfg instead of their standard counterpart: - - mod_last_odbc.erl - mod_offline_odbc.erl - mod_roster_odbc.erl - - The database schema is located in the src/odbc/pq.sql file. - - Look at the src/ejabberd.cfg.example file for more information on - how to configure ejabberd with odbc support. You can get support - on how to configure ejabberd with a relational database. - - -Migration from ejabberd 0.7.5 - - Migration is pretty straightforward as Mnesia database schema - conversions is handled automatically. Remember however that you - must backup your ejabberd database before migration. - - Here are the following steps to proceed: - - 1. Stop your instance of ejabberd. - - 2. In ejabberd.cfg, define the host lists. Change the host - directive to the hosts one: - Before: - {host, "erlang-projects.org"}. - After: - {hosts, ["erlang-projects.org", "erlang-fr.org"]}. - Note that when you restart the server the existing users will be - affected to the first virtual host, so the order is important. You - should keep the previous hostname as the first virtual host. - - 3. Restart ejabberd. - - -Bugfixes - - This release contains several bugfixes and architectural changes. - Please refer to the Changelog file supplied with this release for - details of all improvements in the ejabberd code. diff --git a/doc/release_notes_1.0.0.txt b/doc/release_notes_1.0.0.txt deleted file mode 100644 index 426ba63fa47..00000000000 --- a/doc/release_notes_1.0.0.txt +++ /dev/null @@ -1,120 +0,0 @@ - Release Notes - ejabberd 1.0.0 - 14 December 2005 - - This document describes the main changes in ejabberd 1.0.0. Unique in this - version is the compliancy with the XMPP (eXtensible Messaging and Presence - Protocol) standard. ejabberd is the first Open Source Jabber server claiming - to fully comply to the XMPP standard. - - ejabberd can be downloaded from the Process-one website: - http://www.process-one.net/en/projects/ejabberd/ - - Detailed information can be found in the ejabberd Feature Sheet and User - Guide which are available on the Process-one website: - http://www.process-one.net/en/projects/ejabberd/docs.html - - - Recent changes include: - - -Server-to-server Encryption for Enhanced Security - - - Support for STARTTLS and SASL EXTERNAL to secure server-to-server traffic - has been added. - - Also, STARTTLS and Dialback has been implemented for server-to-server (s2s) - connections. Detailed information about these new features can be found on - http://ejabberd.jabber.ru/s2s-encryption - - commonName and dNSName fields matching were introduced to ease the process - of retrieving certificates. - - Different certificates can be defined for each virtual host. - -ODBC Support - - - ODBC support has been improved to allow production use of ejabberd with - relational databases. - - Support for vCard storage in ODBC has been added. - - ejd2odbc.erl is a tool to convert an installation from Erlang's database - Mnesia to an ODBC compatible relational database. - -Native PostgreSQL Support - - - Native PostgreSQL support gives you a better performance when you use - PostgreSQL. - -Shared Roster groups - - - Shared Roster groups support has been enhanced. New is the ability to add - all registered users to everyone's roster. Detailed information about this - new feature can be found on http://ejabberd.jabber.ru/shared-roster-all - -Web Interface - - - The web interface internal code has been modified for better integration - and compliancy with J-EAI, an ejabberd-based Enterprise Application - Integration platform. - - More XHTML 1.0 Transitional compliancy work was done. - -Transports - - - A transport workaround can be enabled during compilation. To do this, you - can pass the "--enable-roster-gateway-workaround" option to the configure - script. (./configure --enable-roster-gateway-workaround) - This option allows transports to add items with subscription "to" in the - roster by sending stanza to user. This option - is only needed for JIT ICQ transport. - Warning: by enabling this option, ejabberd will not be fully XMPP compliant - anymore. - -Documentation and Internationalization - - - Documentation has been extended to cover more topics. - - Translations have been updated. - -Bugfixes - - - This release contains several bugfixes. - - Among other bugfixes include improvements to the client-to-server (c2s) - connection management module. - - Please refer to the ChangeLog file supplied - with this release regarding all improvements in ejabberd. - - - Installation Notes - - -Supported Erlang Version - - - You need at least Erlang/OTP R9C to run ejabberd 1.0.0. - -Installation - - Installers are provided for Microsoft Windows and Linux/x86. - Installers can be retrieved from: - http://www.process-one.net/en/projects/ejabberd/download.html - -Migration Notes - - - Before any migration, ejabberd system and database must be properly - backed up. - - When upgrading an ODBC-based installation, you will need to change the - relational database schema. The following SQL commands must be run on the - database: - CREATE SEQUENCE spool_seq_seq; - ALTER TABLE spool ADD COLUMN seq integer; - ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq'); - UPDATE spool SET seq = DEFAULT; - ALTER TABLE spool ALTER COLUMN seq SET NOT NULL; - -References - - Contributed tutorials of interest are: - - Migration from Jabberd1.4 to ejabberd: - http://ejabberd.jabber.ru/jabberd1-to-ejabberd - - Migration from Jabberd2 to ejabberd: - http://ejabberd.jabber.ru/jabberd2-to-ejabberd - - Transport configuration for connecting to other networks: - http://ejabberd.jabber.ru/tutorials-transports - -END - diff --git a/doc/release_notes_1.1.0.txt b/doc/release_notes_1.1.0.txt deleted file mode 100644 index fbef6a93469..00000000000 --- a/doc/release_notes_1.1.0.txt +++ /dev/null @@ -1,115 +0,0 @@ - Release Notes - ejabberd 1.1.0 - 24 April 2006 - - This document describes the main changes in ejabberd 1.1.0. This version - introduce new features including support for new Jabber Enhancement - Proposals and several performance improvements enabling deployments on an - even larger scale than already possible. - - ejabberd can be downloaded from the Process-one website: - http://www.process-one.net/en/projects/ejabberd/ - - Detailed information can be found in the ejabberd Feature Sheet and User - Guide which are available on the Process-one website: - http://www.process-one.net/en/projects/ejabberd/docs.html - - A complete list of changes is available from: - http://support.process-one.net/secure/ReleaseNote.jspa?projectId=10011&styleName=Html&version=10025 - - - Recent changes include: - - -New Jabber Enhancement Proposal support: - - - JEP-0050: Ad-Hoc Commands. - - JEP-0138: Stream Compression. - - JEP-0175: SASL anonymous. - -Anonymous login - - - SASL anonymous. - - Anonymous login for clients that do not yet support SASL Anonymous. - -Relational database Support - - - MySQL is now fully supported through ODBC and in native mode. - - Various improvements to the native database interfaces. - - The migration tool can use relational databases. - -Multi-User Chat improvements - - - Logging of room discussion to text file is now supported. - - Better reconfiguration support. - - Security oriented fixes. - - Several improvements and updates to latest JEP-0045. - -Performance scalability improvements for large clusters - - - Improved session synchronisation management between cluster nodes. - - Internal architecture has been reworked to use generalize Erlang/OTP - framework usage. - - Speed improvement on logger. - - TCP/IP packet reception change for better network throttling and - regulation. - As a result, these improvements will reduce load on large scale deployments. - -XMPP Protocol related improvements - - - XML stanza size can be limited. - - Messages are send to all resources with the same highest priority. - -Documentation and Internationalization - - - Documentation has been extended to cover more topics. - - Translations have been updated. - -Web interface - - - XHTML 1.0 compliance. - -Bugfixes - - - This release contains many bugfixes on various areas such as Publish-Subscribe, build - chain, installers, IRC gateway, ejabberdctl, amongst others. - - Please refer to the ChangeLog file supplied with this release regarding - all improvements in ejabberd. - - - - Installation Notes - -Supported Erlang Version - - - You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.0. - -Installation - - Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC. - Installers can be retrieved from: - http://www.process-one.net/en/projects/ejabberd/download.html - -Migration Notes - - - Before any migration, ejabberd system and database must be properly - backed up. - - The database schema has not been changed comparing to version 1.0.0 and - consequently it does not require any migration. - - -References - - Contributed tutorials and documents of interest are: - - Migration from Jabberd1.4, Jabberd2 and WPJabber to ejabberd: - http://ejabberd.jabber.ru/migrate-to-ejabberd - - Transport configuration for connecting to other networks: - http://ejabberd.jabber.ru/tutorials-transports - - Using ejabberd with MySQL native driver: - http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver - - Anonymous User Support: - http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support - - Frequently Asked Questions: - http://ejabberd.jabber.ru/faq - -END diff --git a/doc/release_notes_1.1.1.txt b/doc/release_notes_1.1.1.txt deleted file mode 100644 index e2f4273daff..00000000000 --- a/doc/release_notes_1.1.1.txt +++ /dev/null @@ -1,119 +0,0 @@ - Release Notes - ejabberd 1.1.1 - 28 April 2006 - - This document describes the main changes in ejabberd 1.1.x. This version - introduce new features including support for new Jabber Enhancement - Proposals and several performance improvements enabling deployments on an - even larger scale than already possible. - - This release fix a security issue introduced in ejabberd 1.1.0. In SASL - mode, anonymous login was enabled as a default. Upgrading ejabberd 1.1.0 to - ejabberd 1.1.1 is highly recommended. - - ejabberd can be downloaded from the Process-one website: - http://www.process-one.net/en/projects/ejabberd/ - - Detailed information can be found in the ejabberd Feature Sheet and User - Guide which are available on the Process-one website: - http://www.process-one.net/en/projects/ejabberd/docs.html - - A complete list of changes is available from: - http://support.process-one.net/secure/ReleaseNote.jspa?projectId=10011&styleName=Html&version=10025 - - - Recent changes include: - - -New Jabber Enhancement Proposal support: - - - JEP-0050: Ad-Hoc Commands. - - JEP-0138: Stream Compression. - - JEP-0175: SASL anonymous. - -Anonymous login - - - SASL anonymous. - - Anonymous login for clients that do not yet support SASL Anonymous. - -Relational database Support - - - MySQL is now fully supported through ODBC and in native mode. - - Various improvements to the native database interfaces. - - The migration tool can use relational databases. - -Multi-User Chat improvements - - - Logging of room discussion to text file is now supported. - - Better reconfiguration support. - - Security oriented fixes. - - Several improvements and updates to latest JEP-0045. - -Performance scalability improvements for large clusters - - - Improved session synchronisation management between cluster nodes. - - Internal architecture has been reworked to use generalize Erlang/OTP - framework usage. - - Speed improvement on logger. - - TCP/IP packet reception change for better network throttling and - regulation. - As a result, these improvements will reduce load on large scale deployments. - -XMPP Protocol related improvements - - - XML stanza size can be limited. - - Messages are send to all resources with the same highest priority. - -Documentation and Internationalization - - - Documentation has been extended to cover more topics. - - Translations have been updated. - -Web interface - - - XHTML 1.0 compliance. - -Bugfixes - - - This release contains many bugfixes on various areas such as Publish-Subscribe, build - chain, installers, IRC gateway, ejabberdctl, amongst others. - - Please refer to the ChangeLog file supplied with this release regarding - all improvements in ejabberd. - - - - Installation Notes - -Supported Erlang Version - - - You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.0. - -Installation - - Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC. - Installers can be retrieved from: - http://www.process-one.net/en/projects/ejabberd/download.html - -Migration Notes - - - Before any migration, ejabberd system and database must be properly - backed up. - - The database schema has not been changed comparing to version 1.0.0 and - consequently it does not require any migration. - - -References - - Contributed tutorials and documents of interest are: - - Migration from Jabberd1.4, Jabberd2 and WPJabber to ejabberd: - http://ejabberd.jabber.ru/migrate-to-ejabberd - - Transport configuration for connecting to other networks: - http://ejabberd.jabber.ru/tutorials-transports - - Using ejabberd with MySQL native driver: - http://support.process-one.net/doc/display/MESSENGER/Using+ejabberd+with+MySQL+native+driver - - Anonymous User Support: - http://support.process-one.net/doc/display/MESSENGER/Anonymous+users+support - - Frequently Asked Questions: - http://ejabberd.jabber.ru/faq - -END diff --git a/doc/release_notes_1.1.2.txt b/doc/release_notes_1.1.2.txt deleted file mode 100644 index e7c8f3551ff..00000000000 --- a/doc/release_notes_1.1.2.txt +++ /dev/null @@ -1,119 +0,0 @@ - Release Notes - ejabberd 1.1.2 - 27 September 2006 - - This document describes the main changes in ejabberd 1.1.2. - - This version is a major improvement over ejabberd 1.1.1, improving the - overall behaviour of the server in many areas. Users of ejabberd 1.1.1 - should upgrade to this new release for improved robustness and compliance. - - ejabberd can be downloaded from the Process-one website: - http://www.process-one.net/en/projects/ejabberd/ - - Detailed information can be found in the Feature Sheet and in the - Installation and Operation Guide which are both available on the - Process-one website: - http://www.process-one.net/en/projects/ejabberd/docs.html - - ejabberd includes 44 improvements. A complete list of changes can be - retrieved from: - http://redir.process-one.net/ejabberd-1.1.2 - - - Recent changes include: - -LDAP Improvements - - - Major improvements have been made on the LDAP module. It is now more - flexible and more robust. - -HTTP Polling Fixes - - - The HTTP polling modules have been fixed and improved: the connections are - closed properly and polled messages cannot be lost anymore. - -Roster Management Improvement - - - Roster management improvements increase reliability, especially in cases - where users are on different servers. - - Shared rosters are more reliable. - -Improved Robustness - - - It is now possible to limit the number of opened connections for a single - user. - -Relational databases - - - Database support: Microsoft SQL Server is now officially supported in ODBC - mode. - -Publish-Subscribe Improvement - - - Restricting node creation with a dedicated ACL rule is now possible. - -Localization - - - A Czech translation has been added. - - Translations have been updated. - -Binary Installer - - - New binary installer for Windows including all requirements. - - Improved installers for Linux and MacOSX (PowerPC) - -XMPP Compliancy - - - Some protocol compliance fix have been added, after the Portland XMPP - Interop Meeting in July. - -Miscelanous - - - MUC have been improved (logging rendering). - - The command line tool ejabberdctl has been improved. - - The build chain has been improved, including MacOSX support. - - The documentation has been improved and updated to describe the new - features. - -Bugfixes - - - Anonymous login bugfixes. - - Please refer to the ChangeLog file supplied with this release regarding - all improvements in ejabberd. - - - Installation Notes - -Supported Erlang Version - - - You need at least Erlang/OTP R9C-2 to run ejabberd 1.1.2. - - The recommanded version is Erlang/OTP R10B-10. - - Erlang/OTP R11B has not yet been fully certified for ejabberd. - -Installation - - Installers are provided for Microsoft Windows, Linux/x86 and MacOSX/PPC. - They can be retrieved from: - http://www.process-one.net/en/projects/ejabberd/download.html - -Migration Notes - - - Before any migration, ejabberd system and database must be properly - backed up. - - The relational database schema has changed between version 1.1.1 and - 1.1.2. An "askmessage" column needs to be added in the "rosterusers" table - to perform the migration. - - -References - - Contributed tutorials and documents of interest are: - - Migration from other XMPP servers to ejabberd: - http://ejabberd.jabber.ru/migrate-to-ejabberd - - Transport configuration for connecting to other networks: - http://ejabberd.jabber.ru/tutorials-transports - - Frequently Asked Questions: - http://ejabberd.jabber.ru/faq - -END diff --git a/doc/release_notes_1.1.3.txt b/doc/release_notes_1.1.3.txt deleted file mode 100644 index f298f2bab16..00000000000 --- a/doc/release_notes_1.1.3.txt +++ /dev/null @@ -1,14 +0,0 @@ - Release Notes - ejabberd 1.1.3 - 2 February 2007 - - ejabberd 1.1.3 is a security fix release for ejabberd roster ODBC - module. - - The upgrade is only necessary if you are using ejabberd with the - mod_roster_odbc. - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/projects/ejabberd/ - -END diff --git a/doc/release_notes_1.1.4.txt b/doc/release_notes_1.1.4.txt deleted file mode 100644 index 76c10890467..00000000000 --- a/doc/release_notes_1.1.4.txt +++ /dev/null @@ -1,31 +0,0 @@ - Release Notes - ejabberd 1.1.4 - 3 september 2007 - - ejabberd 1.1.4 is a bugfix release for ejabberd 1.1.x branch. - - ejabberd 1.1.4 includes 10 improvements. A complete list of changes - can be retrieved from: - http://redir.process-one.net/ejabberd-1.1.4 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/projects/ejabberd/ - - - Recent changes include: - -- Better LDAP support. -- Support for UTF-8 with MySQL 5. -- Roster migration script bugfixes. -- Performance improvements on user removal. -- Traffic shapers bugfix. -- Configuration: host value is now case insensitive. -- Build: ejabberd.cfg file is not overwritten with 'make install' command. - - -Bugs report - - You can officially report bugs on Process-one support site: - http://support.process-one.net/ - -END diff --git a/doc/release_notes_2.0.0.txt b/doc/release_notes_2.0.0.txt deleted file mode 100644 index 963a6524685..00000000000 --- a/doc/release_notes_2.0.0.txt +++ /dev/null @@ -1,208 +0,0 @@ - - Release Notes - ejabberd 2.0.0 - 21 February 2008 - - ejabberd 2.0.0 is a major new version for ejabberd adding plenty of - new features, performance and scalability improvements and - architectural changes. - - ejabberd 2.0.0 includes more than 200 improvements over ejabberd - 1.1.x. A complete list of changes can be retrieved from: - http://redir.process-one.net/ejabberd-2.0.0 - - The new code can be downloaded from ejabberd downloads page: - http://www.process-one.net/en/ejabberd/ - - - Recent changes include: - - -* Clustering and Architecture - -- New front-end and back-end cluster architecture for better - scalability and robustness. Back-end nodes are able to run a fully - fault-tolerant XMPP router and services, but you can now deploy - many front-end nodes to share the load without needing to synchronize - any state with the back-ends. -- All components now run in cluster mode (For example, Multi-User chat - service and file transfer proxy). -- New load balancing algorithm to support Multi-User chat and gateways - clustering. More generally it supports any external component load - balancing. -- ejabberd watchdog to receive warning on suspicious resources consumption. -- Traffic shapers are now supported on components. This protect - ejabberd from components and gateways abuses. - - -* Publish and Subscribe - -- Complete rewrite of the PubSub module. The new PubSub module is - plugin-based, allowing developers to create new nodes type. Any - application can be plugged to ejabberd and can provide rich presence - as a pubsub plugin. -- Personal Eventing via Pubsub support (XEP-0163). This module is - implemented as a PubSub service. It supports user mood (XEP-107), - User Tune (XEP-118), user location (XEP-0080) or user avatar - (XEP-0084) for example. - - -* Server to Server (s2s) - -- More robust code with connection timeout implementation. -- Support for multiple s2s connections per domain. -- s2s whitelist and blacklist support. -- s2s retrial interval. - - -* LDAP - -- Many enterprise-class enhancements such as better behaviour under - heavy load. -- Support for LDAP servers pool. -- Simplified use of virtual hosting with LDAP with domain substitution - in config. -- Ability to match on several userid attributes. - - -* Multi-User Chat - -- Clustering and load balancing support. -- Ability to define default room configuration in ejabberd config file. -- Many anti abuse features have been added: - . New ACL to limit the creation of persistent room to authorized users. - . Ability to define the maximum number of users per room. - . Limitation of the rate of message and presence packets. - . Limitation of the maximum number of room a user can join at the same time. - - -* File Transfer - -- XEP-0065 - Proxy65 file transfer proxy. The proxy can run in - cluster mode. - - -* Authentication - -- PAM (Pluggable Authentication Modules) support on *nix systems. -- External Authentication protocol is now fully documented. - - -* Web Client Support - -- XEP-0124 - BOSH support: BOSH (Bidirectional-streams Over - Synchronous HTTP) was formerly known as "HTTP binding". It provides - an efficient alternative to HTTP polling for scalable Web based chat - solutions. -- HTTP module can now serve static documents (with - mod_http_fileserver). It is needed for high-performance Web 2.0 chat - / IM application. System administrators can now avoid using a proxy - (like Apache) that handles much less simultaneous than ejabberd HTTP - module. -- Added limitations enforcement on HTTP poll and HTTP bind modules - (bandwidth, packet size). - - -* System Administration - -- XEP-0133 - Service administration support. System administrators can - now perform lot of ejabberd related admin tasks from their XMPP - client, through adhoc commands. -- Dynamic log levels: Improved logging with more log levels. You can - now change the loglevel at run time. No performance penalty is - involved when less verbose levels are used. -- The ejabberdctl command-line administration script now can start - and stop ejabberd. It also includes other useful options. - - -* Localization - -- ejabberd is now translated to 24 languages: Catalan, Chinese, Czech, - Dutch, English, Esperanto, French, Galician, German, Italian, Japanese, - Norwegian, Polish, Portuguese, Portuguese (Brazil), Russian, Slovak, - Spanish, Swedish, Thai, Turkish, Ukrainian, Vietnamese, Walloon. - - -* Build and Installer - -- Many launch script improvements. -- New translations. The binary installer is now available in Chinese, - Dutch, English, French, German, Spanish, Russian. -- Makefile now implements uninstall command. -- Full MacOSX compliance in Makefile. -- Configure script is clever at finding libraries in unusual places. - - -* Development API - -- Several hooks have been added for module developers (most notably - presence related hooks). -- HTTP request handler to write HTTP based plugins. -- Manage connections IP address. - - -* Bugfixes - -- ejabberd 2.0.0 also fixes numerous small bugs :) Read the full - changelog for details. - - - - Important Note: - -- Since this release, ejabberd requires Erlang R10B-5 or higher. - R11B-5 is the recommended version. R12 is not yet officially - supported, and is not recommended for production servers. - - - - Upgrading From ejabberd 1.x: - -- If you upgrade from a version older than 1.1.4, please check the - Release Notes of the intermediate versions for additional - information about database or configuration changes. - -- The database schemas didn't change since ejabberd 1.1.4. Of course, - you are encouraged to make a database backup of your SQL database, - or your Mnesia spool directory before upgrading ejabberd. - -- The ejabberdctl command line administration script is improved in - ejabberd 2.0.0, and now it can start and stop ejabberd. If you - already wrote your own start script for ejabberd 1.x, you can - continue using it, or try ejabberdctl. For your convenience, the - ejabberd Guide describes all the ejabberd and Erlang options used by - ejabberdctl. - -- The example ejabberd.cfg file has been reorganized, but its format - and syntax rules are the same. So, you can continue using your - ejabberd.cfg file from 1.x if you want. The most important changes - are described now. - -- The 'ssl' option is no longer available in the listening ports. For - legacy SSL encryption use the option 'tls'. For STARTTLS encryption - as defined in RFC 3920 XMPP-CORE use the option 'starttls'. Check - the ejabberd Guide for more information about configuring listening - ports. - -- The options 'welcome_message' and 'registration_watchers' are now - options of the module mod_register. Check in the ejabberd Guide how - to configure that module. - -- To enable PEP support in mod_pubsub, you need to enable it in the - mod_pubsub configuration, and also enable the new module - mod_caps. Check the section about mod_pubsub in the ejabberd Guide. - -- Other new features and improvements also require changes in the - ejabberd.cfg, like mod_http_bind, mod_http_fileserver, mod_proxy65, - loglevel, pam_service, and watchdog_admins. Search for those words - in the ejabberd Guide and the example ejabberd.cfg. - - - - Bug Reports - - You can officially report bugs on Process-one support site: - https://support.process-one.net/ - - -END \ No newline at end of file diff --git a/doc/release_notes_2.0.1.txt b/doc/release_notes_2.0.1.txt deleted file mode 100644 index b9b075576db..00000000000 --- a/doc/release_notes_2.0.1.txt +++ /dev/null @@ -1,30 +0,0 @@ - - Release Notes - ejabberd 2.0.1 - 20 May 2008 - - ejabberd 2.0.1 is a bugfix release for ejabberd 2.0.x branch. - - ejabberd 2.0.1 includes 10 improvements and 32 bugfixes. - A complete list of changes can be retrieved from: - http://redir.process-one.net/ejabberd-2.0.1 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/projects/ejabberd/ - - - Recent changes include: - -- Erlang R12 support. -- Better LDAP handling. -- PubSub bugfixes. -- Documentation improvements. -- inband registration limitation per IP. -- s2s improvements. - -Bugs report - - You can officially report bugs on Process-one support site: - http://support.process-one.net/ - -END diff --git a/doc/release_notes_2.0.2.txt b/doc/release_notes_2.0.2.txt deleted file mode 100644 index 767ae136767..00000000000 --- a/doc/release_notes_2.0.2.txt +++ /dev/null @@ -1,34 +0,0 @@ - - Release Notes - ejabberd 2.0.2 - 28 August 2008 - - ejabberd 2.0.2 is the second bug fix release for ejabberd 2.0.x branch. - - ejabberd 2.0.2 includes many bugfixes and a few improvements. - A complete list of changes can be retrieved from: - http://redir.process-one.net/ejabberd-2.0.2 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - Recent changes include: - -- Anti-abuse feature: client blacklist support by IP. -- Guide: new section Securing ejabberd; improved usability. -- LDAP filter optimisation: ability to filter user in ejabberd and not LDAP. -- MUC improvements: room options to restrict visitors; broadcast reasons. -- Privacy rules: fix MySQL storage. -- Pub/Sub and PEP: many improvements in implementation and protocol compliance. -- Proxy65: send valid SOCKS5 reply (removed support for Psi < 0.10). -- Web server embedded: better support for HTTPS. -- Binary installers: SMP on Windows; don't remove config when uninstalling. - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ - -END diff --git a/doc/release_notes_2.0.3.txt b/doc/release_notes_2.0.3.txt deleted file mode 100644 index 13fe9a17424..00000000000 --- a/doc/release_notes_2.0.3.txt +++ /dev/null @@ -1,35 +0,0 @@ - - Release Notes - ejabberd 2.0.3 - 14 January 2009 - - ejabberd 2.0.3 is the third bugfix release for ejabberd 2.0.x branch. - - ejabberd 2.0.3 includes several bugfixes and a few improvements. - A complete list of changes can be retrieved from: - http://redir.process-one.net/ejabberd-2.0.3 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - Recent changes include: - -- Do not ask certificate for client (c2s) -- Check digest-uri in SASL digest authentication -- Use send timeout to avoid locking on gen_tcp:send -- Fix ejabberd reconnection to database -- HTTP-Bind: handle wrong order of packets -- MUC: Improve traffic regulation management -- PubSub: Several bugfixes and improvements for best coverage of XEP-0060 v1.12 -- Shared Roster Groups: push immediately membership changes -- Rotate also sasl.log on "reopen-log" command -- Binary Windows installer: better detect "Error running Post Install Script" - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ - -END diff --git a/doc/release_notes_2.0.4.txt b/doc/release_notes_2.0.4.txt deleted file mode 100644 index 24f943779fd..00000000000 --- a/doc/release_notes_2.0.4.txt +++ /dev/null @@ -1,44 +0,0 @@ - - Release Notes - ejabberd 2.0.4 - - ejabberd 2.0.4 is the fourth bugfix release for ejabberd 2.0.x branch. - - ejabberd 2.0.4 includes several bugfixes. - A detailed list of changes can be retrieved from: - http://redir.process-one.net/ejabberd-2.0.4 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - The changes are: - -- Ensure ID attribute in roster push is unique -- Authentication: Fix Anonymous auth when enabled with broken ODBC -- Authentication: Unquote correctly backslash in DIGEST-MD5 SASL responses -- Authentication: Cancel presence subscriptions on account deletion -- LDAP: Close a connection on tcp_error -- LDAP: Implemented queue for pending queries -- LDAP: On failure of LDAP connection, waiting is done on pending queue -- MUC: Owner of a password protected room must also provide the password -- MUC: Prevent XSS in MUC logs by linkifying only a few known protocols -- Privacy rules: Items are now processed in the specified order -- Privacy rules: Fix to correctly block subscription requests -- Proxy65: If ip option is not defined, take an IP address of a local hostname -- PubSub: Add roster subscription handling; send PEP events to all resources -- PubSub: Allow node creation without configure item -- PubSub: Requesting items on a node which exists, but empty returns an error -- PEP: Fix sending notifications to other domains and s2s -- S2S: Fix problem with encrypted connection to Gtalk and recent Openfire -- S2S: Workaround to get DNS SRV lookup to work on Windows machine -- Shared Roster Groups: Fix to not resend authorization request -- WebAdmin: Fix encryption problem for ejabberd_http after timeout - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ - -END diff --git a/doc/release_notes_2.0.5.txt b/doc/release_notes_2.0.5.txt deleted file mode 100644 index cf652ccfee9..00000000000 --- a/doc/release_notes_2.0.5.txt +++ /dev/null @@ -1,33 +0,0 @@ - - Release Notes - ejabberd 2.0.5 - - ejabberd 2.0.5 is the fifth bugfix release in ejabberd 2.0.x branch. - - ejabberd 2.0.5 includes three bugfixes. - More details of those fixes can be retrieved from: - http://redir.process-one.net/ejabberd-2.0.5 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - The changes are: - -- Fix two problems introduced in ejabberd 2.0.4: subscription request - produced many authorization requests with some clients and - transports; and subscription requests were not stored for later - delivery when receiver was offline. - -- Fix warning in expat_erl.c about implicit declaration of x_fix_buff - -- HTTP-Bind (BOSH): Fix a missing stream:error in the returned - remote-stream-error stanza - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ - -END diff --git a/doc/release_notes_2.1.0.txt b/doc/release_notes_2.1.0.txt deleted file mode 100644 index 85f2f48ffda..00000000000 --- a/doc/release_notes_2.1.0.txt +++ /dev/null @@ -1,281 +0,0 @@ - - Release Notes - ejabberd 2.1.0 - - ejabberd 2.1.0 is a major new version for ejabberd adding many - new features, performance and scalability improvements. - - ejabberd 2.1.0 includes many new features, improvements and bug fixes. - A complete list of changes can be retrieved from: - http://redir.process-one.net/ejabberd-2.1.0 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - New features and improvements: - -* Anti-abuse -- Captcha support (XEP-0158). The example script uses ImageMagick. -- New option: registration_timeout to limit registrations by time -- Use send timeout to avoid locking on gen_tcp:send -- mod_ip_blacklist: client blacklist support by IP - -* API -- ejabberd_http provides Host, Port, Headers and Protocol in HTTP requests -- Export function to create MUC room -- New events: s2s_send_packet and s2s_receive_packet -- New event: webadmin_user_parse_query when POST in web admin user page -- Support distributed hooks over the cluster - -* Authentification -- Extauth responses: log strange responses and add timeout - -* Binary Installer -- Includes exmpp library to support import/export XML files - -* Caps -- Remove useless caps tables entries -- mod_caps must handle correctly external contacts with several resources -- Complain if mod_caps disabled and mod_pubsub has PEP plugin enabled - -* Clustering and Architecture - -* Configuration -- Added option access_max_user_messages for mod_offline -- Added option backlog for ejabberd_listener to increase TCP backlog -- Added option define_macro and use_macro -- Added option include_config_file to include additional configuration files -- Added option max_fsm_queue -- Added option outgoing_s2s_options to define IP address families and timeout -- Added option registration_timeout to ejabberd.cfg.example -- Added option s2s_dns_options to define DNS timeout and retries -- Added option ERL_OPTIONS to ejabberdctl.cfg -- Added option FIREWALL_WINDOW to ejabberdctl.cfg -- Added option EJABBERD_PID_PATH to ejabberdctl.cfg -- Deleted option user_max_messages of mod_offline -- Check certfiles are readable on server start and listener start -- Config file management mix file reading and sanity check -- Include example PAM configuration file: ejabberd.pam -- New ejabberd listener: ejabberd_stun -- Support to bind the same port to multiple interfaces -- New syntax to specify the IP address and IPv6 in listeners - configuration. The old options {ip,{1,2,3,4}} and inet6 are - supported even if they aren't documented. -- New syntax to specify the network protocol: tcp or udp -- Report error at startup if a listener module isn't available -- Only listen in a port when actually ready to serve requests -- In default config, only local accounts can create rooms and PubSub nodes - -* Core architecture -- More verbose error reporting for xml:element_to_string -- Deliver messages when first presence is Invisible -- Better log message when config file is not found -- Include original timestamp on delayed presences - -* Crypto -- Do not ask certificate for client (c2s) -- SSL code remove from ejabberd in favor of TLS -- Support Zlib compression after STARTTLS encryption -- tls v1 client hello - -* Documentation -- Document possible default MUC room options -- Document service_check_from in the Guide -- Document s2s_default_policy and s2s_host in the Guide -- new command and guide instructions to change node name in a Mnesia database - -* ejabberd commands -- ejabberd commands: separate command definition and calling interface -- access_commands restricts who can execute what commands and arguments -- ejabberdctl script now displays help and categorization of commands - -* HTTP Binding and HTTP Polling -- HTTP-Bind: module optimization and clean-up -- HTTP-Bind: allow configuration of max_inactivity timeout -- HTTP-Poll: turn session timeout into a config file parameter - -* Jingle -- STUN server that facilitates the client-to-client negotiation process - -* LDAP -- Faster reconnection to LDAP servers -- LDAP filter optimisation: Add ability to filter user in ejabberd and not LDAP -- LDAP differentiates failed auth and unavailable auth service -- Improve LDAP logging -- LDAPS support using TLS. - -* Localization -- Use Gettext PO for translators, export to ejabberd MSG -- Support translation files for additional projects -- Most translations are updated to latest code -- New translation to Greek language - -* Multi-User Chat (MUC) -- Allow admins to send messages to rooms -- Allow to store room description -- Captcha support in MUC: the admin of a room can configure it to - require participants to fill a captcha to join the room. -- Limit number of characters in Room ID, Name and Description -- Prevent unvoiced occupants from changing nick -- Support Result Set Management (XEP-0059) for listing rooms -- Support for decline of invitation to MUC room -- mod_muc_log options: plaintext format; filename with only room name - -* Performance -- Run roster_get_jid_info only if privacy list has subscription or group item -- Significant PubSub performance improvements - -* Publish-Subscribe -- Add nodetree filtering/authorization -- Add subscription option support for collection nodes -- Allow Multiple Subscriptions -- Check option of the nodetree instead of checking configuration -- Implement whitelist authorize and roster access model -- Implicit item deletion is not notified when deleting node -- Make PubSub x-data configuration form handles list value -- Make default node name convention XEP-compatible, document usage of hierarchy -- Node names are used verbatim, without separating by slash, unless a - node plugin uses its own separator -- Send authorization update event (XEP-0060, 8.6) -- Support of collection node subscription options -- Support ODBC storage. Experimental, needs more testing. - -* Relational databases: -- Added MSSQL 2000 and 2005 -- Privacy rules storage in MySQL -- Implement reliable ODBC transaction nesting - -* Source Package -- Default installation directories changed. Please see the upgrade notes below. -- Allow more environment variable overrides in ejabberdctl -- ChangeLog is not edited manually anymore; it's generated automatically. -- Install the ejabberd Guide -- Install the ejabberd include files -- New option for the 'configure' script: --enable-user which installs - ejabberd granting permission to manage it to a regular system user; - no need to use root account to. -- Only try to install epam if pam was enabled in configure script -- Spool, config and log dirs: owner writes, group reads, others do nothing. -- Provides an example ejabberd.init file - -* S2S -- Option to define s2s outgoing behaviour: IPv4, IPv6 and timeout -- DNS timeout and retries, configurable with s2s_dns_options. - -* Shared rosters -- When a member is added/removed to group, send roster upgrade to group members - -* Users management -- When account is deleted, cancel presence subscription for all roster items - -* XEP Support -- Added XEP-0059 Result Set Management (for listing rooms) -- Added XEP-0082 Date Time -- Added XEP-0085 Chat State Notifications -- Added XEP-0157 Contact Addresses for XMPP Services -- Added XEP-0158 CAPTCHA Forms (in MUC rooms) -- Added STUN server, for XEP-0176: Jingle ICE-UDP Transport Method -- Added XEP-0199 XMPP Ping -- Added XEP-0202 Entity Time -- Added XEP-0203 Delayed Delivery -- Added XEP-0227 Portable Import/Export Format for XMPP-IM Servers -- Added XEP-0237 Roster Versioning - -* Web Admin -- Display the connection method of user sessions -- Cross link of ejabberd users in the list of users and rosters -- Improved the browsing menu: don't disappear when browsing a host or node -- Include Last-Modified HTTP header in responses to allow caching -- Make some Input areas multiline: options of listening ports and modules -- Support PUT and DELETE methods in ejabberd_http -- WebAdmin serves Guide and links to related sections - -* Web plugins -- mod_http_fileserver: new option directory_indices, and improve logging - - - Important Notes: - -- ejabberd 2.1.0 requires Erlang R10B-9 or higher. - R12B-5 is the recommended version. Support for R13B is experimental. - - - Upgrading From ejabberd 1.x.x: - -- Check the Release Notes of the intermediate versions for additional - information about database or configuration changes. - - - Upgrading From ejabberd 2.0.x: - -- The database schemas have three changes since ejabberd 2.0.x. - Check the database creation SQL files and update your database. - 1) New table roster_version to support roster versioning. - 2) Six new tables for optional pubsub ODBC storage. - 3) Some tables in the MySQL database have a new created_at column. - -- As usual, it is recommended to backup the Mnesia spool directory and - your SQL database (if used) before upgrading ejabberd. - -- Between ejabberd 2.0.0 and 2.0.5, mod_pubsub used "default" as the - default node plugin. But in 2.1.0 this is renamed to "hometree". - You have to edit your ejabberd config file and replace those names. - If you used ejabberd 2.0.5 or older, the database will be updated - automatically. But if you were using ejabberd from SVN, you must - manually run ejabberdctl with the command: rename_default_nodeplugin. - Running this command on already updated database does nothing. - -- The listener options 'ip' and 'inet6' are not documented anymore - but they are supported and you can continue using them. - There is a new syntax to define IP address and IP version. - As usual, check the ejabberd Guide for more information. - -- The log file sasl.log is now called erlang.log - -- ejabberdctl commands now have _ characters instead of -. - For backwards compatibility, it is still supported -. - -- mod_offline has a new option: access_max_user_messages. - The old option user_max_messages is no longer supported. - -- If you upgrade from ejabberd trunk SVN, you must execute this: - $ ejabberdctl rename_default_nodeplugin - -- Default installation directories changed a bit: - * The Mnesia spool files that were previously stored in - /var/lib/ejabberd/db/NODENAME/* - are now stored in - /var/lib/ejabberd/* - * The directories - /var/lib/ejabberd/ebin - /var/lib/ejabberd/priv - and their content is now installed as - /lib/ejabberd/ebin - /lib/ejabberd/priv - * There is a new directory with Erlang header files: - /lib/ejabberd/include - * There is a new directory for ejabberd documentation, - which includes the Admin Guide and the release notes:: - /share/doc/ejabberd - -- How to upgrade from previous version to ejabberd 2.1.0: - 1. Stop the old instance of ejabberd. - 2. Run 'make install' of new ejabberd 2.1.0 to create the new directories. - 3. Copy the content of your old directory: - /var/lib/ejabberd/db/NODENAME/ - to the new location: - /var/lib/ejabberd/ - so you will have the files like this: - /var/lib/ejabberd/acl.DCD ... - 4. You can backup the content of those directories and delete them: - /var/lib/ejabberd/ebin - /var/lib/ejabberd/priv - /var/lib/ejabberd/db - 5. Now try to start your new ejabberd 2.1.0. - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.1.txt b/doc/release_notes_2.1.1.txt deleted file mode 100644 index b97462c9f0f..00000000000 --- a/doc/release_notes_2.1.1.txt +++ /dev/null @@ -1,47 +0,0 @@ - - Release Notes - ejabberd 2.1.1 - - ejabberd 2.1.1 is the first bugfix release in ejabberd 2.1.x branch. - - ejabberd 2.1.1 includes several important bugfixes. - More details of those fixes can be retrieved from: - http://redir.process-one.net/ejabberd-2.1.1 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - The changes are: - -* Core -- Call ejabberd_router:route/3 instead of sending a message -- Can't connect if starttls_required and zlib are set -- Routes vCard request to the occupant full JID, but should to bare JID -- S2S: fix allow_host/2 on subdomains. added hook s2s_allow_host - -* MUC -- Support converting one-to-one chat to MUC -- Add support for serving a Unique Room Name - -* Publish Subscribe -- Receive same last published PEP items at reconnect if several resources online -- Typo in mod_pubsub_odbc breaks Service Discovery and more - -* Web -- Fix memory and port leak when TLS is enabled in HTTP -- WebAdmin doesn't report correct last activity with postgresql backend -- Option to define custom HTTP headers in mod_http_fileserver -- Show informative webpage when browsing the HTTP-Poll page - -* Other -- Change captcha.sh to not depend on bash -- Generate main XML file also when exporting only a vhost -- Fix last newline in ejabberdctl result -- Guide: fix -setcookie, mod_pubsub_odbc host, content_types - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.10.txt b/doc/release_notes_2.1.10.txt deleted file mode 100644 index bf118594ec1..00000000000 --- a/doc/release_notes_2.1.10.txt +++ /dev/null @@ -1,39 +0,0 @@ - - Release Notes - ejabberd 2.1.10 - - ejabberd 2.1.10 includes a few bugfixes and improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.10 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - The major changes are: - -* Erlang/OTP compatibility -- Support Erlang/OTP R15B regexp and drivers (EJAB-1521) -- Fix modules update in R14B04 and higher -- Fix modules update of stripped beams (EJAB-1520) - -* XMPP Core -- Fix presence problem in C2S after first unavailable (EJAB-1466) -- Fix bug on S2S shaper when TLS is used -- Prevent overload of incoming S2S connections - -* XEPs -- BOSH: Get rid of useless mnesia transaction (EJAB-1502) -- MUC: Don't reveal invitee resource when room informs invitor -- Privacy: Activate "Blocked Contacts" to current c2s connection (EJAB-1519) -- Privacy: Always allow packets from user's server and bare jid (EJAB-1441) -- Pubsub: Add hooks for node creation/deletion (EJAB-1470) -- Shared Rosters: support groupname@vhost in Displayed Groups (EJAB-506) -- Vcard: Fix error when lowercasing some search results (EJAB-1490) - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.11.txt b/doc/release_notes_2.1.11.txt deleted file mode 100644 index 44d15f0b248..00000000000 --- a/doc/release_notes_2.1.11.txt +++ /dev/null @@ -1,58 +0,0 @@ - - Release Notes - ejabberd 2.1.11 - - ejabberd 2.1.11 includes a few bugfixes and improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.11 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - The major changes are: - -* HTTP service -- Fix ejabberd_http:get_line -- Don't use binary:match to extract lines from binaries -- Parse and encode https header names like native http parser does -- Parse correctly https request split into multiple packets -- Properly handle HEAD request in mod_http_bind (EJAB-1538) -- New option default_host for handling requests with ambiguous Host (EJAB-1261) - -* ODBC -- New ODBC support for mod_announce -- New ODBC support for mod_blocking -- New ODBC support for mod_irc -- New ODBC support for mod_muc -- New ODBC support for mod_shared_roster -- New ODBC support for mod_vcard_xupdate -- Add ODBC exporting function for privacy table -- Work also with some unicode strings in PgSQL (EJAB-1490) -- Replace a single quote with double quotes in an ODBC escape - -* SSL -- Make sure that res is initialized in all cases -- Parse correctly https request split into multiple packets (EJAB-1537) -- Added missed tls:recv_data/2 -- Don't ignore Length parameter in tls:recv -- Avoid quadratic behavior in reading SSL data -- Dix http_bind webserver TLS fail on Chrome (EJAB-1530) - -* Miscelanea -- Assume we have only one CPU when an auto-detection fails (EJAB-1516) -- Auth: Relax digest-uri handling (EJAB-1529) -- Caps: Cache caps timestamp before the IQ-request is done -- IRC: Use of MUC password -- Private: misc errors cases fixes -- Pubsub: return user affiliation for a specified node (EJAB-1294) -- Shared Roster: Foreign items were not pushed (EJAB-1509) -- Shared Roster LDAP: user substitution in ldap_rfilter (EJAB-1555) -- Windows: Fix makefile rules for building DLLs - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.12.txt b/doc/release_notes_2.1.12.txt deleted file mode 100644 index f8fd7382cf4..00000000000 --- a/doc/release_notes_2.1.12.txt +++ /dev/null @@ -1,67 +0,0 @@ - - Release Notes - ejabberd 2.1.12 - - ejabberd 2.1.12 includes a many bugfixes and a few improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.12 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - The changes are: - -* Core ejabberd -- Make terms serialization faster -- Reduce size of XML stream state - -* Administration -- Add SCRAM and remove MD5 support to ejabberd commands auth verification -- Added command to list all the vhosts registered in an ejabberd node -- Added export2odbc command, copied from mod_admin_extra.erl -- Fix ejabberdctl number of arguments error report with R15 -- Check node name is available before starting ejabberd (EJAB-1572) -- Fix ejabberd_xmlrpc commands authentication with SCRAM -- Fix mod_offline:store_offline_msg argument (EJAB-1581) -- Log IP address when auth attempt fails -- Make sure update_info returns atoms only (EJAB-1595) -- On shutdown, first stop listeners, then modules - -* Encryption -- Detect OpenSSL version at runtime, not at compile time -- Fixed signedness issue in tls_drv GET_DESCRYPTED_INPUT (EJAB-1591) -- Enable DHE key exchange in TLS driver -- Enable ECDHE key exchange in TSL driver -- Disable old and unsecure ciphers in TLS driver -- Disable SSL 2.0 in TLS driver - -* HTTP-Bind -- Do not trigger item-not-found errors in mod_http_bind -- Repeated http-bind request should abort only requests with same rid -- Receiving missing request shouldn't close waiting out-ouf-order request - -* XMPP -- Allow multiple fqdn values in configuration (EJAB-1578) -- Fix get_subscription_lists/4 -- Fix account registration -- Send announce Message stanzas as Headline type instead of Normal - -* Other -- Guide: Fix file name of Name Service Switch -- Guide: Document the db_type modules option (EJAB-1560) -- LDAP: Fix broken JPEG photo (EJAB-1526) -- LDAP: Fix compatibility with Erlang R16A (EJAB-1612) -- MUC: Fix angle brackets handle in plaintext log (EJAB-1610) -- MUC: Fix MUC start when Mnesia tables don't exist yet -- MUC: New mod_muc_log option file_permissions (EJAB-1588) -- ODBC: Merge SQL and Mnesia code into one module (EJAB-1560) -- Translation: New Hebrew -- Translation: Update Slovak - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.2.txt b/doc/release_notes_2.1.2.txt deleted file mode 100644 index 56f5069358d..00000000000 --- a/doc/release_notes_2.1.2.txt +++ /dev/null @@ -1,51 +0,0 @@ - - Release Notes - ejabberd 2.1.2 - - ejabberd 2.1.2 is the second bugfix release in ejabberd 2.1.x branch. - - ejabberd 2.1.2 includes several bugfixes. - More details of those fixes can be retrieved from: - http://redir.process-one.net/ejabberd-2.1.2 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - The major changes are: - -* Core -- Close sessions that were half connected -- Fix SASL PLAIN authentication message for RFC4616 compliance -- Fix support for old Erlang/OTP R10 and R11 -- Return proper error (not 'conflict') when register is forbidden by ACL -- When ejabberd stops, send stream close to clients - -* ejabberdctl -- Check for EGID in ejabberdctl command -- Command to stop ejabberd informing users, with grace period -- If there's a problem in config file, display config lines and stop node - -* MUC -- Kick occupants with reason when room is stopped due to MUC shutdown -- Write in room log when a room is created, destroyed, started, stopped - -* PubSub and PEP -- Don't call gen_server on internal event (improves performance and scalability) -- Fix duplicate SHIM header in Pubsub message -- Notification messages of Pubsub node config change contained a SHIM header -- SubID SHIM header missing in Pubsub message with multiple - subscriptions on the same node -- PEP: last published item not sent from unavailable users when the - subscription is implicit (XEP-0115) -- pep_mapping not working due to Node type mismatch - -* WebAdmin -- If big offline message queue, show only subset on WebAdmin -- Support in user list page of WebAdmin when mod_offline is disabled - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.3.txt b/doc/release_notes_2.1.3.txt deleted file mode 100644 index ac2c26e6f38..00000000000 --- a/doc/release_notes_2.1.3.txt +++ /dev/null @@ -1,91 +0,0 @@ - - Release Notes - ejabberd 2.1.3 - - ejabberd 2.1.3 is the third release in ejabberd 2.1.x branch. - - ejabberd 2.1.3 includes many bugfixes, and some improvements. - More details of those fixes can be retrieved from: - http://redir.process-one.net/ejabberd-2.1.3 - - The new code can be downloaded from ejabberd download page: - http://www.process-one.net/en/ejabberd/ - - - This is the full list of changes: - -* Client connections -- Avoid 'invalid' value in iq record -- Avoid resending stream:error stanzas on terminate (EJAB-1180) -- Close also legacy sessions that were half connected (EJAB-1165) -- iq_query_info/1 now returns 'invalid' if XMLNS is invalid -- New ejabberd_c2s option support: max_fsm_queue -- Rewrite mnesia counter functions to use dirty_update_counter (EJAB-1177) -- Run user_receive_packet also when sending offline messages (EJAB-1193) -- Use p1_fsm behaviour in c2s FSM (EJAB-1173) - -* Clustering -- Fix cluster race condition in route read -- New command to set master Mnesia node -- Use mnesia:async_dirty when cleaning table from failed node - -* Documentation -- Add quotes in documentation of some erl arguments (EJAB-1191) -- Add option access_from (EJAB-1187) -- Add option max_fsm_queue (EJAB-1185) -- Fix documentation installation, no need for executable permission (EJAB-1170) -- Fix typo in EJABBERD_BIN_PATH (EJAB-891) -- Fix typos in example config comments (EJAB-1192) - -* ejabberdctl -- Support concurrent connections with bound connection names -- Add support for Jot in ctl and TTY in debug -- Support help command names with old - characters -- Fix to really use the variable ERL_PROCESSES - -* Erlang compatibility -- Don't call queue:filter/2 to keep compatibility with older Erlang versions -- Use alternative of file:read_line/1 to not require R13B02 - -* HTTP -- Add new debugging hook to the http receiving process -- Allow a request_handler to serve a file in root of HTTP - -* HTTP-Bind (BOSH) -- Cross-domain HTTP-Bind support (EJAB-1168) -- Hibernate http-bind process after handling a request -- Reduce verbosity of HTTP Binding log messages - -* LDAP -- Document ldap_dn_filter, fetch only needed attributes in search (EJAB-1204) -- Use "%u" pattern as default for ldap_uids (EJAB-1203) - -* Localization -- Fix German translation (EJAB-1195) -- Fix Russian translation - -* ODBC -- Fix MSSQL support, which was broken (EJAB-1201) -- Improved SQL reconnect behaviour - -* Pubsub, PEP and Caps -- Add extended stanza addressing 'replyto' on PEP (EJAB-1198) -- Add pubsub#purge_offline (EJAB-1186) -- Fix pubsub#title option (EJAB-1190) -- Fix remove_user for node subscriptions (EJAB-1172) -- Optimizations in mod_caps - -* Other -- mod_register: Add new acl access_from, default is to deny -- mod_sic: new module for the experimental XEP-0279 Server IP Check (EJAB-1205) -- PIEFXIS: Catch errors when exporting to PIEFXIS file (EJAB-1178) -- Proxy65: new option "hostname" (EJAB-838) -- Roster: Fix resending authorization problem -- Shared Roster Groups: get contacts nickname from vcard (EJAB-114) -- S2S: Improved s2s connections clean up (EJAB-1202) - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.4.txt b/doc/release_notes_2.1.4.txt deleted file mode 100644 index c4fe4bf8c9a..00000000000 --- a/doc/release_notes_2.1.4.txt +++ /dev/null @@ -1,80 +0,0 @@ - - Release Notes - ejabberd 2.1.4 - - ejabberd 2.1.4 is the fourth release in ejabberd 2.1.x branch, - and includes many small bugfixes and improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.4 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - This is the full list of changes: - -* Authentication -- Extauth: Optionally cache extauth users in mnesia (EJAB-641) -- LDAP: Allow inband password change (EJAB-199) -- LDAP: Extensible match support (EJAB-722) -- LDAP: New option ldap_tls_verify is added (EJAB-1229) -- PAM: New option pam_userinfotype to provide username or JID (EJAB-652) - -* HTTP -- Add xml default content type -- Don't show HTTP request in logs, because reveals password (EJAB-1231) -- Move HTTP session timeout log from warning level to info -- New Access rule webadmin_view for read-only - -* HTTP-Bind (BOSH) -- Change max inactivity from 30 to 120 seconds -- Export functions to facilitate prebinding methods -- Use dirty_delete when removing the session -- Remove an unneeded delay of 100 milliseconds - -* Pubsub, PEP and Caps -- Enforce pubsub#presence_based_delivery (EJAB-1221) -- Enforce pubsub#show_values subscription option (EJAB-1096) -- Fix error code when unsubscribing from a non-existent node -- Fix to send node notifications (EJAB-1225) -- Full support for XEP-0115 v1.5 (EJAB-1223)(EJAB-1189) -- Make last_item_cache feature to be cluster aware -- Prevent orphaned pubsub node (EJAB-1233) -- Send created node notifications - -* Other -- Bounce messages when closing c2s session -- Bugfixes when handling Service Discovery to contacts (EJAB-1207) -- Compilation of ejabberd_debug.erl is now optional -- Don't send error stanza as reply to error stanza (EJAB-930) -- Don't store blocked messages in offline queue -- Reduce verbosity of log when captcha_cmd is checked but not configured -- Use a standard method to get a random seed (EJAB-1229) -- Commands: new update_list and update to update modified modules (EJAB-1237) -- Localization: Updated most translations -- MUC: Refactor code to reduce calls to get_affiliation and get_role -- ODBC: Add created_at column also to PostgreSQL schema -- Vcard: Automatic vcard avatar addition in presence - - - Upgrading From previous ejabberd releases: - -- If you use PostgreSQL, maybe you want to add the column created_at - to several tables. This is only a suggestion; ejabberd doesn't use - that column. Add it to your existing database executing those SQL - statements: - -ALTER TABLE users ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now(); -ALTER TABLE rosterusers ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now(); -ALTER TABLE spool ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now(); -ALTER TABLE vcard ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now(); -ALTER TABLE privacy_list ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now(); -ALTER TABLE privacy_storage ADD COLUMN created_at TIMESTAMP NOT NULL DEFAULT now(); - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ - diff --git a/doc/release_notes_2.1.5.txt b/doc/release_notes_2.1.5.txt deleted file mode 100644 index a13b452d6af..00000000000 --- a/doc/release_notes_2.1.5.txt +++ /dev/null @@ -1,70 +0,0 @@ - - Release Notes - ejabberd 2.1.5 - - ejabberd 2.1.5 is the fifth release in ejabberd 2.1.x branch, - and includes several minor bugfixes and a few improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.4 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - This is the full list of changes: - -* Authentication -- Extauth: Support parallel script running (EJAB-1280) -- mod_register: Return Registered element when account exists - -* ejabberdctl -- Fix print of command result that contains ~ -- Fix problem when FIREWALL_WINDOW options for erl kernel were used -- Fix typo in update_list command (EJAB-1237) -- Some systems delete the lock dir; in such case don't use flock at all -- The command Update now returns meaningful message and exit-status (EJAB-1237) - -* HTTP-Bind (BOSH) -- Don't say v1.2 in the Bind HTTP page -- New optional BOSH connection attribute process-delay (EJAB-1257) - -* MUC -- Document the mod_muc option captcha_protected -- Now admins are able to see private rooms in disco (EJAB-1269) -- Show some more room options in the log file - -* ODBC -- Correct handling of SQL boolean types (EJAB-1275) -- Discard too old queued requests (the caller has already got a timeout) -- Fixes wrong SQL escaping when --enable-full-xml is set -- Use ets insead of asking supervisor in ejabberd_odbc_sup:get_pids/1 - -* Pubsub, PEP and Caps -- Enforce disco features results (EJAB-1033, EJAB-1228, EJAB-1238) -- Support all the hash functions required by Caps XEP-0115 - -* Requirements -- Fixed support for Erlang R12; which doesn't support: true andalso ok -- Support OTP R14A by using public_key library instead of old ssl (EJAB-953) -- Requirement of OpenSSL increased from 0.9.6 to 0.9.8 -- OpenSSL is now required, not optional - -* Other -- Don't ask for client certificate when using tls (EJAB-1267) -- Fix typo in --enable-transient_supervisors -- Fix privacy check when serving local Last (EJAB-1271) -- Inform client that SSL session caching is disabled -- New configure option: --enable-nif -- Use driver allocator in C files for reflecting memory in erlang:memory(system) -- Debug: New p1_prof compiled with: make debugtools=true -- Debug: Added functions to collect stats about queues, memory, reductions etc -- HTTP: Log error if request has ambiguous Host header (EJAB-1261) -- Logs: When logging s2s out connection attempt or success, log if TLS is used -- Shared Rosters: When account is deleted, delete also member of stored rosters - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.6.txt b/doc/release_notes_2.1.6.txt deleted file mode 100644 index 64f02a3bcba..00000000000 --- a/doc/release_notes_2.1.6.txt +++ /dev/null @@ -1,67 +0,0 @@ - - Release Notes - ejabberd 2.1.6 - - ejabberd 2.1.6 is the sixth release in ejabberd 2.1.x branch, - and includes a lot of bugfixes and improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.6 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - Some of the changes are: - -* Account register -- mod_register: New ip_access option restricts which IPs can register (EJAB-915) -- mod_register: Default configuration allows registrations only from localhost -- mod_register: New password_strength for entropy check (EJAB-1326) -- mod_register: New captcha_protected option to require CAPTCHA (EJAB-1262) -- mod_register_web: New module, with CAPTCHA support (EJAB-471) - -* BOSH -- Don't loop when there is nothing after a stream start (EJAB-1358) -- Fix http-bind supervisor to support multiple vhosts (EJAB-1321) -- Support to restart http-bind (EJAB-1318) -- Support for X-Forwarded-For HTTP header (EJAB-1356) - -* Erlang/OTP compatibility -- R11: Fix detection of Erlang R11 and older (EJAB-1287) -- R12B5: Fix compatibility in ejabberd_http_bind.erl (EJAB-1343) -- R14A: Make xml.c correctly compile (EJAB-1288) -- R14A, R14B: Disapprove the use of R14A and R14B due to the rwlock bug -- R14B: Use pg2 from this version in systems with older ones (EJAB-1349) - -* Listeners -- Bind listener ports early and start accepting connections later -- Fix a leak of ejabberd_receiver processes -- Speed up ejabberd_s2s:is_service/2, allow_host/2 (EJAB-1319) -- S2S: New option to require encryption (EJAB-495) -- S2S: New option to reject connection if untrusted certificate (EJAB-464) -- S2S: Include From attribute in the stream header of outgoing S2S connections -- S2S: Fix domain_certfile tlsopts modifications for S2S connections (EJAB-1086) - -* Pubsub/PEP/Caps -- Fix pubsub cross domain eventing (EJAB-1340) -- Use one_queue IQ discipline by default -- Implement lifetime for broken hashes -- New CAPS processing - -* ODBC -- Increase maximum restart strategy to handle some SQL timeouts -- Support PostgreSQL 9.0 (EJAB-1359) -- Use MEDIUMTEXT type for vcard avatars in MySQL schema (EJAB-1252) - -* Miscellanea: -- mod_shared_roster_ldap: New Shared Roster Groups using LDAP information -- mod_privacy: Fix to allow block by group and subscription again -- Support timezone West of UTC (EJAB-1301) -- Support to change loglevel per module at runtime (EJAB-225) - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.7.txt b/doc/release_notes_2.1.7.txt deleted file mode 100644 index 3f4c224bfa7..00000000000 --- a/doc/release_notes_2.1.7.txt +++ /dev/null @@ -1,97 +0,0 @@ - - Release Notes - ejabberd 2.1.7 - - ejabberd 2.1.7 is the eighth release in ejabberd 2.1.x branch, - and includes a lot of bugfixes and improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.7 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - The changes are: - -* BOSH and Web -- Clarify error message when BOSH query is sent to non-running module -- Keep the order of stanzas when BOSH sends several (EJAB-1374) -- Show configuration for HTTPS http_bind -- Support as read-only HTTP method not only GET, also HEAD -- The responses to HEAD must have empty Body - -* CAPTCHA -- If the port number isn't listener, then specify the protocol (EJAB-1418) -- New CAPTCHA limit -- New CAPTCHA whitelist support -- Only check system at startup if option is enabled -- Provide HTTPS URL in CAPTCHA form when listener has 'tls' option (EJAB-1406) -- Show captcha_limit option in the example config -- Support more captcha_host value formats (EJAB-1418) -- Throw error when captcha fails at server start, not later at runtime -- captcha_host must have the port number to get protocol (EJAB-1418) - -* Core ejabberd -- Disable all entity expansions (EJAB-1451) -- Do not accept XML with undefined prefixes (EJAB-680) -- Make jlib:ip_to_list safe to use -- Make sure 'closed' event is correctly processed on every state -- New route_iq/5 accepting Timeout (EJAB-1398) -- Take into consideration internal queue length when sorting processes queues -- Use route instead of send_element to go through standard workflow - -* Erlang/OTP compatibility -- Remove Type and Spec, backport list comprehensions, so R12B-5 can compile -- Tweak pg2_backport.erl to work with Erlang older than R13A (EJAB-1349) - -* ODBC -- Don't let presence-in privacy rule block a presence subscription (EJAB-255) -- Escape user input in mod_privacy_odbc (EJAB-1442) -- Try to improve support for roster_version in MSSQL (EJAB-1437) - -* Pubsub/PEP/Caps -- Apply filtered notification to PEP last items (EJAB-1456) -- Fix empty pubsub payload check -- Owner can delete any items from its own node (EJAB-1445) -- Pubsub node maxitem forced to 0 if non persistent node (EJAB-1434) -- Reorganize the push_item function, and handle version not_found (EJAB-1420) - -* Scripts -- ejabberd.init: Several fixes and improvements -- ejabberdctl: Escape output from ctlexec() to erl script (EJAB-1399) -- ejabberdctl: Fix bashism and mimic master branch (EJAB-1404) -- ejabberdctl: Fix space between INET_DIST_INTERFACE (EJAB-1416) -- ejabberdctl: New DIST_USE_INTERFACE restricts IP of erlang listen (EJAB-1404) -- ejabberdctl: New ERL_EPMD_ADDRESS that works since Erlang/OTP R14B03 -- extauth: Fix delayed response of timeout was reused for next login (EJAB-1385) -- extauth: Forward old messages to newly spawned extauth process (EJAB-1385) -- extauth: If script crashes, ejabberd should restart it (EJAB-1428) - -* XEP support -- mod_blocking: New XEP-0191 Simple Communications Blocking (EJAB-695) -- No need to inform that XEP-0237 is optional; clarified in XEP version 1.2 - -* Miscellanea: -- If a module start fails during server start, stop erlang (EJAB-1446) -- New Indonesian translation (EJAB-1407) -- LDAP: Note that ejabberd works with CGP LDAP server -- S2S: Handle Tigase's unexpected version=1.0 (EJAB-1379) -- mod_irc: Send presence unavailable to the departing occupant (EJAB-1417) -- mod_last: Allow user to query his own Last activity -- mod_muc: Do not decrease MUC admin's role/affiliation -- mod_muc: Send jid attribute when occupant is banned (EJAB-1432) -- mod_offline: Change c2s state before offline messages resending -- mod_ping: Use iqdisc no_queue by default (EJAB-1435) -- mod_pres_counter: Prevent subscription flood (EJAB-1388) -- mod_register Access now also controls account unregistrations -- mod_register: Clarify more the expected content of welcome_message option -- mod_shared_roster: Fix support for anonymous accounts in @all@ (EJAB-1264) -- mod_shared_roster: New @online@ directive (EJAB-1391) - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ - diff --git a/doc/release_notes_2.1.8.txt b/doc/release_notes_2.1.8.txt deleted file mode 100644 index 3e109da4481..00000000000 --- a/doc/release_notes_2.1.8.txt +++ /dev/null @@ -1,21 +0,0 @@ - - Release Notes - ejabberd 2.1.8 - - ejabberd 2.1.8 is the ninth release in ejabberd 2.1.x branch, - and includes a PubSub regression bugfix. - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - The change is: - -- Fix issue on PubSub preventing publication of items (EJAB-1457) - - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ diff --git a/doc/release_notes_2.1.9.txt b/doc/release_notes_2.1.9.txt deleted file mode 100644 index 77cc9ac1dbf..00000000000 --- a/doc/release_notes_2.1.9.txt +++ /dev/null @@ -1,56 +0,0 @@ - - Release Notes - ejabberd 2.1.9 - - ejabberd 2.1.9 is the eighth release in ejabberd 2.1.x branch, - and includes a lot of bugfixes and improvements. - - Read more details about the changes in: - http://redir.process-one.net/ejabberd-2.1.9 - - Download the source code and installers from: - http://www.process-one.net/en/ejabberd/ - - - The changes are: - -* Core ejabberd -- Decrease CPU usage caused by tls:send with large data -- Escape iolist correctly when NIFs are disabled (EJAB-1462) -- Fix code to satisfy Dialyzer warnings -- Fix compilation in Windows -- Replace calls of OTP's Binary, since they would require R14 - -* LDAP -- Document ldap_tls_cacertfile and ldap_tls_depth options (EJAB-1299) -- Log an error when an LDAP filter is incorrect (EJAB-1395) -- New options: ldap_tls_cacertfile and ldap_tls_depth (EJAB-1299) -- New option: ldap_deref_aliases (EJAB-639) -- Match ldap_uidattr_format case-insensitively (EJAB-1449) - -* MUC -- Support for multiple entry with same nick to MUC rooms (EJAB-305) -- Support voice request and approvement -- New room option: allow_private_messages_from_visitors -- New room options: allow_voice_requests and voice_request_min_interval -- Include status 110 in presence to new occupant (EJAB-740) -- Fix mod_muc_log crash when first log entry is room destroy (EJAB-1499) -- Many fixes and improvements in mod_muc - -* Pubsub -- Enable pubsub#deliver_notification checking (EJAB-1453) -- Fix Denial of Service when user sends malformed publish stanza (EJAB-1498) - -* ODBC -- Fix ODBC account counting (EJAB-1491) -- Optimized mod_roster_odbc:get_roster - -* Miscellanea: -- New SASL SCRAM-SHA-1 authentication mechanism (EJAB-1196) -- New option: resource_conflict (EJAB-650) - - - Bug reports - - You can officially report bugs on ProcessOne support site: - http://support.process-one.net/ From 2e194bd997132f4fde5959b54e6bfe269d4de433 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 22 Apr 2015 13:27:25 +0200 Subject: [PATCH 035/695] Add private and roster local handlers to get listed in disco#info (EJAB-682) --- src/mod_private.erl | 3 +++ src/mod_roster.erl | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/mod_private.erl b/src/mod_private.erl index f09c6100ede..e127c20294e 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -60,12 +60,15 @@ start(Host, Opts) -> end, ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_PRIVATE, ?MODULE, process_sm_iq, IQDisc), 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_local, Host, ?NS_PRIVATE), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE). diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 605e8e36702..2f5d771ce4d 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -100,6 +100,8 @@ start(Host, Opts) -> webadmin_page, 50), ejabberd_hooks:add(webadmin_user, Host, ?MODULE, webadmin_user, 50), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_ROSTER, ?MODULE, process_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER, ?MODULE, process_iq, IQDisc). @@ -126,6 +128,7 @@ stop(Host) -> webadmin_page, 50), ejabberd_hooks:delete(webadmin_user, Host, ?MODULE, webadmin_user, 50), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ROSTER), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). From df3afafb48265bfd266c66fdef0a3199cb079b32 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Apr 2015 18:10:35 +0200 Subject: [PATCH 036/695] Add publish_only to affiliation type spec --- include/pubsub.hrl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pubsub.hrl b/include/pubsub.hrl index 2f85bdbfab6..f43e1644bf5 100644 --- a/include/pubsub.hrl +++ b/include/pubsub.hrl @@ -98,7 +98,7 @@ -type(affiliation() :: 'none' | 'owner' | 'publisher' - %| 'publish-only' + | 'publish_only' | 'member' | 'outcast' ). From 38dd44e18fdc0c08c0de5411f982e508cbb4d50a Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Apr 2015 18:11:39 +0200 Subject: [PATCH 037/695] Improve purge_offline filter and speed (#543) --- src/mod_pubsub.erl | 93 +++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index a8b7b0ecb0d..0531374dc57 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -4268,63 +4268,78 @@ on_user_offline(_, JID, _) -> _ -> true end. -purge_offline({User, Server, _} = LJID) -> +purge_offline(LJID) -> Host = host(element(2, LJID)), Plugins = plugins(Host), Result = lists:foldl(fun (Type, {Status, Acc}) -> + Features = plugin_features(Host, Type), case lists:member(<<"retrieve-affiliations">>, plugin_features(Host, Type)) of false -> - {{error, - extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, + {{error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"retrieve-affiliations">>)}, Acc}; true -> - {result, Affs} = node_action(Host, Type, - get_entity_affiliations, - [Host, LJID]), - {Status, [Affs | Acc]} + Items = lists:member(<<"retract-items">>, Features) + andalso lists:member(<<"persistent-items">>, Features), + if Items -> + {result, Affs} = node_action(Host, Type, + get_entity_affiliations, [Host, LJID]), + {Status, [Affs | Acc]}; + true -> + {Status, Acc} + end end end, {ok, []}, Plugins), case Result of {ok, Affs} -> + lists:foreach( + fun ({Node, Affiliation}) -> + Options = Node#pubsub_node.options, + Publisher = lists:member(Affiliation, [owner,publisher,publish_only]), + Open = (get_option(Options, publish_model) == open), + Purge = (get_option(Options, purge_offline) + andalso get_option(Options, persist_items)), + if (Publisher or Open) and Purge -> + purge_offline(Host, LJID, Node); + true -> + ok + end + end, lists:usort(lists:flatten(Affs))); + {Error, _} -> + ?DEBUG("on_user_offline ~p", [Error]) + end. + +purge_offline(Host, LJID, Node) -> + Nidx = Node#pubsub_node.id, + Type = Node#pubsub_node.type, + Options = Node#pubsub_node.options, + case node_action(Host, Type, get_items, [Nidx, service_jid(Host), none]) of + {result, {[], _}} -> + ok; + {result, {Items, _}} -> + {User, Server, _} = LJID, + PublishModel = get_option(Options, publish_model), + ForceNotify = get_option(Options, notify_retract), + {_, NodeId} = Node#pubsub_node.nodeid, lists:foreach(fun - ({#pubsub_node{nodeid = {_, Node}, options = Options, type = Type}, Aff}) - when Aff == owner orelse Aff == publisher -> - Action = fun (#pubsub_node{type = NType, id = Nidx}) -> - node_call(Host, NType, get_items, [Nidx, service_jid(Host), none]) - end, - case transaction(Host, Node, Action, sync_dirty) of - {result, {_, {[], _}}} -> - true; - {result, {_, {Items, _}}} -> - Features = plugin_features(Host, Type), - case {lists:member(<<"retract-items">>, Features), - lists:member(<<"persistent-items">>, Features), - get_option(Options, persist_items), - get_option(Options, purge_offline)} - of - {true, true, true, true} -> - ForceNotify = get_option(Options, notify_retract), - lists:foreach(fun - (#pubsub_item{itemid = {ItemId, _}, - modification = {_, {U, S, _}}}) - when (U == User) and (S == Server) -> - delete_item(Host, Node, LJID, ItemId, ForceNotify); - (_) -> - true - end, - Items); - _ -> - true + (#pubsub_item{itemid = {ItemId, _}, modification = {_, {U, S, _}}}) + when (U == User) and (S == Server) -> + case node_action(Host, Type, delete_item, [Nidx, {U, S, <<>>}, PublishModel, ItemId]) of + {result, {_, broadcast}} -> + broadcast_retract_items(Host, NodeId, Nidx, Type, Options, [ItemId], ForceNotify), + case get_cached_item(Host, Nidx) of + #pubsub_item{itemid = {ItemId, Nidx}} -> unset_cached_item(Host, Nidx); + _ -> ok end; + {result, _} -> + ok; Error -> Error end; (_) -> true - end, - lists:usort(lists:flatten(Affs))); - {Error, _} -> - ?DEBUG("on_user_offline ~p", [Error]) + end, Items); + Error -> + Error end. From 23aa8598ab8a586f2c6300b8f6d1b0b672e2e7f4 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 23 Apr 2015 10:14:08 +0200 Subject: [PATCH 038/695] Allow bypassing script interraction (#516) --- tools/joincluster | 28 +++++++++++++++------------- tools/leavecluster | 28 ++++++++++++++++------------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/tools/joincluster b/tools/joincluster index de36e437c31..e62084bc4d8 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -21,19 +21,21 @@ function error exit $2 } -echo "--------------------------------------------------------------------" -echo "" -echo "ejabberd cluster configuration" -echo "" -echo "This ejabberd node will be configured for use in an ejabberd cluster." -echo "IMPORTANT: all local data from the database will be lost, and" -echo "cluster database will be initialized. All data from the master" -echo "node will be replicated to this one." -echo "" -echo "--------------------------------------------------------------------" -echo "Press any key to continue, or Ctrl+C to stop now" -read foo -echo "" +[ -z $NO_WARNINGS ] && { + echo "--------------------------------------------------------------------" + echo "" + echo "ejabberd cluster configuration" + echo "" + echo "This ejabberd node will be configured for use in an ejabberd cluster." + echo "IMPORTANT: all local data from the database will be lost, and" + echo "cluster database will be initialized. All data from the master" + echo "node will be replicated to this one." + echo "" + echo "--------------------------------------------------------------------" + echo "Press any key to continue, or Ctrl+C to stop now" + read foo + echo "" +} [ $# -eq 0 ] && { echo "Make sure you have a running remote master ejabberd node" diff --git a/tools/leavecluster b/tools/leavecluster index cb4737adb5d..7acc2b46ce8 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -17,18 +17,22 @@ function error exit $2 } -echo "--------------------------------------------------------------------" -echo "" -echo "ejabberd cluster configuration" -echo "" -echo "This ejabberd node will be removed from the cluster." -echo "IMPORTANT: this node will be stopped. At least one other clustered" -echo "node must be running." -echo "" -echo "--------------------------------------------------------------------" -echo "Press any key to continue, or Ctrl+C to stop now" -read foo -echo "" +[ -z $NO_WARNINGS ] && { + echo "--------------------------------------------------------------------" + echo "" + echo "ejabberd cluster configuration" + echo "" + echo "This ejabberd node will be removed from the cluster." + echo "IMPORTANT: this node will be stopped. At least one other clustered" + echo "node must be running." + echo "" + echo "--------------------------------------------------------------------" + echo "Press any key to continue, or Ctrl+C to stop now" + read foo + echo "" +} +echo ok +exit PA=/tmp/clustersetup_$$ CTL=$(which ejabberdctl) From 9c85cb5f250f141688e69116d5740c0c8f5973c6 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 23 Apr 2015 14:59:18 +0300 Subject: [PATCH 039/695] Fix validating function for iqdisc --- src/mod_pubsub.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 0531374dc57..80f6c05a935 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -252,7 +252,7 @@ init([ServerHost, Opts]) -> PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, fun(A) when is_boolean(A) -> A end, true), IQDisc = gen_mod:get_opt(iqdisc, Opts, - fun(A) when is_atom(A) -> A end, one_queue), + fun gen_iq_handler:check_type/1, one_queue), LastItemCache = gen_mod:get_opt(last_item_cache, Opts, fun(A) when is_boolean(A) -> A end, false), MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, From 50f35f1b0747ba9616392b9f8011b68cda7bfa5b Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 26 Apr 2015 16:22:09 +0200 Subject: [PATCH 040/695] Fix service disco handling for bare account JIDs Don't swap the sending and receiving JIDs while checking whether the client that requested service discovery information for a bare account JID is a subscribed contact. --- src/mod_disco.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 40f0f8e0601..4231df68df1 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -357,13 +357,13 @@ is_presence_subscribed(#jid{luser = User, #jid{luser = LUser, lserver = LServer}) -> lists:any(fun (#roster{jid = {TUser, TServer, _}, subscription = S}) -> - if LUser == TUser, LServer == TServer, S /= none -> + if User == TUser, Server == TServer, S /= none -> true; true -> false end end, - ejabberd_hooks:run_fold(roster_get, Server, [], - [{User, Server}])) + ejabberd_hooks:run_fold(roster_get, LServer, [], + [{LUser, LServer}])) orelse User == LUser andalso Server == LServer. process_sm_iq_info(From, To, From 0edba763fbcef233c2fe7b5b33895fac370226c8 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 26 Apr 2015 16:32:03 +0200 Subject: [PATCH 041/695] mod_disco: Omit 'roster_get' call if possible As a small optimization, avoid running the 'roster_get' hook in the (common) case where a client requests service discovery information for its own bare JID. --- src/mod_disco.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 4231df68df1..724b9b95766 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -352,6 +352,9 @@ get_sm_items(empty, From, To, _Node, _Lang) -> _ -> {error, ?ERR_NOT_ALLOWED} end. +is_presence_subscribed(#jid{luser = User, + lserver = Server}, + #jid{luser = User, lserver = Server}) -> true; is_presence_subscribed(#jid{luser = User, lserver = Server}, #jid{luser = LUser, lserver = LServer}) -> @@ -363,8 +366,7 @@ is_presence_subscribed(#jid{luser = User, end end, ejabberd_hooks:run_fold(roster_get, LServer, [], - [{LUser, LServer}])) - orelse User == LUser andalso Server == LServer. + [{LUser, LServer}])). process_sm_iq_info(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> From dc449687a01c9e874f3f8f8e8d3d5cd1c8c5f422 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 26 Apr 2015 16:36:17 +0200 Subject: [PATCH 042/695] mod_disco: Apply minor readability improvements --- src/mod_disco.erl | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 724b9b95766..00b65d23edb 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -352,21 +352,19 @@ get_sm_items(empty, From, To, _Node, _Lang) -> _ -> {error, ?ERR_NOT_ALLOWED} end. -is_presence_subscribed(#jid{luser = User, - lserver = Server}, +is_presence_subscribed(#jid{luser = User, lserver = Server}, #jid{luser = User, lserver = Server}) -> true; -is_presence_subscribed(#jid{luser = User, - lserver = Server}, - #jid{luser = LUser, lserver = LServer}) -> - lists:any(fun (#roster{jid = {TUser, TServer, _}, - subscription = S}) -> - if User == TUser, Server == TServer, S /= none -> - true; - true -> false - end +is_presence_subscribed(#jid{luser = FromUser, lserver = FromServer}, + #jid{luser = ToUser, lserver = ToServer}) -> + lists:any(fun (#roster{jid = {SubUser, SubServer, _}, subscription = Sub}) + when FromUser == SubUser, FromServer == SubServer, + Sub /= none -> + true; + (_RosterEntry) -> + false end, - ejabberd_hooks:run_fold(roster_get, LServer, [], - [{LUser, LServer}])). + ejabberd_hooks:run_fold(roster_get, ToServer, [], + [{ToUser, ToServer}])). process_sm_iq_info(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl} = IQ) -> From 987e337c66c3ce8943c22b0d2dbee0d2be7bed34 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 27 Apr 2015 17:00:22 +0200 Subject: [PATCH 043/695] Rely on core routine for handling affiliation changes (thanks to Ben Langfeld) This ensures that all of the usual stanzas and such go out --- src/mod_muc_admin.erl | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 9c69628bec1..dee50650cc8 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -825,23 +825,13 @@ set_room_affiliation(Name, Service, JID, AffiliationString) -> [R] -> %% Get the PID for the online room so we can get the state of the room Pid = R#muc_online_room.pid, - {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, get_state), - SJID = jlib:string_to_jid(JID), - LJID = jlib:jid_remove_resource(jlib:jid_tolower(SJID)), - Affiliations = change_affiliation(Affiliation, LJID, StateData#state.affiliations), - Res = StateData#state{affiliations = Affiliations}, - {ok, _State} = gen_fsm:sync_send_all_state_event(Pid, {change_state, Res}), - mod_muc:store_room(Res#state.server_host, Res#state.host, Res#state.room, make_opts(Res)), + {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jlib:string_to_jid(JID), affiliation, Affiliation, <<"">>}, <<"">>}), + mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)), ok; [] -> error end. -change_affiliation(none, LJID, Affiliations) -> - ?DICT:erase(LJID, Affiliations); -change_affiliation(Affiliation, LJID, Affiliations) -> - ?DICT:store(LJID, Affiliation, Affiliations). - -define(MAKE_CONFIG_OPT(Opt), {Opt, Config#config.Opt}). make_opts(StateData) -> From bd4338541542c9803207a2523dba9d64f82670f7 Mon Sep 17 00:00:00 2001 From: Johan Oudinet Date: Mon, 27 Apr 2015 17:25:07 +0200 Subject: [PATCH 044/695] ejabberdctl: define mnesia options In addition to factorize how the mnesia dir option is given to erl commands, it allows one to set extra mnesia options via the MNESIA_OPTIONS environment variable. --- ejabberdctl.template | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index dca995e99d8..6c131ace024 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -112,6 +112,8 @@ DATETIME=`date "+%Y%m%d-%H%M%S"` ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump ERL_INETRC=$ETC_DIR/inetrc +# define mnesia options +MNESIA_OPTS="-mnesia dir \"\\\"$SPOOL_DIR\\\"\" $MNESIA_OPTIONS" # define erl parameters ERL_OPTIONS=$(echo $ERL_OPTIONS | sed 's/ /\\ /g') ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" @@ -177,7 +179,7 @@ start() $NAME $ERLANG_NODE \ -noinput -detached \ -pa $EJABBERD_EBIN_PATH \ - -mnesia dir \"\\\"$SPOOL_DIR\\\"\" \ + $MNESIA_OPTS \ $KERNEL_OPTS \ $EJABBERD_OPTS \ -s ejabberd \ @@ -218,7 +220,7 @@ live() $EXEC_CMD "$ERL \ $NAME $ERLANG_NODE \ -pa $EJABBERD_EBIN_PATH \ - -mnesia dir \"\\\"$SPOOL_DIR\\\"\" \ + $MNESIA_OPTS \ $KERNEL_OPTS \ $EJABBERD_OPTS \ -s ejabberd \ From 4440b03b8976da2041df6004c0e56b8273d83268 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 29 Apr 2015 10:19:15 +0200 Subject: [PATCH 045/695] Fix fetching from git@github url and allow compilation from ejabberd sources --- src/ext_mod.erl | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index b2b426cec30..35c2a78d732 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -302,7 +302,15 @@ extract_url(Path, DestDir) -> ++[{error, unsupported_source}]). extract_github_master(Repos, DestDir) -> - case extract(zip, geturl(Repos ++ "/archive/master.zip"), DestDir) of + Base = case string:tokens(Repos, ":") of + ["git@github.com", T1] -> "https://github.com/"++T1; + _ -> Repos + end, + Url = case lists:reverse(Base) of + [$t,$i,$g,$.|T2] -> lists:reverse(T2); + _ -> Base + end, + case extract(zip, geturl(Url++"/archive/master.zip"), DestDir) of ok -> RepDir = filename:join(DestDir, module_name(Repos)), file:rename(RepDir++"-master", RepDir); @@ -445,10 +453,13 @@ compile(_Module, _Spec, DestDir) -> {file, _} -> [{d, 'LAGER'}]; _ -> [] end, + ExtLib = case filelib:is_file(filename:join(EjabInc, "xml.hrl")) of + true -> [{d, 'NO_EXT_LIB'}]; %% use include instead of include_lib + false -> [] + end, Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc}, - {d, 'NO_EXT_LIB'}, %% use include instead of include_lib verbose, report_errors, report_warnings] - ++ Logger, + ++ Logger ++ ExtLib, Result = [case compile:file(File, Options) of {ok, _} -> ok; {ok, _, _} -> ok; From 7492ecae527b29f55193fe411981e22df924360c Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 29 Apr 2015 13:21:41 +0200 Subject: [PATCH 046/695] New command get_user_rooms --- src/mod_muc_admin.erl | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index dee50650cc8..11f96b9bd29 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -18,6 +18,7 @@ create_room/3, destroy_room/3, create_rooms_file/1, destroy_rooms_file/1, rooms_unused_list/2, rooms_unused_destroy/2, + get_user_rooms/2, get_room_occupants/2, get_room_occupants_number/2, send_direct_invitation/4, @@ -107,6 +108,12 @@ commands() -> args = [{host, binary}, {days, integer}], result = {rooms, {list, {room, string}}}}, + #ejabberd_commands{name = get_user_rooms, tags = [muc], + desc = "Get the list of rooms where this user is occupant", + module = ?MODULE, function = get_user_rooms, + args = [{user, binary}, {host, binary}], + result = {rooms, {list, {room, string}}}}, + #ejabberd_commands{name = get_room_occupants, tags = [muc_room], desc = "Get the list of occupants of a MUC room", module = ?MODULE, function = get_room_occupants, @@ -193,6 +200,15 @@ muc_unregister_nick(Nick) -> error end. +get_user_rooms(LUser, LServer) -> + US = {LUser, LServer}, + case catch ets:select(muc_online_users, + [{#muc_online_users{us = US, room='$1', host='$2', _ = '_'}, [], [{{'$1', '$2'}}]}]) + of + Res when is_list(Res) -> + [<> || {R, H} <- Res]; + _ -> [] + end. %%---------------------------- %% Ad-hoc commands @@ -524,7 +540,7 @@ rooms_unused_destroy(Host, Days) -> rooms_unused_report(Action, Host, Days) -> {NA, NP, RP} = muc_unused(Action, Host, Days), io:format("Unused rooms: ~p out of ~p~n", [NP, NA]), - [[R, <<"@">>, H] || {R, H, _P} <- RP]. + [<> || {R, H, _P} <- RP]. muc_unused(Action, ServerHost, Days) -> Host = find_host(ServerHost), From 6987e85602daec7b1f04fe5fb1b0ddca7263aa27 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 29 Apr 2015 13:30:03 +0200 Subject: [PATCH 047/695] Improve module install code, allows better error checking --- src/ext_mod.erl | 53 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 35c2a78d732..f83fe2c6bc5 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -318,9 +318,23 @@ extract_github_master(Repos, DestDir) -> Error end. -copy_file(From, To) -> - filelib:ensure_dir(To), - file:copy(From, To). +copy(From, To) -> + case filelib:is_dir(From) of + true -> + Copy = fun(F) -> + SubFrom = filename:join(From, F), + SubTo = filename:join(To, F), + copy(SubFrom, SubTo) + end, + lists:foldl(fun({ok, C2}, {ok, C1}) -> {ok, C1+C2}; + ({ok, _}, Error) -> Error; + (Error, _) -> Error + end, {ok, 0}, + [Copy(filename:basename(X)) || X<-filelib:wildcard(From++"/*")]); + false -> + filelib:ensure_dir(To), + file:copy(From, To) + end. delete_path(Path) -> case filelib:is_dir(Path) of @@ -449,14 +463,9 @@ compile(_Module, _Spec, DestDir) -> filelib:ensure_dir(filename:join(Ebin, ".")), EjabBin = filename:dirname(code:which(ejabberd)), EjabInc = filename:join(filename:dirname(EjabBin), "include"), - Logger = case code:is_loaded(lager) of - {file, _} -> [{d, 'LAGER'}]; - _ -> [] - end, - ExtLib = case filelib:is_file(filename:join(EjabInc, "xml.hrl")) of - true -> [{d, 'NO_EXT_LIB'}]; %% use include instead of include_lib - false -> [] - end, + XmlHrl = filename:join(EjabInc, "xml.hrl"), + Logger = [{d, 'LAGER'} || code:is_loaded(lager)=/=false], + ExtLib = [{d, 'NO_EXT_LIB'} || filelib:is_file(XmlHrl)], Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc}, verbose, report_errors, report_warnings] ++ Logger ++ ExtLib, @@ -476,11 +485,23 @@ compile(_Module, _Spec, DestDir) -> [Error|_] -> Error end. -install(Module, _Spec, DestDir) -> - SpecFile = filename:flatten([Module, ".spec"]), - [copy_file(File, filename:join(DestDir, File)) - || File <- [SpecFile | filelib:wildcard("{ebin,priv,conf,include}/**")]], - ok. +install(Module, Spec, DestDir) -> + Errors = lists:dropwhile(fun({_, {ok, _}}) -> true; + (_) -> false + end, [{File, copy(File, filename:join(DestDir, File))} + || File <- filelib:wildcard("{ebin,priv,conf,include}/**")]), + Result = case Errors of + [{F, {error, E}}|_] -> + {error, {F, E}}; + [] -> + SpecPath = proplists:get_value(path, Spec), + SpecFile = filename:flatten([Module, ".spec"]), + copy(filename:join(SpecPath, SpecFile), filename:join(DestDir, SpecFile)) + end, + case Result of + {ok, _} -> ok; + Error -> Error + end. %% -- YAML spec parser From 60fe008268b5260a17f8c1a232c6cad6cb64451f Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 29 Apr 2015 14:51:45 +0300 Subject: [PATCH 048/695] Remove duplicated code --- src/gen_mod.erl | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/gen_mod.erl b/src/gen_mod.erl index e628b06abc8..b8e155a0493 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -209,6 +209,13 @@ get_opt_host(Host, Opts, Default) -> Val = get_opt(host, Opts, fun iolist_to_binary/1, Default), ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host). +-spec v_db(odbc | mnesia | riak | internal) -> odbc | mnesia | riak. + +v_db(odbc) -> odbc; +v_db(internal) -> mnesia; +v_db(mnesia) -> mnesia; +v_db(riak) -> riak. + -spec db_type(opts()) -> odbc | mnesia | riak. db_type(Opts) -> @@ -217,31 +224,14 @@ db_type(Opts) -> -spec db_type(binary() | global, atom() | opts()) -> odbc | mnesia | riak. db_type(Host, Module) when is_atom(Module) -> - get_module_opt(Host, Module, db_type, - fun(odbc) -> odbc; - (internal) -> mnesia; - (mnesia) -> mnesia; - (riak) -> riak - end, - default_db(Host)); + get_module_opt(Host, Module, db_type, fun v_db/1, default_db(Host)); db_type(Host, Opts) when is_list(Opts) -> - get_opt(db_type, Opts, - fun(odbc) -> odbc; - (internal) -> mnesia; - (mnesia) -> mnesia; - (riak) -> riak - end, - default_db(Host)). + get_opt(db_type, Opts, fun v_db/1, default_db(Host)). -spec default_db(binary() | global) -> odbc | mnesia | riak. default_db(Host) -> - ejabberd_config:get_option({default_db, Host}, - fun(odbc) -> odbc; - (mnesia) -> mnesia; - (riak) -> riak; - (internal) -> mnesia - end, mnesia). + ejabberd_config:get_option({default_db, Host}, fun v_db/1, mnesia). -spec loaded_modules(binary()) -> [atom()]. From 77e57afae1d3f4f531afa6556b0d3c45f8e1f418 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 5 May 2015 12:45:53 +0200 Subject: [PATCH 049/695] Fix set_last command to work with recent ejabberd (#555) --- src/mod_admin_extra.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 49e6a986978..12270a54ad3 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -446,7 +446,7 @@ commands() -> longdesc = "Timestamp is the seconds since" "1970-01-01 00:00:00 UTC, for example: date +%s", module = ?MODULE, function = set_last, - args = [{user, string}, {host, string}, {timestamp, integer}, {status, string}], + args = [{user, binary}, {host, binary}, {timestamp, integer}, {status, binary}], result = {res, rescode}}, #ejabberd_commands{name = private_get, tags = [private], From 96c62acb1b9c6b307ec37a1ad1041589c2b7375a Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 5 May 2015 12:46:21 +0200 Subject: [PATCH 050/695] Improve get_last command to provide also last activity status --- src/mod_admin_extra.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 12270a54ad3..75233a732c9 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -435,7 +435,7 @@ commands() -> result = {res, rescode}}, #ejabberd_commands{name = get_last, tags = [last], - desc = "Get last activity information", + desc = "Get last activity information (timestamp and status)", longdesc = "Timestamp is the seconds since" "1970-01-01 00:00:00 UTC, for example: date +%s", module = ?MODULE, function = get_last, @@ -1226,7 +1226,7 @@ get_last(User, Server) -> case Mod:get_last_info(User, Server) of not_found -> "Never"; - {ok, Shift, _Status} -> + {ok, Shift, Status} -> TimeStamp = {Shift div 1000000, Shift rem 1000000, 0}, @@ -1234,8 +1234,8 @@ get_last(User, Server) -> calendar:now_to_local_time(TimeStamp), lists:flatten( io_lib:format( - "~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w", - [Year, Month, Day, Hour, Minute, Second])) + "~w-~.2.0w-~.2.0w ~.2.0w:~.2.0w:~.2.0w ~s", + [Year, Month, Day, Hour, Minute, Second, Status])) end; _ -> "Online" From fa99519f8bc3c73359ab88e7759e1d0c9405c05d Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 5 May 2015 12:54:20 +0200 Subject: [PATCH 051/695] Simplify internal code of get_last and set_last commands --- src/mod_admin_extra.erl | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 75233a732c9..023c29dcd94 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -70,7 +70,6 @@ push_alltoall/2, %% mod_last get_last/2, - set_last/4, %% mod_private private_get/4, private_set/3, @@ -445,7 +444,7 @@ commands() -> desc = "Set last activity information", longdesc = "Timestamp is the seconds since" "1970-01-01 00:00:00 UTC, for example: date +%s", - module = ?MODULE, function = set_last, + module = mod_last, function = store_last_info, args = [{user, binary}, {host, binary}, {timestamp, integer}, {status, binary}], result = {res, rescode}}, @@ -680,7 +679,7 @@ delete_old_users(Days, Users) -> %% If it isnt [] -> %% Look for his last_activity - case (get_lastactivity_module(LServer)):get_last_info(LUser, LServer) of + case mod_last:get_last_info(LUser, LServer) of %% If it is %% existent: {ok, TimeStamp, _Status} -> @@ -714,13 +713,6 @@ delete_old_users(Days, Users) -> Users_removed = lists:filter(F, Users), {removed, length(Users_removed), Users_removed}. -get_lastactivity_module(Server) -> - case lists:member(mod_last, gen_mod:loaded_modules(Server)) of - true -> mod_last; - _ -> mod_last_odbc - end. - - %% %% Ban account @@ -1220,10 +1212,9 @@ build_broadcast(U, S, SubsAtom) when is_atom(SubsAtom) -> %%% get_last(User, Server) -> - Mod = get_lastactivity_module(Server), case ejabberd_sm:get_user_resources(User, Server) of [] -> - case Mod:get_last_info(User, Server) of + case mod_last:get_last_info(User, Server) of not_found -> "Never"; {ok, Shift, Status} -> @@ -1241,10 +1232,6 @@ get_last(User, Server) -> "Online" end. -set_last(User, Server, Timestamp, Status) -> - Mod = get_lastactivity_module(Server), - Mod:store_last_info(User, Server, Timestamp, Status). - %%% %%% Private Storage %%% From 6eab111d05de00bbe2cba178674ab5f398cdcf0a Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Tue, 5 May 2015 09:24:31 -0300 Subject: [PATCH 052/695] Point out availability of development environment --- README | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README b/README index 91bad4209b5..2f78d1973da 100644 --- a/README +++ b/README @@ -152,6 +152,14 @@ Operation Guide available online and in the `doc` directory of the source tarball. +Development +----------- + +In order to assist in the development of ejabberd, and particularly the +execution of the test suite, a Vagrant environment is available at +https://github.com/processone/ejabberd-vagrant-dev. + + Links ----- From 7297b23508391a8d03e7801ce6bf46db9bef4e90 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 5 May 2015 22:00:05 +0200 Subject: [PATCH 053/695] Tag private MUC messages with muc#user namespace Make it possible for clients to identify private MUC messages. One use case would be to filter out undesired carbon copies of those. --- src/mod_muc_room.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index f381e845823..8d0b36b6cdc 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -570,7 +570,10 @@ normal_state({route, From, ToNick, FromNickJID = jlib:jid_replace_resource(StateData#state.jid, FromNick), - [ejabberd_router:route(FromNickJID, ToJID, Packet) + X = #xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_MUC_USER}]}, + PrivMsg = xml:append_subtags(Packet, [X]), + [ejabberd_router:route(FromNickJID, ToJID, PrivMsg) || ToJID <- ToJIDs]; true -> ErrText = From d9814709e26c78fde942f312ee0cf1de876354b8 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Tue, 14 Apr 2015 18:14:20 -0300 Subject: [PATCH 054/695] Remove commented code --- src/cyrsasl_digest.erl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 10f9641308d..be9867bad69 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -80,9 +80,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State, bad -> {error, <<"bad-protocol">>}; KeyVals -> DigestURI = proplists:get_value(<<"digest-uri">>, KeyVals, <<>>), - %DigestURI = xml:get_attr_s(<<"digest-uri">>, KeyVals), UserName = proplists:get_value(<<"username">>, KeyVals, <<>>), - %UserName = xml:get_attr_s(<<"username">>, KeyVals), case is_digesturi_valid(DigestURI, State#state.host, State#state.hostfqdn) of @@ -94,13 +92,11 @@ mech_step(#state{step = 3, nonce = Nonce} = State, {error, <<"not-authorized">>, UserName}; true -> AuthzId = proplists:get_value(<<"authzid">>, KeyVals, <<>>), - %AuthzId = xml:get_attr_s(<<"authzid">>, KeyVals), case (State#state.get_password)(UserName) of {false, _} -> {error, <<"not-authorized">>, UserName}; {Passwd, AuthModule} -> case (State#state.check_password)(UserName, <<"">>, proplists:get_value(<<"response">>, KeyVals, <<>>), - %xml:get_attr_s(<<"response">>, KeyVals), fun (PW) -> response(KeyVals, UserName, From 917d48f30bca65f984c4e1305eefe7266097ff65 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Wed, 8 Apr 2015 22:21:09 -0300 Subject: [PATCH 055/695] Use SASL PLAIN authzid as client identity if auth module permits it This allows the authentication modules to perform SASL proxy authentication. It puts the onus on them to authorize the authcid to masquerade as the authzid. Doesn't currently implement such functionality in existing auth modules, since they cannot currently codify a relationship between the two identities. Does not permit the authzid to use a domain differently from the one of the connection. Note: digest might not work, but I have no interest in it, being deprecated. --- src/cyrsasl.erl | 2 +- src/cyrsasl_digest.erl | 10 +- src/cyrsasl_plain.erl | 15 ++- src/ejabberd_auth.erl | 42 ++++---- src/ejabberd_auth_anonymous.erl | 10 +- src/ejabberd_auth_external.erl | 54 +++++----- src/ejabberd_auth_internal.erl | 84 ++++++++------- src/ejabberd_auth_ldap.erl | 26 +++-- src/ejabberd_auth_odbc.erl | 174 +++++++++++++++++--------------- src/ejabberd_auth_pam.erl | 36 ++++--- src/ejabberd_auth_riak.erl | 78 +++++++------- src/ejabberd_c2s.erl | 28 ++--- src/ejabberd_commands.erl | 2 +- src/ejabberd_web_admin.erl | 2 +- src/mod_proxy65_stream.erl | 2 +- src/mod_register_web.erl | 2 +- 16 files changed, 306 insertions(+), 261 deletions(-) diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 764473bab09..09b1a1a6f12 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -128,7 +128,7 @@ register_mechanism(Mechanism, Module, PasswordType) -> %% end. check_credentials(_State, Props) -> - User = proplists:get_value(username, Props, <<>>), + User = proplists:get_value(authzid, Props, <<>>), case jlib:nodeprep(User) of error -> {error, <<"not-authorized">>}; <<"">> -> {error, <<"not-authorized">>}; diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index be9867bad69..12e5555a18b 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -47,7 +47,7 @@ username = <<"">> :: binary(), authzid = <<"">> :: binary(), get_password = fun(_) -> {false, <<>>} end :: get_password_fun(), - check_password = fun(_, _, _, _) -> false end :: check_password_fun(), + check_password = fun(_, _, _, _, _) -> false end :: check_password_fun(), auth_module :: atom(), host = <<"">> :: binary(), hostfqdn = <<"">> :: binary()}). @@ -95,7 +95,7 @@ mech_step(#state{step = 3, nonce = Nonce} = State, case (State#state.get_password)(UserName) of {false, _} -> {error, <<"not-authorized">>, UserName}; {Passwd, AuthModule} -> - case (State#state.check_password)(UserName, <<"">>, + case (State#state.check_password)(UserName, UserName, <<"">>, proplists:get_value(<<"response">>, KeyVals, <<>>), fun (PW) -> response(KeyVals, @@ -123,7 +123,11 @@ mech_step(#state{step = 5, auth_module = AuthModule, username = UserName, authzid = AuthzId}, <<"">>) -> {ok, - [{username, UserName}, {authzid, AuthzId}, + [{username, UserName}, {authzid, case AuthzId of + <<"">> -> UserName; + _ -> AuthzId + end + }, {auth_module, AuthModule}]}; mech_step(A, B) -> ?DEBUG("SASL DIGEST: A ~p B ~p", [A, B]), diff --git a/src/cyrsasl_plain.erl b/src/cyrsasl_plain.erl index d2fb373e420..ceceacca867 100644 --- a/src/cyrsasl_plain.erl +++ b/src/cyrsasl_plain.erl @@ -45,7 +45,7 @@ mech_new(_Host, _GetPassword, CheckPassword, _CheckPasswordDigest) -> mech_step(State, ClientIn) -> case prepare(ClientIn) of [AuthzId, User, Password] -> - case (State#state.check_password)(User, Password) of + case (State#state.check_password)(User, AuthzId, Password) of {true, AuthModule} -> {ok, [{username, User}, {authzid, AuthzId}, @@ -60,12 +60,17 @@ prepare(ClientIn) -> [<<"">>, UserMaybeDomain, Password] -> case parse_domain(UserMaybeDomain) of %% login@domainpwd - [User, _Domain] -> [UserMaybeDomain, User, Password]; + [User, _Domain] -> [User, User, Password]; %% loginpwd - [User] -> [<<"">>, User, Password] + [User] -> [User, User, Password] end; - %% login@domainloginpwd - [AuthzId, User, Password] -> [AuthzId, User, Password]; + [AuthzId, User, Password] -> + case parse_domain(AuthzId) of + %% login@domainloginpwd + [AuthzUser, _Domain] -> [AuthzUser, User, Password]; + %% loginloginpwd + [AuthzUser] -> [AuthzUser, User, Password] + end; _ -> error end. diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 991cb664b91..bf47af85bff 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -30,9 +30,9 @@ -author('alexey@process-one.net'). %% External exports --export([start/0, set_password/3, check_password/3, - check_password/5, check_password_with_authmodule/3, - check_password_with_authmodule/5, try_register/3, +-export([start/0, set_password/3, check_password/4, + check_password/6, check_password_with_authmodule/4, + check_password_with_authmodule/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, export/1, import/1, get_vh_registered_users_number/1, import/3, @@ -61,8 +61,8 @@ -callback remove_user(binary(), binary()) -> any(). -callback remove_user(binary(), binary(), binary()) -> any(). -callback is_user_exists(binary(), binary()) -> boolean() | {error, atom()}. --callback check_password(binary(), binary(), binary()) -> boolean(). --callback check_password(binary(), binary(), binary(), binary(), +-callback check_password(binary(), binary(), binary(), binary()) -> boolean(). +-callback check_password(binary(), binary(), binary(), binary(), binary(), fun((binary()) -> binary())) -> boolean(). -callback try_register(binary(), binary(), binary()) -> {atomic, atom()} | {error, atom()}. @@ -100,10 +100,10 @@ store_type(Server) -> end, plain, auth_modules(Server)). --spec check_password(binary(), binary(), binary()) -> boolean(). +-spec check_password(binary(), binary(), binary(), binary()) -> boolean(). -check_password(User, Server, Password) -> - case check_password_with_authmodule(User, Server, +check_password(User, AuthzId, Server, Password) -> + case check_password_with_authmodule(User, AuthzId, Server, Password) of {true, _AuthModule} -> true; @@ -111,15 +111,15 @@ check_password(User, Server, Password) -> end. %% @doc Check if the user and password can login in server. -%% @spec (User::string(), Server::string(), Password::string(), +%% @spec (User::string(), AuthzId::string(), Server::string(), Password::string(), %% Digest::string(), DigestGen::function()) -> %% true | false --spec check_password(binary(), binary(), binary(), binary(), +-spec check_password(binary(), binary(), binary(), binary(), binary(), fun((binary()) -> binary())) -> boolean(). - -check_password(User, Server, Password, Digest, + +check_password(User, AuthzId, Server, Password, Digest, DigestGen) -> - case check_password_with_authmodule(User, Server, + case check_password_with_authmodule(User, AuthzId, Server, Password, Digest, DigestGen) of {true, _AuthModule} -> true; @@ -130,28 +130,28 @@ check_password(User, Server, Password, Digest, %% The user can login if at least an authentication method accepts the user %% and the password. %% The first authentication method that accepts the credentials is returned. -%% @spec (User::string(), Server::string(), Password::string()) -> +%% @spec (User::string(), AuthzId::string(), Server::string(), Password::string()) -> %% {true, AuthModule} | false %% where %% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external %% | ejabberd_auth_internal | ejabberd_auth_ldap -%% | ejabberd_auth_odbc | ejabberd_auth_pam --spec check_password_with_authmodule(binary(), binary(), binary()) -> false | +%% | ejabberd_auth_odbc | ejabberd_auth_pam | ejabberd_auth_riak +-spec check_password_with_authmodule(binary(), binary(), binary(), binary()) -> false | {true, atom()}. -check_password_with_authmodule(User, Server, +check_password_with_authmodule(User, AuthzId, Server, Password) -> check_password_loop(auth_modules(Server), - [User, Server, Password]). + [User, AuthzId, Server, Password]). --spec check_password_with_authmodule(binary(), binary(), binary(), binary(), +-spec check_password_with_authmodule(binary(), binary(), binary(), binary(), binary(), fun((binary()) -> binary())) -> false | {true, atom()}. -check_password_with_authmodule(User, Server, Password, +check_password_with_authmodule(User, AuthzId, Server, Password, Digest, DigestGen) -> check_password_loop(auth_modules(Server), - [User, Server, Password, Digest, DigestGen]). + [User, AuthzId, Server, Password, Digest, DigestGen]). check_password_loop([], _Args) -> false; check_password_loop([AuthModule | AuthModules], Args) -> diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index cb320dea557..05f790db675 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -38,8 +38,8 @@ %% Function used by ejabberd_auth: --export([login/2, set_password/3, check_password/3, - check_password/5, try_register/3, +-export([login/2, set_password/3, check_password/4, + check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password_s/2, @@ -174,11 +174,11 @@ purge_hook(true, LUser, LServer) -> %% When anonymous login is enabled, check the password for permenant users %% before allowing access -check_password(User, Server, Password) -> - check_password(User, Server, Password, undefined, +check_password(User, AuthzId, Server, Password) -> + check_password(User, AuthzId, Server, Password, undefined, undefined). -check_password(User, Server, _Password, _Digest, +check_password(User, _AuthzId, Server, _Password, _Digest, _DigestGen) -> case ejabberd_auth:is_user_exists_in_other_modules(?MODULE, diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 0aa825f73bf..44c931cbf09 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -30,8 +30,8 @@ -behaviour(ejabberd_auth). %% External exports --export([start/1, set_password/3, check_password/3, - check_password/5, try_register/3, +-export([start/1, set_password/3, check_password/4, + check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, @@ -75,16 +75,20 @@ plain_password_required() -> true. store_type() -> external. -check_password(User, Server, Password) -> - case get_cache_option(Server) of - false -> check_password_extauth(User, Server, Password); - {true, CacheTime} -> - check_password_cache(User, Server, Password, CacheTime) +check_password(User, AuthzId, Server, Password) -> + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + case get_cache_option(Server) of + false -> check_password_extauth(User, AuthzId, Server, Password); + {true, CacheTime} -> + check_password_cache(User, AuthzId, Server, Password, CacheTime) + end end. -check_password(User, Server, Password, _Digest, +check_password(User, AuthzId, Server, Password, _Digest, _DigestGen) -> - check_password(User, Server, Password). + check_password(User, AuthzId, Server, Password). set_password(User, Server, Password) -> case extauth:set_password(User, Server, Password) of @@ -177,8 +181,8 @@ get_cache_option(Host) -> CacheTime -> {true, CacheTime} end. -%% @spec (User, Server, Password) -> true | false -check_password_extauth(User, Server, Password) -> +%% @spec (User, AuthzId, Server, Password) -> true | false +check_password_extauth(User, _AuthzId, Server, Password) -> extauth:check_password(User, Server, Password) andalso Password /= <<"">>. @@ -186,35 +190,35 @@ check_password_extauth(User, Server, Password) -> try_register_extauth(User, Server, Password) -> extauth:try_register(User, Server, Password). -check_password_cache(User, Server, Password, 0) -> - check_password_external_cache(User, Server, Password); -check_password_cache(User, Server, Password, +check_password_cache(User, AuthzId, Server, Password, 0) -> + check_password_external_cache(User, AuthzId, Server, Password); +check_password_cache(User, AuthzId, Server, Password, CacheTime) -> case get_last_access(User, Server) of online -> - check_password_internal(User, Server, Password); + check_password_internal(User, AuthzId, Server, Password); never -> - check_password_external_cache(User, Server, Password); + check_password_external_cache(User, AuthzId, Server, Password); mod_last_required -> ?ERROR_MSG("extauth is used, extauth_cache is enabled " "but mod_last is not enabled in that " "host", []), - check_password_external_cache(User, Server, Password); + check_password_external_cache(User, AuthzId, Server, Password); TimeStamp -> case is_fresh_enough(TimeStamp, CacheTime) of %% If no need to refresh, check password against Mnesia true -> - case check_password_internal(User, Server, Password) of + case check_password_internal(User, AuthzId, Server, Password) of %% If password valid in Mnesia, accept it true -> true; %% Else (password nonvalid in Mnesia), check in extauth and cache result false -> - check_password_external_cache(User, Server, Password) + check_password_external_cache(User, AuthzId, Server, Password) end; %% Else (need to refresh), check in extauth and cache result false -> - check_password_external_cache(User, Server, Password) + check_password_external_cache(User, AuthzId, Server, Password) end end. @@ -240,8 +244,8 @@ get_password_cache(User, Server, CacheTime) -> end. %% Check the password using extauth; if success then cache it -check_password_external_cache(User, Server, Password) -> - case check_password_extauth(User, Server, Password) of +check_password_external_cache(User, AuthzId, Server, Password) -> + case check_password_extauth(User, AuthzId, Server, Password) of true -> set_password_internal(User, Server, Password), true; false -> false @@ -255,9 +259,9 @@ try_register_external_cache(User, Server, Password) -> _ -> {error, not_allowed} end. -%% @spec (User, Server, Password) -> true | false -check_password_internal(User, Server, Password) -> - ejabberd_auth_internal:check_password(User, Server, +%% @spec (User, AuthzId, Server, Password) -> true | false +check_password_internal(User, AuthzId, Server, Password) -> + ejabberd_auth_internal:check_password(User, AuthzId, Server, Password). %% @spec (User, Server, Password) -> ok | {error, invalid_jid} diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index fc128ac5a54..bb4ceab5192 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -30,8 +30,8 @@ -behaviour(ejabberd_auth). %% External exports --export([start/1, set_password/3, check_password/3, - check_password/5, try_register/3, +-export([start/1, set_password/3, check_password/4, + check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, @@ -85,45 +85,53 @@ store_type() -> true -> scram %% allows: PLAIN SCRAM end. -check_password(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - US = {LUser, LServer}, - case catch mnesia:dirty_read({passwd, US}) of - [#passwd{password = Password}] - when is_binary(Password) -> - Password /= <<"">>; - [#passwd{password = Scram}] - when is_record(Scram, scram) -> - is_password_scram_valid(Password, Scram); - _ -> false +check_password(User, AuthzId, Server, Password) -> + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + US = {LUser, LServer}, + case catch mnesia:dirty_read({passwd, US}) of + [#passwd{password = Password}] + when is_binary(Password) -> + Password /= <<"">>; + [#passwd{password = Scram}] + when is_record(Scram, scram) -> + is_password_scram_valid(Password, Scram); + _ -> false + end end. -check_password(User, Server, Password, Digest, +check_password(User, AuthzId, Server, Password, Digest, DigestGen) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - US = {LUser, LServer}, - case catch mnesia:dirty_read({passwd, US}) of - [#passwd{password = Passwd}] when is_binary(Passwd) -> - DigRes = if Digest /= <<"">> -> - Digest == DigestGen(Passwd); - true -> false - end, - if DigRes -> true; - true -> (Passwd == Password) and (Password /= <<"">>) - end; - [#passwd{password = Scram}] - when is_record(Scram, scram) -> - Passwd = jlib:decode_base64(Scram#scram.storedkey), - DigRes = if Digest /= <<"">> -> - Digest == DigestGen(Passwd); - true -> false - end, - if DigRes -> true; - true -> (Passwd == Password) and (Password /= <<"">>) - end; - _ -> false + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + US = {LUser, LServer}, + case catch mnesia:dirty_read({passwd, US}) of + [#passwd{password = Passwd}] when is_binary(Passwd) -> + DigRes = if Digest /= <<"">> -> + Digest == DigestGen(Passwd); + true -> false + end, + if DigRes -> true; + true -> (Passwd == Password) and (Password /= <<"">>) + end; + [#passwd{password = Scram}] + when is_record(Scram, scram) -> + Passwd = jlib:decode_base64(Scram#scram.storedkey), + DigRes = if Digest /= <<"">> -> + Digest == DigestGen(Passwd); + true -> false + end, + if DigRes -> true; + true -> (Passwd == Password) and (Password /= <<"">>) + end; + _ -> false + end end. %% @spec (User::string(), Server::string(), Password::string()) -> diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index 3055d1044b5..45964d669b5 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -36,7 +36,7 @@ %% External exports -export([start/1, stop/1, start_link/1, set_password/3, - check_password/3, check_password/5, try_register/3, + check_password/4, check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, @@ -115,19 +115,23 @@ plain_password_required() -> true. store_type() -> external. -check_password(User, Server, Password) -> - if Password == <<"">> -> false; - true -> - case catch check_password_ldap(User, Server, Password) - of - {'EXIT', _} -> false; - Result -> Result - end +check_password(User, AuthzId, Server, Password) -> + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + if Password == <<"">> -> false; + true -> + case catch check_password_ldap(User, Server, Password) + of + {'EXIT', _} -> false; + Result -> Result + end + end end. -check_password(User, Server, Password, _Digest, +check_password(User, AuthzId, Server, Password, _Digest, _DigestGen) -> - check_password(User, Server, Password). + check_password(User, AuthzId, Server, Password). set_password(User, Server, Password) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index 881b86ccad9..b3bcd369ab0 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -30,8 +30,8 @@ -behaviour(ejabberd_auth). %% External exports --export([start/1, set_password/3, check_password/3, - check_password/5, try_register/3, +-export([start/1, set_password/3, check_password/4, + check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, @@ -63,89 +63,97 @@ store_type() -> true -> scram %% allows: PLAIN SCRAM end. -%% @spec (User, Server, Password) -> true | false | {error, Error} -check_password(User, Server, Password) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), - if (LUser == error) or (LServer == error) -> - false; - (LUser == <<>>) or (LServer == <<>>) -> - false; - true -> - Username = ejabberd_odbc:escape(LUser), - case is_scrammed() of - true -> - try odbc_queries:get_password_scram(LServer, Username) of - {selected, [<<"password">>, <<"serverkey">>, - <<"salt">>, <<"iterationcount">>], - [[StoredKey, ServerKey, Salt, IterationCount]]} -> - Scram = - #scram{storedkey = StoredKey, - serverkey = ServerKey, - salt = Salt, - iterationcount = jlib:binary_to_integer( - IterationCount)}, - is_password_scram_valid(Password, Scram); - {selected, [<<"password">>, <<"serverkey">>, - <<"salt">>, <<"iterationcount">>], []} -> - false; %% Account does not exist - {error, _Error} -> - false %% Typical error is that table doesn't exist - catch - _:_ -> - false %% Typical error is database not accessible - end; - false -> - try odbc_queries:get_password(LServer, Username) of - {selected, [<<"password">>], [[Password]]} -> - Password /= <<"">>; - {selected, [<<"password">>], [[_Password2]]} -> - false; %% Password is not correct - {selected, [<<"password">>], []} -> - false; %% Account does not exist - {error, _Error} -> - false %% Typical error is that table doesn't exist - catch - _:_ -> - false %% Typical error is database not accessible - end - end +%% @spec (User, AuthzId, Server, Password) -> true | false | {error, Error} +check_password(User, AuthzId, Server, Password) -> + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + LServer = jlib:nameprep(Server), + LUser = jlib:nodeprep(User), + if (LUser == error) or (LServer == error) -> + false; + (LUser == <<>>) or (LServer == <<>>) -> + false; + true -> + Username = ejabberd_odbc:escape(LUser), + case is_scrammed() of + true -> + try odbc_queries:get_password_scram(LServer, Username) of + {selected, [<<"password">>, <<"serverkey">>, + <<"salt">>, <<"iterationcount">>], + [[StoredKey, ServerKey, Salt, IterationCount]]} -> + Scram = + #scram{storedkey = StoredKey, + serverkey = ServerKey, + salt = Salt, + iterationcount = jlib:binary_to_integer( + IterationCount)}, + is_password_scram_valid(Password, Scram); + {selected, [<<"password">>, <<"serverkey">>, + <<"salt">>, <<"iterationcount">>], []} -> + false; %% Account does not exist + {error, _Error} -> + false %% Typical error is that table doesn't exist + catch + _:_ -> + false %% Typical error is database not accessible + end; + false -> + try odbc_queries:get_password(LServer, Username) of + {selected, [<<"password">>], [[Password]]} -> + Password /= <<"">>; + {selected, [<<"password">>], [[_Password2]]} -> + false; %% Password is not correct + {selected, [<<"password">>], []} -> + false; %% Account does not exist + {error, _Error} -> + false %% Typical error is that table doesn't exist + catch + _:_ -> + false %% Typical error is database not accessible + end + end + end end. -%% @spec (User, Server, Password, Digest, DigestGen) -> true | false | {error, Error} -check_password(User, Server, Password, Digest, +%% @spec (User, AuthzId, Server, Password, Digest, DigestGen) -> true | false | {error, Error} +check_password(User, AuthzId, Server, Password, Digest, DigestGen) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), - if (LUser == error) or (LServer == error) -> - false; - (LUser == <<>>) or (LServer == <<>>) -> - false; - true -> - case is_scrammed() of - false -> - Username = ejabberd_odbc:escape(LUser), - try odbc_queries:get_password(LServer, Username) of - %% Account exists, check if password is valid - {selected, [<<"password">>], [[Passwd]]} -> - DigRes = if Digest /= <<"">> -> - Digest == DigestGen(Passwd); - true -> false - end, - if DigRes -> true; - true -> (Passwd == Password) and (Password /= <<"">>) - end; - {selected, [<<"password">>], []} -> - false; %% Account does not exist - {error, _Error} -> - false %% Typical error is that table doesn't exist - catch - _:_ -> - false %% Typical error is database not accessible - end; - true -> - false - end + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + LServer = jlib:nameprep(Server), + LUser = jlib:nodeprep(User), + if (LUser == error) or (LServer == error) -> + false; + (LUser == <<>>) or (LServer == <<>>) -> + false; + true -> + case is_scrammed() of + false -> + Username = ejabberd_odbc:escape(LUser), + try odbc_queries:get_password(LServer, Username) of + %% Account exists, check if password is valid + {selected, [<<"password">>], [[Passwd]]} -> + DigRes = if Digest /= <<"">> -> + Digest == DigestGen(Passwd); + true -> false + end, + if DigRes -> true; + true -> (Passwd == Password) and (Password /= <<"">>) + end; + {selected, [<<"password">>], []} -> + false; %% Account does not exist + {error, _Error} -> + false %% Typical error is that table doesn't exist + catch + _:_ -> + false %% Typical error is database not accessible + end; + true -> + false + end + end end. %% @spec (User::string(), Server::string(), Password::string()) -> @@ -352,7 +360,7 @@ remove_user(User, Server, Password) -> true -> case is_scrammed() of true -> - case check_password(User, Server, Password) of + case check_password(User, <<"">>, Server, Password) of true -> remove_user(User, Server), ok; diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl index f3fdf628dd4..da893eb4674 100644 --- a/src/ejabberd_auth_pam.erl +++ b/src/ejabberd_auth_pam.erl @@ -32,8 +32,8 @@ %%==================================================================== %% API %%==================================================================== --export([start/1, set_password/3, check_password/3, - check_password/5, try_register/3, +-export([start/1, set_password/3, check_password/4, + check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, get_vh_registered_users_number/2, @@ -47,21 +47,25 @@ start(_Host) -> set_password(_User, _Server, _Password) -> {error, not_allowed}. -check_password(User, Server, Password, _Digest, +check_password(User, AuthzId, Server, Password, _Digest, _DigestGen) -> - check_password(User, Server, Password). - -check_password(User, Host, Password) -> - Service = get_pam_service(Host), - UserInfo = case get_pam_userinfotype(Host) of - username -> User; - jid -> <> - end, - case catch epam:authenticate(Service, UserInfo, - Password) - of - true -> true; - _ -> false + check_password(User, AuthzId, Server, Password). + +check_password(User, AuthzId, Host, Password) -> + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + Service = get_pam_service(Host), + UserInfo = case get_pam_userinfotype(Host) of + username -> User; + jid -> <> + end, + case catch epam:authenticate(Service, UserInfo, + Password) + of + true -> true; + _ -> false + end end. try_register(_User, _Server, _Password) -> diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 3f3484c146b..8c926f4bd6c 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -30,8 +30,8 @@ -behaviour(ejabberd_auth). %% External exports --export([start/1, set_password/3, check_password/3, - check_password/5, try_register/3, +-export([start/1, set_password/3, check_password/4, + check_password/6, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, get_vh_registered_users/2, get_vh_registered_users_number/1, @@ -66,42 +66,50 @@ store_type() -> passwd_schema() -> {record_info(fields, passwd), #passwd{}}. -check_password(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of - {ok, #passwd{password = Password}} when is_binary(Password) -> - Password /= <<"">>; - {ok, #passwd{password = Scram}} when is_record(Scram, scram) -> - is_password_scram_valid(Password, Scram); - _ -> - false +check_password(User, AuthzId, Server, Password) -> + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of + {ok, #passwd{password = Password}} when is_binary(Password) -> + Password /= <<"">>; + {ok, #passwd{password = Scram}} when is_record(Scram, scram) -> + is_password_scram_valid(Password, Scram); + _ -> + false + end end. -check_password(User, Server, Password, Digest, +check_password(User, AuthzId, Server, Password, Digest, DigestGen) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of - {ok, #passwd{password = Passwd}} when is_binary(Passwd) -> - DigRes = if Digest /= <<"">> -> - Digest == DigestGen(Passwd); - true -> false - end, - if DigRes -> true; - true -> (Passwd == Password) and (Password /= <<"">>) - end; - {ok, #passwd{password = Scram}} - when is_record(Scram, scram) -> - Passwd = jlib:decode_base64(Scram#scram.storedkey), - DigRes = if Digest /= <<"">> -> - Digest == DigestGen(Passwd); - true -> false - end, - if DigRes -> true; - true -> (Passwd == Password) and (Password /= <<"">>) - end; - _ -> false + if AuthzId /= <<>> andalso AuthzId /= User -> + false; + true -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of + {ok, #passwd{password = Passwd}} when is_binary(Passwd) -> + DigRes = if Digest /= <<"">> -> + Digest == DigestGen(Passwd); + true -> false + end, + if DigRes -> true; + true -> (Passwd == Password) and (Password /= <<"">>) + end; + {ok, #passwd{password = Scram}} + when is_record(Scram, scram) -> + Passwd = jlib:decode_base64(Scram#scram.storedkey), + DigRes = if Digest /= <<"">> -> + Digest == DigestGen(Passwd); + true -> false + end, + if DigRes -> true; + true -> (Passwd == Password) and (Password /= <<"">>) + end; + _ -> false + end end. set_password(User, Server, Password) -> diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f2d16e878ba..22e17bee0de 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -397,13 +397,13 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> ejabberd_auth:get_password_with_authmodule( U, Server) end, - fun(U, P) -> + fun(U, AuthzId, P) -> ejabberd_auth:check_password_with_authmodule( - U, Server, P) + U, AuthzId, Server, P) end, - fun(U, P, D, DG) -> + fun(U, AuthzId, P, D, DG) -> ejabberd_auth:check_password_with_authmodule( - U, Server, P, D, DG) + U, AuthzId, Server, P, D, DG) end), Mechs = case TLSEnabled or not TLSRequired of @@ -635,7 +635,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> DGen = fun (PW) -> p1_sha:sha(<<(StateData#state.streamid)/binary, PW/binary>>) end, - case ejabberd_auth:check_password_with_authmodule(U, + case ejabberd_auth:check_password_with_authmodule(U, U, StateData#state.server, P, D, DGen) of @@ -753,9 +753,7 @@ wait_for_feature_request({xmlstreamelement, El}, of {ok, Props} -> (StateData#state.sockmod):reset_stream(StateData#state.socket), - %U = xml:get_attr_s(username, Props), - U = proplists:get_value(username, Props, <<>>), - %AuthModule = xml:get_attr_s(auth_module, Props), + U = identity(Props), AuthModule = proplists:get_value(auth_module, Props, undefined), ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", @@ -906,9 +904,7 @@ wait_for_sasl_response({xmlstreamelement, El}, {ok, Props} -> catch (StateData#state.sockmod):reset_stream(StateData#state.socket), -% U = xml:get_attr_s(username, Props), - U = proplists:get_value(username, Props, <<>>), -% AuthModule = xml:get_attr_s(auth_module, Props), + U = identity(Props), AuthModule = proplists:get_value(auth_module, Props, <<>>), ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", @@ -929,9 +925,7 @@ wait_for_sasl_response({xmlstreamelement, El}, user = U}); {ok, Props, ServerOut} -> (StateData#state.sockmod):reset_stream(StateData#state.socket), -% U = xml:get_attr_s(username, Props), - U = proplists:get_value(username, Props, <<>>), -% AuthModule = xml:get_attr_s(auth_module, Props), + U = identity(Props), AuthModule = proplists:get_value(auth_module, Props, undefined), ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", @@ -3126,3 +3120,9 @@ pack_string(String, Pack) -> transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +identity(Props) -> + case proplists:get_value(authzid, Props, <<>>) of + <<>> -> proplists:get_value(username, Props, <<>>); + AuthzId -> AuthzId + end. diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index a4f38e83669..ca40d5dc31c 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -397,7 +397,7 @@ check_auth(noauth) -> no_auth_provided; check_auth({User, Server, Password}) -> %% Check the account exists and password is valid - case ejabberd_auth:check_password(User, Server, Password) of + case ejabberd_auth:check_password(User, <<"">>, Server, Password) of true -> {ok, User, Server}; _ -> throw({error, invalid_account_data}) end. diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 29ecb7346ea..7cf15210cc8 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -263,7 +263,7 @@ get_auth_admin(Auth, HostHTTP, RPath, Method) -> get_auth_account(HostOfRule, AccessRule, User, Server, Pass) -> - case ejabberd_auth:check_password(User, Server, Pass) of + case ejabberd_auth:check_password(User, <<"">>, Server, Pass) of true -> case is_acl_match(HostOfRule, AccessRule, jlib:make_jid(User, Server, <<"">>)) diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 663fbf72989..db894de7614 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -154,7 +154,7 @@ wait_for_auth(Packet, #state{socket = Socket, host = Host} = StateData) -> case mod_proxy65_lib:unpack_auth_request(Packet) of {User, Pass} -> - Result = ejabberd_auth:check_password(User, Host, Pass), + Result = ejabberd_auth:check_password(User, <<"">>, Host, Pass), gen_tcp:send(Socket, mod_proxy65_lib:make_auth_reply(Result)), case Result of diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index b9f799b41b9..b415d85e887 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -437,7 +437,7 @@ check_account_exists(Username, Host) -> end. check_password(Username, Host, Password) -> - case ejabberd_auth:check_password(Username, Host, + case ejabberd_auth:check_password(Username, <<"">>, Host, Password) of true -> password_correct; From f7d9bb7ce4b9309a72954b65a21a34b384ac0b83 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 7 May 2015 11:41:59 +0200 Subject: [PATCH 056/695] Don't announce register feature once user is authenticated (#41) --- src/ejabberd_c2s.erl | 14 +++++++------- src/mod_register.erl | 13 +++++++++---- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f2d16e878ba..5cdb8e1c9df 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -457,14 +457,14 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> false -> [] end, + StreamFeatures1 = TLSFeature ++ CompressFeature ++ Mechs, + StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features, + Server, StreamFeatures1, [Server]), send_element(StateData, #xmlel{name = <<"stream:features">>, attrs = [], children = - TLSFeature ++ CompressFeature ++ Mechs - ++ - ejabberd_hooks:run_fold(c2s_stream_features, - Server, [], [Server])}), + StreamFeatures}), fsm_next_state(wait_for_feature_request, StateData#state{ server = Server, @@ -489,7 +489,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> false -> [] end, - StreamFeatures = [#xmlel{name = <<"bind">>, + StreamFeatures1 = [#xmlel{name = <<"bind">>, attrs = [{<<"xmlns">>, ?NS_BIND}], children = []}, #xmlel{name = <<"session">>, @@ -499,9 +499,9 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> RosterVersioningFeature ++ StreamManagementFeature ++ ejabberd_hooks:run_fold(c2s_post_auth_features, - Server, [], [Server]) ++ - ejabberd_hooks:run_fold(c2s_stream_features, Server, [], [Server]), + StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features, + Server, StreamFeatures1, [Server]), send_element(StateData, #xmlel{name = <<"stream:features">>, attrs = [], diff --git a/src/mod_register.erl b/src/mod_register.erl index cd68af93643..1c03fb3e93c 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -68,10 +68,15 @@ stop(Host) -> ?NS_REGISTER). stream_feature_register(Acc, _Host) -> - [#xmlel{name = <<"register">>, - attrs = [{<<"xmlns">>, ?NS_FEATURE_IQREGISTER}], - children = []} - | Acc]. + case lists:keymember(<<"mechanisms">>, 2, Acc) of + true -> + [#xmlel{name = <<"register">>, + attrs = [{<<"xmlns">>, ?NS_FEATURE_IQREGISTER}], + children = []} + | Acc]; + false -> + Acc + end. unauthenticated_iq_register(_Acc, Server, #iq{xmlns = ?NS_REGISTER} = IQ, IP) -> From b0b004b26e273b6549b0cf8b9dab86e540abff99 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 7 May 2015 17:07:49 +0200 Subject: [PATCH 057/695] Revert "Add private and roster local handlers (EJAB-682)" due to #556 This reverts commit 2e194bd997132f4fde5959b54e6bfe269d4de433. --- src/mod_private.erl | 3 --- src/mod_roster.erl | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/mod_private.erl b/src/mod_private.erl index e127c20294e..f09c6100ede 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -60,15 +60,12 @@ start(Host, Opts) -> end, ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, - ?NS_PRIVATE, ?MODULE, process_sm_iq, IQDisc), 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_local, Host, ?NS_PRIVATE), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PRIVATE). diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 2f5d771ce4d..605e8e36702 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -100,8 +100,6 @@ start(Host, Opts) -> webadmin_page, 50), ejabberd_hooks:add(webadmin_user, Host, ?MODULE, webadmin_user, 50), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, - ?NS_ROSTER, ?MODULE, process_iq, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_ROSTER, ?MODULE, process_iq, IQDisc). @@ -128,7 +126,6 @@ stop(Host) -> webadmin_page, 50), ejabberd_hooks:delete(webadmin_user, Host, ?MODULE, webadmin_user, 50), - gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_ROSTER), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_ROSTER). From 7ab6c4b4fd65d75e670152c38551d4311e1b481b Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 7 May 2015 18:34:05 +0200 Subject: [PATCH 058/695] Try to support access_commands in YAML (ejabberd-contrib#45) --- src/ejabberd_commands.erl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index a4f38e83669..a5ba98ae808 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -376,6 +376,15 @@ check_access_commands(AccessCommands, Auth, Method, Command, Arguments) -> AccessCommandsAllowed = lists:filter( fun({Access, Commands, ArgumentRestrictions}) -> + case check_access(Access, Auth) of + true -> + check_access_command(Commands, Command, ArgumentRestrictions, + Method, Arguments); + false -> + false + end; + ({Access, Commands}) -> + ArgumentRestrictions = [], case check_access(Access, Auth) of true -> check_access_command(Commands, Command, ArgumentRestrictions, From 25beb463910735bdf304b5c56de71d50a570625a Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 8 May 2015 12:04:04 +0200 Subject: [PATCH 059/695] Fix check_password_hash argument parsing (#559) --- src/mod_admin_extra.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 023c29dcd94..3687c1edf37 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -190,7 +190,7 @@ commands() -> desc = "Check if the password hash is correct", longdesc = "Allowed hash methods: md5, sha.", module = ?MODULE, function = check_password_hash, - args = [{user, binary}, {host, binary}, {passwordhash, binary}, {hashmethod, binary}], + args = [{user, binary}, {host, binary}, {passwordhash, string}, {hashmethod, string}], result = {res, rescode}}, #ejabberd_commands{name = change_password, tags = [accounts], desc = "Change the password of an account", From f817762cc48c13476a531bc40059cd17aea4cf0b Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 8 May 2015 13:09:13 +0200 Subject: [PATCH 060/695] New max_users_presence mod_muc option (thanks to anhcoi123)(#562) --- src/mod_muc_room.erl | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 8d0b36b6cdc..c52b4e320d5 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -55,6 +55,8 @@ -define(MAX_USERS_DEFAULT_LIST, [5, 10, 20, 30, 50, 100, 200, 500, 1000, 2000, 5000]). +-define(DEFAULT_MAX_USERS_PRESENCE,1000). + %-define(DBGFSM, true). -ifdef(DBGFSM). @@ -2101,10 +2103,23 @@ extract_history([#xmlel{attrs = Attrs} = El | Els], extract_history([_ | Els], Type) -> extract_history(Els, Type). +is_room_overcrowded(StateData) -> + MaxUsersPresence = gen_mod:get_module_opt(StateData#state.server_host, + mod_muc, max_users_presence, + fun(MUP) when is_integer(MUP) -> MUP end, + ?DEFAULT_MAX_USERS_PRESENCE), + (?DICT):size(StateData#state.users) > MaxUsersPresence. + send_update_presence(JID, StateData) -> send_update_presence(JID, <<"">>, StateData). send_update_presence(JID, Reason, StateData) -> + case is_room_overcrowded(StateData) of + true -> ok; + false -> send_update_presence1(JID, Reason, StateData) + end. + +send_update_presence1(JID, Reason, StateData) -> LJID = jlib:jid_tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> @@ -2130,6 +2145,12 @@ send_new_presence(NJID, StateData) -> send_new_presence(NJID, <<"">>, StateData). send_new_presence(NJID, Reason, StateData) -> + case is_room_overcrowded(StateData) of + true -> ok; + false -> send_new_presence1(NJID, Reason, StateData) + end. + +send_new_presence1(NJID, Reason, StateData) -> #user{nick = Nick} = (?DICT):fetch(jlib:jid_tolower(NJID), StateData#state.users), @@ -2216,6 +2237,12 @@ send_new_presence(NJID, Reason, StateData) -> (?DICT):to_list(StateData#state.users)). send_existing_presences(ToJID, StateData) -> + case is_room_overcrowded(StateData) of + true -> ok; + false -> send_existing_presences1(ToJID, StateData) + end. + +send_existing_presences1(ToJID, StateData) -> LToJID = jlib:jid_tolower(ToJID), {ok, #user{jid = RealToJID, role = Role}} = (?DICT):find(LToJID, StateData#state.users), From d885435552094515347465beac5842f470b9178c Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 12 May 2015 17:37:39 +0200 Subject: [PATCH 061/695] Fix setting 'description' with change_room_option command (#567) --- src/mod_muc_admin.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 11f96b9bd29..1d77d3ebe56 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -785,6 +785,7 @@ change_option(Option, Value, Config) -> allow_query_users -> Config#config{allow_query_users = Value}; allow_user_invites -> Config#config{allow_user_invites = Value}; anonymous -> Config#config{anonymous = Value}; + description -> Config#config{description = Value}; logging -> Config#config{logging = Value}; max_users -> Config#config{max_users = Value}; members_by_default -> Config#config{members_by_default = Value}; From dbcfd38c18a29d1170a046eb6cc48da30cd98303 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 13 May 2015 15:54:28 +0200 Subject: [PATCH 062/695] Allow run joincluster as non root when ejabberd installed as root (#497) --- tools/joincluster | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/joincluster b/tools/joincluster index e62084bc4d8..b3516d94df8 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -95,8 +95,7 @@ REMOTENAME=-name set -o errexit set -o nounset -[ -d $SPOOL_DIR ] && rm -Rf $SPOOL_DIR -mkdir $SPOOL_DIR || error "$SPOOL_DIR cannot be created" 20 +[ -d $SPOOL_DIR ] && rm -Rf $SPOOL_DIR/* || mkdir -p $SPOOL_DIR || error "$SPOOL_DIR cannot be created" 20 [ -w $SPOOL_DIR ] || error "$SPOOL_DIR directory is not writable" 21 mkdir -p $PA || error "$PA cannot be created" 22 cd $PA From 42c7205739f68757c9c5fead70faeb9add7df48a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 May 2015 00:58:36 +0200 Subject: [PATCH 063/695] Don't assume send_element/2 returns ok or error Let send_text/2 and (therefore) send_element/2 return {error, Reason} instead of error for consistency, and let send_stanza_and_ack_req/2 interpret any non-ok value as an error. (EJAB-1739) --- src/ejabberd_c2s.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 5cdb8e1c9df..82dce0f08b1 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1891,7 +1891,7 @@ send_text(StateData, Text) when StateData#state.mgmt_state == active -> case catch (StateData#state.sockmod):send(StateData#state.socket, Text) of {'EXIT', _} -> (StateData#state.sockmod):close(StateData#state.socket), - error; + {error, closed}; _ -> ok end; @@ -1915,7 +1915,7 @@ send_stanza(StateData, Stanza) when StateData#state.mgmt_state == active -> NewStateData = case send_stanza_and_ack_req(StateData, Stanza) of ok -> StateData; - error -> + _Error -> StateData#state{mgmt_state = pending} end, mgmt_queue_add(NewStateData, Stanza); @@ -2833,8 +2833,8 @@ send_stanza_and_ack_req(StateData, Stanza) -> case send_element(StateData, Stanza) of ok -> send_element(StateData, AckReq); - error -> - error + Error -> + Error end. mgmt_queue_add(StateData, El) -> From 6efce7f7062a6a1e16dfd0411ae9f93a593f632c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 May 2015 01:04:23 +0200 Subject: [PATCH 064/695] Cosmetic change: Simplify error checking Let send_stanza_and_ack_req/2 update the #state instead of propagating the value returned by send_element/2. This doesn't change the behavior. --- src/ejabberd_c2s.erl | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 82dce0f08b1..a6112673bf3 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1912,12 +1912,7 @@ send_stanza(StateData, Stanza) when StateData#state.csi_state == inactive -> send_stanza(StateData, Stanza) when StateData#state.mgmt_state == pending -> mgmt_queue_add(StateData, Stanza); send_stanza(StateData, Stanza) when StateData#state.mgmt_state == active -> - NewStateData = case send_stanza_and_ack_req(StateData, Stanza) of - ok -> - StateData; - _Error -> - StateData#state{mgmt_state = pending} - end, + NewStateData = send_stanza_and_ack_req(StateData, Stanza), mgmt_queue_add(NewStateData, Stanza); send_stanza(StateData, Stanza) -> send_element(StateData, Stanza), @@ -2830,11 +2825,12 @@ send_stanza_and_ack_req(StateData, Stanza) -> AckReq = #xmlel{name = <<"r">>, attrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns}], children = []}, - case send_element(StateData, Stanza) of - ok -> - send_element(StateData, AckReq); - Error -> - Error + case send_element(StateData, Stanza) == ok andalso + send_element(StateData, AckReq) == ok of + true -> + StateData; + false -> + StateData#state{mgmt_state = pending} end. mgmt_queue_add(StateData, El) -> From 5dbe7a3c6c374139692a4764582127ac79b3f498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 15 May 2015 12:27:59 +0200 Subject: [PATCH 065/695] Export modules_dir/0 --- src/ext_mod.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index f83fe2c6bc5..473aeb4ebee 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -32,7 +32,8 @@ installed_command/0, installed/0, installed/1, install/1, uninstall/1, upgrade/0, upgrade/1, - add_sources/2, del_sources/1]). + add_sources/2, del_sources/1, + modules_dir/0]). -include("ejabberd_commands.hrl"). From de7ff536b2f4044d1f0a3f4534074af2d1abe414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 15 May 2015 12:30:15 +0200 Subject: [PATCH 066/695] Load config snippets for modules installed with ext_mod (EJAB-1741) --- src/ejabberd_config.erl | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 5d1df50560f..f07ee7477b2 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -114,7 +114,8 @@ get_env_config() -> %% @spec (File::string()) -> #state{}. read_file(File) -> read_file(File, [{replace_macros, true}, - {include_files, true}]). + {include_files, true}, + {include_modules_configs, true}]). read_file(File, Opts) -> Terms1 = get_plain_terms_file(File, Opts), @@ -200,7 +201,14 @@ get_plain_terms_file(File1, Opts) -> File = get_absolute_path(File1), case consult(File) of {ok, Terms} -> - BinTerms = strings_to_binary(Terms), + BinTerms1 = strings_to_binary(Terms), + ModInc = case proplists:get_bool(include_modules_configs, Opts) of + true -> + filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.yaml"); + _ -> + [] + end, + BinTerms = BinTerms1 ++ [{include_config_file, list_to_binary(V)} || V <- ModInc], case proplists:get_bool(include_files, Opts) of true -> include_config_files(BinTerms); @@ -374,7 +382,23 @@ include_config_files(Terms) -> fun({File, Opts}) -> include_config_file(File, Opts) end, lists:flatten(FileOpts)), - Terms1 ++ Terms2. + + SpecialTerms = dict:from_list([{hosts, none}, {listen, none}, {modules, none}]), + Partition = fun(L) -> + lists:foldr(fun({Name, Val} = Pair, Dict) -> + case dict:find(Name, SpecialTerms) of + {ok, _} -> + dict:store(Name, Val, Dict); + _ -> + dict:update(rest, fun(L1) -> [Pair|L1] end, Dict) + end + end, dict:from_list([{rest, []}]), L) + end, + + Merged = dict:merge(fun(_Name, V1, V2) -> V1 ++ V2 end, + Partition(Terms1), Partition(Terms2)), + Rest = dict:fetch(rest, Merged), + dict:to_list(dict:erase(rest, Merged)) ++ Rest. transform_include_option({include_config_file, File}) when is_list(File) -> case is_string(File) of @@ -452,11 +476,11 @@ split_terms_macros(Terms) -> lists:foldl( fun(Term, {TOs, Ms}) -> case Term of - {define_macro, Key, Value} -> + {define_macro, Key, Value} -> case is_correct_macro({Key, Value}) of - true -> + true -> {TOs, Ms++[{Key, Value}]}; - false -> + false -> exit({macro_not_properly_defined, Term}) end; {define_macro, KeyVals} -> From 61afd668c2b471c88a7c91faaf970f13a5f1fb2d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 15 May 2015 15:50:43 +0200 Subject: [PATCH 067/695] Fix indentation --- src/ejabberd_config.erl | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index f07ee7477b2..4931fe72ed0 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -769,14 +769,24 @@ replace_module(Module) -> false -> Module end. -replace_modules(Modules) -> lists:map( fun({Module, Opts}) -> case - replace_module(Module) of {NewModule, DBType} -> - emit_deprecation_warning(Module, NewModule, DBType), NewOpts = - [{db_type, DBType} | lists:keydelete(db_type, 1, Opts)], - {NewModule, transform_module_options(Module, NewOpts)}; NewModule - -> if Module /= NewModule -> emit_deprecation_warning(Module, - NewModule); true -> ok end, {NewModule, - transform_module_options(Module, Opts)} end end, Modules). +replace_modules(Modules) -> + lists:map( + fun({Module, Opts}) -> + case replace_module(Module) of + {NewModule, DBType} -> + emit_deprecation_warning(Module, NewModule, DBType), + NewOpts = [{db_type, DBType} | + lists:keydelete(db_type, 1, Opts)], + {NewModule, transform_module_options(Module, NewOpts)}; + NewModule -> + if Module /= NewModule -> + emit_deprecation_warning(Module, NewModule); + true -> + ok + end, + {NewModule, transform_module_options(Module, Opts)} + end + end, Modules). %% Elixir module naming %% ==================== From 084d0c4efe9e22c0dcfaf8a9132ee6bda21c8e99 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 15 May 2015 17:47:10 +0200 Subject: [PATCH 068/695] New command get_room_options (#567) --- src/ejabberd_ctl.erl | 9 +++++++++ src/ejabberd_xmlrpc.erl | 6 ++++++ src/mod_muc_admin.erl | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 6ab383b1238..1eae7f758ed 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -353,6 +353,15 @@ format_result(String, {_Name, string}) when is_list(String) -> format_result(Binary, {_Name, string}) when is_binary(Binary) -> io_lib:format("~s", [binary_to_list(Binary)]); +format_result(Atom, {_Name, string}) when is_atom(Atom) -> + io_lib:format("~s", [atom_to_list(Atom)]); + +format_result(Integer, {_Name, string}) when is_integer(Integer) -> + io_lib:format("~s", [integer_to_list(Integer)]); + +format_result(Other, {_Name, string}) -> + io_lib:format("~p", [Other]); + format_result(Code, {_Name, rescode}) -> make_status(Code); diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 904604fc9bc..7e437104993 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -466,6 +466,12 @@ format_result(String, {Name, string}) when is_list(String) -> {struct, [{Name, lists:flatten(String)}]}; format_result(Binary, {Name, string}) when is_binary(Binary) -> {struct, [{Name, binary_to_list(Binary)}]}; +format_result(Atom, {Name, string}) when is_atom(Atom) -> + {struct, [{Name, atom_to_list(Atom)}]}; +format_result(Integer, {Name, string}) when is_integer(Integer) -> + {struct, [{Name, integer_to_list(Integer)}]}; +format_result(Other, {Name, string}) -> + {struct, [{Name, io_lib:format("~p", [Other])}]}; format_result(String, {Name, binary}) when is_list(String) -> {struct, [{Name, lists:flatten(String)}]}; format_result(Binary, {Name, binary}) when is_binary(Binary) -> diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 1d77d3ebe56..1a6d8a865c8 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -23,6 +23,7 @@ get_room_occupants_number/2, send_direct_invitation/4, change_room_option/4, + get_room_options/2, set_room_affiliation/4, get_room_affiliations/2, web_menu_main/2, web_page_main/2, % Web Admin API @@ -145,6 +146,16 @@ commands() -> args = [{name, binary}, {service, binary}, {option, binary}, {value, binary}], result = {res, rescode}}, + #ejabberd_commands{name = get_room_options, tags = [muc_room], + desc = "Get options from a MUC room", + module = ?MODULE, function = get_room_options, + args = [{name, binary}, {service, binary}], + result = {options, {list, + {option, {tuple, + [{name, string}, + {value, string} + ]}} + }}}, #ejabberd_commands{name = set_room_affiliation, tags = [muc_room], desc = "Change an affiliation in a MUC room", @@ -799,6 +810,22 @@ change_option(Option, Value, Config) -> title -> Config#config{title = Value} end. +%%---------------------------- +%% Get Room Options +%%---------------------------- + +get_room_options(Name, Service) -> + Pid = get_room_pid(Name, Service), + get_room_options(Pid). + +get_room_options(Pid) -> + Config = get_room_config(Pid), + get_options(Config). + +get_options(Config) -> + Fields = record_info(fields, config), + [config | Values] = tuple_to_list(Config), + lists:zip(Fields, Values). %%---------------------------- %% Get Room Affiliations From f5c9dfbc934970cf86129ca54c83c8e60c8e6539 Mon Sep 17 00:00:00 2001 From: Matthias Rieber Date: Sun, 17 May 2015 19:15:52 +0200 Subject: [PATCH 069/695] fixed erl_prettypr in encode_term --- src/ejabberd_odbc.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 09f17a6351a..c2db2130752 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -193,7 +193,8 @@ to_bool(_) -> false. encode_term(Term) -> escape(list_to_binary( - erl_prettypr:format(erl_syntax:abstract(Term)))). + erl_prettypr:format(erl_syntax:abstract(Term), + [{paper, 65535}, {ribbon, 65535}]))). decode_term(Bin) -> Str = binary_to_list(<>), From 0800a9733ca45c84ebd8be2988678b4dc29bbc5f Mon Sep 17 00:00:00 2001 From: Matthias Rieber Date: Sun, 17 May 2015 17:45:49 +0200 Subject: [PATCH 070/695] pg - added sm table --- sql/pg.sql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sql/pg.sql b/sql/pg.sql index 8412c3c6b51..966614f4858 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -288,3 +288,18 @@ CREATE TABLE caps_features ( ); CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode); + +CREATE TABLE sm ( + usec bigint NOT NULL, + pid text NOT NULL, + node text NOT NULL, + username text NOT NULL, + resource text NOT NULL, + priority text NOT NULL, + info text NOT NULL +); + +CREATE UNIQUE INDEX i_sid ON sm USING btree (usec, pid); +CREATE INDEX i_node ON sm USING btree (node); +CREATE INDEX i_username ON sm USING btree (username); + From 555c1736b7a6c491c2734505e4dc88ea7fe6cd76 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 18 May 2015 00:48:56 +0200 Subject: [PATCH 071/695] Revert "Fix EJABBERD_OPTS quoting for Elixir" This reverts commit 2a15453d98425c72ae24e9da4d56ad295a57be1d. The commit broke the case where 'log_rotate_date' is set to "$D0", for example. --- ejabberdctl.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 79d47f83a5a..6c131ace024 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -140,17 +140,17 @@ if [ "$EJABBERD_CONFIG_PATH" != "${EJABBERD_CONFIG_PATH%.yml}" ] ; then rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) count=$(sed '/^[ ]*log_rotate_count/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) - date=$(sed '/^[ ]*log_rotate_date/!d;s/.*://;s/ *//;s/""/[]/' $EJABBERD_CONFIG_PATH) + date=$(sed '/^[ ]*log_rotate_date/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) else rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) count=$(sed '/^[ ]*log_rotate_count/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) - date=$(sed '/^[ ]*log_rotate_date/!d;s/.*,//;s/ *//;s/""/[]/;s/}\.//' $EJABBERD_CONFIG_PATH) + date=$(sed '/^[ ]*log_rotate_date/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) fi [ -z "$rate" ] || EJABBERD_OPTS="log_rate_limit $rate" [ -z "$rotate" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_size $rotate" [ -z "$count" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_count $count" -[ -z "$date" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_date $date" +[ -z "$date" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_date '$date'" [ -z "$EJABBERD_OPTS" ] || EJABBERD_OPTS="-ejabberd ${EJABBERD_OPTS}" [ -d $SPOOL_DIR ] || $EXEC_CMD "mkdir -p $SPOOL_DIR" From 16532dd643708924b6ebfcfb26866d9cbd11d89c Mon Sep 17 00:00:00 2001 From: Matthias Rieber Date: Mon, 18 May 2015 12:14:56 +0200 Subject: [PATCH 072/695] Fixed some string()/binary() issues in ejabberd_odbc --- src/ejabberd_odbc.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index c2db2130752..dbae9f49b5c 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -510,7 +510,8 @@ abort_on_driver_error(Reply, From) -> %% Open an ODBC database connection odbc_connect(SQLServer) -> ejabberd:start_app(odbc), - odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}]). + odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}, + {binary_strings, on}]). %% == Native SQLite code @@ -635,7 +636,7 @@ mysql_item_to_odbc(Columns, Recs) -> {selected, [element(2, Column) || Column <- Columns], Recs}. to_odbc({selected, Columns, Recs}) -> - {selected, Columns, [tuple_to_list(Rec) || Rec <- Recs]}; + {selected, [list_to_binary(Column) || Column <- Columns], [tuple_to_list(Rec) || Rec <- Recs]}; to_odbc(Res) -> Res. From 2af659b73762befddab5095630379c1acdef6741 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 18 May 2015 12:38:07 +0200 Subject: [PATCH 073/695] Remove deprecated XEP-0090 Entity Time and 91 Delayed Delivery (EJAB-849) --- include/ns.hrl | 2 -- src/jlib.erl | 21 +++++---------------- src/mod_time.erl | 27 +-------------------------- 3 files changed, 6 insertions(+), 44 deletions(-) diff --git a/include/ns.hrl b/include/ns.hrl index a96edc7ab09..f4c8bf3b0bc 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -35,12 +35,10 @@ -define(NS_BLOCKING, <<"urn:xmpp:blocking">>). -define(NS_PRIVATE, <<"jabber:iq:private">>). -define(NS_VERSION, <<"jabber:iq:version">>). --define(NS_TIME90, <<"jabber:iq:time">>). -define(NS_TIME, <<"urn:xmpp:time">>). -define(NS_LAST, <<"jabber:iq:last">>). -define(NS_XDATA, <<"jabber:x:data">>). -define(NS_IQDATA, <<"jabber:iq:data">>). --define(NS_DELAY91, <<"jabber:x:delay">>). -define(NS_DELAY, <<"urn:xmpp:delay">>). -define(NS_HINTS, <<"urn:xmpp:hints">>). -define(NS_EXPIRE, <<"jabber:x:expire">>). diff --git a/src/jlib.erl b/src/jlib.erl index 76886a7dc8f..8132902579b 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -54,9 +54,6 @@ atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1, l2i/1, i2l/1, i2l/2, queue_drop_while/2]). -%% TODO: Remove once XEP-0091 is Obsolete -%% TODO: Remove once XEP-0091 is Obsolete - -include("ejabberd.hrl"). -include("jlib.hrl"). @@ -612,10 +609,7 @@ add_delay_info(El, From, Time) -> binary()) -> xmlel(). add_delay_info(El, From, Time, Desc) -> - %% TODO: Remove support for , XEP-0091 is obsolete. - El1 = add_delay_info(El, From, Time, Desc, <<"delay">>, ?NS_DELAY), - El2 = add_delay_info(El1, From, Time, Desc, <<"x">>, ?NS_DELAY91), - El2. + add_delay_info(El, From, Time, Desc, <<"delay">>, ?NS_DELAY). -spec add_delay_info(xmlel(), jid() | ljid() | binary(), erlang:timestamp(), binary(), binary(), binary()) -> xmlel(). @@ -652,20 +646,15 @@ add_delay_info(El, From, Time, Desc, Name, XMLNS) -> -spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary(), binary()) -> xmlel() | error. -create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) -> +create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) + and (XMLNS == ?NS_DELAY) -> From = jlib:jid_to_string(FromJID), - {Name, Stamp} = case XMLNS of - ?NS_DELAY -> - {<<"delay">>, now_to_utc_string(TimeStamp, 3)}; - ?NS_DELAY91 -> - DateTime = calendar:now_to_universal_time(TimeStamp), - {<<"x">>, timestamp_to_iso(DateTime)} - end, + Stamp = now_to_utc_string(TimeStamp, 3), Children = case Desc of <<"">> -> []; _ -> [{xmlcdata, Desc}] end, - #xmlel{name = Name, + #xmlel{name = <<"delay">>, attrs = [{<<"xmlns">>, XMLNS}, {<<"from">>, From}, {<<"stamp">>, Stamp}], diff --git a/src/mod_time.erl b/src/mod_time.erl index c82fde41c90..417ee6bb0a4 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -30,10 +30,7 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq90/3, - process_local_iq/3]). - - % TODO: Remove once XEP-0090 is Obsolete +-export([start/2, stop/1, process_local_iq/3]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -43,35 +40,13 @@ start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, one_queue), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, - ?NS_TIME90, ?MODULE, process_local_iq90, - IQDisc), gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_TIME, ?MODULE, process_local_iq, IQDisc). stop(Host) -> - gen_iq_handler:remove_iq_handler(ejabberd_local, Host, - ?NS_TIME90), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_TIME). -%% TODO: Remove this function once XEP-0090 is Obsolete -process_local_iq90(_From, _To, - #iq{type = Type, sub_el = SubEl} = IQ) -> - case Type of - set -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; - get -> - UTC = jlib:timestamp_to_iso(calendar:universal_time()), - IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, ?NS_TIME90}], - children = - [#xmlel{name = <<"utc">>, attrs = [], - children = [{xmlcdata, UTC}]}]}]} - end. - process_local_iq(_From, _To, #iq{type = Type, sub_el = SubEl} = IQ) -> case Type of From dfbef8be8f2014c36f778d18f67293b3c724c0a8 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 18 May 2015 14:38:57 +0200 Subject: [PATCH 074/695] Remove XEP-0091 tags from test suite --- test/ejabberd_SUITE.erl | 7 ++--- tools/xmpp_codec.erl | 63 ----------------------------------------- tools/xmpp_codec.hrl | 3 -- tools/xmpp_codec.spec | 10 ------- 4 files changed, 3 insertions(+), 80 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index a827a9174f0..4f082332339 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1286,7 +1286,7 @@ muc_slave(Config) -> %% Receive the room subject ?recv1(#message{from = PeerNickJID, type = groupchat, body = [#text{data = Subject}], - sub_els = [#delay{}, #legacy_delay{}]}), + sub_els = [#delay{}]}), %% Receive MUC history lists:foreach( fun(N) -> @@ -1294,7 +1294,7 @@ muc_slave(Config) -> ?recv1(#message{from = PeerNickJID, type = groupchat, body = [Text], - sub_els = [#delay{}, #legacy_delay{}]}) + sub_els = [#delay{}]}) end, lists:seq(1, 5)), %% Sending a voice request VoiceReq = #xdata{ @@ -1450,7 +1450,6 @@ offline_slave(Config) -> body = [#text{data = <<"body">>}], subject = [#text{data = <<"subject">>}]}), true = lists:keymember(delay, 1, SubEls), - true = lists:keymember(legacy_delay, 1, SubEls), disconnect(Config). carbons_master(Config) -> @@ -1596,7 +1595,7 @@ client_state_slave(Config) -> change_client_state(Config, inactive), wait_for_master(Config), ?recv1(#presence{from = Peer, type = unavailable, - sub_els = [#delay{}, #legacy_delay{}]}), + sub_els = [#delay{}]}), ?recv1(#message{from = Peer, thread = <<"1">>, body = [#text{data = <<"body">>}], sub_els = [#chatstate{type = active}]}), diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 1d5cd88e0f9..187098abc95 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -166,9 +166,6 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> <<"http://jabber.org/protocol/bytestreams">>} -> decode_bytestreams_streamhost(<<"http://jabber.org/protocol/bytestreams">>, IgnoreEls, _el); - {<<"x">>, <<"jabber:x:delay">>} -> - decode_legacy_delay(<<"jabber:x:delay">>, IgnoreEls, - _el); {<<"delay">>, <<"urn:xmpp:delay">>} -> decode_delay(<<"urn:xmpp:delay">>, IgnoreEls, _el); {<<"paused">>, @@ -1109,7 +1106,6 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> {<<"streamhost">>, <<"http://jabber.org/protocol/bytestreams">>} -> true; - {<<"x">>, <<"jabber:x:delay">>} -> true; {<<"delay">>, <<"urn:xmpp:delay">>} -> true; {<<"paused">>, <<"http://jabber.org/protocol/chatstates">>} -> @@ -1936,9 +1932,6 @@ encode({chatstate, paused} = Paused) -> encode({delay, _, _} = Delay) -> encode_delay(Delay, [{<<"xmlns">>, <<"urn:xmpp:delay">>}]); -encode({legacy_delay, _, _} = X) -> - encode_legacy_delay(X, - [{<<"xmlns">>, <<"jabber:x:delay">>}]); encode({streamhost, _, _, _} = Streamhost) -> encode_bytestreams_streamhost(Streamhost, [{<<"xmlns">>, @@ -2181,7 +2174,6 @@ get_ns({chatstate, inactive}) -> get_ns({chatstate, paused}) -> <<"http://jabber.org/protocol/chatstates">>; get_ns({delay, _, _}) -> <<"urn:xmpp:delay">>; -get_ns({legacy_delay, _, _}) -> <<"jabber:x:delay">>; get_ns({streamhost, _, _, _}) -> <<"http://jabber.org/protocol/bytestreams">>; get_ns({bytestreams, _, _, _, _, _, _}) -> @@ -2374,7 +2366,6 @@ pp(pubsub, 8) -> pp(shim, 1) -> [headers]; pp(chatstate, 1) -> [type]; pp(delay, 2) -> [stamp, from]; -pp(legacy_delay, 2) -> [stamp, from]; pp(streamhost, 3) -> [jid, host, port]; pp(bytestreams, 6) -> [hosts, used, activate, dstaddr, mode, sid]; @@ -5397,60 +5388,6 @@ encode_bytestreams_streamhost_attr_port(1080, _acc) -> encode_bytestreams_streamhost_attr_port(_val, _acc) -> [{<<"port">>, enc_int(_val)} | _acc]. -decode_legacy_delay(__TopXMLNS, __IgnoreEls, - {xmlel, <<"x">>, _attrs, _els}) -> - {Stamp, From} = decode_legacy_delay_attrs(__TopXMLNS, - _attrs, undefined, undefined), - {legacy_delay, Stamp, From}. - -decode_legacy_delay_attrs(__TopXMLNS, - [{<<"stamp">>, _val} | _attrs], _Stamp, From) -> - decode_legacy_delay_attrs(__TopXMLNS, _attrs, _val, - From); -decode_legacy_delay_attrs(__TopXMLNS, - [{<<"from">>, _val} | _attrs], Stamp, _From) -> - decode_legacy_delay_attrs(__TopXMLNS, _attrs, Stamp, - _val); -decode_legacy_delay_attrs(__TopXMLNS, [_ | _attrs], - Stamp, From) -> - decode_legacy_delay_attrs(__TopXMLNS, _attrs, Stamp, - From); -decode_legacy_delay_attrs(__TopXMLNS, [], Stamp, - From) -> - {decode_legacy_delay_attr_stamp(__TopXMLNS, Stamp), - decode_legacy_delay_attr_from(__TopXMLNS, From)}. - -encode_legacy_delay({legacy_delay, Stamp, From}, - _xmlns_attrs) -> - _els = [], - _attrs = encode_legacy_delay_attr_from(From, - encode_legacy_delay_attr_stamp(Stamp, - _xmlns_attrs)), - {xmlel, <<"x">>, _attrs, _els}. - -decode_legacy_delay_attr_stamp(__TopXMLNS, undefined) -> - erlang:error({xmpp_codec, - {missing_attr, <<"stamp">>, <<"x">>, __TopXMLNS}}); -decode_legacy_delay_attr_stamp(__TopXMLNS, _val) -> - _val. - -encode_legacy_delay_attr_stamp(_val, _acc) -> - [{<<"stamp">>, _val} | _acc]. - -decode_legacy_delay_attr_from(__TopXMLNS, undefined) -> - undefined; -decode_legacy_delay_attr_from(__TopXMLNS, _val) -> - case catch dec_jid(_val) of - {'EXIT', _} -> - erlang:error({xmpp_codec, - {bad_attr_value, <<"from">>, <<"x">>, __TopXMLNS}}); - _res -> _res - end. - -encode_legacy_delay_attr_from(undefined, _acc) -> _acc; -encode_legacy_delay_attr_from(_val, _acc) -> - [{<<"from">>, enc_jid(_val)} | _acc]. - decode_delay(__TopXMLNS, __IgnoreEls, {xmlel, <<"delay">>, _attrs, _els}) -> {Stamp, From} = decode_delay_attrs(__TopXMLNS, _attrs, diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index 4098a7fd672..af5903c93a7 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -137,9 +137,6 @@ -record(feature_csi, {xmlns :: binary()}). --record(legacy_delay, {stamp :: binary(), - from :: any()}). - -record(muc_user_destroy, {reason :: binary(), jid :: any()}). diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 61f438cbee3..e8cf0612b76 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -1808,16 +1808,6 @@ dec = {dec_jid, []}, enc = {enc_jid, []}}]}). --xml(legacy_delay, - #elem{name = <<"x">>, - xmlns = <<"jabber:x:delay">>, - result = {legacy_delay, '$stamp', '$from'}, - attrs = [#attr{name = <<"stamp">>, - required = true}, - #attr{name = <<"from">>, - dec = {dec_jid, []}, - enc = {enc_jid, []}}]}). - -xml(bytestreams_streamhost, #elem{name = <<"streamhost">>, xmlns = <<"http://jabber.org/protocol/bytestreams">>, From 8bb994dbca7c7466065ff492416f2d37642d6a8f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 18 May 2015 17:30:25 +0200 Subject: [PATCH 075/695] Call integer_to_binary using jlib (#554) --- src/mod_pubsub.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 80f6c05a935..8553db4e0ed 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3662,7 +3662,7 @@ max_items(Host, Options) -> -define(INTEGER_CONFIG_FIELD(Label, Var), ?STRINGXFIELD(Label, <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, - (integer_to_binary(get_option(Options, Var))))). + (jlib:integer_to_binary(get_option(Options, Var))))). -define(JLIST_CONFIG_FIELD(Label, Var, Opts), ?LISTXFIELD(Label, From fba13a0b93f067029a52c6f186a144adfa871095 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 18 May 2015 21:26:51 +0200 Subject: [PATCH 076/695] Simplify XEP-0203 (Delayed Delivery) code a bit Now that XEP-0091 support is removed, the XEP-0203 code can be simplified a little further. This doesn't change the behavior. --- src/jlib.erl | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index 8132902579b..c0d5ebd2294 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -609,16 +609,10 @@ add_delay_info(El, From, Time) -> binary()) -> xmlel(). add_delay_info(El, From, Time, Desc) -> - add_delay_info(El, From, Time, Desc, <<"delay">>, ?NS_DELAY). - --spec add_delay_info(xmlel(), jid() | ljid() | binary(), erlang:timestamp(), - binary(), binary(), binary()) -> xmlel(). - -add_delay_info(El, From, Time, Desc, Name, XMLNS) -> - case xml:get_subtag_with_xmlns(El, Name, XMLNS) of + case xml:get_subtag_with_xmlns(El, <<"delay">>, ?NS_DELAY) of false -> %% Add new tag - DelayTag = create_delay_tag(Time, From, Desc, XMLNS), + DelayTag = create_delay_tag(Time, From, Desc), xml:append_subtags(El, [DelayTag]); DelayTag -> %% Update existing tag @@ -639,15 +633,14 @@ add_delay_info(El, From, Time, Desc, Name, XMLNS) -> DelayTag#xmlel{children = [{xmlcdata, OldDesc}]} end end, - NewEl = xml:remove_subtags(El, Name, {<<"xmlns">>, XMLNS}), + NewEl = xml:remove_subtags(El, <<"delay">>, {<<"xmlns">>, ?NS_DELAY}), xml:append_subtags(NewEl, [NewDelayTag]) end. -spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary(), binary()) -> xmlel() | error. -create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) - and (XMLNS == ?NS_DELAY) -> +create_delay_tag(TimeStamp, FromJID, Desc) when is_tuple(FromJID) -> From = jlib:jid_to_string(FromJID), Stamp = now_to_utc_string(TimeStamp, 3), Children = case Desc of @@ -656,12 +649,12 @@ create_delay_tag(TimeStamp, FromJID, Desc, XMLNS) when is_tuple(FromJID) end, #xmlel{name = <<"delay">>, attrs = - [{<<"xmlns">>, XMLNS}, {<<"from">>, From}, + [{<<"xmlns">>, ?NS_DELAY}, {<<"from">>, From}, {<<"stamp">>, Stamp}], children = Children}; -create_delay_tag(DateTime, Host, Desc, XMLNS) when is_binary(Host) -> +create_delay_tag(DateTime, Host, Desc) when is_binary(Host) -> FromJID = jlib:make_jid(<<"">>, Host, <<"">>), - create_delay_tag(DateTime, FromJID, Desc, XMLNS). + create_delay_tag(DateTime, FromJID, Desc). -type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc. From 3b267eaa61c3659e51be69aac47ef2efbf1f8958 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 19 May 2015 10:51:49 +0300 Subject: [PATCH 077/695] Do not bounce normal messages sent to unavailable resource --- src/ejabberd_sm.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 678452951d0..bfe6e934f95 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -539,6 +539,8 @@ do_route(From, To, #xmlel{} = Packet) -> <<"message">> -> case xml:get_attr_s(<<"type">>, Attrs) of <<"chat">> -> route_message(From, To, Packet, chat); + <<"normal">> -> route_message(From, To, Packet, normal); + <<"">> -> route_message(From, To, Packet, normal); <<"error">> -> ok; _ -> Err = jlib:make_error_reply(Packet, From 1854b5e411445beeece621a4058941ba0266704d Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 20 May 2015 11:43:29 +0200 Subject: [PATCH 078/695] Remove obsolete doc and win32 files (EJAB-1738) --- Makefile.in | 15 +- Makefile.win32 | 176 -- doc/Makefile | 62 - doc/api/Makefile | 18 - doc/api/overview.edoc | 10 - doc/api/process-one.css | 92 - doc/dev.html | 437 --- doc/dev.tex | 470 --- doc/discorus.png | Bin 10052 -> 0 bytes doc/features.html | 143 - doc/features.tex | 136 - doc/flow.dot | 105 - doc/guide.tex | 6494 -------------------------------------- doc/introduction.tex | 135 - doc/logo.png | Bin 83054 -> 0 bytes doc/msrl-dit-deep.png | Bin 142873 -> 0 bytes doc/msrl-dit-flat.png | Bin 79322 -> 0 bytes doc/msrl-roster-deep.png | Bin 23093 -> 0 bytes doc/msrl-roster-flat.png | Bin 21565 -> 0 bytes doc/webadmmain.png | Bin 6542 -> 0 bytes doc/webadmmainru.png | Bin 13085 -> 0 bytes doc/yozhikheader.png | Bin 160944 -> 0 bytes 22 files changed, 2 insertions(+), 8291 deletions(-) delete mode 100644 Makefile.win32 delete mode 100644 doc/Makefile delete mode 100644 doc/api/Makefile delete mode 100644 doc/api/overview.edoc delete mode 100644 doc/api/process-one.css delete mode 100644 doc/dev.html delete mode 100644 doc/dev.tex delete mode 100644 doc/discorus.png delete mode 100644 doc/features.html delete mode 100644 doc/features.tex delete mode 100644 doc/flow.dot delete mode 100644 doc/guide.tex delete mode 100644 doc/introduction.tex delete mode 100644 doc/logo.png delete mode 100644 doc/msrl-dit-deep.png delete mode 100644 doc/msrl-dit-flat.png delete mode 100644 doc/msrl-roster-deep.png delete mode 100644 doc/msrl-roster-flat.png delete mode 100644 doc/webadmmain.png delete mode 100644 doc/webadmmainru.png delete mode 100644 doc/yozhikheader.png diff --git a/Makefile.in b/Makefile.in index 87ace381a46..ffd1d30f73b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -101,10 +101,6 @@ xref: all translations: contrib/extract_translations/prepare-translation.sh -updateall -doc: - echo making $$target in doc; \ - (cd doc && $(MAKE) $$target) || exit 1 - edoc: $(ERL) -noinput +B -eval \ 'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.' @@ -207,16 +203,9 @@ install: all # # Documentation $(INSTALL) -d $(DOCDIR) - [ -f doc/dev.html ] \ - && $(INSTALL) -m 644 doc/dev.html $(DOCDIR) \ - || echo "No doc/dev.html was built" [ -f doc/guide.html ] \ && $(INSTALL) -m 644 doc/guide.html $(DOCDIR) \ - || echo "No doc/guide.html was built" - [ -f doc/guide.pdf ] \ - && $(INSTALL) -m 644 doc/guide.pdf $(DOCDIR) \ - || echo "No doc/guide.pdf was built" - $(INSTALL) -m 644 doc/*.png $(DOCDIR) + || echo "Documentation not included in sources" $(INSTALL) -m 644 COPYING $(DOCDIR) uninstall: uninstall-binary @@ -326,6 +315,6 @@ test: quicktest: $(REBAR) skip_deps=true ct suites=elixir -.PHONY: src doc edoc dialyzer Makefile TAGS clean clean-rel distclean rel \ +.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \ install uninstall uninstall-binary uninstall-all translations deps test spec \ quicktest erlang_plt deps_plt ejabberd_plt diff --git a/Makefile.win32 b/Makefile.win32 deleted file mode 100644 index 8a1192fce25..00000000000 --- a/Makefile.win32 +++ /dev/null @@ -1,176 +0,0 @@ - -include Makefile.inc - -ALL : build - -REL=..\release -EREL=$(REL)\ejabberd-$(EJABBERD_VERSION) -EBIN_DIR=$(EREL)\ebin -SRC_DIR=$(EREL)\src -PRIV_DIR=$(EREL)\priv -SO_DIR=$(EREL) -MSGS_DIR=$(EREL)\msgs -WIN32_DIR=$(EREL)\win32 -DOC_DIR=$(EREL)\doc - -NSIS_SCRIPT=win32\ejabberd.nsi -NSIS_HEADER=win32\ejabberd.nsh - -installer : $(NSIS_SCRIPT) $(NSIS_HEADER) - makensis $(NSIS_SCRIPT) - -$(NSIS_HEADER) : Makefile.inc - echo !define OUTFILEDIR "..\$(REL)" >$(NSIS_HEADER) - echo !define TESTDIR "..\$(REL)\ejabberd-$(EJABBERD_VERSION)" >>$(NSIS_HEADER) - echo !define VERSION "$(EJABBERD_VERSION)" >>$(NSIS_HEADER) - -release_clean : - if exist $(REL) rd /s /q $(REL) - - -release : build release_clean - mkdir $(REL) - mkdir $(EREL) - mkdir $(EBIN_DIR) - copy *.beam $(EBIN_DIR) - @erase $(EBIN_DIR)\configure.beam - copy *.app $(EBIN_DIR) - copy *.dll $(SO_DIR) - mkdir $(MSGS_DIR) - copy msgs\*.msg $(MSGS_DIR) - mkdir $(WIN32_DIR) - copy win32\ejabberd.cfg $(EREL) - copy win32\inetrc $(EREL) - copy $(SYSTEMROOT)\system32\libeay32.dll $(EREL) - copy $(SYSTEMROOT)\system32\ssleay32.dll $(EREL) - copy win32\ejabberd.ico $(WIN32_DIR) - mkdir $(SRC_DIR) - copy *.app $(SRC_DIR) - copy *.erl $(SRC_DIR) - copy *.hrl $(SRC_DIR) - copy *.c $(SRC_DIR) - mkdir $(SRC_DIR)\eldap - copy eldap\eldap.* $(SRC_DIR)\eldap - copy eldap\ELDAPv3.asn $(SRC_DIR)\eldap - mkdir $(SRC_DIR)\mod_irc - copy mod_irc\*.erl $(SRC_DIR)\mod_irc - copy mod_irc\*.c $(SRC_DIR)\mod_irc - mkdir $(SRC_DIR)\mod_muc - copy mod_muc\*.erl $(SRC_DIR)\mod_muc - mkdir $(SRC_DIR)\mod_pubsub - copy mod_pubsub\*.erl $(SRC_DIR)\mod_pubsub - mkdir $(SRC_DIR)\mod_proxy65 - copy mod_proxy65\*.erl $(SRC_DIR)\mod_proxy65 - copy mod_proxy65\*.hrl $(SRC_DIR)\mod_proxy65 - mkdir $(SRC_DIR)\stringprep - copy stringprep\*.erl $(SRC_DIR)\stringprep - copy stringprep\*.c $(SRC_DIR)\stringprep - copy stringprep\*.tcl $(SRC_DIR)\stringprep - mkdir $(SRC_DIR)\stun - copy stun\*.erl $(SRC_DIR)\stun - copy stun\*.hrl $(SRC_DIR)\stun - mkdir $(SRC_DIR)\tls - copy tls\*.erl $(SRC_DIR)\tls - copy tls\*.c $(SRC_DIR)\tls - mkdir $(SRC_DIR)\ejabberd_zlib - copy ejabberd_zlib\*.erl $(SRC_DIR)\ejabberd_zlib - copy ejabberd_zlib\*.c $(SRC_DIR)\ejabberd_zlib - mkdir $(SRC_DIR)\web - copy web\*.erl $(SRC_DIR)\web - mkdir $(SRC_DIR)\odbc - copy odbc\*.erl $(SRC_DIR)\odbc - copy odbc\*.sql $(EREL) - mkdir $(DOC_DIR) - copy ..\doc\*.txt $(DOC_DIR) - copy ..\doc\*.html $(DOC_DIR) - copy ..\doc\*.png $(DOC_DIR) - -SOURCE = expat_erl.c -OBJECT = expat_erl.o -DLL = expat_erl.dll - -build : $(DLL) compile-beam all-recursive - -all-recursive : - cd eldap - nmake -nologo -f Makefile.win32 - cd ..\mod_irc - nmake -nologo -f Makefile.win32 - cd ..\mod_muc - nmake -nologo -f Makefile.win32 - cd ..\mod_pubsub - nmake -nologo -f Makefile.win32 - cd ..\mod_proxy65 - nmake -nologo -f Makefile.win32 - cd ..\stringprep - nmake -nologo -f Makefile.win32 - cd ..\stun - nmake -nologo -f Makefile.win32 - cd ..\tls - nmake -nologo -f Makefile.win32 - cd ..\ejabberd_zlib - nmake -nologo -f Makefile.win32 - cd ..\web - nmake -nologo -f Makefile.win32 - cd ..\odbc - nmake -nologo -f Makefile.win32 - cd .. - -compile-beam : XmppAddr.hrl - erl -s make all report -noinput -s erlang halt - -XmppAddr.hrl : XmppAddr.asn1 - erlc -bber_bin +der +compact_bit_string +optimize +noobj XmppAddr.asn1 - -CLEAN : clean-recursive clean-local - -clean-local : - -@erase $(OBJECT) - -@erase $(DLL) - -@erase expat_erl.exp - -@erase expat_erl.lib - -@erase *.beam - -@erase XmppAddr.asn1db - -@erase XmppAddr.erl - -@erase XmppAddr.hrl - -clean-recursive : - cd eldap - nmake -nologo -f Makefile.win32 clean - cd ..\mod_irc - nmake -nologo -f Makefile.win32 clean - cd ..\mod_muc - nmake -nologo -f Makefile.win32 clean - cd ..\mod_pubsub - nmake -nologo -f Makefile.win32 clean - cd ..\mod_proxy65 - nmake -nologo -f Makefile.win32 clean - cd ..\stringprep - nmake -nologo -f Makefile.win32 clean - cd ..\stun - nmake -nologo -f Makefile.win32 clean - cd ..\tls - nmake -nologo -f Makefile.win32 clean - cd ..\ejabberd_zlib - nmake -nologo -f Makefile.win32 clean - cd ..\web - nmake -nologo -f Makefile.win32 clean - cd ..\odbc - nmake -nologo -f Makefile.win32 clean - cd .. - -distclean : release_clean clean - -@erase $(NSIS_HEADER) - -@erase Makefile.inc - -CC=cl.exe -CC_FLAGS=-nologo -D__WIN32__ -DWIN32 -DWINDOWS -D_WIN32 -DNT $(EXPAT_FLAG) -MD -Ox -I"$(ERLANG_DIR)\usr\include" -I"$(EI_DIR)\include" -I"$(EXPAT_DIR)\source\lib" - -LD=link.exe -LD_FLAGS=-release -nologo -incremental:no -dll "$(EI_DIR)\lib\ei_md.lib" "$(EI_DIR)\lib\erl_interface_md.lib" "$(EXPAT_LIB)" MSVCRT.LIB kernel32.lib advapi32.lib gdi32.lib user32.lib comctl32.lib comdlg32.lib shell32.lib - -$(DLL) : $(OBJECT) - $(LD) $(LD_FLAGS) -out:$@ $< - -$(OBJECT) : $(SOURCE) - $(CC) $(CC_FLAGS) -c -Fo$@ $< diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 40c7a465263..00000000000 --- a/doc/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# $Id$ - -SHELL = /bin/sh - -CONTRIBUTED_MODULES = "" -#ifeq ($(shell ls mod_http_bind.tex),mod_http_bind.tex) -# CONTRIBUTED_MODULES += "\\n\\setboolean{modhttpbind}{true}" -#endif - - -all: release pdf html - -release: - @printf '%s\n' "Notes for the releaser:" - @printf '%s\n' "* Do not forget to add a link to the release notes in guide.tex" - @printf '%s\n' "* Do not forget to update the version number in ebin/ejabberd.app!" - @printf '%s\n' "* Do not forget to update the features in introduction.tex (including \new{} and \improved{} tags)." - @printf '%s\n' "Press any key to continue" - ##@read foo - @printf '%s\n' "% ejabberd version (automatically generated)." > version.tex - @printf '%s\n' "\newcommand{\version}{"`sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../ebin/ejabberd.app`"}" >> version.tex - @printf '%s' "% Contributed modules (automatically generated)." > contributed_modules.tex - @printf '%b\n' "$(CONTRIBUTED_MODULES)" >> contributed_modules.tex - -html: guide.html dev.html features.html - -pdf: guide.pdf features.pdf - -clean: - rm -f *.aux - rm -f *.haux - rm -f *.htoc - rm -f *.idx - rm -f *.ilg - rm -f *.ind - rm -f *.log - rm -f *.out - rm -f *.pdf - rm -f *.toc - [ ! -f contributed_modules.tex ] || rm contributed_modules.tex - -distclean: clean - rm -f *.html - -guide.html: guide.tex - hevea -fix -pedantic guide.tex - -dev.html: dev.tex - hevea -fix -pedantic dev.tex - -features.html: features.tex - hevea -fix -pedantic features.tex - -guide.pdf: guide.tex - pdflatex guide.tex - pdflatex guide.tex - pdflatex guide.tex - makeindex guide.idx - pdflatex guide.tex - -features.pdf: features.tex - pdflatex features.tex diff --git a/doc/api/Makefile b/doc/api/Makefile deleted file mode 100644 index de356ef20c8..00000000000 --- a/doc/api/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -APPNAME = ejabberd -VSN = $(shell sed '/vsn/!d;s/\(.*\)"\(.*\)"\(.*\)/\2/' ../../src/ejabberd.app) - -DOCDIR=. -SRCDIR=../../src - -.PHONY = all - -all: docs - -clean: - rm -f *.html - rm edoc-info - rm erlang.png - -docs: - erl -noshell -run edoc_run application \ - "'$(APPNAME)'" '"$(SRCDIR)"' '[{dir,"$(DOCDIR)"},{packages, false},{todo,true},{private,true},{def,{vsn,"$(VSN)"}},{stylesheet,"process-one.css"},{overview,"$(DOCDIR)/overview.edoc"}]' -s init stop diff --git a/doc/api/overview.edoc b/doc/api/overview.edoc deleted file mode 100644 index 61d620e87d4..00000000000 --- a/doc/api/overview.edoc +++ /dev/null @@ -1,10 +0,0 @@ -@author Mickael Remond - [http://www.process-one.net/] -@copyright 2013 ProcessOne -@version {@vsn}, {@date} {@time} -@title ejabberd Development API Documentation - -@doc -== Introduction == - -TODO: Insert content from Jerome documentation. diff --git a/doc/api/process-one.css b/doc/api/process-one.css deleted file mode 100644 index 5cd371e105a..00000000000 --- a/doc/api/process-one.css +++ /dev/null @@ -1,92 +0,0 @@ -html, body { - font-family: Verdana, sans-serif; - color: #000; - background-color: #fff; -} - -h1 { - color: #4a5389; - border-bottom: solid 1px #000; -} - -h2 { - font-size: 24px; - text-align: right; - color: #4a5389; - border-bottom: 1px solid #000; -} - -h3 { - font-size: 18px; - color: #900; -} - -h4 { - font-size: 14px; - color: #000; -} - -a[href] { - color: #4a5389; -} - -a[href]:hover { - background-color: #ecefff; -} - -p, li, dd { - text-align: justify; -} - -li { - margin-top: 0.3em; -} - -li:first-child { - margin-top: 0px; -} - -blockquote { - color: #555; -} - -caption { - font-style: italic; - color: #009; - text-align: left; - margin-left: 20px; -} - -table[border="1"] { - border-collapse: collapse; - margin-bottom: 1em; -} - -table[border="1"] td { - border: 1px solid #ddd; -} - -pre, tt, code { - color: #461b7e; -} - -pre { - margin:1ex 2ex; - border:1px dashed lightgrey; - background-color:#f9f9f9; - padding:0.5ex; -} - -pre em { - font-style: normal; - font-weight: bold; -} - -dt { - margin:0ex 2ex; - font-weight:bold; -} - -dd { - margin:0ex 0ex 1ex 4ex; -} diff --git a/doc/dev.html b/doc/dev.html deleted file mode 100644 index 9c96d27164b..00000000000 --- a/doc/dev.html +++ /dev/null @@ -1,437 +0,0 @@ - - - - - - -Ejabberd community 14.05-120-gedfb5fc Developers Guide - - - - -

    - -

    -

    Ejabberd community 14.05-120-gedfb5fc Developers Guide

    Alexey Shchepin
    - mailto:alexey@sevcom.net
    - xmpp:aleksey@jabber.ru

    - -logo.png - - -
    I can thoroughly recommend ejabberd for ease of setup – -Kevin Smith, Current maintainer of the Psi project
    -

    Contents

    Introduction -

    ejabberd is a free and open source instant messaging server written in Erlang/OTP.

    ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.

    ejabberd is designed to be a rock-solid and feature rich XMPP server.

    ejabberd is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.

    - -

    1  Key Features

    - -

    ejabberd is: -

    • -Cross-platform: ejabberd runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
    • Distributed: You can run ejabberd on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.
    • Fault-tolerant: You can deploy an ejabberd cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced ‘on the fly’.
    • Administrator Friendly: ejabberd is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include: -
      • -Comprehensive documentation. -
      • Straightforward installers for Linux, Mac OS X, and Windows.
      • Web Administration. -
      • Shared Roster Groups. -
      • Command line administration tool.
      • Can integrate with existing authentication mechanisms. -
      • Capability to send announce messages. -
    • Internationalized: ejabberd leads in internationalization. Hence it is very well suited in a globalized world. Related features are: -
      • -Translated to 25 languages.
      • Support for IDNA. -
    • Open Standards: ejabberd is the first Open Source Jabber server claiming to fully comply to the XMPP standard. -
    - -

    2  Additional Features

    - -

    Moreover, ejabberd comes with a wide range of other state-of-the-art features: -

    • -Modular -
      • -Load only the modules you want. -
      • Extend ejabberd with your own custom modules. -
      -
    • Security -
      • -SASL and STARTTLS for c2s and s2s connections. -
      • STARTTLS and Dialback s2s connections. -
      • Web Admin accessible via HTTPS secure access. -
      -
    • Databases -
      • -Internal database for fast deployment (Mnesia). -
      • Native MySQL support. -
      • Native PostgreSQL support. -
      • ODBC data storage support. -
      • Microsoft SQL Server support.
      • Riak NoSQL database support. -
      -
    • Authentication -
      • -Internal Authentication. -
      • PAM, LDAP, ODBC and Riak.
      • External Authentication script. -
      -
    • Others -
      • -Support for virtual hosting. -
      • Compressing XML streams with Stream Compression (XEP-0138). -
      • Statistics via Statistics Gathering (XEP-0039). -
      • IPv6 support both for c2s and s2s connections. -
      • Multi-User Chat module with support for clustering and HTML logging.
      • Users Directory based on users vCards. -
      • Publish-Subscribe component with support for Personal Eventing via Pubsub. -
      • Support for web clients: HTTP Polling and HTTP Binding (BOSH) services. -
      • IRC transport. -
      • SIP support. -
      • Component support: interface with networks such as AIM, ICQ and MSN installing special tranports. -
      -
    - -

    3  How it Works

    -

    A XMPP domain is served by one or more ejabberd nodes. These nodes can -be run on different machines that are connected via a network. They all must -have the ability to connect to port 4369 of all another nodes, and must have -the same magic cookie (see Erlang/OTP documentation, in other words the file -~ejabberd/.erlang.cookie must be the same on all nodes). This is -needed because all nodes exchange information about connected users, S2S -connections, registered services, etc…

    Each ejabberd node have following modules: -

    • -router; -
    • local router. -
    • session manager; -
    • S2S manager; -
    - -

    3.1  Router

    This module is the main router of XMPP packets on each node. It routes -them based on their destinations domains. It has two tables: local and global -routes. First, domain of packet destination searched in local table, and if it -found, then the packet is routed to appropriate process. If no, then it -searches in global table, and is routed to the appropriate ejabberd node or -process. If it does not exists in either tables, then it sent to the S2S -manager.

    - -

    3.2  Local Router

    This module routes packets which have a destination domain equal to this server -name. If destination JID has a non-empty user part, then it routed to the -session manager, else it is processed depending on it’s content.

    - -

    3.3  Session Manager

    This module routes packets to local users. It searches for what user resource -packet must be sent via presence table. If this resource is connected to -this node, it is routed to C2S process, if it connected via another node, then -the packet is sent to session manager on that node.

    - -

    3.4  S2S Manager

    This module routes packets to other XMPP servers. First, it checks if an -open S2S connection from the domain of the packet source to the domain of -packet destination already exists. If it is open on another node, then it -routes the packet to S2S manager on that node, if it is open on this node, then -it is routed to the process that serves this connection, and if a connection -does not exist, then it is opened and registered.

    - -

    4  Authentication

    - -

    4.0.1  External

    - -

    The external authentication script follows -the erlang port driver API.

    That script is supposed to do theses actions, in an infinite loop: -

    • -read from stdin: AABBBBBBBBB..... -
      • -A: 2 bytes of length data (a short in network byte order) -
      • B: a string of length found in A that contains operation in plain text -operation are as follows: -
        • -auth:User:Server:Password (check if a username/password pair is correct) -
        • isuser:User:Server (check if it’s a valid user) -
        • setpass:User:Server:Password (set user’s password) -
        • tryregister:User:Server:Password (try to register an account) -
        • removeuser:User:Server (remove this account) -
        • removeuser3:User:Server:Password (remove this account if the password is correct) -
        -
      -
    • write to stdout: AABB -
      • -A: the number 2 (coded as a short, which is bytes length of following result) -
      • B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid -
      -

    Example python script -

    #!/usr/bin/python
    -
    -import sys
    -from struct import *
    -
    -def from_ejabberd():
    -    input_length = sys.stdin.read(2)
    -    (size,) = unpack('>h', input_length)
    -    return sys.stdin.read(size).split(':')
    -
    -def to_ejabberd(bool):
    -    answer = 0
    -    if bool:
    -        answer = 1
    -    token = pack('>hh', 2, answer)
    -    sys.stdout.write(token)
    -    sys.stdout.flush()
    -
    -def auth(username, server, password):
    -    return True
    -
    -def isuser(username, server):
    -    return True
    -
    -def setpass(username, server, password):
    -    return True
    -
    -while True:
    -    data = from_ejabberd()
    -    success = False
    -    if data[0] == "auth":
    -        success = auth(data[1], data[2], data[3])
    -    elif data[0] == "isuser":
    -        success = isuser(data[1], data[2])
    -    elif data[0] == "setpass":
    -        success = setpass(data[1], data[2], data[3])
    -    to_ejabberd(success)
    -
    - -

    5  XML Representation

    -

    Each XML stanza is represented as the following tuple: -

    XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]}
    -        Name = string()
    -        Attrs = [Attr]
    -        Attr = {Key, Val}
    -        Key = string()
    -        Val = string()
    -        ElementOrCDATA = XMLElement | CDATA
    -        CDATA = {xmlcdata, string()}
    -

    E. g. this stanza: -

    <message to='test@conference.example.org' type='groupchat'>
    -  <body>test</body>
    -</message>
    -

    is represented as the following structure: -

    {xmlelement, "message",
    -    [{"to", "test@conference.example.org"},
    -     {"type", "groupchat"}],
    -    [{xmlelement, "body",
    -         [],
    -         [{xmlcdata, "test"}]}]}}
    -
    - -

    6  Module xml

    -

    -
    element_to_string(El) -> string() -
    El = XMLElement
    -
    Returns string representation of XML stanza El.
    crypt(S) -> string() -
    S = string()
    -
    Returns string which correspond to S with encoded XML special -characters.
    remove_cdata(ECList) -> EList -
    ECList = [ElementOrCDATA]
    -EList = [XMLElement]
    -
    EList is a list of all non-CDATA elements of ECList.
    get_path_s(El, Path) -> Res -
    El = XMLElement
    -Path = [PathItem]
    -PathItem = PathElem | PathAttr | PathCDATA
    -PathElem = {elem, Name}
    -PathAttr = {attr, Name}
    -PathCDATA = cdata
    -Name = string()
    -Res = string() | XMLElement
    -
    If Path is empty, then returns El. Else sequentially -consider elements of Path. Each element is one of: -
    -
    {elem, Name} Name is name of subelement of -El, if such element exists, then this element considered in -following steps, else returns empty string. -
    {attr, Name} If El have attribute Name, then -returns value of this attribute, else returns empty string. -
    cdata Returns CDATA of El. -
    TODO: -
             get_cdata/1, get_tag_cdata/1
    -         get_attr/2, get_attr_s/2
    -         get_tag_attr/2, get_tag_attr_s/2
    -         get_subtag/2
    -
    - -

    7  Module xml_stream

    -

    -
    parse_element(Str) -> XMLElement | {error, Err} -
    Str = string()
    -Err = term()
    -
    Parses Str using XML parser, returns either parsed element or error -tuple. -
    - -

    8  Modules

    -

    - -

    8.1  Module gen_iq_handler

    -

    The module gen_iq_handler allows to easily write handlers for IQ packets -of particular XML namespaces that addressed to server or to users bare JIDs.

    In this module the following functions are defined: -

    -
    add_iq_handler(Component, Host, NS, Module, Function, Type) -
    Component = Module = Function = atom()
    -Host = NS = string()
    -Type = no_queue | one_queue | parallel
    -
    Registers function Module:Function as handler for IQ packets on -virtual host Host that contain child of namespace NS in -Component. Queueing discipline is Type. There are at least -two components defined: -
    -
    ejabberd_local Handles packets that addressed to server JID; -
    ejabberd_sm Handles packets that addressed to users bare JIDs. -
    -
    remove_iq_handler(Component, Host, NS) -
    Component = atom()
    -Host = NS = string()
    -
    Removes IQ handler on virtual host Host for namespace NS from -Component. -

    Handler function must have the following type: -

    -
    Module:Function(From, To, IQ) -
    From = To = jid()
    -
    -module(mod_cputime).
    -
    --behaviour(gen_mod).
    -
    --export([start/2,
    -         stop/1,
    -         process_local_iq/3]).
    -
    --include("ejabberd.hrl").
    --include("jlib.hrl").
    -
    --define(NS_CPUTIME, "ejabberd:cputime").
    -
    -start(Host, Opts) ->
    -    IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
    -    gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME,
    -                                  ?MODULE, process_local_iq, IQDisc).
    -
    -stop(Host) ->
    -    gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME).
    -
    -process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) ->
    -    case Type of
    -        set ->
    -            {iq, ID, error, XMLNS,
    -             [SubEl, ?ERR_NOT_ALLOWED]};
    -        get ->
    -            CPUTime = element(1, erlang:statistics(runtime))/1000,
    -            SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)),
    -            {iq, ID, result, XMLNS,
    -             [{xmlelement, "query",
    -               [{"xmlns", ?NS_CPUTIME}],
    -               [{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]}
    -    end.
    -
    - -

    8.2  Services

    -

    -module(mod_echo).
    -
    --behaviour(gen_mod).
    -
    --export([start/2, init/1, stop/1]).
    -
    --include("ejabberd.hrl").
    --include("jlib.hrl").
    -
    -start(Host, Opts) ->
    -    MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host),
    -    register(gen_mod:get_module_proc(Host, ?PROCNAME),
    -             spawn(?MODULE, init, [MyHost])).
    -
    -init(Host) ->
    -    ejabberd_router:register_local_route(Host),
    -    loop(Host).
    -
    -loop(Host) ->
    -    receive
    -        {route, From, To, Packet} ->
    -            ejabberd_router:route(To, From, Packet),
    -            loop(Host);
    -        stop ->
    -            ejabberd_router:unregister_route(Host),
    -            ok;
    -        _ ->
    -            loop(Host)
    -    end.
    -
    -stop(Host) ->
    -    Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
    -    Proc ! stop,
    -    {wait, Proc}.
    -
    - - - -
    This document was translated from LATEX by -HEVEA.
    - diff --git a/doc/dev.tex b/doc/dev.tex deleted file mode 100644 index 4e63b95cee1..00000000000 --- a/doc/dev.tex +++ /dev/null @@ -1,470 +0,0 @@ -\documentclass[a4paper,10pt]{article} - -%% Packages -\usepackage{graphics} -\usepackage{hevea} -\usepackage{makeidx} -\usepackage{verbatim} - -%% Index -\makeindex -% Remove the index anchors from the HTML version to save size and bandwith. -\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}} - -%% Images -\newcommand{\logoscale}{0.7} -\newcommand{\imgscale}{0.58} -\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}} -\newcommand{\insscaleimg}[2]{ - \imgsrc{#2}{} - \begin{latexonly} - \scalebox{#1}{\includegraphics{#2}} - \end{latexonly} -} - -%% Various -\newcommand{\ns}[1]{\texttt{#1}} -\newcommand{\ejabberd}{\texttt{ejabberd}} -\newcommand{\Jabber}{Jabber} -\newcommand{\XMPP}{XMPP} - -%% Modules -\newcommand{\module}[1]{\texttt{#1}} -\newcommand{\modadhoc}{\module{mod\_adhoc}} -\newcommand{\modannounce}{\module{mod\_announce}} -\newcommand{\modconfigure}{\module{mod\_configure}} -\newcommand{\moddisco}{\module{mod\_disco}} -\newcommand{\modecho}{\module{mod\_echo}} -\newcommand{\modirc}{\module{mod\_irc}} -\newcommand{\modlast}{\module{mod\_last}} -\newcommand{\modlastodbc}{\module{mod\_last\_odbc}} -\newcommand{\modmuc}{\module{mod\_muc}} -\newcommand{\modmuclog}{\module{mod\_muc\_log}} -\newcommand{\modoffline}{\module{mod\_offline}} -\newcommand{\modofflineodbc}{\module{mod\_offline\_odbc}} -\newcommand{\modprivacy}{\module{mod\_privacy}} -\newcommand{\modprivate}{\module{mod\_private}} -\newcommand{\modpubsub}{\module{mod\_pubsub}} -\newcommand{\modregister}{\module{mod\_register}} -\newcommand{\modroster}{\module{mod\_roster}} -\newcommand{\modrosterodbc}{\module{mod\_roster\_odbc}} -\newcommand{\modservicelog}{\module{mod\_service\_log}} -\newcommand{\modsharedroster}{\module{mod\_shared\_roster}} -\newcommand{\modstats}{\module{mod\_stats}} -\newcommand{\modtime}{\module{mod\_time}} -\newcommand{\modvcard}{\module{mod\_vcard}} -\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}} -\newcommand{\modvcardodbc}{\module{mod\_vcard\_odbc}} -\newcommand{\modversion}{\module{mod\_version}} - -%% Title page -\include{version} -\title{Ejabberd \version\ Developers Guide} -\author{Alexey Shchepin \\ - \ahrefurl{mailto:alexey@sevcom.net} \\ - \ahrefurl{xmpp:aleksey@jabber.ru}} - -%% Options -\newcommand{\marking}[1]{#1} % Marking disabled -\newcommand{\quoting}[2][yozhik]{} % Quotes disabled -\newcommand{\new}{\begin{latexonly}\marginpar{\textsc{new}}\end{latexonly}} % Highlight new features -\newcommand{\improved}{\begin{latexonly}\marginpar{\textsc{improved}}\end{latexonly}} % Highlight improved features -\newcommand{\moreinfo}[1]{} % Hide details - -%% Footnotes -\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}} -\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}} - -\begin{document} - -\label{titlepage} -\begin{titlepage} - \maketitle{} - - \begin{center} - {\insscaleimg{\logoscale}{logo.png} - \par - } - \end{center} - - \begin{quotation}\textit{I can thoroughly recommend ejabberd for ease of setup -- - Kevin Smith, Current maintainer of the Psi project}\end{quotation} - -\end{titlepage} - -\tableofcontents{} - -% Input introduction.tex -\input{introduction} - -\section{How it Works} -\label{howitworks} - - -A \XMPP{} domain is served by one or more \ejabberd{} nodes. These nodes can -be run on different machines that are connected via a network. They all must -have the ability to connect to port 4369 of all another nodes, and must have -the same magic cookie (see Erlang/OTP documentation, in other words the file -\texttt{\~{}ejabberd/.erlang.cookie} must be the same on all nodes). This is -needed because all nodes exchange information about connected users, S2S -connections, registered services, etc\ldots - - - -Each \ejabberd{} node have following modules: -\begin{itemize} -\item router; -\item local router. -\item session manager; -\item S2S manager; -\end{itemize} - - -\subsection{Router} - -This module is the main router of \XMPP{} packets on each node. It routes -them based on their destinations domains. It has two tables: local and global -routes. First, domain of packet destination searched in local table, and if it -found, then the packet is routed to appropriate process. If no, then it -searches in global table, and is routed to the appropriate \ejabberd{} node or -process. If it does not exists in either tables, then it sent to the S2S -manager. - - -\subsection{Local Router} - -This module routes packets which have a destination domain equal to this server -name. If destination JID has a non-empty user part, then it routed to the -session manager, else it is processed depending on it's content. - - -\subsection{Session Manager} - -This module routes packets to local users. It searches for what user resource -packet must be sent via presence table. If this resource is connected to -this node, it is routed to C2S process, if it connected via another node, then -the packet is sent to session manager on that node. - - -\subsection{S2S Manager} - -This module routes packets to other \XMPP{} servers. First, it checks if an -open S2S connection from the domain of the packet source to the domain of -packet destination already exists. If it is open on another node, then it -routes the packet to S2S manager on that node, if it is open on this node, then -it is routed to the process that serves this connection, and if a connection -does not exist, then it is opened and registered. - - -\section{Authentication} - -\subsubsection{External} -\label{externalauth} -\ind{external authentication} - -The external authentication script follows -\footahref{http://www.erlang.org/doc/tutorial/c_portdriver.html}{the erlang port driver API}. - -That script is supposed to do theses actions, in an infinite loop: -\begin{itemize} -\item read from stdin: AABBBBBBBBB..... - \begin{itemize} - \item A: 2 bytes of length data (a short in network byte order) - \item B: a string of length found in A that contains operation in plain text - operation are as follows: - \begin{itemize} - \item auth:User:Server:Password (check if a username/password pair is correct) - \item isuser:User:Server (check if it's a valid user) - \item setpass:User:Server:Password (set user's password) - \item tryregister:User:Server:Password (try to register an account) - \item removeuser:User:Server (remove this account) - \item removeuser3:User:Server:Password (remove this account if the password is correct) - \end{itemize} - \end{itemize} -\item write to stdout: AABB - \begin{itemize} - \item A: the number 2 (coded as a short, which is bytes length of following result) - \item B: the result code (coded as a short), should be 1 for success/valid, or 0 for failure/invalid - \end{itemize} -\end{itemize} - -Example python script -\begin{verbatim} -#!/usr/bin/python - -import sys -from struct import * - -def from_ejabberd(): - input_length = sys.stdin.read(2) - (size,) = unpack('>h', input_length) - return sys.stdin.read(size).split(':') - -def to_ejabberd(bool): - answer = 0 - if bool: - answer = 1 - token = pack('>hh', 2, answer) - sys.stdout.write(token) - sys.stdout.flush() - -def auth(username, server, password): - return True - -def isuser(username, server): - return True - -def setpass(username, server, password): - return True - -while True: - data = from_ejabberd() - success = False - if data[0] == "auth": - success = auth(data[1], data[2], data[3]) - elif data[0] == "isuser": - success = isuser(data[1], data[2]) - elif data[0] == "setpass": - success = setpass(data[1], data[2], data[3]) - to_ejabberd(success) -\end{verbatim} - -\section{XML Representation} -\label{xmlrepr} - -Each XML stanza is represented as the following tuple: -\begin{verbatim} -XMLElement = {xmlelement, Name, Attrs, [ElementOrCDATA]} - Name = string() - Attrs = [Attr] - Attr = {Key, Val} - Key = string() - Val = string() - ElementOrCDATA = XMLElement | CDATA - CDATA = {xmlcdata, string()} -\end{verbatim} -E.\,g. this stanza: -\begin{verbatim} - - test - -\end{verbatim} -is represented as the following structure: -\begin{verbatim} -{xmlelement, "message", - [{"to", "test@conference.example.org"}, - {"type", "groupchat"}], - [{xmlelement, "body", - [], - [{xmlcdata, "test"}]}]}} -\end{verbatim} - - - -\section{Module \texttt{xml}} -\label{xmlmod} - -\begin{description} -\item{\verb|element_to_string(El) -> string()|} -\begin{verbatim} -El = XMLElement -\end{verbatim} - Returns string representation of XML stanza \texttt{El}. - -\item{\verb|crypt(S) -> string()|} -\begin{verbatim} -S = string() -\end{verbatim} - Returns string which correspond to \texttt{S} with encoded XML special - characters. - -\item{\verb|remove_cdata(ECList) -> EList|} -\begin{verbatim} -ECList = [ElementOrCDATA] -EList = [XMLElement] -\end{verbatim} - \texttt{EList} is a list of all non-CDATA elements of ECList. - - - -\item{\verb|get_path_s(El, Path) -> Res|} -\begin{verbatim} -El = XMLElement -Path = [PathItem] -PathItem = PathElem | PathAttr | PathCDATA -PathElem = {elem, Name} -PathAttr = {attr, Name} -PathCDATA = cdata -Name = string() -Res = string() | XMLElement -\end{verbatim} - If \texttt{Path} is empty, then returns \texttt{El}. Else sequentially - consider elements of \texttt{Path}. Each element is one of: - \begin{description} - \item{\verb|{elem, Name}|} \texttt{Name} is name of subelement of - \texttt{El}, if such element exists, then this element considered in - following steps, else returns empty string. - \item{\verb|{attr, Name}|} If \texttt{El} have attribute \texttt{Name}, then - returns value of this attribute, else returns empty string. - \item{\verb|cdata|} Returns CDATA of \texttt{El}. - \end{description} - -\item{TODO:} -\begin{verbatim} - get_cdata/1, get_tag_cdata/1 - get_attr/2, get_attr_s/2 - get_tag_attr/2, get_tag_attr_s/2 - get_subtag/2 -\end{verbatim} -\end{description} - - -\section{Module \texttt{xml\_stream}} -\label{xmlstreammod} - -\begin{description} -\item{\verb!parse_element(Str) -> XMLElement | {error, Err}!} -\begin{verbatim} -Str = string() -Err = term() -\end{verbatim} - Parses \texttt{Str} using XML parser, returns either parsed element or error - tuple. -\end{description} - - -\section{Modules} -\label{emods} - - -%\subsection{gen\_mod behaviour} -%\label{genmod} - -%TBD - -\subsection{Module gen\_iq\_handler} -\label{geniqhandl} - -The module \verb|gen_iq_handler| allows to easily write handlers for IQ packets -of particular XML namespaces that addressed to server or to users bare JIDs. - -In this module the following functions are defined: -\begin{description} -\item{\verb|add_iq_handler(Component, Host, NS, Module, Function, Type)|} -\begin{verbatim} -Component = Module = Function = atom() -Host = NS = string() -Type = no_queue | one_queue | parallel -\end{verbatim} - Registers function \verb|Module:Function| as handler for IQ packets on - virtual host \verb|Host| that contain child of namespace \verb|NS| in - \verb|Component|. Queueing discipline is \verb|Type|. There are at least - two components defined: - \begin{description} - \item{\verb|ejabberd_local|} Handles packets that addressed to server JID; - \item{\verb|ejabberd_sm|} Handles packets that addressed to users bare JIDs. - \end{description} -\item{\verb|remove_iq_handler(Component, Host, NS)|} -\begin{verbatim} -Component = atom() -Host = NS = string() -\end{verbatim} - Removes IQ handler on virtual host \verb|Host| for namespace \verb|NS| from - \verb|Component|. -\end{description} - -Handler function must have the following type: -\begin{description} -\item{\verb|Module:Function(From, To, IQ)|} -\begin{verbatim} -From = To = jid() -\end{verbatim} -\end{description} - - - -\begin{verbatim} --module(mod_cputime). - --behaviour(gen_mod). - --export([start/2, - stop/1, - process_local_iq/3]). - --include("ejabberd.hrl"). --include("jlib.hrl"). - --define(NS_CPUTIME, "ejabberd:cputime"). - -start(Host, Opts) -> - IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), - gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_CPUTIME, - ?MODULE, process_local_iq, IQDisc). - -stop(Host) -> - gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_CPUTIME). - -process_local_iq(From, To, {iq, ID, Type, XMLNS, SubEl}) -> - case Type of - set -> - {iq, ID, error, XMLNS, - [SubEl, ?ERR_NOT_ALLOWED]}; - get -> - CPUTime = element(1, erlang:statistics(runtime))/1000, - SCPUTime = lists:flatten(io_lib:format("~.3f", CPUTime)), - {iq, ID, result, XMLNS, - [{xmlelement, "query", - [{"xmlns", ?NS_CPUTIME}], - [{xmlelement, "cputime", [], [{xmlcdata, SCPUTime}]}]}]} - end. -\end{verbatim} - - -\subsection{Services} -\label{services} - -%TBD - - -%TODO: use \verb|proc_lib| -\begin{verbatim} --module(mod_echo). - --behaviour(gen_mod). - --export([start/2, init/1, stop/1]). - --include("ejabberd.hrl"). --include("jlib.hrl"). - -start(Host, Opts) -> - MyHost = gen_mod:get_opt(host, Opts, "echo." ++ Host), - register(gen_mod:get_module_proc(Host, ?PROCNAME), - spawn(?MODULE, init, [MyHost])). - -init(Host) -> - ejabberd_router:register_local_route(Host), - loop(Host). - -loop(Host) -> - receive - {route, From, To, Packet} -> - ejabberd_router:route(To, From, Packet), - loop(Host); - stop -> - ejabberd_router:unregister_route(Host), - ok; - _ -> - loop(Host) - end. - -stop(Host) -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - Proc ! stop, - {wait, Proc}. -\end{verbatim} - - - -\end{document} diff --git a/doc/discorus.png b/doc/discorus.png deleted file mode 100644 index 982f8818209878b11e1846bed583b9390d86d506..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10052 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 RraTm&qoJ=}p=SH)zW|3V`2qj{ diff --git a/doc/features.html b/doc/features.html deleted file mode 100644 index f922a1cca28..00000000000 --- a/doc/features.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - -Ejabberd community 14.05-120-gedfb5fc Feature Sheet - - - - -

    - -

    -

    Ejabberd community 14.05-120-gedfb5fc Feature Sheet

    Sander Devrieze
    - mailto:s.devrieze@pandora.be
    - xmpp:sander@devrieze.dyndns.org

    - -logo.png - - -
    I can thoroughly recommend ejabberd for ease of setup – -Kevin Smith, Current maintainer of the Psi project

    Introduction -

    I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. — -Joeri

    ejabberd is a free and open source instant messaging server written in Erlang/OTP.

    ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication.

    ejabberd is designed to be a rock-solid and feature rich XMPP server.

    ejabberd is suitable for small deployments, whether they need to be scalable or not, as well as extremely big deployments.

    - -

    Key Features

    - -

    Erlang seems to be tailor-made for writing stable, robust servers. — -Peter Saint-André, Executive Director of the Jabber Software Foundation

    ejabberd is: -

    • -Cross-platform: ejabberd runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD.
    • Distributed: You can run ejabberd on a cluster of machines and all of them will serve the same Jabber domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users.
    • Fault-tolerant: You can deploy an ejabberd cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced ‘on the fly’.
    • Administrator Friendly: ejabberd is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include: -
      • -Comprehensive documentation. -
      • Straightforward installers for Linux, Mac OS X, and Windows.
      • Web Administration. -
      • Shared Roster Groups. -
      • Command line administration tool.
      • Can integrate with existing authentication mechanisms. -
      • Capability to send announce messages. -
    • Internationalized: ejabberd leads in internationalization. Hence it is very well suited in a globalized world. Related features are: -
      • -Translated to 25 languages.
      • Support for IDNA. -
    • Open Standards: ejabberd is the first Open Source Jabber server claiming to fully comply to the XMPP standard. -
    - -

    Additional Features

    - -

    ejabberd is making inroads to solving the "buggy incomplete server" problem — -Justin Karneges, Founder of the Psi and the Delta projects

    Moreover, ejabberd comes with a wide range of other state-of-the-art features: -

    • -Modular -
      • -Load only the modules you want. -
      • Extend ejabberd with your own custom modules. -
      -
    • Security -
      • -SASL and STARTTLS for c2s and s2s connections. -
      • STARTTLS and Dialback s2s connections. -
      • Web Admin accessible via HTTPS secure access. -
      -
    • Databases -
      • -Internal database for fast deployment (Mnesia). -
      • Native MySQL support. -
      • Native PostgreSQL support. -
      • ODBC data storage support. -
      • Microsoft SQL Server support.
      • Riak NoSQL database support. -
      -
    • Authentication -
      • -Internal Authentication. -
      • PAM, LDAP, ODBC and Riak.
      • External Authentication script. -
      -
    • Others -
      • -Support for virtual hosting. -
      • Compressing XML streams with Stream Compression (XEP-0138). -
      • Statistics via Statistics Gathering (XEP-0039). -
      • IPv6 support both for c2s and s2s connections. -
      • Multi-User Chat module with support for clustering and HTML logging.
      • Users Directory based on users vCards. -
      • Publish-Subscribe component with support for Personal Eventing via Pubsub. -
      • Support for web clients: HTTP Polling and HTTP Binding (BOSH) services. -
      • IRC transport. -
      • SIP support. -
      • Component support: interface with networks such as AIM, ICQ and MSN installing special tranports. -
      -
    - - - -
    This document was translated from LATEX by -HEVEA.
    - diff --git a/doc/features.tex b/doc/features.tex deleted file mode 100644 index 1a512571f0e..00000000000 --- a/doc/features.tex +++ /dev/null @@ -1,136 +0,0 @@ -\documentclass[a4paper,10pt]{article} - -%% Packages -\usepackage{epsfig} -\usepackage{fancyhdr} -\usepackage{graphics} -\usepackage{hevea} -\usepackage[pdftex,colorlinks,unicode,urlcolor=blue,linkcolor=blue,pdftitle=Ejabberd\ - Feature\ Sheet,pdfauthor=Sander\ - Devrieze,pdfsubject=ejabberd,pdfkeywords=ejabberd]{hyperref} -\usepackage{verbatim} -\usepackage{color} - -%% Index -% Remove the index anchors from the HTML version to save size and bandwith. -\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}} - -%% Images -\newcommand{\logoscale}{0.7} -\newcommand{\imgscale}{0.58} -\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}} -\newcommand{\insscaleimg}[2]{ - \imgsrc{#2}{} - \begin{latexonly} - \scalebox{#1}{\includegraphics{#2}} - \end{latexonly} -} - -%% Various -\newcommand{\bracehack}{\def\{{\char"7B}\def\}{\char"7D}} -\newcommand{\titem}[1]{\item[\bracehack\texttt{#1}]} -\newcommand{\ns}[1]{\texttt{#1}} -\newcommand{\jid}[1]{\texttt{#1}} -\newcommand{\option}[1]{\texttt{#1}} -\newcommand{\poption}[1]{{\bracehack\texttt{#1}}} -\newcommand{\node}[1]{\texttt{#1}} -\newcommand{\term}[1]{\texttt{#1}} -\newcommand{\shell}[1]{\texttt{#1}} -\newcommand{\ejabberd}{\texttt{ejabberd}} -\newcommand{\Jabber}{Jabber} - -%% Title page -\include{version} -\title{Ejabberd \version\ Feature Sheet} -\author{Sander Devrieze \\ - \ahrefurl{mailto:s.devrieze@pandora.be} \\ - \ahrefurl{xmpp:sander@devrieze.dyndns.org}} - -% Options -\newcommand{\marking}[1]{\textbf{\begin{large}\textcolor{ejblue}{#1}\end{large}}} % Marking enabled -\newcommand{\quoting}[2][yozhik]{\begin{quotation}\textcolor{#1}{\textit{#2}}\end{quotation}} % Quotes enabled -\newcommand{\new}{\marginpar{\textcolor{red}{\textsc{new}}}} % Highlight new features -\newcommand{\improved}{\marginpar{\textcolor{orange}{\textsc{improved}}}} % Highlight improved features -\setcounter{secnumdepth}{-1} % Disable section numbering - -%% To by-pass errors in the HTML version. -\newstyle{SPAN}{width:20\%; float:right; text-align:left; margin-left:auto;} -\definecolor{orange} {cmyk}{0.000,0.333,1.000,0.000} - -%% Footnotes -\begin{latexonly} -\global\parskip=9pt plus 3pt minus 1pt -\global\parindent=0pt -\gdef\ahrefurl#1{\href{#1}{\texttt{#1}}} -\gdef\footahref#1#2{#2\footnote{\href{#1}{\texttt{#1}}}} -\end{latexonly} -\newcommand{\txepref}[2]{\footahref{http://www.xmpp.org/extensions/xep-#1.html}{#2}} -\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}} - -%% Fancy header -\fancyhf{} -\pagestyle{fancy} -\rhead{\textcolor{ejblue}{The Expandable Jabber/XMPP Daemon.}} -\renewcommand{\headrule}{{\color{ejblue}% -\hrule width\headwidth height\headrulewidth \vskip-\headrulewidth}} -\lhead{\setlength{\unitlength}{-6mm} - \begin{picture}(0,0) - \put(5.8,3.25){\includegraphics[width=1.3\textwidth]{yozhikheader.png}} - \end{picture}} - -% Official ejabberd colours -\definecolor{ejblue} {cmyk}{1.000,0.831,0.000,0.537} %RGB: 0,0,118 HTML: 000076 -\definecolor{ejgreenyellow}{cmyk}{0.079,0.000,0.275,0.102} %RGB: 209,229,159 HTML: d1e59f -\definecolor{ejgreendark} {cmyk}{0.131,0.000,0.146,0.220} %RGB: 166,199,162 HTML: a6c7a2 -\definecolor{ejgreen} {cmyk}{0.077,0.000,0.081,0.078} %RGB: 216,236,215 HTML: d8ecd7 -\definecolor{ejgreenwhite} {cmyk}{0.044,0.000,0.048,0.020} %RGB: 239,250,238 HTML: effaee -\definecolor{yozhik} {cmyk}{0.000,0.837,1.000,0.424} %RGB: 147,0,0 HTML: 930000 - -\begin{document} - -\label{titlepage} -\begin{titlepage} - \maketitle{} - - \thispagestyle{empty} - - \begin{center} - {\insscaleimg{\logoscale}{logo.png} - \par - } - \end{center} - \quoting{I can thoroughly recommend ejabberd for ease of setup -- - Kevin Smith, Current maintainer of the Psi project} - -\end{titlepage} - -\newpage -% Set the page counter to 2 so that the titlepage and the second page do not -% have the same page number. This fixes the PDFLaTeX warning "destination with -% the same identifier". -\begin{latexonly} -\setcounter{page}{2} -\pagecolor{ejgreenwhite} -\end{latexonly} - -% Input introduction.tex -\input{introduction} - -\end{document} - -%% TODO -% * illustrations (e.g. screenshot from web interface) -% * commented parts -% * slides, guide and html version -% * cleaning and improving LaTeX code -% * key features: something like this (shorter)? (more focussed on Erlang now): "To reach the goal of high -% availability, performance and clustering, ejabberd is written in Erlang, a programming language perfectly -% suited for this. Besides that, some parts are written in C to also incude the advantages of this language. In -% short, ejabberd is a perfect mix of mainly Erlang code, peppered with some C code to get the final touch!" -% -% * key features: saying that ejabberd the only XMPP server is that can do real clustering: -% http://www.jivesoftware.org/forums/thread.jspa?threadID=14602 -% "What I find interesting is that *no* XMPP servers truly provide clustering. This includes all the commercial -% servers. The one partial exception appears to be ejabberd, which can cluster certain data such as sessions, -% but not all services such as MUC." -% * try it today: links to migration tutorials diff --git a/doc/flow.dot b/doc/flow.dot deleted file mode 100644 index b1a8affb81d..00000000000 --- a/doc/flow.dot +++ /dev/null @@ -1,105 +0,0 @@ -digraph messages { - //concentrate=true; - subgraph clusterclients { - client1 [shape = box]; - client2 [shape = box]; - client3 [shape = box]; - - style = dashed; - label = "Clients"; - } - - subgraph clusternode1 { - subgraph clusterc2s1 { - c2s11; - c2s12; - style = invis; - } - subgraph clusterservices1 { - service11; - service12; - service13; - style = invis; - } - //subgraph clusters2s1 { - //s2s11; - //s2s12; - //style = invis; - //} - c2s11 -> auth1; - c2s12 -> auth1; - auth1 -> c2s11; - auth1 -> c2s12; - c2s11 -> sm1; - c2s11 -> router1; - c2s12 -> sm1; - c2s12 -> router1; - router1 -> local1; - router1 -> service11; - router1 -> service12; - router1 -> service13; - router1 -> s2s11; - router1 -> s2s12; - service11 -> router1; - service12 -> router1; - service13 -> router1; - s2s11 -> router1; - s2s12 -> router1; - local1 -> sm1; - sm1 -> c2s11; - sm1 -> c2s12; - - style = dashed; - label = "Node1"; - } - - subgraph clusternode2 { - c2s2 -> auth2; - auth2 -> c2s2; - c2s2 -> sm2; - c2s2 -> router2; - router2 -> local2; - router2 -> service21; - router2 -> s2s21; - service21 -> router2; - s2s21 -> router2; - local2 -> sm2; - sm2 -> c2s2; - - style = dashed; - label = "Node2"; - } - - - - subgraph clusterservers { - server1 [shape = box]; - server2 [shape = box]; - server3 [shape = box]; - - style = dashed; - label = "Servers"; - } - - - client1 -> c2s11; - client2 -> c2s12; - client3 -> c2s2; - c2s11 -> client1 [constraint=false]; - c2s12 -> client2 [constraint=false]; - c2s2 -> client3 [constraint=false]; - - s2s11 -> server1 [minlen = 2]; - s2s12 -> server2 [minlen = 2]; - s2s21 -> server3 [minlen = 2]; - server1 -> s2s11 [constraint=false]; - server2 -> s2s12 [constraint=false]; - server3 -> s2s21 [constraint=false]; - - router1 -> router2; - router2 -> router1; - sm1 -> sm2; - sm2 -> sm1; - - label = "Data Flows"; -} diff --git a/doc/guide.tex b/doc/guide.tex deleted file mode 100644 index 9817dc229e8..00000000000 --- a/doc/guide.tex +++ /dev/null @@ -1,6494 +0,0 @@ -\documentclass[a4paper,10pt]{book} - -%% Packages -\usepackage{float} -\usepackage{graphics} -\usepackage{hevea} -\usepackage[pdftex,colorlinks,unicode,urlcolor=blue,linkcolor=blue, - pdftitle=Ejabberd\ Installation\ and\ Operation\ Guide,pdfauthor=ProcessOne,pdfsubject=ejabberd,pdfkeywords=ejabberd, - pdfpagelabels=false]{hyperref} -\usepackage{makeidx} -%\usepackage{showidx} % Only for verifying the index entries. -\usepackage{verbatim} -\usepackage{geometry} -\usepackage{fancyhdr} - -\pagestyle{fancy} %Forces the page to use the fancy template -\renewcommand{\chaptermark}[1]{\markboth{\textbf{\thechapter}.\ \emph{#1}}{}} -\renewcommand{\sectionmark}[1]{\markright{\thesection\ \boldmath\textbf{#1}\unboldmath}} -\fancyhf{} -\fancyhead[LE,RO]{\textbf{\thepage}} %Displays the page number in bold in the header, - % to the left on even pages and to the right on odd pages. -\fancyhead[RE]{\nouppercase{\leftmark}} %Displays the upper-level (chapter) information--- - % as determined above---in non-upper case in the header, to the right on even pages. -\fancyhead[LO]{\rightmark} %Displays the lower-level (section) information---as - % determined above---in the header, to the left on odd pages. -\renewcommand{\headrulewidth}{0.5pt} %Underlines the header. (Set to 0pt if not required). -\renewcommand{\footrulewidth}{0.5pt} %Underlines the footer. (Set to 0pt if not required). - -%% Index -\makeindex -% Remove the index anchors from the HTML version to save size and bandwith. -\newcommand{\ind}[1]{\begin{latexonly}\index{#1}\end{latexonly}} -\newcommand{\makechapter}[2]{ \aname{#1}{} \chapter{\ahrefloc{#1}{#2}} \label{#1} } -\newcommand{\makesection}[2]{ \aname{#1}{} \section{\ahrefloc{#1}{#2}} \label{#1} } -\newcommand{\makesubsection}[2]{ \aname{#1}{} \subsection{\ahrefloc{#1}{#2}} \label{#1} } -\newcommand{\makesubsubsection}[2]{ \aname{#1}{} \subsubsection{\ahrefloc{#1}{#2}} \label{#1} } -\newcommand{\makeparagraph}[2]{ \aname{#1}{} \paragraph{\ahrefloc{#1}{#2}} \label{#1} } - -%% Images -\newcommand{\logoscale}{0.7} -\newcommand{\imgscale}{0.58} -\newcommand{\insimg}[1]{\insscaleimg{\imgscale}{#1}} -\newcommand{\insscaleimg}[2]{ - \imgsrc{#2}{} - \begin{latexonly} - \scalebox{#1}{\includegraphics{#2}} - \end{latexonly} -} - -%% Various -\newcommand{\bracehack}{\def\{{\char"7B}\def\}{\char"7D}} -\newcommand{\titem}[1]{\item[\bracehack\texttt{#1}]} -\newcommand{\ns}[1]{\texttt{#1}} -\newcommand{\jid}[1]{\texttt{#1}} -\newcommand{\option}[1]{\texttt{#1}} -\newcommand{\poption}[1]{{\bracehack\texttt{#1}}} -\newcommand{\node}[1]{\texttt{#1}} -\newcommand{\term}[1]{\texttt{#1}} -\newcommand{\shell}[1]{\texttt{#1}} -\newcommand{\ejabberd}{\texttt{ejabberd}} -\newcommand{\Jabber}{Jabber} -\newcommand{\XMPP}{XMPP} -\newcommand{\esyntax}[1]{\begin{description}\titem{#1}\end{description}} - -%% Modules -\newcommand{\module}[1]{\texttt{#1}} -\newcommand{\modadhoc}{\module{mod\_adhoc}} -\newcommand{\modannounce}{\module{mod\_announce}} -\newcommand{\modclientstate}{\module{mod\_client\_state}} -\newcommand{\modblocking}{\module{mod\_blocking}} -\newcommand{\modcaps}{\module{mod\_caps}} -\newcommand{\modcarboncopy}{\module{mod\_carboncopy}} -\newcommand{\modconfigure}{\module{mod\_configure}} -\newcommand{\moddisco}{\module{mod\_disco}} -\newcommand{\modecho}{\module{mod\_echo}} -\newcommand{\modfailban}{\module{mod\_fail2ban}} -\newcommand{\modhttpbind}{\module{mod\_http\_bind}} -\newcommand{\modhttpfileserver}{\module{mod\_http\_fileserver}} -\newcommand{\modirc}{\module{mod\_irc}} -\newcommand{\modlast}{\module{mod\_last}} -\newcommand{\modmuc}{\module{mod\_muc}} -\newcommand{\modmuclog}{\module{mod\_muc\_log}} -\newcommand{\modoffline}{\module{mod\_offline}} -\newcommand{\modping}{\module{mod\_ping}} -\newcommand{\modprescounter}{\module{mod\_pres\_counter}} -\newcommand{\modprivacy}{\module{mod\_privacy}} -\newcommand{\modprivate}{\module{mod\_private}} -\newcommand{\modproxy}{\module{mod\_proxy65}} -\newcommand{\modpubsub}{\module{mod\_pubsub}} -\newcommand{\modpubsubodbc}{\module{mod\_pubsub\_odbc}} -\newcommand{\modregister}{\module{mod\_register}} -\newcommand{\modregisterweb}{\module{mod\_register\_web}} -\newcommand{\modroster}{\module{mod\_roster}} -\newcommand{\modservicelog}{\module{mod\_service\_log}} -\newcommand{\modsharedroster}{\module{mod\_shared\_roster}} -\newcommand{\modsharedrosterldap}{\module{mod\_shared\_roster\_ldap}} -\newcommand{\modsic}{\module{mod\_sic}} -\newcommand{\modsip}{\module{mod\_sip}} -\newcommand{\modstats}{\module{mod\_stats}} -\newcommand{\modtime}{\module{mod\_time}} -\newcommand{\modvcard}{\module{mod\_vcard}} -\newcommand{\modvcardldap}{\module{mod\_vcard\_ldap}} -\newcommand{\modvcardxupdate}{\module{mod\_vcard\_xupdate}} -\newcommand{\modversion}{\module{mod\_version}} - -%% Contributed modules -%\usepackage{ifthen} -%\newboolean{modhttpbind} -%\newcommand{\modhttpbind}{\module{mod\_http\_bind}} -%\include{contributed_modules} -% -% Then in the document you can input the partial tex file with: -%\ifthenelse{\boolean{modhttpbind}}{\input{mod_http_bind.tex}}{} - -%% Common options -\newcommand{\iqdiscitem}[1]{\titem{iqdisc: Discipline} \ind{options!iqdisc}This specifies -the processing discipline for #1 IQ queries (see section~\ref{modiqdiscoption}).} -\newcommand{\hostitem}[1]{ - \titem{host: HostName} \ind{options!host} This option defines the Jabber ID of the - service. If the \texttt{host} option is not specified, the Jabber ID will be the - hostname of the virtual host with the prefix `\jid{#1.}'. The keyword "@HOST@" - is replaced at start time with the real virtual host name. -} -\newcommand{\dbtype}{\titem{db\_type: internal|odbc} \ind{options!dbtype} - Define the type of storage where the module will create the tables and store user information. - The default is to store in the internal Mnesia database. - If \term{odbc} value is defined, make sure you have defined the database, see~\ref{database}. -} - -%% Title page -\include{version} -\newlength{\larg} -\setlength{\larg}{14.5cm} -\title{ -{\rule{\larg}{1mm}}\vspace{7mm} -\begin{tabular}{r} - {\huge {\bf ejabberd \version\ }} \\ - \\ - {\huge Installation and Operation Guide} -\end{tabular}\\ -\vspace{2mm} -{\rule{\larg}{1mm}} -\begin{latexonly} -\vspace{2mm} \\ -\vspace{5.5cm} -\end{latexonly} -} -\begin{latexonly} -\author{\begin{tabular}{p{13.7cm}} -ejabberd Development Team -\end{tabular}} -\date{} -\end{latexonly} - - -%% Options -\newcommand{\marking}[1]{#1} % Marking disabled -\newcommand{\quoting}[2][yozhik]{} % Quotes disabled -%\newcommand{\new}{\marginpar{\textsc{new}}} % Highlight new features -%\newcommand{\improved}{\marginpar{\textsc{improved}}} % Highlight improved features - -%% To by-pass errors in the HTML version: -\newstyle{.SPAN}{width:20\%; float:right; text-align:left; margin-left:auto;} -\newstyle{H1.titlemain HR}{display:none;} -\newstyle{TABLE.title}{border-top:1px solid grey;border-bottom:1px solid grey; background: \#efefef} -\newstyle{H1.chapter A, H2.section A, H3.subsection A, H4.subsubsection A, H5.paragraph A} - {color:\#000000; text-decoration:none;} -\newstyle{H1.chapter, H2.section, H3.subsection, H4.subsubsection, H5.paragraph} - {border-top: 1px solid grey; background: \#efefef; padding: 0.5ex} -\newstyle{pre.verbatim}{margin:1ex 2ex;border:1px dashed lightgrey;background-color:\#f9f9f9;padding:0.5ex;} -\newstyle{.dt-description}{margin:0ex 2ex;} -\newstyle{table[border="1"]}{border-collapse:collapse;margin-bottom:1em;} -\newstyle{table[border="1"] td}{border:1px solid \#aaa;padding:2px} -% Don't display
    before and after tables or images: -\newstyle{BLOCKQUOTE.table DIV.center DIV.center HR}{display:none;} -\newstyle{BLOCKQUOTE.figure DIV.center DIV.center HR}{display:none;} - -%% Footnotes -\begin{latexonly} -\global\parskip=9pt plus 3pt minus 1pt -\global\parindent=0pt -\gdef\ahrefurl#1{\href{#1}{\texttt{#1}}} -\gdef\footahref#1#2{#2\footnote{\href{#1}{\texttt{#1}}}} -\end{latexonly} -\newcommand{\txepref}[2]{\footahref{http://xmpp.org/extensions/xep-#1.html}{#2}} -\newcommand{\xepref}[1]{\txepref{#1}{XEP-#1}} - -\begin{document} - -\label{titlepage} -\begin{titlepage} - \maketitle{} - -%% Commenting. Breaking clean layout for now: -%% \begin{center} -%% {\insscaleimg{\logoscale}{logo.png} -%% \par -%% } -%% \end{center} - -%% \begin{quotation}\textit{I can thoroughly recommend ejabberd for ease of setup --- -%% Kevin Smith, Current maintainer of the Psi project}\end{quotation} - -\end{titlepage} - -% Set the page counter to 2 so that the titlepage and the second page do not -% have the same page number. This fixes the PDFLaTeX warning "destination with -% the same identifier". -\begin{latexonly} -\setcounter{page}{2} -\end{latexonly} - -\label{toc} -\tableofcontents{} - -% Input introduction.tex -\input{introduction} - -\makechapter{installing}{Installing \ejabberd{}} - -\makesection{install.binary}{Installing \ejabberd{} with Binary Installer} - -Probably the easiest way to install an \ejabberd{} instant messaging server -is using the binary installer published by ProcessOne. -The binary installers of released \ejabberd{} versions -are available in the ProcessOne \ejabberd{} downloads page: -\ahrefurl{http://www.process-one.net/en/ejabberd/downloads} - -The installer will deploy and configure a full featured \ejabberd{} -server and does not require any extra dependencies. - -In *nix systems, remember to set executable the binary installer before starting it. For example: -\begin{verbatim} -chmod +x ejabberd-2.0.0_1-linux-x86-installer.bin -./ejabberd-2.0.0_1-linux-x86-installer.bin -\end{verbatim} - -\ejabberd{} can be started manually at any time, -or automatically by the operating system at system boot time. - -To start and stop \ejabberd{} manually, -use the desktop shortcuts created by the installer. -If the machine doesn't have a graphical system, use the scripts 'start' -and 'stop' in the 'bin' directory where \ejabberd{} is installed. - -The Windows installer also adds ejabberd as a system service, -and a shortcut to a debug console for experienced administrators. -If you want ejabberd to be started automatically at boot time, -go to the Windows service settings and set ejabberd to be automatically started. -Note that the Windows service is a feature still in development, -and for example it doesn't read the file ejabberdctl.cfg. - -On a *nix system, if you want ejabberd to be started as daemon at boot time, -copy \term{ejabberd.init} from the 'bin' directory to something like \term{/etc/init.d/ejabberd} -(depending on your distribution). -Create a system user called \term{ejabberd}, -give it write access to the directories \term{database/} and \term{logs/}, and set that as home; -the script will start the server with that user. -Then you can call \term{/etc/inid.d/ejabberd start} as root to start the server. - -When ejabberd is started, the processes that are started in the system -are \term{beam} or \term{beam.smp}, and also \term{epmd}. -In Microsoft Windows, the processes are \term{erl.exe} and \term{epmd.exe}. -For more information regarding \term{epmd} consult the section \ref{epmd}. - -If \term{ejabberd} doesn't start correctly in Windows, -try to start it using the shortcut in desktop or start menu. -If the window shows error 14001, the solution is to install: -"Microsoft Visual C++ 2005 SP1 Redistributable Package". -You can download it from -\footahref{http://www.microsoft.com/}{www.microsoft.com}. -Then uninstall \ejabberd{} and install it again. - -If \term{ejabberd} doesn't start correctly and a crash dump is generated, -there was a severe problem. -You can try starting \term{ejabberd} with -the script \term{bin/live.bat} in Windows, -or with the command \term{bin/ejabberdctl live} in other Operating Systems. -This way you see the error message provided by Erlang -and can identify what is exactly the problem. - -The \term{ejabberdctl} administration script is included in the \term{bin} directory. -Please refer to the section~\ref{ejabberdctl} for details about \term{ejabberdctl}, -and configurable options to fine tune the Erlang runtime system. - -\makesection{install.os}{Installing \ejabberd{} with Operating System Specific Packages} - -Some Operating Systems provide a specific \ejabberd{} package adapted to -the system architecture and libraries. -It usually also checks dependencies -and performs basic configuration tasks like creating the initial -administrator account. Some examples are Debian and Gentoo. Consult the -resources provided by your Operating System for more information. - -Usually those packages create a script like \term{/etc/init.d/ejabberd} -to start and stop \ejabberd{} as a service at boot time. - -\makesection{install.cean}{Installing \ejabberd{} with CEAN} - -\footahref{http://cean.process-one.net/}{CEAN} -(Comprehensive Erlang Archive Network) is a repository that hosts binary -packages from many Erlang programs, including \ejabberd{} and all its dependencies. -The binaries are available for many different system architectures, so this is an -alternative to the binary installer and Operating System's \ejabberd{} packages. - -You will have to create your own \ejabberd{} start -script depending of how you handle your CEAN installation. -The default \term{ejabberdctl} script is located -into \ejabberd{}'s priv directory and can be used as an example. - -\makesection{installation}{Installing \ejabberd{} from Source Code} -\ind{install} - -The canonical form for distribution of \ejabberd{} stable releases is the source code package. -Compiling \ejabberd{} from source code is quite easy in *nix systems, -as long as your system have all the dependencies. - -\makesubsection{installreq}{Requirements} -\ind{installation!requirements} - -To compile \ejabberd{} on a `Unix-like' operating system, you need: -\begin{itemize} -\item GNU Make -\item GCC -\item Libexpat 1.95 or higher -\item Erlang/OTP R15B or higher. -\item Libyaml 0.1.4 or higher -\item OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption. -\item Zlib 1.2.3 or higher, for Stream Compression support (\xepref{0138}). Optional. -\item PAM library. Optional. For Pluggable Authentication Modules (PAM). See section \ref{pam}. -\item GNU Iconv 1.8 or higher, for the IRC Transport (mod\_irc). Optional. Not needed on systems with GNU Libc. See section \ref{modirc}. -\item ImageMagick's Convert program. Optional. For CAPTCHA challenges. See section \ref{captcha}. -\end{itemize} - -\makesubsection{download}{Download Source Code} -\ind{install!download} - -Released versions of \ejabberd{} are available in the ProcessOne \ejabberd{} downloads page: -\ahrefurl{http://www.process-one.net/en/ejabberd/downloads} - -\ind{Git repository} -Alternatively, the latest development source code can be retrieved from the Git repository using the commands: -\begin{verbatim} -git clone git://github.com/processone/ejabberd.git ejabberd -cd ejabberd -./autogen.sh -\end{verbatim} - - -\makesubsection{compile}{Compile} -\ind{install!compile} - -To compile \ejabberd{} execute the commands: -\begin{verbatim} -./configure -make -\end{verbatim} - -The build configuration script allows several options. -To get the full list run the command: -\begin{verbatim} -./configure --help -\end{verbatim} - -Some options that you may be interested in modifying: -\begin{description} - \titem{--prefix=/} - Specify the path prefix where the files will be copied when running - the \term{make install} command. - - \titem{--enable-user[=USER]} - Allow this normal system user to execute the ejabberdctl script - (see section~\ref{ejabberdctl}), - read the configuration files, - read and write in the spool directory, - read and write in the log directory. - The account user and group must exist in the machine - before running \term{make install}. - This account doesn't need an explicit HOME directory, because - \term{/var/lib/ejabberd/} will be used by default. - - \titem{--enable-pam} - Enable the PAM authentication method (see section \ref{pam}). - - \titem{--enable-mssql} - Required if you want to use an external database. - See section~\ref{database} for more information. - - \titem{--enable-tools} - Enable the use of development tools. - - \titem{--enable-mysql} - Enable MySQL support (see section \ref{odbc}). - - \titem{--enable-pgsql} - Enable PostgreSQL support (see section \ref{odbc}). - - \titem{--enable-zlib} - Enable Stream Compression (XEP-0138) using zlib. - - \titem{--enable-iconv} - Enable iconv support. This is needed for \term{mod\_irc} (see seciont \ref{modirc}). - - \titem{--enable-debug} - Compile with \term{+debug\_info} enabled. - - \titem{--enable-full-xml} - Enable the use of XML based optimisations. - It will for example use CDATA to escape characters in the XMPP stream. - Use this option only if you are sure your XMPP clients include a fully compliant XML parser. - - \titem{--disable-transient-supervisors} - Disable the use of Erlang/OTP supervision for transient processes. - - \titem{--enable-nif} - Replaces some critical Erlang functions with equivalents written in C to improve performance. -\end{description} - -\makesubsection{install}{Install} -\ind{install!install} - -To install \ejabberd{} in the destination directories, run the command: -\begin{verbatim} -make install -\end{verbatim} -Note that you probably need administrative privileges in the system -to install \term{ejabberd}. - -The files and directories created are, by default: -\begin{description} - \titem{/etc/ejabberd/} Configuration directory: - \begin{description} - \titem{ejabberd.yml} ejabberd configuration file - \titem{ejabberdctl.cfg} Configuration file of the administration script - \titem{inetrc} Network DNS configuration file - \end{description} - \titem{/lib/ejabberd/} - \begin{description} - \titem{ebin/} Erlang binary files (*.beam) - \titem{include/} Erlang header files (*.hrl) - \titem{priv/} Additional files required at runtime - \begin{description} - \titem{bin/} Executable programs - \titem{lib/} Binary system libraries (*.so) - \titem{msgs/} Translation files (*.msgs) - \end{description} - \end{description} - \titem{/sbin/ejabberdctl} Administration script (see section~\ref{ejabberdctl}) - \titem{/share/doc/ejabberd/} Documentation of ejabberd - \titem{/var/lib/ejabberd/} Spool directory: - \begin{description} - \titem{.erlang.cookie} Erlang cookie file (see section \ref{cookie}) - \titem{acl.DCD, ...} Mnesia database spool files (*.DCD, *.DCL, *.DAT) - \end{description} - \titem{/var/log/ejabberd/} Log directory (see section~\ref{logfiles}): - \begin{description} - \titem{ejabberd.log} ejabberd service log - \titem{erlang.log} Erlang/OTP system log - \end{description} -\end{description} - - -\makesubsection{start}{Start} -\ind{install!start} - -You can use the \term{ejabberdctl} command line administration script to start and stop \ejabberd{}. -If you provided the configure option \term{--enable-user=USER} (see \ref{compile}), -you can execute \term{ejabberdctl} with either that system account or root. - -Usage example: -\begin{verbatim} -ejabberdctl start - -ejabberdctl status -The node ejabberd@localhost is started with status: started -ejabberd is running in that node - -ejabberdctl stop -\end{verbatim} - -If \term{ejabberd} doesn't start correctly and a crash dump is generated, -there was a severe problem. -You can try starting \term{ejabberd} with -the command \term{ejabberdctl live} -to see the error message provided by Erlang -and can identify what is exactly the problem. - -Please refer to the section~\ref{ejabberdctl} for details about \term{ejabberdctl}, -and configurable options to fine tune the Erlang runtime system. - -If you want ejabberd to be started as daemon at boot time, -copy \term{ejabberd.init} to something like \term{/etc/init.d/ejabberd} -(depending on your distribution). -Create a system user called \term{ejabberd}; -it will be used by the script to start the server. -Then you can call \term{/etc/inid.d/ejabberd start} as root to start the server. - -\makesubsection{bsd}{Specific Notes for BSD} -\ind{install!bsd} - -The command to compile \ejabberd{} in BSD systems is: -\begin{verbatim} -gmake -\end{verbatim} - - -\makesubsection{solaris}{Specific Notes for Sun Solaris} -\ind{install!solaris} - -You need to have \term{GNU install}, -but it isn't included in Solaris. -It can be easily installed if your Solaris system -is set up for \footahref{http://www.blastwave.org/}{blastwave.org} -package repository. -Make sure \term{/opt/csw/bin} is in your \term{PATH} and run: -\begin{verbatim} -pkg-get -i fileutils -\end{verbatim} - -If that program is called \term{ginstall}, -modify the \ejabberd{} \term{Makefile} script to suit your system, -for example: -\begin{verbatim} -cat Makefile | sed s/install/ginstall/ > Makefile.gi -\end{verbatim} -And finally install \ejabberd{} with: -\begin{verbatim} -gmake -f Makefile.gi ginstall -\end{verbatim} - - -\makesubsection{windows}{Specific Notes for Microsoft Windows} -\ind{install!windows} - -\makesubsubsection{windowsreq}{Requirements} - -To compile \ejabberd{} on a Microsoft Windows system, you need: -\begin{itemize} -\item MS Visual C++ 6.0 Compiler -\item \footahref{http://www.erlang.org/download.html}{Erlang/OTP R11B-5} -\item \footahref{http://sourceforge.net/project/showfiles.php?group\_id=10127\&package\_id=11277}{Expat 2.0.0 or higher} -\item -\footahref{http://www.gnu.org/software/libiconv/}{GNU Iconv 1.9.2} -(optional) -\item \footahref{http://www.slproweb.com/products/Win32OpenSSL.html}{Shining Light OpenSSL 0.9.8d or higher} -(to enable SSL connections) -\item \footahref{http://www.zlib.net/}{Zlib 1.2.3 or higher} -\end{itemize} - - -\makesubsubsection{windowscom}{Compilation} - -We assume that we will try to put as much library as possible into \verb|C:\sdk\| to make it easier to track what is install for \ejabberd{}. - -\begin{enumerate} -\item Install Erlang emulator (for example, into \verb|C:\sdk\erl5.5.5|). -\item Install Expat library into \verb|C:\sdk\Expat-2.0.0| - directory. - - Copy file \verb|C:\sdk\Expat-2.0.0\Libs\libexpat.dll| - to your Windows system directory (for example, \verb|C:\WINNT| or - \verb|C:\WINNT\System32|) -\item Build and install the Iconv library into the directory - \verb|C:\sdk\GnuWin32|. - - Copy file \verb|C:\sdk\GnuWin32\bin\lib*.dll| to your - Windows system directory (more installation instructions can be found in the - file README.woe32 in the iconv distribution). - - Note: instead of copying libexpat.dll and iconv.dll to the Windows - directory, you can add the directories - \verb|C:\sdk\Expat-2.0.0\Libs| and - \verb|C:\sdk\GnuWin32\bin| to the \verb|PATH| environment - variable. -\item Install OpenSSL in \verb|C:\sdk\OpenSSL| and add \verb|C:\sdk\OpenSSL\lib\VC| to your path or copy the binaries to your system directory. -\item Install ZLib in \verb|C:\sdk\gnuWin32|. Copy - \verb|C:\sdk\GnuWin32\bin\zlib1.dll| to your system directory. If you change your path it should already be set after libiconv install. -\item Make sure the you can access Erlang binaries from your path. For example: \verb|set PATH=%PATH%;"C:\sdk\erl5.6.5\bin"| -\item Depending on how you end up actually installing the library you might need to check and tweak the paths in the file configure.erl. -\item While in the directory \verb|ejabberd\src| run: -\begin{verbatim} -configure.bat -nmake -f Makefile.win32 -\end{verbatim} -\item Edit the file \verb|ejabberd\src\ejabberd.yml| and run -\begin{verbatim} -werl -s ejabberd -name ejabberd -\end{verbatim} -\end{enumerate} - -%TODO: how to compile database support on windows? - - -\makesection{initialadmin}{Create an XMPP Account for Administration} - -You need an XMPP account and grant him administrative privileges -to enter the \ejabberd{} Web Admin: -\begin{enumerate} -\item Register an XMPP account on your \ejabberd{} server, for example \term{admin1@example.org}. - There are two ways to register an XMPP account: - \begin{enumerate} - \item Using \term{ejabberdctl}\ind{ejabberdctl} (see section~\ref{ejabberdctl}): -\begin{verbatim} -ejabberdctl register admin1 example.org FgT5bk3 -\end{verbatim} - \item Using an XMPP client and In-Band Registration (see section~\ref{modregister}). - \end{enumerate} -\item Edit the \ejabberd{} configuration file to give administration rights to the XMPP account you created: -\begin{verbatim} -acl: - admin: - user: - - "admin1": "example.org" -access: - configure: - admin: allow -\end{verbatim} - You can grant administrative privileges to many XMPP accounts, - and also to accounts in other XMPP servers. -\item Restart \ejabberd{} to load the new configuration. -\item Open the Web Admin (\verb|http://server:port/admin/|) in your - favourite browser. Make sure to enter the \emph{full} JID as username (in this - example: \jid{admin1@example.org}. The reason that you also need to enter the - suffix, is because \ejabberd{}'s virtual hosting support. -\end{enumerate} - -\makesection{upgrade}{Upgrading \ejabberd{}} - -To upgrade an ejabberd installation to a new version, -simply uninstall the old version, and then install the new one. -Of course, it is important that the configuration file -and Mnesia database spool directory are not removed. - -\ejabberd{} automatically updates the Mnesia table definitions at startup when needed. -If you also use an external database for storage of some modules, -check if the release notes of the new ejabberd version -indicates you need to also update those tables. - - -\makechapter{configure}{Configuring \ejabberd{}} -\ind{configuration file} - -\makesection{basicconfig}{Basic Configuration} - -The configuration file will be loaded the first time you start \ejabberd{}. -The configuration file name MUST have ``.yml'' extension. This helps ejabberd -to differentiate between the new and legacy file formats (see section~\ref{oldconfig}). - -Note that \ejabberd{} never edits the configuration file. - -The configuration file is written in -\footahref{http://en.wikipedia.org/wiki/YAML}{YAML}. -However, different scalars are treated as different types: -\begin{itemize} -\item unquoted or single-quoted strings. The type is called \verb|atom()| - in this document. - Examples: \verb|dog|, \verb|'Jupiter'|, \verb|'3.14159'|, \verb|YELLOW|. -\item numeric literals. The type is called \verb|integer()|, \verb|float()| or, - if both are allowed, \verb|number()|. - Examples: \verb|3|, \verb|-45.0|, \verb|.0| -\item double-quoted or folded strings. The type is called \verb|string()|. - Examples of a double-quoted string: - \verb|"Lizzard"|, \verb|"orange"|, \verb|"3.14159"|. - Examples of a folded string: -\begin{verbatim} -> Art thou not Romeo, - and a Montague? -\end{verbatim} -\begin{verbatim} -| Neither, fair saint, - if either thee dislike. -\end{verbatim} -For associative arrays ("mappings") and lists you can use both outline -indentation and compact syntax (aka ``JSON style''). For example, the following is equivalent: -\begin{verbatim} -{param1: ["val1", "val2"], param2: ["val3", "val4"]} -\end{verbatim} -and -\begin{verbatim} -param1: - - "val1" - - "val2" -param2: - - "val3" - - "val4" -\end{verbatim} -Note that both styles are used in this document. -\end{itemize} - -\makesubsection{oldconfig}{Legacy Configuration File} -In previous \ejabberd{} version the configuration file should be written -in Erlang terms. The format is still supported, but it is highly recommended -to convert it to the new YAML format using \term{convert\_to\_yaml} command -from \term{ejabberdctl} (see~\ref{ejabberdctl} and \ref{list-eja-commands} for details). - -If you want to specify some options using the old Erlang format, -you can set them in an additional cfg file, and include it using -the \option{include\_config\_file} option, see \ref{includeconfigfile} -for the option description and a related example in \ref{accesscommands}. - -If you just want to provide an erlang term inside an option, -you can use the \term{"> erlangterm."} syntax for embedding erlang terms in a YAML file, for example: -\begin{verbatim} -modules: - mod_cron: - tasks: - - time: 10 - units: seconds - module: mnesia - function: info - arguments: "> []." - - time: 3 - units: seconds - module: ejabberd_auth - function: try_register - arguments: "> [\"user1\", \"localhost\", \"pass\"]." -\end{verbatim} - -\makesubsection{hostnames}{Host Names} -\ind{options!hosts}\ind{host names} - -The option \option{hosts} defines a list containing one or more domains that -\ejabberd{} will serve. - -The syntax is: -\esyntax{[HostName]} - -Examples: -\begin{itemize} -\item Serving one domain: -\begin{verbatim} -hosts: ["example.org"] -\end{verbatim} -\item Serving three domains: -\begin{verbatim} -hosts: - - "example.net" - - "example.com" - - "jabber.somesite.org" -\end{verbatim} -\end{itemize} - -\makesubsection{virtualhost}{Virtual Hosting} -\ind{virtual hosting}\ind{virtual hosts}\ind{virtual domains} - -Options can be defined separately for every virtual host using the -\term{host\_config} option. - -The syntax is: \ind{options!host\_config} -\esyntax{\{HostName: [Option, ...]\}} - -Examples: -\begin{itemize} -\item Domain \jid{example.net} is using the internal authentication method while - domain \jid{example.com} is using the \ind{LDAP}LDAP server running on the - domain \jid{localhost} to perform authentication: -\begin{verbatim} -host_config: - "example.net" - auth_method: internal - "example.com": - auth_method: ldap - ldap_servers: - - "localhost" - ldap_uids: - - "uid" - ldap_rootdn: "dc=localdomain" - ldap_rootdn: "dc=example,dc=com" - ldap_password: "" -\end{verbatim} -\item Domain \jid{example.net} is using \ind{odbc}ODBC to perform authentication - while domain \jid{example.com} is using the LDAP servers running on the domains - \jid{localhost} and \jid{otherhost}: -\begin{verbatim} -host_config: - "example.net": - auth_method: odbc - odbc_type: odbc - odbc_server: "DSN=ejabberd;UID=ejabberd;PWD=ejabberd" - "example.com": - auth_method: ldap - ldap_servers: - - "localhost" - - "otherhost" - ldap_uids: - - "uid" - ldap_rootdn: "dc=localdomain" - ldap_rootdn: "dc=example,dc=com" - ldap_password: "" -\end{verbatim} -\end{itemize} - -To define specific ejabberd modules in a virtual host, -you can define the global \term{modules} option with the common modules, -and later add specific modules to certain virtual hosts. -To accomplish that, instead of defining each option in \term{host\_config} -use \term{append\_host\_config} with the same syntax. - -In this example three virtual hosts have some similar modules, but there are also -other different modules for some specific virtual hosts: -\begin{verbatim} -## This ejabberd server has three vhosts: -hosts: - - "one.example.org" - - "two.example.org" - - "three.example.org" - -## Configuration of modules that are common to all vhosts -modules: - mod_roster: {} - mod_configure: {} - mod_disco: {} - mod_private: {} - mod_time: {} - mod_last: {} - mod_version: {} - -## Add some modules to vhost one: -append_host_config: - "one.example.org": - modules: - mod_echo: - host: "echo-service.one.example.org" - mod_http_bind: {} - mod_logxml: {} - -## Add a module just to vhost two: -append_host_config: - "two.example.org": - modules: - mod_echo: - host: "mirror.two.example.org" -\end{verbatim} - -\makesubsection{listened}{Listening Ports} -\ind{options!listen} - -The option \option{listen} defines for which ports, addresses and network protocols \ejabberd{} -will listen and what services will be run on them. Each element of the list is an -associative array with the following elements: -\begin{itemize} -\item Port number. Optionally also the IP address and/or a transport protocol. -\item Listening module that serves this port. -\item Options for the TCP socket and for the listening module. -\end{itemize} - -The option syntax is: -\esyntax{[Listener, ...]} -Example: -\begin{verbatim} -listen: - - - port: 5222 - module: ejabberd_c2s - starttls: true - certfile: "/path/to/certfile.pem" - - - port: 5269 - module: ejabberd_s2s_in - transport: tcp -\end{verbatim} - -\makesubsubsection{listened-port}{Port Number, IP Address and Transport Protocol} - -The port number defines which port to listen for incoming connections. -It can be a Jabber/XMPP standard port -(see section \ref{firewall}) or any other valid port number. - -The IP address can be represented as a string. -The socket will listen only in that network interface. -It is possible to specify a generic address, -so \ejabberd{} will listen in all addresses. -Depending in the type of the IP address, IPv4 or IPv6 will be used. -When not specified the IP address, it will listen on all IPv4 network addresses. - -Some example values for IP address: -\begin{itemize} -\item \verb|"0.0.0.0"| to listen in all IPv4 network interfaces. This is the default value when no IP is specified. -\item \verb|"::"| to listen in all IPv6 network interfaces -\item \verb|"10.11.12.13"| is the IPv4 address \verb|10.11.12.13| -\item \verb|"::FFFF:127.0.0.1"| is the IPv6 address \verb|::FFFF:127.0.0.1/128| -\end{itemize} - -The transport protocol can be \term{tcp} or \term{udp}. -Default is \term{tcp}. - - -\makesubsubsection{listened-module}{Listening Module} - -\ind{modules!ejabberd\_c2s}\ind{modules!ejabberd\_s2s\_in}\ind{modules!ejabberd\_service}\ind{modules!ejabberd\_http}\ind{protocols!XEP-0114: Jabber Component Protocol} -The available modules, their purpose and the options allowed by each one are: -\begin{description} - \titem{\texttt{ejabberd\_c2s}} - Handles c2s connections.\\ - Options: \texttt{access}, \texttt{certfile}, \texttt{ciphers}, \texttt{protocol\_options} - \texttt{max\_ack\_queue}, \texttt{max\_fsm\_queue}, - \texttt{max\_stanza\_size}, \texttt{resend\_on\_timeout}, - \texttt{resume\_timeout}, \texttt{shaper}, - \texttt{starttls}, \texttt{starttls\_required}, - \texttt{stream\_management}, \texttt{tls}, - \texttt{zlib}, \texttt{tls\_compression} - \titem{\texttt{ejabberd\_s2s\_in}} - Handles incoming s2s connections.\\ - Options: \texttt{max\_stanza\_size}, \texttt{shaper}, \texttt{tls\_compression} - \titem{\texttt{ejabberd\_service}} - Interacts with an \footahref{http://www.ejabberd.im/tutorials-transports}{external component} - (as defined in the Jabber Component Protocol (\xepref{0114}).\\ - Options: \texttt{access}, \texttt{hosts}, \texttt{max\_fsm\_queue}, - \texttt{service\_check\_from}, \texttt{shaper\_rule} - \titem{\texttt{ejabberd\_sip}} - Handles SIP requests as defined in - \footahref{http://tools.ietf.org/html/rfc3261}{RFC 3261}.\\ - Options: \texttt{certfile}, \texttt{tls} - \titem{\texttt{ejabberd\_stun}} - Handles STUN/TURN requests as defined in - \footahref{http://tools.ietf.org/html/rfc5389}{RFC 5389} and - \footahref{http://tools.ietf.org/html/rfc5766}{RFC 5766}.\\ - Options: \texttt{certfile}, \texttt{tls}, \texttt{use\_turn}, \texttt{turn\_ip}, - \texttt{turn\_port\_range}, \texttt{turn\_max\_allocations}, - \texttt{turn\_max\_permissions}, \texttt{shaper}, \texttt{server\_name}, - \texttt{auth\_realm}, \texttt{auth\_type} - \titem{\texttt{ejabberd\_http}} - Handles incoming HTTP connections.\\ - Options: \texttt{captcha}, \texttt{certfile}, \texttt{default\_host}, \texttt{http\_bind}, \texttt{http\_poll}, - \texttt{request\_handlers}, \texttt{tls}, \texttt{tls\_compression}, \texttt{trusted\_proxies}, \texttt{web\_admin}\\ - \titem{\texttt{ejabberd\_xmlrpc}} - Handles XML-RPC requests to execute ejabberd commands (\ref{eja-commands}).\\ - Options: \texttt{access\_commands}, \texttt{maxsessions}, \texttt{timeout}.\\ - You can find option explanations, example configuration in old and new format, - and example calls in several languages in the old - \footahref{http://www.ejabberd.im/ejabberd\_xmlrpc}{ejabberd\_xmlrpc documentation}. -\end{description} - - -\makesubsubsection{listened-options}{Options} - -This is a detailed description of each option allowed by the listening modules: -\begin{description} - \titem{access: AccessName} \ind{options!access}This option defines - access to the port. The default value is \term{all}. - \titem{backlog: Value} \ind{options!backlog}The backlog value - defines the maximum length that the queue of pending connections may - grow to. This should be increased if the server is going to handle - lots of new incoming connections as they may be dropped if there is - no space in the queue (and ejabberd was not able to accept them - immediately). Default value is 5. - \titem{captcha: true|false} \ind{options!http-captcha} - Simple web page that allows a user to fill a CAPTCHA challenge (see section \ref{captcha}). - \titem{certfile: Path} Full path to a file containing the default SSL certificate. - To define a certificate file specific for a given domain, use the global option \term{domain\_certfile}. - \titem{ciphers: Ciphers} OpenSSL ciphers list in the same format accepted by - `\verb|openssl ciphers|' command. - \titem{protocol\_options: ProtocolOpts} \ind{options!protocol\_options} - List of general options relating to SSL/TLS. These map to - \footahref{https://www.openssl.org/docs/ssl/SSL\_CTX\_set\_options.html}{OpenSSL's set\_options()}. - For a full list of options available in ejabberd, - \footahref{https://github.com/processone/tls/blob/master/c\_src/options.h}{see the source}. - The default entry is: \verb|"no_sslv2"| - \titem{default\_host: undefined|HostName\}} - If the HTTP request received by ejabberd contains the HTTP header \term{Host} - with an ambiguous virtual host that doesn't match any one defined in ejabberd (see \ref{hostnames}), - then this configured HostName is set as the request Host. - The default value of this option is: \term{undefined}. - \titem{hosts: \{Hostname: [HostOption, ...]\}}\ind{options!hosts} - The external Jabber component that connects to this \term{ejabberd\_service} - can serve one or more hostnames. - As \term{HostOption} you can define options for the component; - currently the only allowed option is the password required to the component - when attempt to connect to ejabberd: \poption{password: Secret}. - Note that you cannot define in a single \term{ejabberd\_service} components of - different services: add an \term{ejabberd\_service} for each service, - as seen in an example below. - \titem{http\_bind: true|false} \ind{options!http\_bind}\ind{protocols!XEP-0206: HTTP Binding}\ind{JWChat}\ind{web-based XMPP client} - This option enables HTTP Binding (\xepref{0124} and \xepref{0206}) support. HTTP Bind - enables access via HTTP requests to \ejabberd{} from behind firewalls which - do not allow outgoing sockets on port 5222. - - Remember that you must also install and enable the module mod\_http\_bind. - - If HTTP Bind is enabled, it will be available at - \verb|http://server:port/http-bind/|. Be aware that support for HTTP Bind - is also needed in the \XMPP{} client. Remark also that HTTP Bind can be - interesting to host a web-based \XMPP{} client such as - \footahref{http://jwchat.sourceforge.net/}{JWChat} - (check the tutorials to install JWChat with ejabberd and an - \footahref{http://www.ejabberd.im/jwchat-localserver}{embedded local web server} - or \footahref{http://www.ejabberd.im/jwchat-apache}{Apache}). - \titem{http\_poll: true|false} \ind{options!http\_poll}\ind{protocols!XEP-0025: HTTP Polling}\ind{JWChat}\ind{web-based XMPP client} - This option enables HTTP Polling (\xepref{0025}) support. HTTP Polling - enables access via HTTP requests to \ejabberd{} from behind firewalls which - do not allow outgoing sockets on port 5222. - - If HTTP Polling is enabled, it will be available at - \verb|http://server:port/http-poll/|. Be aware that support for HTTP Polling - is also needed in the \XMPP{} client. Remark also that HTTP Polling can be - interesting to host a web-based \XMPP{} client such as - \footahref{http://jwchat.sourceforge.net/}{JWChat}. - - The maximum period of time to keep a client session active without - an incoming POST request can be configured with the global option - \term{http\_poll\_timeout}. The default value is five minutes. - The option can be defined in \term{ejabberd.yml}, expressing the time - in seconds: \verb|{http_poll_timeout, 300}.| - \titem{max\_ack\_queue: Size} - This option specifies the maximum number of unacknowledged stanzas - queued for possible retransmission if \term{stream\_management} is - enabled. When the limit is exceeded, the client session is - terminated. This option can be specified for \term{ejabberd\_c2s} - listeners. The allowed values are positive integers and - \term{infinity}. Default value: \term{500}. - \titem{max\_fsm\_queue: Size} - This option specifies the maximum number of elements in the queue of the FSM - (Finite State Machine). - Roughly speaking, each message in such queues represents one XML - stanza queued to be sent into its relevant outgoing stream. If queue size - reaches the limit (because, for example, the receiver of stanzas is too slow), - the FSM and the corresponding connection (if any) will be terminated - and error message will be logged. - The reasonable value for this option depends on your hardware configuration. - However, there is no much sense to set the size above 1000 elements. - This option can be specified for \term{ejabberd\_service} and - \term{ejabberd\_c2s} listeners, - or also globally for \term{ejabberd\_s2s\_out}. - If the option is not specified for \term{ejabberd\_service} or - \term{ejabberd\_c2s} listeners, - the globally configured value is used. - The allowed values are integers and 'undefined'. - Default value: 'undefined'. - \titem{max\_stanza\_size: Size} - \ind{options!max\_stanza\_size}This option specifies an - approximate maximum size in bytes of XML stanzas. Approximate, - because it is calculated with the precision of one block of read - data. For example \verb|{max_stanza_size, 65536}|. The default - value is \term{infinity}. Recommended values are 65536 for c2s - connections and 131072 for s2s connections. s2s max stanza size - must always much higher than c2s limit. Change this value with - extreme care as it can cause unwanted disconnect if set too low. - \titem{request\_handlers: \{Path: Module\}} To define one or several handlers that will serve HTTP requests. - The Path is a string; so the URIs that start with that Path will be served by Module. - For example, if you want \term{mod\_foo} to serve the URIs that start with \term{/a/b/}, - and you also want \term{mod\_http\_bind} to serve the URIs \term{/http-bind/}, - use this option: -\begin{verbatim} -request_handlers: - /"a"/"b": mod_foo - /"http-bind": mod_http_bind -\end{verbatim} - \titem{resend\_on\_timeout: true|false|if\_offline} - If \term{stream\_management} is enabled and this option is set to - \term{true}, any stanzas that weren't acknowledged by the client - will be resent on session timeout. This behavior might often be - desired, but could have unexpected results under certain - circumstances. For example, a message that was sent to two resources - might get resent to one of them if the other one timed out. - Therefore, the default value for this option is \term{false}, which - tells ejabberd to generate an error message instead. As an - alternative, the option may be set to \term{if\_offline}. In this - case, unacknowledged stanzas are resent only if no other resource is - online when the session times out. Otherwise, error messages are - generated. The option can be specified for \term{ejabberd\_c2s} - listeners. - \titem{resume\_timeout: Seconds} - This option configures the number of seconds until a session times - out if the connection is lost. During this period of time, a client - may resume the session if \term{stream\_management} is enabled. This - option can be specified for \term{ejabberd\_c2s} listeners. Setting - it to \term{0} effectively disables session resumption. The default - value is \term{300}. - \titem{service\_check\_from: true|false} - \ind{options!service\_check\_from} - This option can be used with \term{ejabberd\_service} only. - \xepref{0114} requires that the domain must match the hostname of the component. - If this option is set to \term{false}, \ejabberd{} will allow the component - to send stanzas with any arbitrary domain in the 'from' attribute. - Only use this option if you are completely sure about it. - The default value is \term{true}, to be compliant with \xepref{0114}. - \titem{shaper: none|ShaperName} \ind{options!shaper}This option defines a - shaper for the port (see section~\ref{shapers}). The default value - is \term{none}. - \titem{shaper\_rule: none|ShaperRule} \ind{options!shaperrule}This option defines a - shaper rule for the \term{ejabberd\_service} (see section~\ref{shapers}). The recommended value - is \term{fast}. - \titem{starttls: true|false} \ind{options!starttls}\ind{STARTTLS}This option - specifies that STARTTLS encryption is available on connections to the port. - You should also set the \option{certfile} option. - You can define a certificate file for a specific domain using the global option \option{domain\_certfile}. - \titem{starttls\_required: true|false} \ind{options!starttls\_required}This option - specifies that STARTTLS encryption is required on connections to the port. - No unencrypted connections will be allowed. - You should also set the \option{certfile} option. - You can define a certificate file for a specific domain using the global option \option{domain\_certfile}. - \titem{stream\_management: true|false} - Setting this option to \term{false} disables ejabberd's support for - Stream Management (\xepref{0198}). It can be specified for - \term{ejabberd\_c2s} listeners. The default value is \term{true}. - \titem{timeout: Integer} \ind{options!timeout} - Timeout of the connections, expressed in milliseconds. - Default: 5000 - \titem{tls: true|false} \ind{options!tls}\ind{TLS}This option specifies that traffic on - the port will be encrypted using SSL immediately after connecting. - This was the traditional encryption method in the early Jabber software, - commonly on port 5223 for client-to-server communications. - But this method is nowadays deprecated and not recommended. - The preferable encryption method is STARTTLS on port 5222, as defined - \footahref{http://xmpp.org/rfcs/rfc6120.html\#tls}{RFC 6120: XMPP Core}, - which can be enabled in \ejabberd{} with the option \term{starttls}. - If this option is set, you should also set the \option{certfile} option. - The option \term{tls} can also be used in \term{ejabberd\_http} to support HTTPS. - \titem{tls\_compression: true|false} - Whether to enable or disable TLS compression. The default value is \term{true}. - \titem{trusted\_proxies: all | [IpString]} \ind{options!trusted\_proxies} - Specify what proxies are trusted when an HTTP request contains the header \term{X-Forwarded-For} - You can specify \term{all} to allow all proxies, or specify a list of IPs in string format. - The default value is: \term{["127.0.0.1"]} - \titem{web\_admin: true|false} \ind{options!web\_admin}\ind{web admin}This option - enables the Web Admin for \ejabberd{} administration which is available - at \verb|http://server:port/admin/|. Login and password are the username and - password of one of the registered users who are granted access by the - `configure' access rule. - \titem{zlib: true|false} \ind{options!zlib}\ind{protocols!XEP-0138: Stream Compression}\ind{Zlib}This - option specifies that Zlib stream compression (as defined in \xepref{0138}) - is available on connections to the port. -\end{description} - -There are some additional global options that can be specified in the ejabberd configuration file (outside \term{listen}): -\begin{description} - \titem{s2s\_use\_starttls: false|optional|required|required\_trusted} - \ind{options!s2s\_use\_starttls}\ind{STARTTLS}This option defines if - s2s connections don't use STARTTLS encryption; if STARTTLS can be used optionally; - if STARTTLS is required to establish the connection; - or if STARTTLS is required and the remote certificate must be valid and trusted. - The default value is to not use STARTTLS: \term{false}. - \titem{s2s\_certfile: Path} \ind{options!s2s\_certificate}Full path to a - file containing a SSL certificate. - \titem{domain\_certfile: Path} \ind{options!domain\_certfile} - Full path to the file containing the SSL certificate for a specific domain. - \titem{s2s\_ciphers: Ciphers} \ind{options!s2s\_ciphers} OpenSSL ciphers list - in the same format accepted by `\verb|openssl ciphers|' command. - \titem{s2s\_protocol\_options: ProtocolOpts} \ind{options!s2s\_protocol\_options} - List of general options relating to SSL/TLS. These map to - \footahref{https://www.openssl.org/docs/ssl/SSL\_CTX\_set\_options.html}{OpenSSL's set\_options()}. - For a full list of options available in ejabberd, - \footahref{https://github.com/processone/tls/blob/master/c\_src/options.h}{see the source}. - The default entry is: \verb|"no_sslv2"| - \titem{outgoing\_s2s\_families: [Family, ...]} \ind{options!outgoing\_s2s\_families} - Specify which address families to try, in what order. - By default it first tries connecting with IPv4, if that fails it tries using IPv6. - \titem{outgoing\_s2s\_timeout: Timeout} \ind{options!outgoing\_s2s\_timeout} - The timeout in milliseconds for outgoing S2S connection attempts. - \titem{s2s\_dns\_timeout: Timeout} \ind{options!s2s\_dns\_timeout} - The timeout in seconds for DNS resolving. The default value is \term{10}. - \titem{s2s\_dns\_retries: Number} \ind{options!s2s\_dns\_retries} - DNS resolving retries in seconds. The default value is \term{2}. - \titem{s2s\_policy: Access} \ind{options!s2s\_policy} - The policy for incoming and outgoing s2s connections to other XMPP servers. - The default value is \term{all}. - \titem{s2s\_max\_retry\_delay: Seconds} \ind{options!s2s\_max\_retry\_delay} - The maximum allowed delay for retry to connect after a failed connection attempt. - Specified in seconds. The default value is 300 seconds (5 minutes). - \titem{s2s\_tls\_compression: true|false} - Whether to enable or disable TLS compression for s2s connections. - The default value is \term{true}. - \titem{max\_fsm\_queue: Size} - This option specifies the maximum number of elements in the queue of the FSM - (Finite State Machine). - Roughly speaking, each message in such queues represents one XML - stanza queued to be sent into its relevant outgoing stream. If queue size - reaches the limit (because, for example, the receiver of stanzas is too slow), - the FSM and the corresponding connection (if any) will be terminated - and error message will be logged. - The reasonable value for this option depends on your hardware configuration. - However, there is no much sense to set the size above 1000 elements. - This option can be specified for \term{ejabberd\_service} and - \term{ejabberd\_c2s} listeners, - or also globally for \term{ejabberd\_s2s\_out}. - If the option is not specified for \term{ejabberd\_service} or - \term{ejabberd\_c2s} listeners, - the globally configured value is used. - The allowed values are integers and 'undefined'. - Default value: 'undefined'. - \titem{route\_subdomains: local|s2s} - Defines if ejabberd must route stanzas directed to subdomains locally (compliant with - \footahref{http://xmpp.org/rfcs/rfc6120.html\#rules-local}{RFC 6120 Local Domain rules}), - or to foreign server using S2S (compliant with - \footahref{http://xmpp.org/rfcs/rfc6120.html\#rules-remote}{RFC 6120 Remote Domain rules}). -\end{description} - -\makesubsubsection{listened-examples}{Examples} - -For example, the following simple configuration defines: -\begin{itemize} -\item There are three domains. The default certificate file is \term{server.pem}. -However, the c2s and s2s connections to the domain \term{example.com} use the file \term{example\_com.pem}. -\item Port 5222 listens for c2s connections with STARTTLS, - and also allows plain connections for old clients. -\item Port 5223 listens for c2s connections with the old SSL. -\item Port 5269 listens for s2s connections with STARTTLS. The socket is set for IPv6 instead of IPv4. -\item Port 3478 listens for STUN requests over UDP. -\item Port 5280 listens for HTTP requests, and serves the HTTP Poll service. -\item Port 5281 listens for HTTP requests, using HTTPS to serve HTTP-Bind (BOSH) and the Web Admin as explained in - section~\ref{webadmin}. The socket only listens connections to the IP address 127.0.0.1. -\end{itemize} -\begin{verbatim} -hosts: - - "example.com" - - "example.org" - - "example.net" - -listen: - - - port: 5222 - module: ejabberd_c2s - access: c2s - shaper: c2s_shaper - starttls: true - certfile: "/etc/ejabberd/server.pem" - max_stanza_size: 65536 - - - port: 5223 - module: ejabberd_c2s - access: c2s - shaper: c2s_shaper - tls: true - certfile: "/etc/ejabberd/server.pem" - max_stanza_size: 65536 - - - port: 5269 - ip: "::" - module: ejabberd_s2s_in - shaper: s2s_shaper - max_stanza_size: 131072 - - - port: 3478 - transport: udp - module: ejabberd_stun - - - port: 5280 - module: ejabberd_http - http_poll: true - - - port: 5281 - ip: "127.0.0.1" - module: ejabberd_http - web_admin: true - http_bind: true - tls: true - certfile: "/etc/ejabberd/server.pem" - -s2s_use_starttls: optional -s2s_certfile: "/etc/ejabberd/server.pem" -host_config: - "example.com": - domain_certfile: "/etc/ejabberd/example_com.pem" -outgoing_s2s_families: - - ipv4 - - ipv6 -outgoing_s2s_timeout: 10000 -\end{verbatim} - -In this example, the following configuration defines that: -\begin{itemize} -\item c2s connections are listened for on port 5222 (all IPv4 addresses) and - on port 5223 (SSL, IP 192.168.0.1 and fdca:8ab6:a243:75ef::1) and denied - for the user called `\term{bad}'. -\item s2s connections are listened for on port 5269 (all IPv4 addresses) - with STARTTLS for secured traffic strictly required, and the certificates are verified. - Incoming and outgoing connections of remote XMPP servers are denied, - only two servers can connect: "jabber.example.org" and "example.com". -\item Port 5280 is serving the Web Admin and the HTTP Polling service - in all the IPv4 addresses. Note - that it is also possible to serve them on different ports. The second - example in section~\ref{webadmin} shows how exactly this can be done. -\item All users except for the administrators have a traffic of limit - 1,000\,Bytes/second -\item \ind{transports!AIM}The - \footahref{http://www.ejabberd.im/pyaimt}{AIM transport} - \jid{aim.example.org} is connected to port 5233 on localhost IP addresses - (127.0.0.1 and ::1) with password `\term{aimsecret}'. -\item \ind{transports!ICQ}The ICQ transport JIT (\jid{icq.example.org} and - \jid{sms.example.org}) is connected to port 5234 with password - `\term{jitsecret}'. -\item \ind{transports!MSN}The - \footahref{http://www.ejabberd.im/pymsnt}{MSN transport} - \jid{msn.example.org} is connected to port 5235 with password - `\term{msnsecret}'. -\item \ind{transports!Yahoo}The - \footahref{http://www.ejabberd.im/yahoo-transport-2}{Yahoo! transport} - \jid{yahoo.example.org} is connected to port 5236 with password - `\term{yahoosecret}'. -\item \ind{transports!Gadu-Gadu}The \footahref{http://www.ejabberd.im/jabber-gg-transport}{Gadu-Gadu transport} \jid{gg.example.org} is - connected to port 5237 with password `\term{ggsecret}'. -\item \ind{transports!email notifier}The - \footahref{http://www.ejabberd.im/jmc}{Jabber Mail Component} - \jid{jmc.example.org} is connected to port 5238 with password - `\term{jmcsecret}'. -\item The service custom has enabled the special option to avoiding checking the \term{from} attribute in the packets send by this component. The component can send packets in behalf of any users from the server, or even on behalf of any server. -\end{itemize} -\begin{verbatim} -acl: - blocked: - user: "bad" - trusted_servers: - server: - - "example.com" - - "jabber.example.org" - xmlrpc_bot: - user: - - "xmlrpc-robot": "example.org" -shaper: - normal: 1000 -access: - c2s: - blocked: deny - all: allow - c2s_shaper: - admin: none - all: normal - xmlrpc_access: - xmlrpc_bot: allow - s2s: - trusted_servers: allow - all: deny -s2s_certfile: "/path/to/ssl.pem" -s2s_access: s2s -s2s_use_starttls: required_trusted -listen: - - - port: 5222 - module: ejabberd_c2s - shaper: c2s_shaper - access: c2s - - - ip: "192.168.0.1" - port: 5223 - module: ejabberd_c2s - certfile: "/path/to/ssl.pem" - tls: true - access: c2s - - - ip: "FDCA:8AB6:A243:75EF::1" - port: 5223 - module: ejabberd_c2s - certfile: "/path/to/ssl.pem" - tls: true - access: c2s - - - port: 5269 - module: ejabberd_s2s_in - - - port: 5280 - module: ejabberd_http - web_admin: true - http_poll: true - - - port: 4560 - module: ejabberd_xmlrpc - - - ip: "127.0.0.1" - port: 5233 - module: ejabberd_service - hosts: - "aim.example.org": - password: "aimsecret" - - - ip: "::1" - port: 5233 - module: ejabberd_service - hosts: - "aim.example.org": - password: "aimsecret" - - - port: 5234 - module: ejabberd_service - hosts: - "icq.example.org": - password: "jitsecret" - "sms.example.org": - password: "jitsecret" - - - port: 5235 - module: ejabberd_service - hosts: - "msn.example.org": - password: "msnsecret" - - - port: 5236 - module: ejabberd_service - hosts: - "yahoo.example.org": - password: "yahoosecret" - - - port: 5237 - module: ejabberd_service - hosts: - "gg.example.org": - password: "ggsecret" - - - port: 5238 - module: ejabberd_service - hosts: - "jmc.example.org": - password: "jmcsecret" - - - port: 5239 - module: ejabberd_service - service_check_from: false - hosts: - "custom.example.org": - password: "customsecret" -\end{verbatim} -Note, that for services based in \ind{jabberd14}jabberd14 or \ind{WPJabber}WPJabber -you have to make the transports log and do \ind{XDB}XDB by themselves: -\begin{verbatim} - - - - - - %d: [%t] (%h): %s - /var/log/jabber/service.log - - - - - - - - - /usr/lib/jabber/xdb_file.so - - - /var/spool/jabber - - -\end{verbatim} - -\makesubsection{auth}{Authentication} -\ind{authentication}\ind{options!auth\_method} - -The option \option{auth\_method} defines the authentication methods that are used -for user authentication. The syntax is: -\esyntax{[Method, ...]} - -The following authentication methods are supported by \ejabberd{}: -\begin{itemize} -\item internal (default) --- See section~\ref{internalauth}. -\item external --- See section~\ref{extauth}. -\item ldap --- See section~\ref{ldap}. -\item odbc --- See section~\ref{odbc}. -\item anonymous --- See section~\ref{saslanonymous}. -\item pam --- See section~\ref{pam}. -\end{itemize} - -Account creation is only supported by internal, external and odbc methods. - -The option \option{resource\_conflict} defines the action when a client attempts to -login to an account with a resource that is already connected. -The option syntax is: -\esyntax{resource\_conflict: setresource|closenew|closeold} -The possible values match exactly the three possibilities described in -\footahref{http://tools.ietf.org/html/rfc6120\#section-7.7.2.2}{XMPP Core: section 7.7.2.2}. -The default value is \term{closeold}. -If the client uses old Jabber Non-SASL authentication (\xepref{0078}), -then this option is not respected, and the action performed is \term{closeold}. - -The option \option{fqdn} allows you to define the Fully Qualified Domain Name -of the machine, in case it isn't detected automatically. -The FQDN is used to authenticate some clients that use the DIGEST-MD5 SASL mechanism. -The option syntax is: -\esyntax{fqdn: undefined|FqdnString|[FqdnString]} - -The option \option{disable\_sasl\_mechanisms} specifies a list of SASL -mechanisms that should \emph{not} be offered to the client. The mechanisms can -be listed as lowercase or uppercase strings. The option syntax is: -\esyntax{disable\_sasl\_mechanisms: [Mechanism, ...]} - -\makesubsubsection{internalauth}{Internal} -\ind{internal authentication}\ind{Mnesia} - -\ejabberd{} uses its internal Mnesia database as the default authentication method. -The value \term{internal} will enable the internal authentication method. - -The option \term{auth\_password\_format: plain|scram} -defines in what format the users passwords are stored: -\begin{description} - \titem{plain} - The password is stored as plain text in the database. - This is risky because the passwords can be read if your database gets compromised. - This is the default value. - This format allows clients to authenticate using: - the old Jabber Non-SASL (\xepref{0078}), \term{SASL PLAIN}, - \term{SASL DIGEST-MD5}, and \term{SASL SCRAM-SHA-1}. - - \titem{scram} - The password is not stored, only some information that allows to verify the hash provided by the client. - It is impossible to obtain the original plain password from the stored information; - for this reason, when this value is configured it cannot be changed to \term{plain} anymore. - This format allows clients to authenticate using: \term{SASL PLAIN} and \term{SASL SCRAM-SHA-1}. -\end{description} - -Examples: -\begin{itemize} -\item To use internal authentication on \jid{example.org} and LDAP - authentication on \jid{example.net}: -\begin{verbatim} -host_config: - "example.org": - auth_method: [internal] - "example.net": - auth_method: [ldap] -\end{verbatim} -\item To use internal authentication with hashed passwords on all virtual hosts: -\begin{verbatim} -auth_method: internal -auth_password_format: scram -\end{verbatim} -\end{itemize} - -\makesubsubsection{extauth}{External Script} -\ind{external authentication} - -In this authentication method, when \ejabberd{} starts, -it start a script, and calls it to perform authentication tasks. - -The server administrator can write the external authentication script -in any language. -The details on the interface between ejabberd and the script are described -in the \term{ejabberd Developers Guide}. -There are also \footahref{http://www.ejabberd.im/extauth}{several example authentication scripts}. - -These are the specific options: -\begin{description} - \titem{extauth\_program: PathToScript} - Indicate in this option the full path to the external authentication script. - The script must be executable by ejabberd. - - \titem{extauth\_instances: Integer} - Indicate how many instances of the script to run simultaneously to serve authentication in the virtual host. - The default value is the minimum number: 1. - - \titem{extauth\_cache: false|CacheTimeInteger} - The value \term{false} disables the caching feature, this is the default. - The integer \term{0} (zero) enables caching for statistics, but doesn't use that cached information to authenticate users. - If another integer value is set, caching is enabled both for statistics and for authentication: - the CacheTimeInteger indicates the number of seconds that ejabberd can reuse - the authentication information since the user last disconnected, - to verify again the user authentication without querying again the extauth script. - Note: caching should not be enabled in a host if internal auth is also enabled. - If caching is enabled, \term{mod\_last} must be enabled also in that vhost. -\end{description} - -This example sets external authentication, the extauth script, enables caching for 10 minutes, -and starts three instances of the script for each virtual host defined in ejabberd: -\begin{verbatim} -auth_method: [external] -extauth_program: "/etc/ejabberd/JabberAuth.class.php" -extauth_cache: 600 -extauth_instances: 3 -\end{verbatim} - - -\makesubsubsection{saslanonymous}{Anonymous Login and SASL Anonymous} -\ind{sasl anonymous}\ind{anonymous login} - -The \term{anonymous} authentication method enables two modes for anonymous authentication: -\begin{description} -\titem{Anonymous login:} This is a standard login, that use the - classical login and password mechanisms, but where password is - accepted or preconfigured for all anonymous users. This login is - compliant with SASL authentication, password and digest non-SASL - authentication, so this option will work with almost all XMPP - clients - -\titem{SASL Anonymous:} This is a special SASL authentication - mechanism that allows to login without providing username or - password (see \xepref{0175}). The main advantage of SASL Anonymous - is that the protocol was designed to give the user a login. This is - useful to avoid in some case, where the server has many users - already logged or registered and when it is hard to find a free - username. The main disavantage is that you need a client that - specifically supports the SASL Anonymous protocol. -\end{description} - -%TODO: introduction; tell what people can do with this -The anonymous authentication method can be configured with the following -options. Remember that you can use the \term{host\_config} option to set virtual -host specific options (see section~\ref{virtualhost}). - -\begin{description} -\titem{allow\_multiple\_connections: false|true} This option is only used - when the anonymous mode is - enabled. Setting it to \term{true} means that the same username can be taken - multiple times in anonymous login mode if different resource are used to - connect. This option is only useful in very special occasions. The default - value is \term{false}. -\titem{anonymous\_protocol: login\_anon | sasl\_anon | both} - \term{login\_anon} means that the anonymous login method will be used. - \term{sasl\_anon} means that the SASL Anonymous method will be used. - \term{both} means that SASL Anonymous and login anonymous are both enabled. -\end{description} - -Those options are defined for each virtual host with the \term{host\_config} -parameter (see section~\ref{virtualhost}). - -Examples: -\begin{itemize} -\item To enable anonymous login on all virtual hosts: -\begin{verbatim} -auth_method: [anonymous] -anonymous_protocol: login_anon -\end{verbatim} -\item Similar as previous example, but limited to \jid{public.example.org}: -\begin{verbatim} -host_config: - "public.example.org": - auth_method: [anonymous] - anonymous_protoco: login_anon -\end{verbatim} -\item To enable anonymous login and internal authentication on a virtual host: -\begin{verbatim} -host_config: - "public.example.org": - auth_method: - - internal - - anonymous - anonymous_protocol: login_anon -\end{verbatim} -\item To enable SASL Anonymous on a virtual host: -\begin{verbatim} -host_config: - "public.example.org": - auth_method: [anonymous] - anonymous_protocol: sasl_anon -\end{verbatim} -\item To enable SASL Anonymous and anonymous login on a virtual host: -\begin{verbatim} -host_config: - "public.example.org": - auth_method: [anonymous] - anonymous_protocol: both -\end{verbatim} -\item To enable SASL Anonymous, anonymous login, and internal authentication on -a virtual host: -\begin{verbatim} -host_config: - "public.example.org": - auth_method: - - internal - - anonymous - anonymous_protocol: both -\end{verbatim} -\end{itemize} - -There are more configuration examples and XMPP client example stanzas in -\footahref{http://www.ejabberd.im/Anonymous-users-support}{Anonymous users support}. - - -\makesubsubsection{pam}{PAM Authentication} -\ind{PAM authentication}\ind{Pluggable Authentication Modules} - -\ejabberd{} supports authentication via Pluggable Authentication Modules (PAM). -PAM is currently supported in AIX, FreeBSD, HP-UX, Linux, Mac OS X, NetBSD and Solaris. -PAM authentication is disabled by default, so you have to configure and compile -\ejabberd{} with PAM support enabled: -\begin{verbatim} -./configure --enable-pam && make install -\end{verbatim} - -Options: -\begin{description} -\titem{pam\_service: Name}\ind{options!pam\_service}This option defines the PAM service name. -Default is \term{"ejabberd"}. Refer to the PAM documentation of your operation system -for more information. -\titem{pam\_userinfotype: username|jid}\ind{options!pam\_userinfotype} -This option defines what type of information about the user ejabberd -provides to the PAM service: only the username, or the user JID. -Default is \term{username}. -\end{description} - -Example: -\begin{verbatim} -auth_method: [pam] -pam_service: "ejabberd" -\end{verbatim} - -Though it is quite easy to set up PAM support in \ejabberd{}, PAM itself introduces some -security issues: - -\begin{itemize} -\item To perform PAM authentication \ejabberd{} uses external C-program called -\term{epam}. By default, it is located in \verb|/var/lib/ejabberd/priv/bin/| -directory. You have to set it root on execution in the case when your PAM module -requires root privileges (\term{pam\_unix.so} for example). Also you have to grant access -for \ejabberd{} to this file and remove all other permissions from it. -Execute with root privileges: -\begin{verbatim} -chown root:ejabberd /var/lib/ejabberd/priv/bin/epam -chmod 4750 /var/lib/ejabberd/priv/bin/epam -\end{verbatim} -\item Make sure you have the latest version of PAM installed on your system. -Some old versions of PAM modules cause memory leaks. If you are not able to use the latest -version, you can \term{kill(1)} \term{epam} process periodically to reduce its memory -consumption: \ejabberd{} will restart this process immediately. -\item \term{epam} program tries to turn off delays on authentication failures. -However, some PAM modules ignore this behavior and rely on their own configuration options. -You can create a configuration file \term{ejabberd.pam}. -This example shows how to turn off delays in \term{pam\_unix.so} module: -\begin{verbatim} -#%PAM-1.0 -auth sufficient pam_unix.so likeauth nullok nodelay -account sufficient pam_unix.so -\end{verbatim} -That is not a ready to use configuration file: you must use it -as a hint when building your own PAM configuration instead. Note that if you want to disable -delays on authentication failures in the PAM configuration file, you have to restrict access -to this file, so a malicious user can't use your configuration to perform brute-force -attacks. -\item You may want to allow login access only for certain users. \term{pam\_listfile.so} -module provides such functionality. -\item If you use \term{pam\_winbind} to authorise against a Windows Active Directory, -then \term{/etc/nsswitch.conf} must be configured to use \term{winbind} as well. -\end{itemize} - -\makesubsection{accessrules}{Access Rules} -\ind{access rules}\ind{ACL}\ind{Access Control List} - -\makesubsubsection{ACLDefinition}{ACL Definition} -\ind{ACL}\ind{options!acl}\ind{ACL}\ind{Access Control List} - -Access control in \ejabberd{} is performed via Access Control Lists (ACLs). The -declarations of ACLs in the configuration file have the following syntax: -\esyntax{acl: \{ ACLName: \{ ACLType: ACLValue \} \}} - -\term{ACLType: ACLValue} can be one of the following: -\begin{description} -\titem{all} Matches all JIDs. Example: -\begin{verbatim} -acl: - world: all -\end{verbatim} -\titem{user: Username} Matches the user with the name - \term{Username} at the first virtual host. Example: -\begin{verbatim} -acl: - admin: - user: "yozhik" -\end{verbatim} -\titem{user: \{Username: Server\}} Matches the user with the JID - \term{Username@Server} and any resource. Example: -\begin{verbatim} -acl: - admin: - user: - "yozhik": "example.org" -\end{verbatim} -\titem{server: Server} Matches any JID from server - \term{Server}. Example: -\begin{verbatim} -acl: - exampleorg: - server: "example.org" -\end{verbatim} -\titem{resource: Resource} Matches any JID with a resource - \term{Resource}. Example: -\begin{verbatim} -acl: - mucklres: - resource: "muckl" -\end{verbatim} -\titem{shared\_group: Groupname} Matches any member of a Shared Roster Group with name \term{Groupname} in the virtual host. Example: -\begin{verbatim} -acl: - techgroupmembers: - shared_group: "techteam" -\end{verbatim} -\titem{shared\_group: \{Groupname: Server\}} Matches any member of a Shared Roster Group with name \term{Groupname} in the virtual host \term{Server}. Example: -\begin{verbatim} -acl: - techgroupmembers: - shared_group: - "techteam": "example.org" -\end{verbatim} -\titem{ip: Network} Matches any IP address from the \term{Network}. Example: -\begin{verbatim} -acl: - loopback: - ip: - - "127.0.0.0/8" - - "::1" -\end{verbatim} -\titem{user\_regexp: Regexp} Matches any local user with a name that - matches \term{Regexp} on local virtual hosts. Example: -\begin{verbatim} -acl: - tests: - user_regexp: "^test[0-9]*$" -\end{verbatim} -%$ -\titem{user\_regexp: \{Regexp: Server\}} Matches any user with a name - that matches \term{Regexp} at server \term{Server}. Example: -\begin{verbatim} -acl: - tests: - user_regexp: - "^test": "example.org" -\end{verbatim} -\titem{server\_regexp: Regexp} Matches any JID from the server that - matches \term{Regexp}. Example: -\begin{verbatim} -acl: - icq: - server_regexp: "^icq\\." -\end{verbatim} -\titem{resource\_regexp: Regexp} Matches any JID with a resource that - matches \term{Regexp}. Example: -\begin{verbatim} -acl: - icq: - resource_regexp: "^laptop\\." -\end{verbatim} -\titem{node\_regexp: \{UserRegexp: ServerRegexp\}} Matches any user - with a name that matches \term{UserRegexp} at any server that matches - \term{ServerRegexp}. Example: -\begin{verbatim} -acl: - yozhik: - node_regexp: - "^yozhik$": "^example.(com|org)$" -\end{verbatim} -\titem{user\_glob: Glob\}} -\titem{user\_glob: \{Glob: Server\}} -\titem{server\_glob: Glob} -\titem{resource\_glob: Glob} -\titem{node\_glob: \{UserGlob: ServerGlob\}} This is the same as - above. However, it uses shell glob patterns instead of regexp. These patterns - can have the following special characters: - \begin{description} - \titem{*} matches any string including the null string. - \titem{?} matches any single character. - \titem{[...]} matches any of the enclosed characters. Character - ranges are specified by a pair of characters separated by a \term{`-'}. - If the first character after \term{`['} is a \term{`!'}, any - character not enclosed is matched. - \end{description} -\end{description} - -The following \term{ACLName} are pre-defined: -\begin{description} -\titem{all} Matches any JID. -\titem{none} Matches no JID. -\end{description} - -\makesubsubsection{AccessRights}{Access Rights} -\ind{access}\ind{ACL}\ind{options!acl}\ind{ACL}\ind{Access Control List} - -An entry allowing or denying access to different services. -The syntax is: -\esyntax{access: \{ AccessName: \{ ACLName: allow|deny \} \}} - -When a JID is checked to have access to \term{Accessname}, the server -sequentially checks if that JID matches any of the ACLs that are named in the -first elements of the tuples in the list. If it matches, the second element of -the first matched tuple is returned, otherwise the value `\term{deny}' is -returned. - -If you define specific Access rights in a virtual host, -remember that the globally defined Access rights have precedence over those. -This means that, in case of conflict, the Access granted or denied in the global server is used -and the Access of a virtual host doesn't have effect. - -Example: -\begin{verbatim} -access: - configure: - admin: allow - something - badmans: deny - all: allow -\end{verbatim} - -The following \term{AccessName} are pre-defined: -\begin{description} -\titem{all} Always returns the value `\term{allow}'. -\titem{none} Always returns the value `\term{deny}'. -\end{description} - -\makesubsubsection{configmaxsessions}{Limiting Opened Sessions with ACL} -\ind{options!max\_user\_sessions} - -The special access \term{max\_user\_sessions} specifies the maximum -number of sessions (authenticated connections) per user. If a user -tries to open more sessions by using different resources, the first -opened session will be disconnected. The error \term{session replaced} -will be sent to the disconnected session. The value for this option -can be either a number, or \term{infinity}. The default value is -\term{infinity}. - -The syntax is: -\esyntax{\{ max\_user\_sessions: \{ ACLName: MaxNumber \} \}} - -This example limits the number of sessions per user to 5 for all users, and to 10 for admins: -\begin{verbatim} -access: - max_user_sessions: - admin: 10 - all: 5 -\end{verbatim} - -\makesubsubsection{configmaxs2sconns}{Several connections to a remote XMPP server with ACL} -\ind{options!max\_s2s\_connections} - -The special access \term{max\_s2s\_connections} specifies how many -simultaneous S2S connections can be established to a specific remote XMPP server. -The default value is \term{1}. -There's also available the access \term{max\_s2s\_connections\_per\_node}. - -The syntax is: -\esyntax{\{ max\_s2s\_connections: \{ ACLName: MaxNumber \} \}} - -Examples: -\begin{itemize} -\item Allow up to 3 connections with each remote server: -\begin{verbatim} -access: - max_s2s_connections: - all: 3 -\end{verbatim} -\end{itemize} - -\makesubsection{shapers}{Shapers} -\ind{options!shaper}\ind{shapers}\ind{traffic speed} - -Shapers enable you to limit connection traffic. -The syntax is: -\esyntax{shaper: \{ ShaperName: Rate \}} -where \term{Rate} stands for the maximum allowed incoming rate in bytes per -second. -When a connection exceeds this limit, \ejabberd{} stops reading from the socket -until the average rate is again below the allowed maximum. - -Examples: -\begin{itemize} -\item To define a shaper named `\term{normal}' with traffic speed limited to -1,000\,bytes/second: -\begin{verbatim} -shaper: - normal: 1000 -\end{verbatim} -\item To define a shaper named `\term{fast}' with traffic speed limited to -50,000\,bytes/second: -\begin{verbatim} -shaper: - fast: 50000 -\end{verbatim} -\end{itemize} - -\makesubsection{language}{Default Language} -\ind{options!language}\ind{language} - -The option \option{language} defines the default language of server strings that -can be seen by \XMPP{} clients. If a \XMPP{} client does not support -\option{xml:lang}, the specified language is used. - -The option syntax is: -\esyntax{language: Language} - -The default value is \term{en}. -In order to take effect there must be a translation file -\term{Language.msg} in \ejabberd{}'s \term{msgs} directory. - -For example, to set Russian as default language: -\begin{verbatim} -language: "ru" -\end{verbatim} - -Appendix \ref{i18ni10n} provides more details about internationalization and localization. - - -\makesubsection{captcha}{CAPTCHA} -\ind{options!captcha}\ind{captcha} - -Some \ejabberd{} modules can be configured to require a CAPTCHA challenge on certain actions. -If the client does not support CAPTCHA Forms (\xepref{0158}), -a web link is provided so the user can fill the challenge in a web browser. - -An example script is provided that generates the image -using ImageMagick's Convert program. - -The configurable options are: -\begin{description} - \titem{captcha\_cmd: Path} - Full path to a script that generates the image. - The default value disables the feature: \term{undefined} - \titem{captcha\_host: ProtocolHostPort} - ProtocolHostPort is a string with the host, and optionally the Protocol and Port number. - It must identify where ejabberd listens for CAPTCHA requests. - The URL sent to the user is formed by: \term{Protocol://Host:Port/captcha/} - The default value is: protocol \term{http}, the first hostname configured, and port \term{80}. - If you specify a port number that does not match exactly an ejabberd listener - (because you are using a reverse proxy or other port-forwarding tool), - then you must specify the transfer protocol, as seen in the example below. -\end{description} - -Additionally, an \term{ejabberd\_http} listener must be enabled with the \term{captcha} option. -See section \ref{listened-module}. - -Example configuration: -\begin{verbatim} -hosts: ["example.org"] - -captcha_cmd: "/lib/ejabberd/priv/bin/captcha.sh" -captcha_host: "example.org:5280" -## captcha_host: "https://example.org:443" -## captcha_host: "http://example.com" - -listen: - ... - - - port: 5280 - module: ejabberd_http - captcha: true - ... -\end{verbatim} - -\makesubsection{stun}{STUN and TURN} -\ind{options!stun}\ind{stun} - -\ejabberd{} is able to act as a stand-alone STUN/TURN server -(\footahref{http://tools.ietf.org/html/rfc5389}{RFC 5389}/\footahref{http://tools.ietf.org/html/rfc5766}{RFC 5766}). In that role \ejabberd{} helps clients with ICE (\footahref{http://tools.ietf.org/html/rfc5245}{RFC 5245}) or Jingle ICE (\xepref{0176}) support to discover their external addresses and ports and to relay media traffic when it is impossible to establish direct -peer-to-peer connection. - -You should configure \term{ejabberd\_stun} listening module as described in \ref{listened} section. -The specific configurable options are: -\begin{description} - \titem{tls: true|false} - If enabled, \option{certfile} option must be set, otherwise \ejabberd{} - will not be able to accept TLS connections. Obviously, this option - makes sense for \term{tcp} transport only. The default is \term{false}. - \titem{certfile: Path} - Path to the certificate file. Only makes sense when \option{tls} is set. - \titem{use\_turn: true|false} - Enables/disables TURN (media relay) functionality. The default is \term{false}. - \titem{turn\_ip: String} - The IPv4 address advertised by your TURN server. The address should not be NAT'ed - or firewalled. There is not default, so you should set this option explicitly. - Implies \term{use\_turn}. - \titem{turn\_min\_port: Integer} - Together with \option{turn\_max\_port} forms port range to allocate from. - The default is 49152. Implies \term{use\_turn}. - \titem{turn\_max\_port: Integer} - Together with \option{turn\_min\_port} forms port range to allocate from. - The default is 65535. Implies \term{use\_turn}. - \titem{turn\_max\_allocations: Integer|infinity} - Maximum number of TURN allocations available from the particular IP address. - The default value is 10. Implies \term{use\_turn}. - \titem{turn\_max\_permissions: Integer|infinity} - Maximum number of TURN permissions available from the particular IP address. - The default value is 10. Implies \term{use\_turn}. - \titem{auth\_type: user|anonymous} - Which authentication type to use for TURN allocation requests. When type \term{user} - is set, ejabberd authentication backend is used. For \term{anonymous} type - no authentication is performed (not recommended for public services). - The default is \term{user}. Implies \term{use\_turn}. - \titem{auth\_realm: String} - When \option{auth\_type} is set to \term{user} and you have several virtual - hosts configured you should set this option explicitly to the virtual host - you want to serve on this particular listening port. Implies \term{use\_turn}. - \titem{shaper: Atom} - For \term{tcp} transports defines shaper to use. The default is \term{none}. - \titem{server\_name: String} - Defines software version to return with every response. The default is the - STUN library version. -\end{description} - -Example configuration with disabled TURN functionality (STUN only): -\begin{verbatim} -listen: - ... - - - port: 3478 - transport: udp - module: ejabberd_stun - - - port: 3478 - module: ejabberd_stun - - - port: 5349 - module: ejabberd_stun - certfile: "/etc/ejabberd/server.pem" - ... -\end{verbatim} - -Example configuration with TURN functionality. Note that STUN is always -enabled if TURN is enabled. Here, only UDP section is shown: -\begin{verbatim} -listen: - ... - - - port: 3478 - transport: udp - use_turn: true - turn_ip: "10.20.30.1" - module: ejabberd_stun - ... -\end{verbatim} - -You also need to configure DNS SRV records properly so clients can easily discover a -STUN/TURN server serving your XMPP domain. Refer to section -\footahref{http://tools.ietf.org/html/rfc5389\#section-9}{DNS Discovery of a Server} -of \footahref{http://tools.ietf.org/html/rfc5389}{RFC 5389} and section -\footahref{http://tools.ietf.org/html/rfc5766\#section-6}{Creating an Allocation} -of \footahref{http://tools.ietf.org/html/rfc5766}{RFC 5766} for details. - -Example DNS SRV configuration for STUN only: -\begin{verbatim} -_stun._udp IN SRV 0 0 3478 stun.example.com. -_stun._tcp IN SRV 0 0 3478 stun.example.com. -_stuns._tcp IN SRV 0 0 5349 stun.example.com. -\end{verbatim} - -And you should also add these in the case if TURN is enabled: -\begin{verbatim} -_turn._udp IN SRV 0 0 3478 turn.example.com. -_turn._tcp IN SRV 0 0 3478 turn.example.com. -_turns._tcp IN SRV 0 0 5349 turn.example.com. -\end{verbatim} - -\makesubsection{sip}{SIP} -\ind{options!sip}\ind{sip} - -\ejabberd{} has built-in SIP support. In order to activate it you need to add -listeners for it, configure DNS properly and enable \modsip{} for -the desired virtual host. - -To add a listener you should configure \term{ejabberd\_sip} listening module as -described in \ref{listened} section. If option \option{tls} is specified, option -\option{certfile} must be specified as well, otherwise incoming TLS connections would fail. - -Example configuration with standard ports -(as per \footahref{http://tools.ietf.org/html/rfc3261}{RFC 3261}): -\begin{verbatim} -listen: - ... - - - port: 5060 - transport: udp - module: ejabberd_sip - - - port: 5060 - module: ejabberd_sip - - - port: 5061 - module: ejabberd_sip - tls: true - certfile: "/etc/ejabberd/server.pem" - ... -\end{verbatim} - -Note that there is no StartTLS support in SIP and \footahref{http://en.wikipedia.org/wiki/Server\_Name\_Indication}{SNI} support is somewhat tricky, so for TLS you have to configure -different virtual hosts on different ports if you have different certificate files for them. - -Next you need to configure DNS SIP records for your virtual domains. -Refer to \footahref{http://tools.ietf.org/html/rfc3263}{RFC 3263} for the detailed explanation. -Simply put, you should add NAPTR and SRV records for your domains. -Skip NAPTR configuration if your DNS provider doesn't support this type of records. -It's not fatal, however, highly recommended. - -Example configuration of NAPTR records: -\begin{verbatim} -example.com IN NAPTR 10 0 "s" "SIPS+D2T" "" _sips._tcp.example.com. -example.com IN NAPTR 20 0 "s" "SIP+D2T" "" _sip._tcp.example.com. -example.com IN NAPTR 30 0 "s" "SIP+D2U" "" _sip._udp.example.com. -\end{verbatim} - -Example configuration of SRV records with standard ports -(as per \footahref{http://tools.ietf.org/html/rfc3261}{RFC 3261}): -\begin{verbatim} -_sip._udp IN SRV 0 0 5060 sip.example.com. -_sip._tcp IN SRV 0 0 5060 sip.example.com. -_sips._tcp IN SRV 0 0 5061 sip.example.com. -\end{verbatim} - -\makesubsection{includeconfigfile}{Include Additional Configuration Files} -\ind{options!includeconfigfile}\ind{includeconfigfile} - -The option \option{include\_config\_file} in a configuration file instructs \ejabberd{} to include other configuration files immediately. - -The basic syntax is: -\esyntax{include\_config\_file: [Filename]} -It is possible to specify suboptions using the full syntax: -\esyntax{include\_config\_file: \{ Filename: [Suboption, ...] \}} - -The filename can be indicated either as an absolute path, -or relative to the main \ejabberd{} configuration file. -It isn't possible to use wildcards. -The file must exist and be readable. - -The allowed suboptions are: -\begin{description} - \titem{disallow: [Optionname, ...]} Disallows the usage of those options in the included configuration file. - The options that match this criteria are not accepted. - The default value is an empty list: \term{[]} - \titem{allow\_only: [Optionname, ...]} Allows only the usage of those options in the included configuration file. - The options that do not match this criteria are not accepted. - The default value is: \term{all} -\end{description} - -This is a basic example: -\begin{verbatim} -include_config_file: "/etc/ejabberd/additional.yml" -\end{verbatim} - -In this example, the included file is not allowed to contain a \term{listen} option. -If such an option is present, the option will not be accepted. -The file is in a subdirectory from where the main configuration file is. -\begin{verbatim} -include_config_file: - "./example.org/additional_not_listen.yml": - disallow: [listen] -\end{verbatim} - -In this example, \term{ejabberd.yml} defines some ACL and Access rules, -and later includes another file with additional rules: -\begin{verbatim} -acl: - admin: - user: - - "admin": "localhost" -access: - announce: - admin: allow -include_config_file: - "/etc/ejabberd/acl_and_access.yml": - allow_only: - - acl - - access -\end{verbatim} -and content of the file \term{acl\_and\_access.yml} can be, for example: -\begin{verbatim} -acl: - admin: - user: - - "bob": "localhost" - - "jan": "localhost" -\end{verbatim} - - -\makesubsection{optionmacros}{Option Macros in Configuration File} -\ind{options!optionmacros}\ind{optionmacros} - -In the \ejabberd{} configuration file, -it is possible to define a macro for a value -and later use this macro when defining an option. - -A macro is defined with this syntax: -\esyntax{define\_macro: \{ 'MACRO': Value \}} -The \term{MACRO} must be surrounded by single quotation marks, -and all letters in uppercase; check the examples bellow. -The \term{value} can be any valid arbitrary Erlang term. - -The first definition of a macro is preserved, -and additional definitions of the same macro are forgotten. - -Macros are processed after -additional configuration files have been included, -so it is possible to use macros that -are defined in configuration files included before the usage. - -It isn't possible to use a macro in the definition -of another macro. - -This example shows the basic usage of a macro: -\begin{verbatim} -define_macro: - 'LOG_LEVEL_NUMBER': 5 -loglevel: 'LOG_LEVEL_NUMBER' -\end{verbatim} -The resulting option interpreted by \ejabberd{} is: \term{loglevel: 5}. - -This example shows that values can be any arbitrary Erlang term: -\begin{verbatim} -define_macro: - 'USERBOB': - user: - - "bob": "localhost" -acl: - admin: 'USERBOB' -\end{verbatim} -The resulting option interpreted by \ejabberd{} is: -\begin{verbatim} -acl: - admin: - user: - - "bob": "localhost" -\end{verbatim} -This complex example: -\begin{verbatim} -define_macro: - 'NUMBER_PORT_C2S': 5222 - 'NUMBER_PORT_HTTP': 5280 -listen: - - - port: 'NUMBER_PORT_C2S' - module: ejabberd_c2s - - - port: 'NUMBER_PORT_HTTP' - module: ejabberd_http -\end{verbatim} -produces this result after being interpreted: -\begin{verbatim} -listen: - - - port: 5222 - module: ejabberd_c2s - - - port: 5280 - module: ejabberd_http -\end{verbatim} -\makesection{database}{Database and LDAP Configuration} -\ind{database} -%TODO: this whole section is not yet 100% optimized - -\ejabberd{} uses its internal Mnesia database by default. However, it is -possible to use a relational database, key-value storage or an LDAP server to store persistent, -long-living data. \ejabberd{} is very flexible: you can configure different -authentication methods for different virtual hosts, you can configure different -authentication mechanisms for the same virtual host (fallback), you can set -different storage systems for modules, and so forth. - -The following databases are supported by \ejabberd{}: -\begin{itemize} -%%\item \footahref{http://www.microsoft.com/sql/}{Microsoft SQL Server} -\item \footahref{http://www.erlang.org/doc/apps/mnesia/index.html}{Mnesia} -\item \footahref{http://www.mysql.com/}{MySQL} -\item \footahref{http://en.wikipedia.org/wiki/Open\_Database\_Connectivity}{Any ODBC compatible database} -\item \footahref{http://www.postgresql.org/}{PostgreSQL} -\item \footahref{http://basho.com/riak/}{Riak} -\end{itemize} - -The following LDAP servers are tested with \ejabberd{}: -\begin{itemize} -\item \footahref{http://www.microsoft.com/activedirectory/}{Active Directory} - (see section~\ref{ad}) -\item \footahref{http://www.openldap.org/}{OpenLDAP} -\item \footahref{http://www.communigate.com/}{CommuniGate Pro} -\item Normally any LDAP compatible server should work; inform us about your - success with a not-listed server so that we can list it here. -\end{itemize} - -Important note about virtual hosting: -if you define several domains in ejabberd.yml (see section \ref{hostnames}), -you probably want that each virtual host uses a different configuration of database, authentication and storage, -so that usernames do not conflict and mix between different virtual hosts. -For that purpose, the options described in the next sections -must be set inside a \term{host\_config} for each vhost (see section \ref{virtualhost}). -For example: -\begin{verbatim} -host_config: - "public.example.org": - odbc_type: pgsql - odbc_server: "localhost" - odbc_database: "database-public-example-org" - odbc_username: "ejabberd" - odbc_password: "password" - auth_method: [odbc] -\end{verbatim} - - -\makesubsection{odbc}{ODBC}\ind{odbc} - -The actual database access is defined in the options with \term{odbc\_} prefix. The -values are used to define if we want to use ODBC, or one of the two native -interface available, PostgreSQL or MySQL. - -The following paramaters are available: -\begin{description} - \titem{odbc\_type: mysql | pgsql | odbc} The type of an ODBC connection. - The default is \term{odbc}. - \titem{odbc\_server: String} A hostname of the ODBC server. The default is - \term{``localhost''}. - \titem{odbc\_port: Port} The port where the ODBC server is accepting connections. - The option is only valid for \term{mysql} and \term{pgsql}. The default is - \term{3306} and \term{5432} respectively. - \titem{odbc\_database: String} The database name. The default is \term{``ejabberd''}. - The option is only valid for \term{mysql} and \term{pgsql}. - \titem{odbc\_username: String} The username. The default is \term{``ejabberd''}. - The option is only valid for \term{mysql} and \term{pgsql}. - \titem{odbc\_password: String} The password. The default is empty string. - The option is only valid for \term{mysql} and \term{pgsql}. - \titem{odbc\_pool\_size: N} By default \ejabberd{} opens 10 connections to - the database for each virtual host. You can change this number by using this option. - \titem{odbc\_keepalive\_interval: N} You can configure an interval to - make a dummy SQL request to keep alive the connections to the database. - The default value is 'undefined', so no keepalive requests are made. - Specify in seconds: for example 28800 means 8 hours. - \titem{odbc\_start\_interval: N} If the connection to the database fails, - \ejabberd{} waits 30 seconds before retrying. - You can modify this interval with this option. -\end{description} - -Example of plain ODBC connection: -\begin{verbatim} -odbc_server: "DSN=database;UID=ejabberd;PWD=password" -\end{verbatim} - -Example of MySQL connection: -\begin{verbatim} -odbc_type: mysql -odbc_server: "server.company.com" -odbc_port: 3306 # the default -odbc_database: "mydb" -odbc_username: "user1" -odbc_password: "**********" -odbc_pool_size: 5 -\end{verbatim} - -\makesubsubsection{odbcstorage}{Storage} -\ind{ODBC!storage} - -An ODBC compatible database also can be used to store information into from -several \ejabberd{} -modules. See section~\ref{modoverview} to see which modules can be used with -relational databases like MySQL. To enable storage to your database, just make -sure that your database is running well (see previous sections), and add the -module option \term{db\_type: odbc}. - -\makesubsection{ldap}{LDAP} -\ind{databases!LDAP} - -\ejabberd{} has built-in LDAP support. You can authenticate users against LDAP -server and use LDAP directory as vCard storage. - -Usually \ejabberd{} treats LDAP as a read-only storage: -it is possible to consult data, but not possible to -create accounts or edit vCard that is stored in LDAP. -However, it is possible to change passwords if \module{mod\_register} module is enabled -and LDAP server supports -\footahref{http://tools.ietf.org/html/rfc3062}{RFC 3062}. - - -\makesubsubsection{ldapconnection}{Connection} - -Two connections are established to the LDAP server per vhost, -one for authentication and other for regular calls. - -Parameters: -\begin{description} -\titem{ldap\_servers: [Servers, ...]} \ind{options!ldap\_server}List of IP addresses or DNS names of your -LDAP servers. This option is required. -\titem{ldap\_encrypt: none|tls} \ind{options!ldap\_encrypt}Type of connection encryption to the LDAP server. -Allowed values are: \term{none}, \term{tls}. -The value \term{tls} enables encryption by using LDAP over SSL. -Note that STARTTLS encryption is not supported. -The default value is: \term{none}. -\titem{ldap\_tls\_verify: false|soft|hard} \ind{options!ldap\_tls\_verify} -This option specifies whether to verify LDAP server certificate or not when TLS is enabled. -When \term{hard} is enabled \ejabberd{} doesn't proceed if a certificate is invalid. -When \term{soft} is enabled \ejabberd{} proceeds even if check fails. -The default is \term{false} which means no checks are performed. -\titem{ldap\_tls\_cacertfile: Path} \ind{options!ldap\_tls\_cacertfile} -Path to file containing PEM encoded CA certificates. This option is needed -(and required) when TLS verification is enabled. -\titem{ldap\_tls\_depth: Number} \ind{options!ldap\_tls\_depth} -Specifies the maximum verification depth when TLS verification is enabled, -i.e. how far in a chain of certificates the verification process can proceed -before the verification is considered to fail. -Peer certificate = 0, CA certificate = 1, higher level CA certificate = 2, etc. -The value 2 thus means that a chain can at most contain peer cert, -CA cert, next CA cert, and an additional CA cert. The default value is 1. -\titem{ldap\_port: Number} \ind{options!ldap\_port}Port to connect to your LDAP server. -The default port is~389 if encryption is disabled; and 636 if encryption is enabled. -If you configure a value, it is stored in \ejabberd{}'s database. -Then, if you remove that value from the configuration file, -the value previously stored in the database will be used instead of the default port. -\titem{ldap\_rootdn: RootDN} \ind{options!ldap\_rootdn}Bind DN. The default value - is~\term{""} which means `anonymous connection'. -\titem{ldap\_password: Password} \ind{options!ldap\_password}Bind password. The default - value is \term{""}. -\titem{ldap\_deref\_aliases: never|always|finding|searching} \ind{options!ldap\_deref\_aliases} Whether or not to dereference aliases. The default is \term{never}. -\end{description} - -Example: -\begin{verbatim} -auth_method: [ldap] -ldap_servers: - - "ldap1.example.org" -ldap_port: 389 -ldap_rootdn: "cn=Manager,dc=domain,dc=org" -ldap_password: "**********" -\end{verbatim} - -\makesubsubsection{ldapauth}{Authentication} - -You can authenticate users against an LDAP directory. -Note that current LDAP implementation does not support SASL authentication. - -Available options are: - -\begin{description} -\titem{ldap\_base: Base}\ind{options!ldap\_base}LDAP base directory which stores - users accounts. This option is required. - \titem{ldap\_uids: [ ldap\_uidattr | \{ldap\_uidattr: ldap\_uidattr\_format\} ]}\ind{options!ldap\_uids} - LDAP attribute which holds a list of attributes to use as alternatives for getting the JID. - The default attributes are \term{[\{"uid", "\%u"\}]}. - The attributes are of the form: - \term{[\{ldap\_uidattr\}]} or \term{[\{ldap\_uidattr, ldap\_uidattr\_format\}]}. - You can use as many comma separated attributes as needed. - The values for \term{ldap\_uidattr} and - \term{ldap\_uidattr\_format} are described as follow: - \begin{description} - \titem{ldap\_uidattr}\ind{options!ldap\_uidattr}LDAP attribute which holds - the user's part of a JID. The default value is \term{"uid"}. - \titem{ldap\_uidattr\_format}\ind{options!ldap\_uidattr\_format}Format of - the \term{ldap\_uidattr} variable. The format \emph{must} contain one and - only one pattern variable \term{"\%u"} which will be replaced by the - user's part of a JID. For example, \term{"\%u@example.org"}. The default - value is \term{"\%u"}. - \end{description} - \titem{ldap\_filter: Filter}\ind{options!ldap\_filter}\ind{protocols!RFC 4515: - LDAP String Representation of Search Filters} - \footahref{http://tools.ietf.org/html/rfc4515}{RFC 4515} LDAP filter. The - default Filter value is: \term{undefined}. Example: - \term{"(\&(objectClass=shadowAccount)(memberOf=Jabber Users))"}. Please, do - not forget to close brackets and do not use superfluous whitespaces. Also you - \emph{must not} use \option{ldap\_uidattr} attribute in filter because this - attribute will be substituted in LDAP filter automatically. - \titem{ldap\_dn\_filter: \{ Filter: FilterAttrs \}}\ind{options!ldap\_dn\_filter} - This filter is applied on the results returned by the main filter. This filter - performs additional LDAP lookup to make the complete result. This is useful - when you are unable to define all filter rules in \term{ldap\_filter}. You - can define \term{"\%u"}, \term{"\%d"}, \term{"\%s"} and \term{"\%D"} pattern - variables in Filter: \term{"\%u"} is replaced by a user's part of a JID, - \term{"\%d"} is replaced by the corresponding domain (virtual host), - all \term{"\%s"} variables are consecutively replaced by values of FilterAttrs - attributes and \term{"\%D"} is replaced by Distinguished Name. By default - \term{ldap\_dn\_filter} is undefined. - Example: -\begin{verbatim} -ldap_dn_filter: - "(&(name=%s)(owner=%D)(user=%u@%d))": ["sn"] -\end{verbatim} - Since this filter makes additional LDAP lookups, use it only in the - last resort: try to define all filter rules in \term{ldap\_filter} if possible. - \titem{\{ldap\_local\_filter, Filter\}}\ind{options!ldap\_local\_filter} - If you can't use \term{ldap\_filter} due to performance reasons - (the LDAP server has many users registered), - you can use this local filter. - The local filter checks an attribute in ejabberd, - not in LDAP, so this limits the load on the LDAP directory. - The default filter is: \term{undefined}. - Example values: -\begin{verbatim} -{ldap_local_filter, {notequal, {"accountStatus",["disabled"]}}}. -{ldap_local_filter, {equal, {"accountStatus",["enabled"]}}}. -{ldap_local_filter, undefined}. -\end{verbatim} - -\end{description} - -\makesubsubsection{ldapexamples}{Examples} - -\makeparagraph{ldapcommonexample}{Common example} - -Let's say \term{ldap.example.org} is the name of our LDAP server. We have -users with their passwords in \term{"ou=Users,dc=example,dc=org"} directory. -Also we have addressbook, which contains users emails and their additional -infos in \term{"ou=AddressBook,dc=example,dc=org"} directory. -The connection to the LDAP server is encrypted using TLS, -and using the custom port 6123. -Corresponding authentication section should looks like this: - -\begin{verbatim} -## Authentication method -auth_method: [ldap] -## DNS name of our LDAP server -ldap_servers: ["ldap.example.org"] -## Bind to LDAP server as "cn=Manager,dc=example,dc=org" with password "secret" -ldap_rootdn: "cn=Manager,dc=example,dc=org" -ldap_password: "secret" -ldap_encrypt: tls -ldap_port: 6123 -## Define the user's base -ldap_base: "ou=Users,dc=example,dc=org" -## We want to authorize users from 'shadowAccount' object class only -ldap_filter: "(objectClass=shadowAccount)" -\end{verbatim} - -Now we want to use users LDAP-info as their vCards. We have four attributes -defined in our LDAP schema: \term{"mail"} --- email address, \term{"givenName"} ---- first name, \term{"sn"} --- second name, \term{"birthDay"} --- birthday. -Also we want users to search each other. Let's see how we can set it up: - -\begin{verbatim} -modules: - ... - mod_vcard_ldap: - ## We use the same server and port, but want to bind anonymously because - ## our LDAP server accepts anonymous requests to - ## "ou=AddressBook,dc=example,dc=org" subtree. - ldap_rootdn: "" - ldap_password: "" - ## define the addressbook's base - ldap_base: "ou=AddressBook,dc=example,dc=org" - ## uidattr: user's part of JID is located in the "mail" attribute - ## uidattr_format: common format for our emails - ldap_uids: - "mail": "%u@mail.example.org" - ## We have to define empty filter here, because entries in addressbook does not - ## belong to shadowAccount object class - ldap_filter: "" - ## Now we want to define vCard pattern - ldap_vcard_map: - "NICKNAME": {"%u": []} # just use user's part of JID as his nickname - "GIVEN": {"%s": ["givenName"]} - "FAMILY": {"%s": ["sn"]} - "FN": {"%s, %s": ["sn", "givenName"]}, # example: "Smith, John" - "EMAIL": {"%s": ["mail"]} - "BDAY": {"%s": ["birthDay"]}]} - ## Search form - ldap_search_fields: - "User": "%u" - "Name": "givenName" - "Family Name": "sn" - "Email": "mail" - "Birthday": "birthDay" - ## vCard fields to be reported - ## Note that JID is always returned with search results - ldap_search_reported: - "Full Name": "FN" - "Nickname": "NICKNAME" - "Birthday": "BDAY" - ... -\end{verbatim} - -Note that \modvcardldap{} module checks for the existence of the user before -searching in his information in LDAP. - - -\makeparagraph{ad}{Active Directory} -\ind{databases!Active Directory} - -Active Directory is just an LDAP-server with predefined attributes. A sample -configuration is shown below: - -\begin{verbatim} -auth_method: [ldap] -ldap_servers: ["office.org"] # List of LDAP servers -ldap_base: "DC=office,DC=org" # Search base of LDAP directory -ldap_rootdn: "CN=Administrator,CN=Users,DC=office,DC=org" # LDAP manager -ldap_password: "*******" # Password to LDAP manager -ldap_uids: ["sAMAccountName"] -ldap_filter: "(memberOf=*)" - -modules: - ... - mod_vcard_ldap: - ldap_vcard_map: - "NICKNAME": {"%u", []} - "GIVEN": {"%s", ["givenName"]} - "MIDDLE": {"%s", ["initials"]} - "FAMILY": {"%s", ["sn"]} - "FN": {"%s", ["displayName"]} - "EMAIL": {"%s", ["mail"]} - "ORGNAME": {"%s", ["company"]} - "ORGUNIT": {"%s", ["department"]} - "CTRY": {"%s", ["c"]} - "LOCALITY": {"%s", ["l"]} - "STREET": {"%s", ["streetAddress"]} - "REGION": {"%s", ["st"]} - "PCODE": {"%s", ["postalCode"]} - "TITLE": {"%s", ["title"]} - "URL": {"%s", ["wWWHomePage"]} - "DESC": {"%s", ["description"]} - "TEL": {"%s", ["telephoneNumber"]}]} - ldap_search_fields: - "User": "%u" - "Name": "givenName" - "Family Name": "sn" - "Email": "mail" - "Company": "company" - "Department": "department" - "Role": "title" - "Description": "description" - "Phone": "telephoneNumber" - ldap_search_reported: - "Full Name": "FN" - "Nickname": "NICKNAME" - "Email": "EMAIL" - ... -\end{verbatim} - -\makesubsection{riak}{Riak} -\ind{databases!Riak} - -\footahref{http://basho.com/riak/}{Riak} is a distributed NoSQL key-value data store. -The actual database access is defined in the options with \term{riak\_} prefix. - -\makesubsubsection{riakconnection}{Connection} -\ind{riak!connection} - -The following paramaters are available: -\begin{description} - \titem{riak\_server: String} A hostname of the Riak server. The default is - \term{``localhost''}. - \titem{riak\_port: Port} The port where the Riak server is accepting connections. - The defalt is 8087. - \titem{riak\_pool\_size: N} By default \ejabberd{} opens 10 connections to - the Riak server. You can change this number by using this option. - \titem{riak\_start\_interval: N} If the connection to the Riak server fails, - \ejabberd{} waits 30 seconds before retrying. - You can modify this interval with this option. -\end{description} - -Example configuration: -\begin{verbatim} -riak_server: "riak.server.com" -riak_port: 9097 -\end{verbatim} - -\makesubsubsection{riakstorage}{Storage} -\ind{riak!storage} - -Several \ejabberd{} modules can be used to store information in Riak database. -Refer to the corresponding module documentation to see if it supports such -ability. To enable storage to Riak database, just make -sure that your database is running well (see the next section), and add the -module option \term{db\_type: riak}. - -\makesubsubsection{riakconfiguration}{Riak Configuration} -\ind{riak!configuration} - -First, you need to configure Riak to use -\footahref{http://en.wikipedia.org/wiki/LevelDB}{LevelDB} as a database backend. - -If you are using Riak 2.x and higher, configure \term{storage\_backend} option -of \term{/etc/riak/riak.conf} as follows: -\begin{verbatim} -... -storage_backend = leveldb -... -\end{verbatim} - -If you are using Riak 1.4.x and older, configure \term{storage\_backend} option -of \term{/etc/riak/app.config} in the section \term{riak\_kv} as follows: -\begin{verbatim} -... - {riak_kv, [ - ... - {storage_backend, riak_kv_eleveldb_backend}, -... -\end{verbatim} - -Second, Riak should be pointed to \ejabberd{} Erlang binary files (*.beam). -As described in \ref{install}, by default those are located -in \term{/lib/ejabberd/ebin} directory. So you -should add the following to \term{/etc/riak/vm.args}: -\begin{verbatim} -... -## Path to ejabberd beams in order to make map/reduce --pz /lib/ejabberd/ebin -... -\end{verbatim} -Important notice: make sure Riak has at least read access to that directory. -Otherwise its startup will likely fail. - -\makesection{modules}{Modules Configuration} -\ind{modules} - -The option \term{modules} defines the list of modules that will be loaded after -\ejabberd{}'s startup. Each entry in the list is a tuple in which the first -element is the name of a module and the second is a list of options for that -module. - -The syntax is: -\esyntax{modules: \{ ModuleName: ModuleOptions \}} - -Examples: -\begin{itemize} -\item In this example only the module \modecho{} is loaded and no module - options are specified between the square brackets: -\begin{verbatim} -modules: - mod_echo: {} -\end{verbatim} -\item In the second example the modules \modecho{}, \modtime{}, and - \modversion{} are loaded without options. -\begin{verbatim} -modules: - mod_echo: {} - mod_time: {} - mod_version: {} -\end{verbatim} -\end{itemize} - -\makesubsection{modoverview}{Modules Overview} -\ind{modules!overview}\ind{XMPP compliancy} - -The following table lists all modules included in \ejabberd{}. - -\begin{table}[H] - \centering - \begin{tabular}{|l|l|l|} - \hline {\bf Module} & {\bf Feature} & {\bf Dependencies} \\ - \hline - \hline \modadhoc{} & Ad-Hoc Commands (\xepref{0050}) & \\ - \hline \ahrefloc{modannounce}{\modannounce{}} & Manage announcements & recommends \modadhoc{} \\ - \hline \modblocking{} & Simple Communications Blocking (\xepref{0191}) & \modprivacy{} \\ - \hline \modcaps{} & Entity Capabilities (\xepref{0115}) & \\ - \hline \modcarboncopy{} & Message Carbons (\xepref{0280}) & \\ - \hline \ahrefloc{modclientstate}{\modclientstate{}} & Filter stanzas for inactive clients & \\ - \hline \modconfigure{} & Server configuration using Ad-Hoc & \modadhoc{} \\ - \hline \ahrefloc{moddisco}{\moddisco{}} & Service Discovery (\xepref{0030}) & \\ - \hline \ahrefloc{modecho}{\modecho{}} & Echoes XMPP stanzas & \\ - \hline \ahrefloc{modfail2ban}{\modfailban{}} & Bans IPs that show the malicious signs & \\ - \hline \ahrefloc{modhttpbind}{\modhttpbind{}} & XMPP over Bosh service (HTTP Binding) & \\ - \hline \ahrefloc{modhttpfileserver}{\modhttpfileserver{}} & Small HTTP file server & \\ - \hline \ahrefloc{modirc}{\modirc{}} & IRC transport & \\ - \hline \ahrefloc{modlast}{\modlast{}} & Last Activity (\xepref{0012}) & \\ - \hline \ahrefloc{modmuc}{\modmuc{}} & Multi-User Chat (\xepref{0045}) & \\ - \hline \ahrefloc{modmuclog}{\modmuclog{}} & Multi-User Chat room logging & \modmuc{} \\ - \hline \ahrefloc{modoffline}{\modoffline{}} & Offline message storage (\xepref{0160}) & \\ - \hline \ahrefloc{modping}{\modping{}} & XMPP Ping and periodic keepalives (\xepref{0199}) & \\ - \hline \ahrefloc{modprescounter}{\modprescounter{}} & Detect presence subscription flood & \\ - \hline \ahrefloc{modprivacy}{\modprivacy{}} & Blocking Communication (\xepref{0016}) & \\ - \hline \ahrefloc{modprivate}{\modprivate{}} & Private XML Storage (\xepref{0049}) & \\ - \hline \ahrefloc{modproxy}{\modproxy{}} & SOCKS5 Bytestreams (\xepref{0065}) & \\ - \hline \ahrefloc{modpubsub}{\modpubsub{}} & Pub-Sub (\xepref{0060}), PEP (\xepref{0163}) & \modcaps{} \\ - \hline \ahrefloc{modpubsub}{\modpubsubodbc{}} & Pub-Sub (\xepref{0060}), PEP (\xepref{0163}) & supported DB (*) and \modcaps{} \\ - \hline \ahrefloc{modregister}{\modregister{}} & In-Band Registration (\xepref{0077}) & \\ - \hline \ahrefloc{modregisterweb}{\modregisterweb{}} & Web for Account Registrations & \\ - \hline \ahrefloc{modroster}{\modroster{}} & Roster management (XMPP IM) & \\ - \hline \ahrefloc{modservicelog}{\modservicelog{}} & Copy user messages to logger service & \\ - \hline \ahrefloc{modsharedroster}{\modsharedroster{}} & Shared roster management & \modroster{} \\ - \hline \ahrefloc{modsharedrosterldap}{\modsharedrosterldap{}} & LDAP Shared roster management & \modroster{} \\ - \hline \ahrefloc{modsic}{\modsic{}} & Server IP Check (\xepref{0279}) & \\ - \hline \ahrefloc{modsip}{\modsip{}} & SIP Registrar/Proxy (\footahref{http://tools.ietf.org/html/rfc3261}{RFC 3261}) & \term{ejabberd\_sip} \\ - \hline \ahrefloc{modstats}{\modstats{}} & Statistics Gathering (\xepref{0039}) & \\ - \hline \ahrefloc{modtime}{\modtime{}} & Entity Time (\xepref{0202}) & \\ - \hline \ahrefloc{modvcard}{\modvcard{}} & vcard-temp (\xepref{0054}) & \\ - \hline \ahrefloc{modvcardldap}{\modvcardldap{}} & vcard-temp (\xepref{0054}) & LDAP server \\ - \hline \ahrefloc{modvcardxupdate}{\modvcardxupdate{}} & vCard-Based Avatars (\xepref{0153}) & \modvcard{} \\ - \hline \ahrefloc{modversion}{\modversion{}} & Software Version (\xepref{0092}) & \\ - \hline - \end{tabular} -\end{table} - -\begin{itemize} -\item (*) This module requires a supported database. For a list of supported databases, see section~\ref{database}. -\end{itemize} - -You can see which database backend each module needs by looking at the suffix: -\begin{itemize} -\item No suffix, this means that the module uses Erlang's built-in database - Mnesia as backend, Riak key-value store or ODBC database (see~\ref{database}). -\item `\_ldap', this means that the module needs an LDAP server as backend. -\end{itemize} - -You can find more -\footahref{http://www.ejabberd.im/contributions}{contributed modules} on the -\ejabberd{} website. Please remember that these contributions might not work or -that they can contain severe bugs and security leaks. Therefore, use them at -your own risk! - - -\makesubsection{modcommonoptions}{Common Options} - -The following options are used by many modules. Therefore, they are described in -this separate section. - -\makesubsubsection{modiqdiscoption}{\option{iqdisc}} -\ind{options!iqdisc} - -Many modules define handlers for processing IQ queries of different namespaces -to this server or to a user (e.\,g.\ to \jid{example.org} or to -\jid{user@example.org}). This option defines processing discipline for -these queries. - -The syntax is: -\esyntax{iqdisc: Value} - -Possible \term{Value} are: -\begin{description} -\titem{no\_queue} All queries of a namespace with this processing discipline are - processed directly. This means that the XMPP connection that sends this IQ query gets blocked: - no other packets can be processed - until this one has been completely processed. Hence this discipline is not - recommended if the processing of a query can take a relatively long time. -\titem{one\_queue} In this case a separate queue is created for the processing - of IQ queries of a namespace with this discipline. In addition, the processing - of this queue is done in parallel with that of other packets. This discipline - is most recommended. -\titem{N} N separate queues are created to process the - queries. The queries are thus processed in parallel, but in a - controlled way. -\titem{parallel} For every packet with this discipline a separate Erlang process - is spawned. Consequently, all these packets are processed in parallel. - Although spawning of Erlang process has a relatively low cost, this can break - the server's normal work, because the Erlang emulator has a limit on the - number of processes (32000 by default). -\end{description} - -Example: -\begin{verbatim} -modules: - ... - mod_time: - iqdisc: no_queue - ... -\end{verbatim} - -\makesubsubsection{modhostoption}{\option{host}} -\ind{options!host} - -This option defines the Jabber ID of a service provided by an \ejabberd{} module. - -The syntax is: -\esyntax{host: HostName} - -If you include the keyword "@HOST@" in the HostName, -it is replaced at start time with the real virtual host string. - -This example configures -the \ind{modules!\modecho{}}echo module to provide its echoing service -in the Jabber ID \jid{mirror.example.org}: -\begin{verbatim} -modules: - ... - mod_echo: - host: "mirror.example.org" - ... -\end{verbatim} - -However, if there are several virtual hosts and this module is enabled in all of them, -the "@HOST@" keyword must be used: -\begin{verbatim} -modules: - ... - mod_echo: - host: "mirror.@HOST@" - ... -\end{verbatim} - -\makesubsection{modannounce}{\modannounce{}} -\ind{modules!\modannounce{}}\ind{MOTD}\ind{message of the day}\ind{announcements} - -This module enables configured users to broadcast announcements and to set -the message of the day (MOTD). -Configured users can perform these actions with a -\XMPP{} client either using Ad-hoc commands -or sending messages to specific JIDs. - -The Ad-hoc commands are listed in the Server Discovery. -For this feature to work, \modadhoc{} must be enabled. - -The specific JIDs where messages can be sent are listed bellow. -The first JID in each entry will apply only to the specified virtual host -\jid{example.org}, while the JID between brackets will apply to all virtual -hosts in ejabberd. -\begin{description} -\titem{example.org/announce/all (example.org/announce/all-hosts/all)} The - message is sent to all registered users. If the user is online and connected - to several resources, only the resource with the highest priority will receive - the message. If the registered user is not connected, the message will be - stored offline in assumption that \ind{modules!\modoffline{}}offline storage - (see section~\ref{modoffline}) is enabled. -\titem{example.org/announce/online (example.org/announce/all-hosts/online)}The - message is sent to all connected users. If the user is online and connected - to several resources, all resources will receive the message. -\titem{example.org/announce/motd (example.org/announce/all-hosts/motd)}The - message is set as the message of the day (MOTD) and is sent to users when they - login. In addition the message is sent to all connected users (similar to - \term{announce/online}). -\titem{example.org/announce/motd/update (example.org/announce/all-hosts/motd/update)} - The message is set as message of the day (MOTD) and is sent to users when they - login. The message is \emph{not sent} to any currently connected user. -\titem{example.org/announce/motd/delete (example.org/announce/all-hosts/motd/delete)} - Any message sent to this JID removes the existing message of the day (MOTD). -\end{description} - -Options: -\begin{description} -\dbtype -\titem{access: AccessName} \ind{options!access}This option specifies who is allowed to - send announcements and to set the message of the day (by default, nobody is - able to send such messages). -\end{description} - -Examples: -\begin{itemize} -\item Only administrators can send announcements: -\begin{verbatim} -access: - announce: - admin: allow - -modules: - ... - mod_adhoc: {} - mod_announce: - access: announce - ... -\end{verbatim} -\item Administrators as well as the direction can send announcements: -\begin{verbatim} -acl: - direction: - user: - "big_boss": "example.org" - "assistant": "example.org" - admin: - user: - "admin": "example.org" -access: - announce: - admin: allow - direction: allow - -modules: - ... - mod_adhoc: {} - mod_announce: - access: announce - ... -\end{verbatim} -\end{itemize} - -Note that \modannounce{} can be resource intensive on large -deployments as it can broadcast lot of messages. This module should be -disabled for instances of \ejabberd{} with hundreds of thousands users. - -\makesubsection{modclientstate}{\modclientstate{}} -\ind{modules!\modclientstate{}}\ind{Client State Indication} -\ind{protocols!XEP-0352: Client State Indication} - -This module allows for queueing or dropping certain types of stanzas -when a client indicates that the user is not actively using the client -at the moment (see \xepref{0352}). This can save bandwidth and -resources. - -Options: -\begin{description} -\titem{drop\_chat\_states: true|false} \ind{options!drop\_chat\_states} - Drop most "standalone" Chat State Notifications (as defined in - \xepref{0085}) while a client indicates inactivity. The default value - is \term{false}. -\titem{queue\_presence: true|false} \ind{options!queue\_presence} - While a client is inactive, queue presence stanzas that indicate - (un)availability. The latest queued stanza of each contact is - delivered as soon as the client becomes active again. The default - value is \term{false}. -\end{description} - -Example: -\begin{verbatim} -modules: - ... - mod_client_state: - drop_chat_states: true - queue_presence: true - ... -\end{verbatim} - -\makesubsection{moddisco}{\moddisco{}} -\ind{modules!\moddisco{}} -\ind{protocols!XEP-0030: Service Discovery} -\ind{protocols!XEP-0011: Jabber Browsing} -\ind{protocols!XEP-0094: Agent Information} -\ind{protocols!XEP-0157: Contact Addresses for XMPP Services} - -This module adds support for Service Discovery (\xepref{0030}). With -this module enabled, services on your server can be discovered by -\XMPP{} clients. Note that \ejabberd{} has no modules with support -for the superseded Jabber Browsing (\xepref{0011}) and Agent Information -(\xepref{0094}). Accordingly, \XMPP{} clients need to have support for -the newer Service Discovery protocol if you want them be able to discover -the services you offer. - -Options: -\begin{description} -\iqdiscitem{Service Discovery (\ns{http://jabber.org/protocol/disco\#items} and - \ns{http://jabber.org/protocol/disco\#info})} -\titem{extra\_domains: [Domain, ...]} \ind{options!extra\_domains}With this option, - you can specify a list of extra domains that are added to the Service Discovery item list. -\titem{server\_info: [ \{ modules: Modules, name: Name, urls: [URL, ...] \} ]} \ind{options!server\_info} - Specify additional information about the server, - as described in Contact Addresses for XMPP Services (\xepref{0157}). - \term{Modules} can be the keyword `all', - in which case the information is reported in all the services; - or a list of \ejabberd{} modules, - in which case the information is only specified for the services provided by those modules. - Any arbitrary \term{Name} and \term{URL} can be specified, not only contact addresses. -\end{description} - -Examples: -\begin{itemize} -\item To serve a link to the Jabber User Directory on \jid{jabber.org}: -\begin{verbatim} -modules: - ... - mod_disco: - extra_domains: ["users.jabber.org"] - ... -\end{verbatim} -\item To serve a link to the transports on another server: -\begin{verbatim} -modules: - ... - mod_disco: - extra_domains: - - "icq.example.com" - - "msn.example.com" - ... -\end{verbatim} -\item To serve a link to a few friendly servers: -\begin{verbatim} -modules: - ... - mod_disco: - extra_domains: - - "example.org" - - "example.com" - ... -\end{verbatim} -\item With this configuration, all services show abuse addresses, -feedback address on the main server, -and admin addresses for both the main server and the vJUD service: -\begin{verbatim} -modules: - ... - mod_disco: - server_info: - - - modules: all - name: "abuse-addresses" - urls: ["mailto:abuse@shakespeare.lit"] - - - modules: [mod_muc] - name: "Web chatroom logs" - urls: ["http://www.example.org/muc-logs"] - - - modules: [mod_disco] - name: "feedback-addresses" - urls: - - "http://shakespeare.lit/feedback.php" - - "mailto:feedback@shakespeare.lit" - - "xmpp:feedback@shakespeare.lit" - - - modules: - - mod_disco - - mod_vcard - name: "admin-addresses" - urls: - - "mailto:xmpp@shakespeare.lit" - - "xmpp:admins@shakespeare.lit" - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modecho}{\modecho{}} -\ind{modules!\modecho{}}\ind{debugging} - -This module simply echoes any \XMPP{} -packet back to the sender. This mirror can be of interest for -\ejabberd{} and \XMPP{} client debugging. - -Options: -\begin{description} -\hostitem{echo} -\end{description} - -Example: Mirror, mirror, on the wall, who is the most beautiful - of them all? -\begin{verbatim} -modules: - ... - mod_echo: - host: "mirror.example.org" - ... -\end{verbatim} - -\makesubsection{modfail2ban}{\modfailban{}} -\ind{modules!\modfailban{}}\ind{modfail2ban} - -The module bans IPs that show the malicious signs. Currently only C2S authentication -failures are detected. - -Available options: -\begin{description} - \titem{c2s\_auth\_ban\_lifetime: Seconds} The lifetime of the IP ban caused by too - many C2S authentication failures. The default is 3600, i.e. one hour. - \titem{c2s\_max\_auth\_failures: Integer} The number of C2S authentication failures to - trigger the IP ban. The default is 20. -\end{description} - -Example: -\begin{verbatim} -modules: - ... - mod_fail2ban: - c2s_auth_block_lifetime: 7200 - c2s_max_auth_failures: 50 - ... -\end{verbatim} - -\makesubsection{modhttpbind}{\modhttpbind{}} -\ind{modules!\modhttpbind{}}\ind{modhttpbind} - -This module implements XMPP over Bosh (formerly known as HTTP Binding) -as defined in \xepref{0124} and \xepref{0206}. -It extends ejabberd's built in HTTP service with a configurable -resource at which this service will be hosted. - -To use HTTP-Binding, enable the module: -\begin{verbatim} -modules: - ... - mod_http_bind: {} - ... -\end{verbatim} -and add \verb|http_bind| in the HTTP service. For example: -\begin{verbatim} -listen: - ... - - - port: 5280 - module: ejabberd_http - http_bind: true - http_poll: true - web_admin: true - ... -\end{verbatim} -With this configuration, the module will serve the requests sent to -\verb|http://example.org:5280/http-bind/| -Remember that this page is not designed to be used by web browsers, -it is used by XMPP clients that support XMPP over Bosh. - -If you want to set the service in a different URI path or use a different module, -you can configure it manually using the option \verb|request_handlers|. -For example: -\begin{verbatim} -listen: - ... - - - port: 5280 - module: ejabberd_http - request_handlers: - "/http-bind": mod_http_bind - http_poll: true - web_admin: true - ... -\end{verbatim} - -Options: -\begin{description} - \titem{\{max\_inactivity, Seconds\}} \ind{options!max\_inactivity} - Define the maximum inactivity period in seconds. - Default value is 30 seconds. - For example, to set 50 seconds: -\begin{verbatim} -modules: - ... - mod_http_bind: - max_inactivity: 50 - ... -\end{verbatim} -\end{description} - - -\makesubsection{modhttpfileserver}{\modhttpfileserver{}} -\ind{modules!\modhttpfileserver{}}\ind{modhttpfileserver} - -This simple module serves files from the local disk over HTTP. - -Options: -\begin{description} - \titem{docroot: Path} \ind{options!docroot} - Directory to serve the files. - \titem{accesslog: Path} \ind{options!accesslog} - File to log accesses using an Apache-like format. - No log will be recorded if this option is not specified. - \titem{directory\_indices: [Index, ...]} \ind{options!directoryindices} - Indicate one or more directory index files, similarly to Apache's - DirectoryIndex variable. When a web request hits a directory - instead of a regular file, those directory indices are looked in - order, and the first one found is returned. - \titem{custom\_headers: \{Name: Value\}} \ind{options!customheaders} - Indicate custom HTTP headers to be included in all responses. - Default value is: \term{[]} - \titem{content\_types: \{Name: Type\}} \ind{options!contenttypes} - Specify mappings of extension to content type. - There are several content types already defined, - with this option you can add new definitions, modify or delete existing ones. - To delete an existing definition, simply define it with a value: `undefined'. - \titem{default\_content\_type: Type} \ind{options!defaultcontenttype} - Specify the content type to use for unknown extensions. - Default value is `application/octet-stream'. -\end{description} - -This example configuration will serve the files from -the local directory \verb|/var/www| -in the address \verb|http://example.org:5280/pub/archive/|. -In this example a new content type \term{ogg} is defined, -\term{png} is redefined, and \term{jpg} definition is deleted. -To use this module you must enable it: -\begin{verbatim} -modules: - ... - mod_http_fileserver: - docroot: "/var/www" - accesslog: "/var/log/ejabberd/access.log" - directory_indices: - - "index.html" - - "main.htm" - custom_headers: - "X-Powered-By": "Erlang/OTP" - "X-Fry": "It's a widely-believed fact!" - content_types: - ".ogg": "audio/ogg" - ".png": "image/png" - ".jpg": undefined - default_content_type: "text/html" - ... -\end{verbatim} -And define it as a handler in the HTTP service: -\begin{verbatim} -listen: - ... - - - port: 5280 - module: ejabberd_http - request_handlers: - ... - "/pub/archive": mod_http_fileserver - ... - ... -\end{verbatim} - -\makesubsection{modirc}{\modirc{}} -\ind{modules!\modirc{}}\ind{IRC} - -This module is an IRC transport that can be used to join channels on IRC -servers. - -End user information: -\ind{protocols!groupchat 1.0}\ind{protocols!XEP-0045: Multi-User Chat} -\begin{itemize} -\item A \XMPP{} client with `groupchat 1.0' support or Multi-User - Chat support (\xepref{0045}) is necessary to join IRC channels. -\item An IRC channel can be joined in nearly the same way as joining a - \XMPP{} Multi-User Chat room. The difference is that the room name will - be `channel\%\jid{irc.example.org}' in case \jid{irc.example.org} is - the IRC server hosting `channel'. And of course the host should point - to the IRC transport instead of the Multi-User Chat service. -\item You can register your nickame by sending `IDENTIFY password' to \\ - \jid{nickserver!irc.example.org@irc.jabberserver.org}. -\item Entering your password is possible by sending `LOGIN nick password' \\ - to \jid{nickserver!irc.example.org@irc.jabberserver.org}. -\item The IRC transport provides Ad-Hoc Commands (\xepref{0050}) - to join a channel, and to set custom IRC username and encoding. -\item When using a popular \XMPP{} server, it can occur that no - connection can be achieved with some IRC servers because they limit the - number of connections from one IP. -\end{itemize} - -Options: -\begin{description} -\hostitem{irc} -\dbtype -\titem{access: AccessName} \ind{options!access}This option can be used to specify who - may use the IRC transport (default value: \term{all}). -\titem{default\_encoding: Encoding} \ind{options!defaultencoding}Set the default IRC encoding. - Default value: \term{"iso8859-1"} -\end{description} - -Examples: -\begin{itemize} -\item In the first example, the IRC transport is available on (all) your - virtual host(s) with the prefix `\jid{irc.}'. Furthermore, anyone is - able to use the transport. The default encoding is set to "iso8859-15". -\begin{verbatim} -modules: - ... - mod_irc: - access: all - default_encoding: "iso8859-15" - ... -\end{verbatim} -\item In next example the IRC transport is available with JIDs with prefix \jid{irc-t.net}. - Moreover, the transport is only accessible to two users - of \term{example.org}, and any user of \term{example.com}: -\begin{verbatim} -acl: - paying_customers: - user: - - "customer1": "example.org" - - "customer2": "example.org" - server: "example.com" - -access: - irc_users: - paying_customers: allow - all: deny - -modules: - ... - mod_irc: - access: irc_users - host: "irc.example.net" - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modlast}{\modlast{}} -\ind{modules!\modlast{}}\ind{protocols!XEP-0012: Last Activity} - -This module adds support for Last Activity (\xepref{0012}). It can be used to -discover when a disconnected user last accessed the server, to know when a -connected user was last active on the server, or to query the uptime of the -\ejabberd{} server. - -Options: -\begin{description} -\iqdiscitem{Last activity (\ns{jabber:iq:last})} -\dbtype -\end{description} - -\makesubsection{modmuc}{\modmuc{}} -\ind{modules!\modmuc{}}\ind{protocols!XEP-0045: Multi-User Chat}\ind{conferencing} - -This module provides a Multi-User Chat (\xepref{0045}) service. -Users can discover existing rooms, join or create them. -Occupants of a room can chat in public or have private chats. - -Some of the features of Multi-User Chat: -\begin{itemize} -\item Sending public and private messages to room occupants. -\item Inviting other users to a room. -\item Setting a room subject. -\item Creating password protected rooms. -\item Kicking and banning occupants. -\end{itemize} - -The MUC service allows any Jabber ID to register a nickname, -so nobody else can use that nickname in any room in the MUC service. -To register a nickname, open the Service Discovery in your -XMPP client and register in the MUC service. - -This module supports clustering and load -balancing. One module can be started per cluster node. Rooms are -distributed at creation time on all available MUC module -instances. The multi-user chat module is clustered but the rooms -themselves are not clustered nor fault-tolerant: if the node managing a -set of rooms goes down, the rooms disappear and they will be recreated -on an available node on first connection attempt. - -Module options: -\begin{description} -\hostitem{conference} -\dbtype -\titem{access: AccessName} \ind{options!access}You can specify who is allowed to use - the Multi-User Chat service. By default everyone is allowed to use it. -\titem{access\_create: AccessName} \ind{options!access\_create}To configure who is - allowed to create new rooms at the Multi-User Chat service, this option can be used. - By default any account in the local ejabberd server is allowed to create rooms. -\titem{access\_persistent: AccessName} \ind{options!access\_persistent}To configure who is - allowed to modify the 'persistent' room option. - By default any account in the local ejabberd server is allowed to modify that option. -\titem{access\_admin: AccessName} \ind{options!access\_admin}This option specifies - who is allowed to administrate the Multi-User Chat service. The default - value is \term{none}, which means that only the room creator can - administer his room. - The administrators can send a normal message to the service JID, - and it will be shown in all active rooms as a service message. - The administrators can send a groupchat message to the JID of an active room, - and the message will be shown in the room as a service message. -\titem{history\_size: Size} \ind{options!history\_size}A small history of - the current discussion is sent to users when they enter the - room. With this option you can define the number of history messages - to keep and send to users joining the room. The value is an - integer. Setting the value to \term{0} disables the history feature - and, as a result, nothing is kept in memory. The default value is - \term{20}. This value is global and thus affects all rooms on the - service. -\titem{max\_users: Number} \ind{options!max\_users} This option defines at - the service level, the maximum number of users allowed per - room. It can be lowered in each room configuration but cannot be - increased in individual room configuration. The default value is - 200. -\titem{max\_users\_admin\_threshold: Number} - \ind{options!max\_users\_admin\_threshold} This option defines the - number of service admins or room owners allowed to enter the room when - the maximum number of allowed occupants was reached. The default limit - is 5. -\titem{max\_user\_conferences: Number} - \ind{options!max\_user\_conferences} This option defines the maximum - number of rooms that any given user can join. The default value - is 10. This option is used to prevent possible abuses. Note that - this is a soft limit: some users can sometimes join more conferences - in cluster configurations. -\titem{max\_room\_id: Number} \ind{options!max\_room\_id} - This option defines the maximum number of characters that Room ID - can have when creating a new room. - The default value is to not limit: \term{infinity}. -\titem{max\_room\_name: Number} \ind{options!max\_room\_name} - This option defines the maximum number of characters that Room Name - can have when configuring the room. - The default value is to not limit: \term{infinity}. -\titem{max\_room\_desc: Number} \ind{options!max\_room\_desc} - This option defines the maximum number of characters that Room Description - can have when configuring the room. - The default value is to not limit: \term{infinity}. -\titem{min\_message\_interval: Number} \ind{options!min\_message\_interval} - This option defines the minimum interval between two messages send - by an occupant in seconds. This option is global and valid for all - rooms. A decimal value can be used. When this option is not defined, - message rate is not limited. This feature can be used to protect a - MUC service from occupant abuses and limit number of messages that will - be broadcasted by the service. A good value for this minimum message - interval is 0.4 second. If an occupant tries to send messages faster, an - error is send back explaining that the message has been discarded - and describing the reason why the message is not acceptable. -\titem{min\_presence\_interval: Number} - \ind{options!min\_presence\_interval} This option defines the - minimum of time between presence changes coming from a given occupant in - seconds. This option is global and valid for all rooms. A - decimal value can be used. When this option is not defined, no - restriction is applied. This option can be used to protect a MUC - service for occupants abuses. If an occupant tries - to change its presence more often than the specified interval, the - presence is cached by \ejabberd{} and only the last presence is - broadcasted to all occupants in the room after expiration of the - interval delay. Intermediate presence packets are silently - discarded. A good value for this option is 4 seconds. -\titem{default\_room\_options: \{OptionName: OptionValue\}} \ind{options!default\_room\_options} - This module option allows to define the desired default room options. - Note that the creator of a room can modify the options of his room - at any time using an XMPP client with MUC capability. - The available room options and the default values are: - \begin{description} - \titem{allow\_change\_subj: true|false} Allow occupants to change the subject. - \titem{allow\_private\_messages: true|false} Occupants can send private messages to other occupants. - \titem{allow\_private\_messages\_from\_visitors: anyone|moderators|nobody} Visitors can send private messages to other occupants. - \titem{allow\_query\_users: true|false} Occupants can send IQ queries to other occupants. - \titem{allow\_user\_invites: false|true} Allow occupants to send invitations. - \titem{allow\_visitor\_nickchange: true|false} Allow visitors to - change nickname. - \titem{allow\_visitor\_status: true|false} Allow visitors to send - status text in presence updates. If disallowed, the \term{status} - text is stripped before broadcasting the presence update to all - the room occupants. - \titem{anonymous: true|false} The room is anonymous: - occupants don't see the real JIDs of other occupants. - Note that the room moderators can always see the real JIDs of the occupants. - \titem{captcha\_protected: false} - When a user tries to join a room where he has no affiliation (not owner, admin or member), - the room requires him to fill a CAPTCHA challenge (see section \ref{captcha}) - in order to accept her join in the room. - \titem{logging: false|true} The public messages are logged using \term{mod\_muc\_log}. - \titem{max\_users: 200} Maximum number of occupants in the room. - \titem{members\_by\_default: true|false} The occupants that enter the room are participants by default, so they have 'voice'. - \titem{members\_only: false|true} Only members of the room can enter. - \titem{moderated: true|false} Only occupants with 'voice' can send public messages. - \titem{password: "roompass123"} Password of the room. You may want to enable the next option too. - \titem{password\_protected: false|true} The password is required to enter the room. - \titem{persistent: false|true} The room persists even if the last participant leaves. - \titem{public: true|false} The room is public in the list of the MUC service, so it can be discovered. - \titem{public\_list: true|false} The list of participants is public, without requiring to enter the room. - \titem{title: "Room Title"} A human-readable title of the room. - \end{description} - All of those room options can be set to \term{true} or \term{false}, - except \term{password} and \term{title} which are strings, - and \term{max\_users} that is integer. -\end{description} - -Examples: -\begin{itemize} -\item In the first example everyone is allowed to use the Multi-User Chat - service. Everyone will also be able to create new rooms but only the user - \jid{admin@example.org} is allowed to administrate any room. In this - example he is also a global administrator. When \jid{admin@example.org} - sends a message such as `Tomorrow, the \XMPP{} server will be moved - to new hardware. This will involve service breakdowns around 23:00 UMT. - We apologise for this inconvenience.' to \jid{conference.example.org}, - it will be displayed in all active rooms. In this example the history - feature is disabled. -\begin{verbatim} -acl: - admin: - user: - - "admin": "example.org" - -access: - muc_admin: - admin: allow - -modules: - ... - mod_muc: - access: all - access_create: all - access_admin: muc_admin - history_size: 0 - ... -\end{verbatim} -\item In the second example the Multi-User Chat service is only accessible by - paying customers registered on our domains and on other servers. Of course - the administrator is also allowed to access rooms. In addition, he is the - only authority able to create and administer rooms. When - \jid{admin@example.org} sends a message such as `Tomorrow, the \Jabber{} - server will be moved to new hardware. This will involve service breakdowns - around 23:00 UMT. We apologise for this inconvenience.' to - \jid{conference.example.org}, it will be displayed in all active rooms. No - \term{history\_size} option is used, this means that the feature is enabled - and the default value of 20 history messages will be send to the users. -\begin{verbatim} -acl: - paying_customers: - user: - - "customer1": "example.net" - - "customer2": "example.com" - - "customer3": "example.org" - admin: - user: - - "admin": "example.org" - -access: - muc_admin - admin: allow - all: deny - muc_access: - paying_customers: allow - admin: allow - all: deny - -modules: - ... - mod_muc: - access: muc_access - access_create: muc_admin - access_admin: muc_admin - ... -\end{verbatim} - -\item In the following example, MUC anti abuse options are used. An -occupant cannot send more than one message every 0.4 seconds and cannot -change its presence more than once every 4 seconds. -The length of Room IDs and Room Names are limited to 20 characters, -and Room Description to 300 characters. No ACLs are -defined, but some user restriction could be added as well: - -\begin{verbatim} -modules: - ... - mod_muc: - min_message_interval: 0.4 - min_presence_interval: 4 - max_room_id: 20 - max_room_name: 20 - max_room_desc: 300 - ... -\end{verbatim} - -\item This example shows how to use \option{default\_room\_options} to make sure - the newly created rooms have by default those options. -\begin{verbatim} -modules: - ... - mod_muc: - access: muc_access - access_create: muc_admin - default_room_options: - allow_change_subj: false - allow_query_users: true - allow_private_messages: true - members_by_default: false - title: "New chatroom" - anonymous: false - access_admin: muc_admin - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modmuclog}{\modmuclog{}} -\ind{modules!\modmuclog{}} - -This module enables optional logging of Multi-User Chat (MUC) public conversations to -HTML. Once you enable this module, users can join a room using a MUC capable -XMPP client, and if they have enough privileges, they can request the -configuration form in which they can set the option to enable room logging. - -Features: -\begin{itemize} -\item Room details are added on top of each page: room title, JID, - author, subject and configuration. -\item \ind{protocols!RFC 5122: Internationalized Resource Identifiers (IRIs) and Uniform Resource Identifiers (URIs) for the Extensible Messaging and Presence Protocol (XMPP)} - The room JID in the generated HTML is a link to join the room (using - \footahref{http://xmpp.org/rfcs/rfc5122.html}{XMPP URI}). -\item Subject and room configuration changes are tracked and displayed. -\item Joins, leaves, nick changes, kicks, bans and `/me' are tracked and - displayed, including the reason if available. -\item Generated HTML files are XHTML 1.0 Transitional and CSS compliant. -\item Timestamps are self-referencing links. -\item Links on top for quicker navigation: Previous day, Next day, Up. -\item CSS is used for style definition, and a custom CSS file can be used. -\item URLs on messages and subjects are converted to hyperlinks. -\item Timezone used on timestamps is shown on the log files. -\item A custom link can be added on top of each page. -\end{itemize} - -Options: -\begin{description} -\titem{access\_log: AccessName}\ind{options!access\_log} - This option restricts which occupants are allowed to enable or disable room - logging. The default value is \term{muc\_admin}. Note for this default setting - you need to have an access rule for \term{muc\_admin} in order to take effect. -\titem{cssfile: false|URL}\ind{options!cssfile} - With this option you can set whether the HTML files should have a custom CSS - file or if they need to use the embedded CSS file. Allowed values are - \term{false} and an URL to a CSS file. With the first value, HTML files will - include the embedded CSS code. With the latter, you can specify the URL of the - custom CSS file (for example: \term{"http://example.com/my.css"}). The default value - is \term{false}. -\titem{dirname: room\_jid|room\_name}\ind{options!dirname} - Allows to configure the name of the room directory. - Allowed values are \term{room\_jid} and \term{room\_name}. - With the first value, the room directory name will be the full room JID. - With the latter, the room directory name will be only the room name, - not including the MUC service name. - The default value is \term{room\_jid}. -\titem{dirtype: subdirs|plain}\ind{options!dirtype} - The type of the created directories can be specified with this option. Allowed - values are \term{subdirs} and \term{plain}. With the first value, - subdirectories are created for each year and month. With the latter, the - names of the log files contain the full date, and there are no subdirectories. - The default value is \term{subdirs}. -\titem{file\_format: html|plaintext}\ind{options!file\_format} - Define the format of the log files: - \term{html} stores in HTML format, - \term{plaintext} stores in plain text. - The default value is \term{html}. -\titem{file\_permissions: \{mode: Mode, group: Group\}}\ind{options!file\_permissions} - Define the permissions that must be used when creating the log files: - the number of the mode, and the numeric id of the group that will own the files. - The default value is \term{\{644, 33\}}. -\titem{outdir: Path}\ind{options!outdir} - This option sets the full path to the directory in which the HTML files should - be stored. Make sure the \ejabberd{} daemon user has write access on that - directory. The default value is \term{"www/muc"}. -\titem{spam\_prevention: true|false}\ind{options!spam\_prevention} - To prevent spam, the \term{spam\_prevention} option adds a special attribute - to links that prevent their indexation by search engines. The default value - is \term{true}, which mean that nofollow attributes will be added to user - submitted links. -\titem{timezone: local|universal}\ind{options!timezone} - The time zone for the logs is configurable with this option. Allowed values - are \term{local} and \term{universal}. With the first value, the local time, - as reported to Erlang by the operating system, will be used. With the latter, - GMT/UTC time will be used. The default value is \term{local}. -\titem{top\_link: \{URL: Text\}}\ind{options!top\_link} - With this option you can customize the link on the top right corner of each - log file. The default value is \term{\{"/", "Home"\}}. -\end{description} - -Examples: -\begin{itemize} -\item In the first example any room owner can enable logging, and a - custom CSS file will be used (http://example.com/my.css). The names - of the log files will contain the full date, and there will be no - subdirectories. The log files will be stored in /var/www/muclogs, and the - time zone will be GMT/UTC. Finally, the top link will be - \verb|Jabber.ru|. -\begin{verbatim} -access: - muc: - all: allow - -modules: - ... - mod_muc_log: - access_log: muc - cssfile: "http://example.com/my.css" - dirtype: plain - dirname: room_jid - outdir: "/var/www/muclogs" - timezone: universal - spam_prevention: true - top_link: - "http://www.jabber.ru/": "Jabber.ru" - ... -\end{verbatim} - \item In the second example only \jid{admin1@example.org} and - \jid{admin2@example.net} can enable logging, and the embedded CSS file will be - used. The names of the log files will only contain the day (number), - and there will be subdirectories for each year and month. The log files will - be stored in /var/www/muclogs, and the local time will be used. Finally, the - top link will be the default \verb|Home|. -\begin{verbatim} -acl: - admin: - user: - - "admin1": "example.org" - - "admin2": "example.net" -access: - muc_log: - admin: allow - all: deny - -modules: - ... - mod_muc_log: - access_log: muc_log - cssfile: false - dirtype: subdirs - file_permissions: - mode: 644 - group: 33 - outdir: "/var/www/muclogs" - timezone: local - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modoffline}{\modoffline{}} -\ind{modules!\modoffline{}} - -This module implements offline message storage (\xepref{0160}). -This means that all messages -sent to an offline user will be stored on the server until that user comes -online again. Thus it is very similar to how email works. Note that -\term{ejabberdctl}\ind{ejabberdctl} has a command to delete expired messages -(see section~\ref{ejabberdctl}). - -\begin{description} - \dbtype - \titem{access\_max\_user\_messages: AccessName}\ind{options!access\_max\_user\_messages} - This option defines which access rule will be enforced to limit - the maximum number of offline messages that a user can have (quota). - When a user has too many offline messages, any new messages that he receive are discarded, - and a resource-constraint error is returned to the sender. - The default value is \term{max\_user\_offline\_messages}. - Then you can define an access rule with a syntax similar to - \term{max\_user\_sessions} (see \ref{configmaxsessions}). - \titem{store\_empty\_body: true|false}\ind{options!store\_empty\_body} Whether or not - to store messages with empty \term{} element. The default value is \term{true}. -\end{description} - -This example allows power users to have as much as 5000 offline messages, -administrators up to 2000, -and all the other users up to 100. -\begin{verbatim} -acl: - admin: - user: - - "admin1": "localhost" - - "admin2": "example.org" - poweruser: - user: - - "bob": "example.org" - - "jane": "example.org" - -access: - max_user_offline_messages: - poweruser: 5000 - admin: 2000 - all: 100 - -modules: - ... - mod_offline: - access_max_user_messages: max_user_offline_messages - ... -\end{verbatim} - -\makesubsection{modping}{\modping{}} -\ind{modules!\modping{}} - -This module implements support for XMPP Ping (\xepref{0199}) and periodic keepalives. -When this module is enabled ejabberd responds correctly to -ping requests, as defined in the protocol. - -Configuration options: -\begin{description} - \titem{send\_pings: true|false}\ind{options!send\_pings} - If this option is set to \term{true}, the server sends pings to connected clients - that are not active in a given interval \term{ping\_interval}. - This is useful to keep client connections alive or checking availability. - By default this option is disabled. - % because it is mostly not needed and consumes resources. - \titem{ping\_interval: Seconds}\ind{options!ping\_interval} - How often to send pings to connected clients, if the previous option is enabled. - If a client connection does not send or receive any stanza in this interval, - a ping request is sent to the client. - The default value is 60 seconds. - \titem{timeout\_action: none|kill}\ind{options!timeout\_action} - What to do when a client does not answer to a server ping request in less than 32 seconds. - % Those 32 seconds are defined in ejabberd_local.erl: -define(IQ_TIMEOUT, 32000). - The default is to do nothing. -\end{description} - -This example enables Ping responses, configures the module to send pings -to client connections that are inactive for 4 minutes, -and if a client does not answer to the ping in less than 32 seconds, its connection is closed: -\begin{verbatim} -modules: - ... - mod_ping: - send_pings: true - ping_interval: 240 - timeout_action: kill - ... -\end{verbatim} - -\makesubsection{modprescounter}{\modprescounter{}} -\ind{modules!\modprescounter{}} - -This module detects flood/spam in presence subscription stanza traffic. -If a user sends or receives more of those stanzas in a time interval, -the exceeding stanzas are silently dropped, and warning is logged. - -Configuration options: -\begin{description} - \titem{count: StanzaNumber}\ind{options!count} - The number of subscription presence stanzas - (subscribe, unsubscribe, subscribed, unsubscribed) - allowed for any direction (input or output) - per time interval. - Please note that two users subscribing to each other usually generate - 4 stanzas, so the recommended value is 4 or more. - The default value is: 5. - \titem{interval: Seconds}\ind{options!interval} - The time interval defined in seconds. - The default value is 60. -\end{description} - -This example enables the module, and allows up to 5 presence subscription stanzas -to be sent or received by the users in 60 seconds: -\begin{verbatim} -modules: - ... - mod_pres_counter: - count: 5 - interval: 60 - ... -\end{verbatim} - -\makesubsection{modprivacy}{\modprivacy{}} -\ind{modules!\modprivacy{}}\ind{Blocking Communication}\ind{Privacy Rules}\ind{protocols!XEP-0016: Privacy Lists} - -This module implements \footahref{http://www.xmpp.org/extensions/xep-0016.html}{XEP-0016: Privacy Lists}. -If end users have support for it in their \XMPP{} client, they will be able to: -\begin{quote} -\begin{itemize} -\item Retrieving one's privacy lists. -\item Adding, removing, and editing one's privacy lists. -\item Setting, changing, or declining active lists. -\item Setting, changing, or declining the default list (i.e., the list that - is active by default). -\item Allowing or blocking messages based on JID, group, or subscription type - (or globally). -\item Allowing or blocking inbound presence notifications based on JID, group, - or subscription type (or globally). -\item Allowing or blocking outbound presence notifications based on JID, group, - or subscription type (or globally). -\item Allowing or blocking IQ stanzas based on JID, group, or subscription type - (or globally). -\item Allowing or blocking all communications based on JID, group, or - subscription type (or globally). -\end{itemize} -\end{quote} - -Options: -\begin{description} -\iqdiscitem{Blocking Communication (\ns{jabber:iq:privacy})} -\dbtype -\end{description} - -\makesubsection{modprivate}{\modprivate{}} -\ind{modules!\modprivate{}}\ind{protocols!XEP-0049: Private XML Storage}\ind{protocols!XEP-0048: Bookmark Storage} - -This module adds support for Private XML Storage (\xepref{0049}): -\begin{quote} -Using this method, XMPP entities can store private data on the server and -retrieve it whenever necessary. The data stored might be anything, as long as -it is valid XML. One typical usage for this namespace is the server-side storage -of client-specific preferences; another is Bookmark Storage (\xepref{0048}). -\end{quote} - -Options: -\begin{description} -\iqdiscitem{Private XML Storage (\ns{jabber:iq:private})} -\dbtype -\end{description} - -\makesubsection{modproxy}{\modproxy{}} -\ind{modules!\modversion{}}\ind{protocols!XEP-0065: SOCKS5 Bytestreams} - -This module implements SOCKS5 Bytestreams (\xepref{0065}). -It allows \ejabberd{} to act as a file transfer proxy between two -XMPP clients. - -Options: -\begin{description} -\hostitem{proxy} -\titem{name: Text}\ind{options!name}Defines Service Discovery name of the service. -Default is \term{"SOCKS5 Bytestreams"}. -\titem{ip: IP}\ind{options!ip}This option specifies which network interface -to listen for. Default is an IP address of the service's DNS name, or, -if fails, \verb|"127.0.0.1"|. -\titem{port: Number}\ind{options!port}This option defines port to listen for -incoming connections. Default is~7777. -\titem{hostname: HostName}\ind{options!hostname}Defines a hostname advertised -by the service when establishing a session with clients. This is useful when -you run the service behind a NAT. The default is the value of \term{ip} option. -Examples: \term{"proxy.mydomain.org"}, \term{"200.150.100.50"}. Note that -not all clients understand domain names in stream negotiation, -so you should think twice before setting domain name in this option. -\titem{auth\_type: anonymous|plain}\ind{options!auth\_type}SOCKS5 authentication type. -Possible values are \term{anonymous} and \term{plain}. Default is -\term{anonymous}. -\titem{access: AccessName}\ind{options!access}Defines ACL for file transfer initiators. -Default is \term{all}. -\titem{max\_connections: Number}\ind{options!max\_connections}Maximum number of -active connections per file transfer initiator. No limit by default. -\titem{shaper: none|ShaperName}\ind{options!shaper}This option defines shaper for -the file transfer peers. Shaper with the maximum bandwidth will be selected. -Default is \term{none}. -\end{description} - -Examples: -\begin{itemize} -\item The simpliest configuration of the module: -\begin{verbatim} -modules: - ... - mod_proxy65: {} - ... -\end{verbatim} -\item More complicated configuration. -\begin{verbatim} -acl: - admin: - user: - - "admin": "example.org" - proxy_users: - server: - - "example.org" - -access: - proxy65_access: - proxy_users: allow - all: deny - proxy65_shaper: - admin: none - proxy_users: proxyrate - -shaper: - proxyrate: 10240 - -modules: - ... - mod_proxy65: - host: "proxy1.example.org" - name: "File Transfer Proxy" - ip: "200.150.100.1" - port: 7778 - max_connections: 5 - access: proxy65_access - shaper: proxy65_shaper - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modpubsub}{\modpubsub{}} -\ind{modules!\modpubsub{}}\ind{protocols!XEP-0060: Publish-Subscribe} - -This module offers a Publish-Subscribe Service (\xepref{0060}). -The functionality in \modpubsub{} can be extended using plugins. -The plugin that implements PEP (Personal Eventing via Pubsub) (\xepref{0163}) -is enabled in the default ejabberd configuration file, -and it requires \modcaps{}. - -Options: -\begin{description} -\hostitem{pubsub} - If you use \modpubsubodbc, please ensure the prefix contains only one dot, - for example `\jid{pubsub.}', or `\jid{publish.}',. -\titem{access\_createnode: AccessName} \ind{options!access\_createnode} - This option restricts which users are allowed to create pubsub nodes using - ACL and ACCESS. - By default any account in the local ejabberd server is allowed to create pubsub nodes. -\titem{max\_items\_node: MaxItems} \ind{options!max\_items\_node} - Define the maximum number of items that can be stored in a node. - Default value is 10. -\titem{plugins: [ Plugin, ...]} \ind{options!plugins} - To specify which pubsub node plugins to use. - The first one in the list is used by default. - If this option is not defined, the default plugins list is: \term{["flat"]}. - PubSub clients can define which plugin to use when creating a node: - add \term{type='plugin-name'} attribute to the \term{create} stanza element. -\titem{nodetree: Nodetree} \ind{options!nodetree} - To specify which nodetree to use. - If not defined, the default pubsub nodetree is used: "tree". - Only one nodetree can be used per host, and is shared by all node plugins. - - The "virtual" nodetree does not store nodes on database. - This saves resources on systems with tons of nodes. - If using the "virtual" nodetree, - you can only enable those node plugins: - ["flat","pep"] or ["flat"]; - any other plugins configuration will not work. - Also, all nodes will have the defaut configuration, - and this can not be changed. - Using "virtual" nodetree requires to start from a clean database, - it will not work if you used the default "tree" nodetree before. - - The "dag" nodetree provides experimental support for PubSub Collection Nodes (\xepref{0248}). - In that case you should also add "dag" node plugin as default, for example: - \term{plugins: ["dag","flat","hometree","pep"]} -\titem{ignore\_pep\_from\_offline: false|true} \ind{options!ignore\_pep\_from\_offline} - To specify whether or not we should get last published PEP items - from users in our roster which are offline when we connect. Value is true or false. - If not defined, pubsub assumes true so we only get last items of online contacts. -\titem{last\_item\_cache: false|true} \ind{options!last\_item\_cache} - To specify whether or not pubsub should cache last items. Value is true - or false. If not defined, pubsub do not cache last items. On systems with not so many nodes, - caching last items speeds up pubsub and allows to raise user connection rate. The cost is memory - usage, as every item is stored in memory. -\titem{pep\_mapping: \{Key, Value\}} \ind{pep\_mapping} - This allow to define a Key-Value list to choose defined node plugins on given PEP namespace. - The following example will use node\_tune instead of node\_pep for every PEP node with tune namespace: -\begin{verbatim} -modules: - ... - mod_pubsub: - pep_mapping: - "http://jabber.org/protocol/tune": "tune" - ... -\end{verbatim} -%\titem{served\_hosts} \ind{options!served\_hosts} -% This option allows to create additional pubsub virtual hosts in a single module instance. -\end{description} - -Example of configuration that uses flat nodes as default, and allows use of flat, nodetree and pep nodes: -\begin{verbatim} -modules: - ... - mod_pubsub: - access_createnode: pubsub_createnode - plugins: - - "flat" - - "hometree" - - "pep" - ... -\end{verbatim} - -Using ODBC database requires using mod\_pubsub\_odbc without option changes. Only flat, hometree and pep plugins supports ODBC. -The following example shows previous configuration with ODBC usage: -\begin{verbatim} -modules: - ... - mod_pubsub_odbc: - access_createnode: pubsub_createnode - plugins: - - "flat" - - "hometree" - - "pep" - ... -\end{verbatim} - -\makesubsection{modregister}{\modregister{}} -\ind{modules!\modregister{}}\ind{protocols!XEP-0077: In-Band Registration}\ind{public registration} - -This module adds support for In-Band Registration (\xepref{0077}). This protocol -enables end users to use a \XMPP{} client to: -\begin{itemize} -\item Register a new account on the server. -\item Change the password from an existing account on the server. -\item Delete an existing account on the server. -\end{itemize} - - -Options: -\begin{description} -\titem{access: AccessName} \ind{options!access} - Specify rules to restrict what usernames can be registered and unregistered. - If a rule returns `deny' on the requested username, - registration and unregistration of that user name is denied. - There are no restrictions by default. -\titem{access\_from: AccessName} \ind{options!access\_from}By default, \ejabberd{} -doesn't allow to register new accounts from s2s or existing c2s sessions. You can -change it by defining access rule in this option. Use with care: allowing registration -from s2s leads to uncontrolled massive accounts creation by rogue users. -\titem{captcha\_protected: false|true} \ind{options!captcha\_protected} -Protect registrations with CAPTCHA (see section \ref{captcha}). The default is \term{false}. -\titem{ip\_access: AccessName} \ind{options!ip\_access} - Define rules to allow or deny account registration depending - on the IP address of the XMPP client. The \term{AccessName} should be - of type \term{ip}. The default value is \term{all}. -\titem{password\_strength: Entropy} \ind{options!password\_strength} -This option sets the minimum informational entropy for passwords. The value \term{Entropy} -is a number of bits of entropy. The recommended minimum is 32 bits. -The default is 0, i.e. no checks are performed. -\titem{welcome\_message: \{subject: Subject, body: Body\}} - \ind{options!welcomem} Set a welcome message that - is sent to each newly registered account. The first string is the subject, and - the second string is the message body. -\titem{registration\_watchers: [ JID, ...]} \ind{options!rwatchers}This option defines a - list of JIDs which will be notified each time a new account is registered. -\iqdiscitem{In-Band Registration (\ns{jabber:iq:register})} -\end{description} - -This module reads also another option defined globally for the server: -\term{registration\_timeout: Timeout}. \ind{options!registratimeout} -This option limits the frequency of registration from a given IP or username. -So, a user that tries to register a new account from the same IP address or JID during -this number of seconds after his previous registration -will receive an error \term{resource-constraint} with the explanation: -``Users are not allowed to register accounts so quickly''. -The timeout is expressed in seconds, and it must be an integer. -To disable this limitation, -instead of an integer put a word like: \term{infinity}. -Default value: 600 seconds. - -Examples: -\begin{itemize} -\item Next example prohibits the registration of too short account names, -and allows to create accounts only to clients of the local network: -\begin{verbatim} -acl: - loopback: - ip: - - "127.0.0.0/8" - - "::1" - shortname: - user_glob: - - "?" - - "??" - ## The same using regexp: - ##user_regexp: "^..?$" - -access: - mynetworks: - loopback: allow - all: deny - register: - shortname: deny - all: allow - -modules: - mod_register: - ip_access: mynetworks - access: register -\end{verbatim} -\item This configuration prohibits usage of In-Band Registration - to create or delete accounts, - but allows existing accounts to change the password: -\begin{verbatim} -access: - register: - all: deny - -modules: - ... - mod_register: - access: register - ... -\end{verbatim} -\item - This configuration disables all In-Band Registration - functionality: create, delete accounts and change password: -\begin{verbatim} -modules: - ... - ## mod_register: - ## access: register - ... -\end{verbatim} -\item Define the welcome message and two registration watchers. -Also define a registration timeout of one hour: -\begin{verbatim} -registration_timeout: 3600 -modules: - ... - mod_register: - welcome_message: - subject: "Welcome!" - body: |- - Hi. - Welcome to this Jabber server. - Check http://www.jabber.org - - Bye - registration_watchers: - - "admin1@example.org" - - "boss@example.net" - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modregisterweb}{\modregisterweb{}} -\ind{modules!\modregisterweb{}} - -This module provides a web page where people can: -\begin{itemize} -\item Register a new account on the server. -\item Change the password from an existing account on the server. -\item Delete an existing account on the server. -\end{itemize} - -This module supports CAPTCHA image to register a new account. -To enable this feature, configure the options captcha\_cmd and captcha\_host. - -Options: -\begin{description} -\titem{registration\_watchers: [ JID, ...]} \ind{options!rwatchers}This option defines a - list of JIDs which will be notified each time a new account is registered. -\end{description} - -This example configuration shows how to enable the module and the web handler: -\begin{verbatim} -hosts: - - "localhost" - - "example.org" - - "example.com" -listen: - ... - - - port: 5281 - module: ejabberd_http - register: true - certfile: "/etc/ejabberd/certificate.pem" - tls: true - ... - -modules: - ... - mod_register_web: {} - ... -\end{verbatim} - -For example, the users of the host \term{example.org} can visit the page: -\ns{https://example.org:5281/register/} -It is important to include the last / character in the URL, -otherwise the subpages URL will be incorrect. - -\makesubsection{modroster}{\modroster{}} -\ind{modules!\modroster{}}\ind{roster management}\ind{protocols!RFC 6121: XMPP IM} - -This module implements roster management as defined in -\footahref{http://tools.ietf.org/html/rfc6121\#section-2}{RFC 6121: XMPP IM}. -It also supports Roster Versioning (\xepref{0237}). - -Options: -\begin{description} -\iqdiscitem{Roster Management (\ns{jabber:iq:roster})} -\dbtype - \titem{versioning: false|true} \ind{options!versioning}Enables - Roster Versioning. - This option is disabled by default. - \titem{store\_current\_id: false|true} \ind{options!storecurrentid} - If this option is enabled, the current version number is stored on the database. - If disabled, the version number is calculated on the fly each time. - Enabling this option reduces the load for both ejabberd and the database. - This option does not affect the client in any way. - This option is only useful if Roster Versioning is enabled. - This option is disabled by default. - Important: if you use \modsharedroster{} or \modsharedrosterldap{}, - you must disable this option. - \titem{access} \ind{options!access} - This option can be configured to specify rules to restrict roster management. - If a rule returns `deny' on the requested user name, - that user cannot modify his personal roster: - not add/remove/modify contacts, - or subscribe/unsubscribe presence. - By default there aren't restrictions. - \titem{managers} \ind{options!managers} - List of remote entities that can manage users rosters using Remote Roster Management - (\xepref{0321}). - The protocol sections implemented are: - \term{4.2. The remote entity requests current user's roster}. - \term{4.3. The user updates roster}. - \term{4.4. The remote entity updates the user's roster}. - A remote entity cab only get or modify roster items that have the same domain as the entity. - Default value is: \term{[]}. -\end{description} - -This example configuration enables Roster Versioning with storage of current id. -The ICQ and MSN transports can get ICQ and MSN contacts, add them, or remove them for any local account: -\begin{verbatim} -modules: - ... - mod_roster: - versioning: true - store_current_id: true - managers: - - "icq.example.org" - - "msn.example.org" - ... -\end{verbatim} - -With this example configuration, only admins can manage their rosters; -everybody else cannot modify the roster: -\begin{verbatim} -acl: - admin: - user: - - "sarah": "example.org" -access: - roster: - admin: allow - -modules: - ... - mod_roster: - access: roster - ... -\end{verbatim} - -\makesubsection{modservicelog}{\modservicelog{}} -\ind{modules!\modservicelog{}}\ind{message auditing}\ind{Bandersnatch} - -This module adds support for logging end user packets via a \XMPP{} message -auditing service such as -\footahref{http://www.funkypenguin.info/project/bandersnatch/}{Bandersnatch}. All user -packets are encapsulated in a \verb|| element and sent to the specified -service(s). - -Options: -\begin{description} -\titem{loggers: [Names, ...]} \ind{options!loggers}With this option a (list of) service(s) - that will receive the packets can be specified. -\end{description} - -Examples: -\begin{itemize} -\item To log all end user packets to the Bandersnatch service running on - \jid{bandersnatch.example.com}: -\begin{verbatim} -modules: - ... - mod_service_log: - loggers: ["bandersnatch.example.com"] - ... -\end{verbatim} -\item To log all end user packets to the Bandersnatch service running on - \jid{bandersnatch.example.com} and the backup service on - \jid{bandersnatch.example.org}: -\begin{verbatim} -modules: - ... - mod_service_log: - loggers: - - "bandersnatch.example.com" - - "bandersnatch.example.org" - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modsharedroster}{\modsharedroster{}} -\ind{modules!\modsharedroster{}}\ind{shared roster groups} - -This module enables you to create shared roster groups. This means that you can -create groups of people that can see members from (other) groups in their -rosters. The big advantages of this feature are that end users do not need to -manually add all users to their rosters, and that they cannot permanently delete -users from the shared roster groups. -A shared roster group can have members from any XMPP server, -but the presence will only be available from and to members -of the same virtual host where the group is created. - -Options: -\begin{description} -\dbtype -\end{description} - -Shared roster groups can be edited \emph{only} via the Web Admin. Each group -has a unique identification and the following parameters: -\begin{description} -\item[Name] The name of the group, which will be displayed in the roster. -\item[Description] The description of the group. This parameter does not affect - anything. -\item[Members] A list of JIDs of group members, entered one per line in - the Web Admin. - The special member directive \term{@all@} - represents all the registered users in the virtual host; - which is only recommended for a small server with just a few hundred users. - The special member directive \term{@online@} - represents the online users in the virtual host. -\item[Displayed groups] - A list of groups that will be in the rosters of this group's members. - A group of other vhost can be identified with \term{groupid@vhost} -\end{description} - -Examples: -\begin{itemize} -\item Take the case of a computer club that wants all its members seeing each - other in their rosters. To achieve this, they need to create a shared roster - group similar to next table: -\begin{table}[H] - \centering - \begin{tabular}{|l|l|} - \hline Identification& Group `\texttt{club\_members}'\\ - \hline Name& Club Members\\ - \hline Description& Members from the computer club\\ - \hline Members& - {\begin{tabular}{l} - \jid{member1@example.org}\\ - \jid{member2@example.org}\\ - \jid{member3@example.org} - \end{tabular} - }\\ - \hline Displayed groups& \texttt{club\_members}\\ - \hline - \end{tabular} -\end{table} -\item In another case we have a company which has three divisions: Management, - Marketing and Sales. All group members should see all other members in their - rosters. Additionally, all managers should have all marketing and sales people - in their roster. Simultaneously, all marketeers and the whole sales team - should see all managers. This scenario can be achieved by creating shared - roster groups as shown in the following table: -\begin{table}[H] - \centering - \begin{tabular}{|l|l|l|l|} - \hline Identification& - Group `\texttt{management}'& - Group `\texttt{marketing}'& - Group `\texttt{sales}'\\ - \hline Name& Management& Marketing& Sales\\ - \hline Description& \\ - Members& - {\begin{tabular}{l} - \jid{manager1@example.org}\\ - \jid{manager2@example.org}\\ - \jid{manager3@example.org}\\ - \jid{manager4@example.org} - \end{tabular} - }& - {\begin{tabular}{l} - \jid{marketeer1@example.org}\\ - \jid{marketeer2@example.org}\\ - \jid{marketeer3@example.org}\\ - \jid{marketeer4@example.org} - \end{tabular} - }& - {\begin{tabular}{l} - \jid{saleswoman1@example.org}\\ - \jid{salesman1@example.org}\\ - \jid{saleswoman2@example.org}\\ - \jid{salesman2@example.org} - \end{tabular} - }\\ - \hline Displayed groups& - {\begin{tabular}{l} - \texttt{management}\\ - \texttt{marketing}\\ - \texttt{sales} - \end{tabular} - }& - {\begin{tabular}{l} - \texttt{management}\\ - \texttt{marketing} - \end{tabular} - }& - {\begin{tabular}{l} - \texttt{management}\\ - \texttt{sales} - \end{tabular} - }\\ - \hline - \end{tabular} -\end{table} -\end{itemize} - -\makesubsection{modsharedrosterldap}{\modsharedrosterldap{}} -\ind{modules!\modsharedrosterldap{}}\ind{shared roster groups ldap} - -This module lets the server administrator -automatically populate users' rosters (contact lists) with entries based on -users and groups defined in an LDAP-based directory. - -\makesubsubsection{msrlconfigparams}{Configuration parameters} - -The module accepts the following configuration parameters. Some of them, if -unspecified, default to the values specified for the top level of -configuration. This lets you avoid specifying, for example, the bind password, -in multiple places. - -\makeparagraph{msrlfilters}{Filters} - -These parameters specify LDAP filters used to query for shared roster information. -All of them are run against the \verb|ldap_base|. - -\begin{description} - - \titem{{\tt ldap\_rfilter}} - So called ``Roster Filter''. Used to find names of all ``shared roster'' groups. - See also the \verb|ldap_groupattr| parameter. - If unspecified, defaults to the top-level parameter of the same name. - You {\em must} specify it in some place in the configuration, there is no default. - - \titem{{\tt ldap\_ufilter}} - ``User Filter'' -- used for retrieving the human-readable name of roster - entries (usually full names of people in the roster). - See also the parameters \verb|ldap_userdesc| and \verb|ldap_useruid|. - If unspecified, defaults to the top-level parameter of the same name. - If that one also is unspecified, then the filter is assembled from values of - other parameters as follows (\verb|[ldap_SOMETHING]| is used to mean ``the - value of the configuration parameter {\tt ldap\_SOMETHING}''): - -\begin{verbatim} -(&(&([ldap_memberattr]=[ldap_memberattr_format])([ldap_groupattr]=%g))[ldap_filter]) -\end{verbatim} - - Subsequently {\tt \%u} and {\tt \%g} are replaced with a {\tt *}. This means - that given the defaults, the filter sent to the LDAP server is would be - \verb|(&(memberUid=*)(cn=*))|. If however the {\tt ldap\_memberattr\_format} - is something like \verb|uid=%u,ou=People,o=org|, then the filter will be - \verb|(&(memberUid=uid=*,ou=People,o=org)(cn=*))|. - - \titem{{\tt ldap\_gfilter}} - ``Group Filter'' -- used when retrieving human-readable name (a.k.a. - ``Display Name'') and the members of a group. - See also the parameters \verb|ldap_groupattr|, \verb|ldap_groupdesc| and \verb|ldap_memberattr|. - If unspecified, defaults to the top-level parameter of the same name. - If that one also is unspecified, then the filter is constructed exactly in the - same way as {\tt User Filter}. - - \titem{{\tt ldap\_filter}} - Additional filter which is AND-ed together with {\tt User Filter} and {\tt - Group Filter}. - If unspecified, defaults to the top-level parameter of the same name. If that - one is also unspecified, then no additional filter is merged with the other - filters. -\end{description} - -Note that you will probably need to manually define the {\tt User} and {\tt -Group Filter}s (since the auto-assembled ones will not work) if: -\begin{itemize} -\item your {\tt ldap\_memberattr\_format} is anything other than a simple {\tt \%u}, -\item {\bf and} the attribute specified with {\tt ldap\_memberattr} does not support substring matches. -\end{itemize} -An example where it is the case is OpenLDAP and {\tt (unique)MemberName} attribute from the {\tt groupOf(Unique)Names} objectClass. -A symptom of this problem is that you will see messages such as the following in your {\tt slapd.log}: -\begin{verbatim} -get_filter: unknown filter type=130 -filter="(&(?=undefined)(?=undefined)(something=else))" -\end{verbatim} - -\makesubsubsection{msrlattrs}{Attributes} - -These parameters specify the names of the attributes which hold interesting data -in the entries returned by running filters specified in -section~\ref{msrlfilters}. - -\begin{description} - \titem{{\tt ldap\_groupattr}} - The name of the attribute that holds the group name, and that is used to differentiate between them. - Retrieved from results of the ``Roster Filter'' and ``Group Filter''. - Defaults to {\tt cn}. - - \titem{{\tt ldap\_groupdesc}} - The name of the attribute which holds the human-readable group name in the - objects you use to represent groups. - Retrieved from results of the ``Group Filter''. - Defaults to whatever {\tt ldap\_groupattr} is set. - - \titem{{\tt ldap\_memberattr}} - The name of the attribute which holds the IDs of the members of a group. - Retrieved from results of the ``Group Filter''. - Defaults to {\tt memberUid}. - - The name of the attribute differs depending on the {\tt objectClass} you use - for your group objects, for example: - \begin{description} - \item{{\tt posixGroup}} $\rightarrow{}$ {\tt memberUid} - \item{{\tt groupOfNames}} $\rightarrow{}$ {\tt member} - \item{{\tt groupOfUniqueNames}} $\rightarrow{}$ {\tt uniqueMember} - \end{description} - - \titem{{\tt ldap\_userdesc}} - The name of the attribute which holds the human-readable user name. - Retrieved from results of the ``User Filter''. - Defaults to {\tt cn}. - - \titem{{\tt ldap\_useruid}} - The name of the attribute which holds the ID of a roster item. Value of this - attribute in the roster item objects needs to match the ID retrieved from the - {\tt ldap\_memberattr} attribute of a group object. - Retrieved from results of the ``User Filter''. - Defaults to {\tt cn}. -\end{description} - -\makesubsubsection{msrlcontrolparams}{Control parameters} - -These paramters control the behaviour of the module. - -\begin{description} - - \titem{{\tt ldap\_memberattr\_format}} - A globbing format for extracting user ID from the value of the attribute named by - \verb|ldap_memberattr|. - Defaults to {\tt \%u}, which means that the whole value is the member ID. If - you change it to something different, you may also need to specify the User - and Group Filters manually --- see section~\ref{msrlfilters}. - - \titem{{\tt ldap\_memberattr\_format\_re}} - A regex for extracting user ID from the value of the attribute named by - \verb|ldap_memberattr|. - - An example value {\tt "CN=($\backslash{}\backslash{}$w*),(OU=.*,)*DC=company,DC=com"} works for user IDs such as the following: - \begin{itemize} - \item \texttt{CN=Romeo,OU=Montague,DC=company,DC=com} - \item \texttt{CN=Abram,OU=Servants,OU=Montague,DC=company,DC=com} - \item \texttt{CN=Juliet,OU=Capulet,DC=company,DC=com} - \item \texttt{CN=Peter,OU=Servants,OU=Capulet,DC=company,DC=com} - \end{itemize} - - In case: - \begin{itemize} - \item the option is unset, - \item or the {\tt re} module in unavailable in the current Erlang environment, - \item or the regular expression does not compile, - \end{itemize} - then instead of a regular expression, a simple format specified by {\tt - ldap\_memberattr\_format} is used. Also, in the last two cases an error - message is logged during the module initialization. - - Also, note that in all cases {\tt ldap\_memberattr\_format} (and {\em not} the - regex version) is used for constructing the default ``User/Group Filter'' --- - see section~\ref{msrlfilters}. - - \titem{{\tt ldap\_auth\_check}} - Whether the module should check (via the ejabberd authentication subsystem) - for existence of each user in the shared LDAP roster. See - section~\ref{msrlconfigroster} form more information. Set to {\tt off} if you - want to disable the check. - Defaults to {\tt on}. - - \titem{{\tt ldap\_user\_cache\_validity}} - Number of seconds for which the cache for roster item full names is considered - fresh after retrieval. 300 by default. See section~\ref{msrlconfigroster} on - how it is used during roster retrieval. - - \titem{{\tt ldap\_group\_cache\_validity}} - Number of seconds for which the cache for group membership is considered - fresh after retrieval. 300 by default. See section~\ref{msrlconfigroster} on - how it is used during roster retrieval. -\end{description} - -\makesubsubsection{msrlconnparams}{Connection parameters} - -The module also accepts the connection parameters, all of which default to the -top-level parameter of the same name, if unspecified. See~\ref{ldapconnection} -for more information about them. - -\makesubsubsection{msrlconfigroster}{Retrieving the roster} - -When the module is called to retrieve the shared roster for a user, the -following algorithm is used: - -\begin{enumerate} -\item \label{step:rfilter} A list of names of groups to display is created: the {\tt Roster Filter} -is run against the base DN, retrieving the values of the attribute named by -{\tt ldap\_groupattr}. - -\item Unless the group cache is fresh (see the {\tt -ldap\_group\_cache\_validity} option), it is refreshed: - - \begin{enumerate} - \item Information for all groups is retrieved using a single query: the {\tt - Group Filter} is run against the Base DN, retrieving the values of attributes - named by {\tt ldap\_groupattr} (group ID), {\tt ldap\_groupdesc} (group - ``Display Name'') and {\tt ldap\_memberattr} (IDs of group members). - - \item group ``Display Name'', read from the attribute named by {\tt - ldap\_groupdesc}, is stored in the cache for the given group - - \item the following processing takes place for each retrieved value of - attribute named by {\tt ldap\_memberattr}: - \begin{enumerate} - \item the user ID part of it is extracted using {\tt - ldap\_memberattr\_format(\_re)}, - - \item then (unless {\tt ldap\_auth\_check} is set to {\tt off}) for each - found user ID, the module checks (using the \ejabberd{} authentication - subsystem) whether such user exists in the given virtual host. It is - skipped if the check is enabled and fails. - - This step is here for historical reasons. If you have a tidy DIT and - properly defined ``Roster Filter'' and ``Group Filter'', it is safe to - disable it by setting {\tt ldap\_auth\_check} to {\tt off} --- it will - speed up the roster retrieval. - - \item the user ID is stored in the list of members in the cache for the - given group - \end{enumerate} - \end{enumerate} - -\item For each item (group name) in the list of groups retrieved in step~\ref{step:rfilter}: - - \begin{enumerate} - \item the display name of a shared roster group is retrieved from the group - cache - - \item for each IDs of users which belong to the group, retrieved from the - group cache: - - \begin{enumerate} - \item the ID is skipped if it's the same as the one for which we are - retrieving the roster. This is so that the user does not have himself in - the roster. - - \item the display name of a shared roster user is retrieved: - \begin{enumerate} - \item first, unless the user name cache is fresh (see the {\tt - ldap\_user\_cache\_validity} option), it is refreshed by running the - {\tt User Filter}, against the Base DN, retrieving the values of - attributes named by {\tt ldap\_useruid} and {\tt ldap\_userdesc}. - \item then, the display name for the given user ID is retrieved from the - user name cache. - \end{enumerate} - \end{enumerate} - - \end{enumerate} - -\end{enumerate} - -\makesubsubsection{msrlconfigexample}{Configuration examples} - -Since there are many possible -\footahref{http://en.wikipedia.org/wiki/Directory\_Information\_Tree}{DIT} -layouts, it will probably be easiest to understand how to configure the module -by looking at an example for a given DIT (or one resembling it). - -\makeparagraph{msrlconfigexampleflat}{Flat DIT} - -This seems to be the kind of DIT for which this module was initially designed. -Basically there are just user objects, and group membership is stored in an -attribute individually for each user. For example in a layout shown in -figure~\ref{fig:msrl-dit-flat}, the group of each user is stored in its {\tt -ou} attribute. - -\begin{figure}[htbp] - \centering - \insscaleimg{0.4}{msrl-dit-flat.png} - \caption{Flat DIT graph} - \label{fig:msrl-dit-flat} -\end{figure} - -Such layout has a few downsides, including: -\begin{itemize} -\item information duplication -- the group name is repeated in every member object -\item difficult group management -- information about group members is not - centralized, but distributed between member objects -\item inefficiency -- the list of unique group names has to be computed by iterating over all users -\end{itemize} - -This however seems to be a common DIT layout, so the module keeps supporting it. -You can use the following configuration\ldots -\begin{verbatim} -modules: - ... - mod_shared_roster_ldap: - ldap_base: "ou=flat,dc=nodomain" - ldap_rfilter: "(objectClass=inetOrgPerson)" - ldap_groupattr: "ou" - ldap_memberattr: "cn" - ldap_filter: "(objectClass=inetOrgPerson)" - ldap_userdesc: "displayName" - ... -\end{verbatim} - -\ldots to be provided with a roster as shown in figure~\ref{fig:msrl-roster-flat} upon connecting as user {\tt czesio}. - -\begin{figure}[htbp] - \centering - \insscaleimg{1}{msrl-roster-flat.png} - \caption{Roster from flat DIT} - \label{fig:msrl-roster-flat} -\end{figure} - -\makeparagraph{msrlconfigexampledeep}{Deep DIT} - -This type of DIT contains distinctly typed objects for users and groups -- see figure~\ref{fig:msrl-dit-deep}. -They are shown separated into different subtrees, but it's not a requirement. - -\begin{figure}[htbp] - \centering - \insscaleimg{0.35}{msrl-dit-deep.png} - \caption{Example ``deep'' DIT graph} - \label{fig:msrl-dit-deep} -\end{figure} - -If you use the following example module configuration with it: -\begin{verbatim} -modules: - ... - mod_shared_roster_ldap: - ldap_base: "ou=deep,dc=nodomain" - ldap_rfilter: "(objectClass=groupOfUniqueNames)" - ldap_filter: "" - ldap_gfilter: "(&(objectClass=groupOfUniqueNames)(cn=%g))" - ldap_groupdesc: "description" - ldap_memberattr: "uniqueMember" - ldap_memberattr_format: "cn=%u,ou=people,ou=deep,dc=nodomain" - ldap_ufilter: "(&(objectClass=inetOrgPerson)(cn=%u))" - ldap_userdesc: "displayName" - ... -\end{verbatim} - -\ldots and connect as user {\tt czesio}, then \ejabberd{} will provide you with -the roster shown in figure~\ref{fig:msrl-roster-deep}. - -\begin{figure}[htbp] - \centering - \insscaleimg{1}{msrl-roster-deep.png} - \caption{Example roster from ``deep'' DIT} - \label{fig:msrl-roster-deep} -\end{figure} - -\makesubsection{modsic}{\modsic{}} -\ind{modules!\modstats{}}\ind{protocols!XEP-0279: Server IP Check} - -This module adds support for Server IP Check (\xepref{0279}). This protocol -enables a client to discover its external IP address. - -Options: -\begin{description} -\iqdiscitem{\ns{urn:xmpp:sic:0}} -\end{description} - -\makesubsection{modsip}{\modsip{}} -\ind{modules!\modsip{}} -This module adds SIP proxy/registrar support for the corresponding virtual host. -Note that it is not enough to just load this module only. You should also configure -listeners and DNS records properly. See section \ref{sip} for the full explanation. - -Example configuration: -\begin{verbatim} -modules: - ... - mod_sip: {} - ... -\end{verbatim} - -Options: -\begin{description} -\titem{record\_route: SIP\_URI}\ind{options!record\_route}When the option -\term{always\_record\_route} is set or when SIP outbound -is utilized \footahref{http://tools.ietf.org/html/rfc5626}{RFC 5626}, -\ejabberd{} inserts \term{Record-Route} header field with this \term{SIP\_URI} -into a SIP message. The default is SIP URI constructed from the virtual host. -\titem{always\_record\_route: true|false}\ind{options!always\_record\_route} -Always insert \term{Record-Route} header into SIP messages. This approach allows -to bypass NATs/firewalls a bit more easily. The default is \term{true}. -\titem{routes: [SIP\_URI]}\ind{options!routes}You can set a list of SIP URIs of routes -pointing to this proxy server. The default is a list of a SIP URI constructed -from the virtual host. -\titem{flow\_timeout\_udp: Seconds}For SIP outbound UDP connections set a keep-alive -timer to \term{Seconds}. The default is 29. -\titem{flow\_timeout\_tcp: Seconds}For SIP outbound TCP connections set a keep-alive -timer to \term{Seconds}. The default is 120. -\titem{via: [\{type: Type, host: Host, port: Port\}]}\ind{options!via}With -this option for every \term{Type} you can specify \term{Host} and \term{Port} -to set in \term{Via} header of outgoing SIP messages, where \term{Type} can be -\term{udp}, \term{tcp} or \term{tls}. \term{Host} is a string and \term{Port} is -a non negative integer. This is useful if you're running your server in a non-standard -network topology. -\end{description} -Example complex configuration: -\begin{verbatim} -modules: - ... - mod_sip: - always_record_route: false - record_route: sip:example.com;lr - routes: - - sip:example.com;lr - - sip:sip.example.com;lr - flow_timeout_udp: 30 - flow_timeout_tcp: 130 - via: - - - type: tls - host: "sip-tls.example.com" - port: 5061 - - - type: tcp - host: "sip-tcp.example.com" - port: 5060 - - - type: udp - host: "sip-udp.example.com" - port: 5060 - ... -\end{verbatim} - -\makesubsection{modstats}{\modstats{}} -\ind{modules!\modstats{}}\ind{protocols!XEP-0039: Statistics Gathering}\ind{statistics} - -This module adds support for Statistics Gathering (\xepref{0039}). This protocol -allows you to retrieve next statistics from your \ejabberd{} deployment: -\begin{itemize} -\item Total number of registered users on the current virtual host (users/total). -\item Total number of registered users on all virtual hosts (users/all-hosts/total). -\item Total number of online users on the current virtual host (users/online). -\item Total number of online users on all virtual hosts (users/all-hosts/online). -\end{itemize} - -Options: -\begin{description} -\iqdiscitem{Statistics Gathering (\ns{http://jabber.org/protocol/stats})} -\end{description} - -As there are only a small amount of clients (for \ind{Tkabber}example -\footahref{http://tkabber.jabber.ru/}{Tkabber}) and software libraries with -support for this XEP, a few examples are given of the XML you need to send -in order to get the statistics. Here they are: -\begin{itemize} -\item You can request the number of online users on the current virtual host - (\jid{example.org}) by sending: -\begin{verbatim} - - - - - -\end{verbatim} -\item You can request the total number of registered users on all virtual hosts - by sending: -\begin{verbatim} - - - - - -\end{verbatim} -\end{itemize} - -\makesubsection{modtime}{\modtime{}} -\ind{modules!\modtime{}}\ind{protocols!XEP-0202: Entity Time} - -This module features support for Entity Time (\xepref{0202}). By using this XEP, -you are able to discover the time at another entity's location. - -Options: -\begin{description} -\iqdiscitem{Entity Time (\ns{jabber:iq:time})} -\end{description} - -\makesubsection{modvcard}{\modvcard{}} -\ind{modules!\modvcard{}}\ind{JUD}\ind{Jabber User Directory}\ind{vCard}\ind{protocols!XEP-0054: vcard-temp} - -This module allows end users to store and retrieve their vCard, and to retrieve -other users vCards, as defined in vcard-temp (\xepref{0054}). The module also -implements an uncomplicated \Jabber{} User Directory based on the vCards of -these users. Moreover, it enables the server to send its vCard when queried. - -Options: -\begin{description} -\hostitem{vjud} -\iqdiscitem{\ns{vcard-temp}} -\dbtype -\titem{search: true|false}\ind{options!search}This option specifies whether the search - functionality is enabled or not - If disabled, the option \term{host} will be ignored and the - \Jabber{} User Directory service will not appear in the Service Discovery item - list. The default value is \term{true}. -\titem{matches: infinity|Number}\ind{options!matches}With this option, the number of reported - search results can be limited. If the option's value is set to \term{infinity}, - all search results are reported. The default value is \term{30}. -\titem{allow\_return\_all: false|true}\ind{options!allow\_return\_all}This option enables - you to specify if search operations with empty input fields should return all - users who added some information to their vCard. The default value is - \term{false}. -\titem{search\_all\_hosts, true|false}\ind{options!search\_all\_hosts}If this option is set - to \term{true}, search operations will apply to all virtual hosts. Otherwise - only the current host will be searched. The default value is \term{true}. - This option is available in \modvcard when using Mnesia, but not when using ODBC storage. -\end{description} - -Examples: -\begin{itemize} -\item In this first situation, search results are limited to twenty items, - every user who added information to their vCard will be listed when people - do an empty search, and only users from the current host will be returned: -\begin{verbatim} -modules: - ... - mod_vcard: - search: true - matches: 20 - allow_return_all: true - search_all_hosts: false - ... -\end{verbatim} -\item The second situation differs in a way that search results are not limited, - and that all virtual hosts will be searched instead of only the current one: -\begin{verbatim} -modules: - ... - mod_vcard: - search: true - matches: infinity - allow_return_all: true - ... -\end{verbatim} -\end{itemize} - -\makesubsection{modvcardldap}{\modvcardldap{}} -\ind{modules!\modvcardldap{}}\ind{JUD}\ind{Jabber User Directory}\ind{vCard}\ind{protocols!XEP-0054: vcard-temp} - -%TODO: verify if the referrers to the LDAP section are still correct - -\ejabberd{} can map LDAP attributes to vCard fields. This behaviour is -implemented in the \modvcardldap{} module. This module does not depend on the -authentication method (see~\ref{ldapauth}). - -Usually \ejabberd{} treats LDAP as a read-only storage: -it is possible to consult data, but not possible to -create accounts or edit vCard that is stored in LDAP. -However, it is possible to change passwords if \module{mod\_register} module is enabled -and LDAP server supports -\footahref{http://tools.ietf.org/html/rfc3062}{RFC 3062}. - -The \modvcardldap{} module has -its own optional parameters. The first group of parameters has the same -meaning as the top-level LDAP parameters to set the authentication method: -\option{ldap\_servers}, \option{ldap\_port}, \option{ldap\_rootdn}, -\option{ldap\_password}, \option{ldap\_base}, \option{ldap\_uids}, -\option{ldap\_deref\_aliases} and \option{ldap\_filter}. -See section~\ref{ldapauth} for detailed information -about these options. If one of these options is not set, \ejabberd{} will look -for the top-level option with the same name. - -The second group of parameters -consists of the following \modvcardldap{}-specific options: - -\begin{description} -\hostitem{vjud} -\iqdiscitem{\ns{vcard-temp}} -\titem{search: true|false}\ind{options!search}This option specifies whether the search - functionality is enabled (value: \term{true}) or disabled (value: - \term{false}). If disabled, the option \term{host} will be ignored and the - \Jabber{} User Directory service will not appear in the Service Discovery item - list. The default value is \term{true}. -\titem{matches: infinity|Number}\ind{options!matches}With this option, the number of reported - search results can be limited. If the option's value is set to \term{infinity}, - all search results are reported. The default value is \term{30}. -\titem{ldap\_vcard\_map: \{ Name: \{Pattern, LDAPattributes\}, ...\}} \ind{options!ldap\_vcard\_map} - With this option you can set the table that maps LDAP attributes to vCard fields. - \ind{protocols!RFC 2426: vCard MIME Directory Profile} - \term{Name} is the type name of the vCard as defined in - \footahref{http://tools.ietf.org/html/rfc2426}{RFC 2426}. - \term{Pattern} is a string which contains pattern variables - \term{"\%u"}, \term{"\%d"} or \term{"\%s"}. - \term{LDAPattributes} is the list containing LDAP attributes. - The pattern variables - \term{"\%s"} will be sequentially replaced - with the values of LDAP attributes from \term{List\_of\_LDAP\_attributes}, - \term{"\%u"} will be replaced with the user part of a JID, - and \term{"\%d"} will be replaced with the domain part of a JID. - The default is: -\begin{verbatim} -"NICKNAME": {"%u": []} -"FN": {"%s": ["displayName"]} -"LAST": {"%s": ["sn"]} -"FIRST": {"%s": ["givenName"]} -"MIDDLE": {"%s": ["initials"]} -"ORGNAME": {"%s": ["o"]} -"ORGUNIT": {"%s": ["ou"]} -"CTRY": {"%s": ["c"]} -"LOCALITY": {"%s": ["l"]} -"STREET": {"%s": ["street"]} -"REGION": {"%s": ["st"]} -"PCODE": {"%s": ["postalCode"]} -"TITLE": {"%s": ["title"]} -"URL": {"%s": ["labeleduri"]} -"DESC": {"%s": ["description"]} -"TEL": {"%s": ["telephoneNumber"]} -"EMAIL": {"%s": ["mail"]} -"BDAY": {"%s": ["birthDay"]} -"ROLE": {"%s": ["employeeType"]} -"PHOTO": {"%s": ["jpegPhoto"]} -\end{verbatim} -\titem{ldap\_search\_fields: \{ Name: Attribute, ...\}}\ind{options!ldap\_search\_fields}This option - defines the search form and the LDAP attributes to search within. - \term{Name} is the name of a search form - field which will be automatically translated by using the translation - files (see \term{msgs/*.msg} for available words). \term{Attribute} is the - LDAP attribute or the pattern \term{"\%u"}. The default is: -\begin{verbatim} -"User": "%u" -"Full Name": "displayName" -"Given Name": "givenName" -"Middle Name": "initials" -"Family Name": "sn" -"Nickname": "%u" -"Birthday": "birthDay" -"Country": "c" -"City": "l" -"Email": "mail" -"Organization Name": "o" -"Organization Unit": "ou" -\end{verbatim} -\titem{ldap\_search\_reported: \{ SearchField: VcardField, ...\}}\ind{options!ldap\_search\_reported}This option - defines which search fields should be reported. - \term{SearchField} is the name of a search form - field which will be automatically translated by using the translation - files (see \term{msgs/*.msg} for available words). \term{VcardField} is the - vCard field name defined in the \option{ldap\_vcard\_map} option. The default - is: -\begin{verbatim} -"Full Name": "FN" -"Given Name": "FIRST" -"Middle Name": "MIDDLE" -"Family Name": "LAST" -"Nickname": "NICKNAME" -"Birthday": "BDAY" -"Country": "CTRY" -"City": "LOCALITY" -"Email": "EMAIL" -"Organization Name": "ORGNAME" -"Organization Unit": "ORGUNIT" -\end{verbatim} -\end{description} - -%TODO: this examples still should be organised better -Examples: -\begin{itemize} -\item - -Let's say \term{ldap.example.org} is the name of our LDAP server. We have -users with their passwords in \term{"ou=Users,dc=example,dc=org"} directory. -Also we have addressbook, which contains users emails and their additional -infos in \term{"ou=AddressBook,dc=example,dc=org"} directory. Corresponding -authentication section should looks like this: - -\begin{verbatim} -## authentication method -auth_method: ldap -## DNS name of our LDAP server -ldap_servers: - - "ldap.example.org" -## We want to authorize users from 'shadowAccount' object class only -ldap_filter: "(objectClass=shadowAccount)" -\end{verbatim} - -Now we want to use users LDAP-info as their vCards. We have four attributes -defined in our LDAP schema: \term{"mail"} --- email address, \term{"givenName"} ---- first name, \term{"sn"} --- second name, \term{"birthDay"} --- birthday. -Also we want users to search each other. Let's see how we can set it up: - -\begin{verbatim} -modules: - mod_vcard_ldap: - ## We use the same server and port, but want to bind anonymously because - ## our LDAP server accepts anonymous requests to - ## "ou=AddressBook,dc=example,dc=org" subtree. - ldap_rootdn: "" - ldap_password: "" - ## define the addressbook's base - ldap_base: "ou=AddressBook,dc=example,dc=org" - ## uidattr: user's part of JID is located in the "mail" attribute - ## uidattr_format: common format for our emails - ldap_uids: {"mail": "%u@mail.example.org"} - ## Now we want to define vCard pattern - ldap_vcard_map: - "NICKNAME": {"%u": []} # just use user's part of JID as his nickname - "FIRST": {"%s": ["givenName"]} - "LAST": {"%s": ["sn"]} - "FN": {"%s, %s": ["sn", "givenName"]} # example: "Smith, John" - "EMAIL": {"%s": ["mail"]} - "BDAY": {"%s": ["birthDay"]} - ## Search form - ldap_search_fields: - "User": "%u" - "Name": "givenName" - "Family Name": "sn" - "Email": "mail" - "Birthday": "birthDay" - ## vCard fields to be reported - ## Note that JID is always returned with search results - ldap_search_reported: - "Full Name": "FN" - "Nickname": "NICKNAME" - "Birthday": "BDAY" -\end{verbatim} - -Note that \modvcardldap{} module checks an existence of the user before -searching his info in LDAP. - -\item \term{ldap\_vcard\_map} example: -\begin{verbatim} -ldap_vcard_map: - "NICKNAME": {"%u": []} # just use user's part of JID as his nickname - "FN": {"%s": ["displayName"]} - "CTRY": {"Russia": []} - "EMAIL": {"%u@%d": []} - "DESC": {"%s\n%s": ["title", "description"]} -\end{verbatim} -\item \term{ldap\_search\_fields} example: -\begin{verbatim} -ldap_search_fields: - "User": "uid" - "Full Name": "displayName" - "Email": "mail" -\end{verbatim} -\item \term{ldap\_search\_reported} example: -\begin{verbatim} -ldap_search_reported: - "Full Name": "FN" - "Email": "EMAIL" - "Birthday": "BDAY" - "Nickname": "NICKNAME" -\end{verbatim} -\end{itemize} - -\makesubsection{modvcardxupdate}{\modvcardxupdate{}} -\ind{modules!\modvcardxupdate{}}\ind{protocols!XEP-0153: vCard-Based Avatars} - -The user's client can store an avatar in the user vCard. -The vCard-Based Avatars protocol (\xepref{0153}) -provides a method for clients to inform the contacts what is the avatar hash value. -However, simple or small clients may not implement that protocol. - -If this module is enabled, all the outgoing client presence stanzas get automatically -the avatar hash on behalf of the client. -So, the contacts receive the presence stanzas with the Update Data described -in \xepref{0153} as if the client would had inserted it itself. -If the client had already included such element in the presence stanza, -it is replaced with the element generated by ejabberd. - -By enabling this module, each vCard modification produces a hash recalculation, -and each presence sent by a client produces hash retrieval and a -presence stanza rewrite. -For this reason, enabling this module will introduce a computational overhead -in servers with clients that change frequently their presence. - -Options: -\begin{description} -\dbtype -\end{description} - -\makesubsection{modversion}{\modversion{}} -\ind{modules!\modversion{}}\ind{protocols!XEP-0092: Software Version} - -This module implements Software Version (\xepref{0092}). Consequently, it -answers \ejabberd{}'s version when queried. - -Options: -\begin{description} -\titem{show\_os: true|false}\ind{options!showos}Should the operating system be revealed or not. - The default value is \term{true}. -\iqdiscitem{Software Version (\ns{jabber:iq:version})} -\end{description} - -\makechapter{manage}{Managing an \ejabberd{} Server} - - -\makesection{ejabberdctl}{\term{ejabberdctl}} - -With the \term{ejabberdctl} command line administration script -you can execute \term{ejabberdctl commands} (described in the next section, \ref{ectl-commands}) -and also many general \term{ejabberd commands} (described in section \ref{eja-commands}). -This means you can start, stop and perform many other administrative tasks -in a local or remote \ejabberd{} server (by providing the argument \term{--node NODENAME}). - -The \term{ejabberdctl} script can be configured in the file \term{ejabberdctl.cfg}. -This file includes detailed information about each configurable option. See section \ref{erlangconfiguration}. - -The \term{ejabberdctl} script returns a numerical status code. -Success is represented by \term{0}, -error is represented by \term{1}, -and other codes may be used for specific results. -This can be used by other scripts to determine automatically -if a command succeeded or failed, -for example using: \term{echo \$?} - -If you use Bash, you can get Bash completion by copying the file \term{tools/ejabberdctl.bc} -to the directory \term{/etc/bash\_completion.d/} (in Debian, Ubuntu, Fedora and maybe others). - -\makesubsection{ectl-commands}{ejabberdctl Commands} - -When \term{ejabberdctl} is executed without any parameter, -it displays the available options. If there isn't an \ejabberd{} server running, -the available parameters are: -\begin{description} -\titem{start} Start \ejabberd{} in background mode. This is the default method. -\titem{debug} Attach an Erlang shell to an already existing \ejabberd{} server. This allows to execute commands interactively in the \ejabberd{} server. -\titem{live} Start \ejabberd{} in live mode: the shell keeps attached to the started server, showing log messages and allowing to execute interactive commands. -\end{description} - -If there is an \ejabberd{} server running in the system, -\term{ejabberdctl} shows the \term{ejabberdctl commands} described bellow -and all the \term{ejabberd commands} available in that server (see \ref{list-eja-commands}). - -The \term{ejabberdctl commands} are: -\begin{description} -\titem{help} Get help about ejabberdctl or any available command. Try \term{ejabberdctl help help}. -\titem{status} Check the status of the \ejabberd{} server. -\titem{stop} Stop the \ejabberd{} server. -\titem{restart} Restart the \ejabberd{} server. -\titem{mnesia} Get information about the Mnesia database. -\end{description} - -The \term{ejabberdctl} script can be restricted to require authentication -and execute some \term{ejabberd commands}; see \ref{accesscommands}. - -If account \term{robot1@example.org} is registered in \ejabberd{} with password \term{abcdef} -(which MD5 is E8B501798950FC58AAD83C8C14978E), -and your old-format configuration file contains this setting: -\begin{verbatim} -{hosts, ["example.org"]}. -{acl, bots, {user, "robot1", "example.org"}}. -{access, ctlaccess, [{allow, bots}]}. -{ejabberdctl_access_commands, [ {ctlaccess, [registered_users, register], []} ]}. -\end{verbatim} -then you can do this in the shell: -\begin{verbatim} -$ ejabberdctl registered_users example.org -Error: no_auth_provided -$ ejabberdctl --auth robot1 example.org abcdef registered_users example.org -robot1 -testuser1 -testuser2 -\end{verbatim} - - -\makesubsection{erlangconfiguration}{Erlang Runtime System} - -\ejabberd{} is an Erlang/OTP application that runs inside an Erlang runtime system. -This system is configured using environment variables and command line parameters. -The \term{ejabberdctl} administration script uses many of those possibilities. -You can configure some of them with the file \term{ejabberdctl.cfg}, -which includes detailed description about them. -This section describes for reference purposes -all the environment variables and command line parameters. - -The environment variables: -\begin{description} - \titem{EJABBERD\_CONFIG\_PATH} - Path to the ejabberd configuration file. - \titem{EJABBERD\_MSGS\_PATH} - Path to the directory with translated strings. - \titem{EJABBERD\_LOG\_PATH} - Path to the ejabberd service log file. - \titem{EJABBERD\_SO\_PATH} - Path to the directory with binary system libraries. - \titem{EJABBERD\_DOC\_PATH} - Path to the directory with ejabberd documentation. - \titem{EJABBERD\_PID\_PATH} - Path to the PID file that ejabberd can create when started. - \titem{HOME} - Path to the directory that is considered \ejabberd{}'s home. - This path is used to read the file \term{.erlang.cookie}. - \titem{ERL\_CRASH\_DUMP} - Path to the file where crash reports will be dumped. - \titem{ERL\_EPMD\_ADDRESS} - IP address where epmd listens for connections (see section \ref{epmd}). - \titem{ERL\_INETRC} - Indicates which IP name resolution to use. - If using \term{-sname}, specify either this option or \term{-kernel inetrc filepath}. - \titem{ERL\_MAX\_PORTS} - Maximum number of simultaneously open Erlang ports. - \titem{ERL\_MAX\_ETS\_TABLES} - Maximum number of ETS and Mnesia tables. -\end{description} - -The command line parameters: -\begin{description} - \titem{-sname ejabberd} - The Erlang node will be identified using only the first part - of the host name, i.\,e. other Erlang nodes outside this domain cannot contact - this node. This is the preferable option in most cases. - \titem{-name ejabberd} - The Erlang node will be fully identified. - This is only useful if you plan to setup an \ejabberd{} cluster with nodes in different networks. - \titem{-kernel inetrc '"/etc/ejabberd/inetrc"'} - Indicates which IP name resolution to use. - If using \term{-sname}, specify either this option or \term{ERL\_INETRC}. - \titem{-kernel inet\_dist\_listen\_min 4200 inet\_dist\_listen\_min 4210} - Define the first and last ports that \term{epmd} (section \ref{epmd}) can listen to. - \titem{-kernel inet\_dist\_use\_interface "\{ 127,0,0,1 \}"} - Define the IP address where this Erlang node listens for other nodes - connections (see section \ref{epmd}). - \titem{-detached} - Starts the Erlang system detached from the system console. - Useful for running daemons and background processes. - \titem{-noinput} - Ensures that the Erlang system never tries to read any input. - Useful for running daemons and background processes. - \titem{-pa /var/lib/ejabberd/ebin} - Specify the directory where Erlang binary files (*.beam) are located. - \titem{-s ejabberd} - Tell Erlang runtime system to start the \ejabberd{} application. - \titem{-mnesia dir '"/var/lib/ejabberd/"'} - Specify the Mnesia database directory. - \titem{-sasl sasl\_error\_logger \{file, "/var/log/ejabberd/erlang.log"\}} - Path to the Erlang/OTP system log file. - SASL here means ``System Architecture Support Libraries'' - not ``Simple Authentication and Security Layer''. - \titem{+K [true|false]} - Kernel polling. - \titem{-smp [auto|enable|disable]} - SMP support. - \titem{+P 250000} - Maximum number of Erlang processes. - \titem{-remsh ejabberd@localhost} - Open an Erlang shell in a remote Erlang node. - \titem{-hidden} - The connections to other nodes are hidden (not published). - The result is that this node is not considered part of the cluster. - This is important when starting a temporary \term{ctl} or \term{debug} node. -\end{description} -Note that some characters need to be escaped when used in shell scripts, for instance \verb|"| and \verb|{}|. -You can find other options in the Erlang manual page (\shell{erl -man erl}). - -\makesection{eja-commands}{\ejabberd{} Commands} - -An \term{ejabberd command} is an abstract function identified by a name, -with a defined number and type of calling arguments and type of result -that is registered in the \term{ejabberd\_commands} service. -Those commands can be defined in any Erlang module and executed using any valid frontend. - -\ejabberd{} includes two frontends to execute \term{ejabberd commands}: the script \term{ejabberdctl} (\ref{ejabberdctl}) -and the \term{ejabberd\_xmlrpc} listener (\ref{listened-module}). -Other known frontends that can be installed to execute ejabberd commands in different ways are: -\term{mod\_rest} (HTTP POST service), -\term{mod\_shcommands} (ejabberd WebAdmin page). - -\makesubsection{list-eja-commands}{List of ejabberd Commands} - -\ejabberd{} includes a few ejabberd Commands by default as listed below. -When more modules are installed, new commands may be available in the frontends. - -The easiest way to get a list of the available commands, and get help for them is to use -the ejabberdctl script: -\begin{verbatim} -$ ejabberdctl help -Usage: ejabberdctl [--node nodename] [--auth user host password] command [options] - -Available commands in this ejabberd node: - backup file Store the database to backup file - connected_users List all established sessions - connected_users_number Get the number of established sessions - ... -\end{verbatim} - -The commands included in ejabberd by default are: -\begin{description} -\titem{stop\_kindly delay announcement} Inform users and rooms, wait, and stop the server. - Provide the delay in seconds, and the announcement quoted. -\titem{registered\_vhosts} List all registered vhosts in SERVER -\titem{reopen\_log} Reopen the log files after they were renamed. - If the old files were not renamed before calling this command, - they are automatically renamed to \term{"*-old.log"}. See section \ref{logfiles}. -\titem {convert\_to\_yaml /etc/ejabberd/ejabberd.cfg /etc/ejabberd/ejabberd-converted.yml} - Convert an old ejabberd.cfg file to the YAML syntax in a new file. -\titem {backup ejabberd.backup} - Store internal Mnesia database to a binary backup file. -\titem {restore ejabberd.backup} - Restore immediately from a binary backup file the internal Mnesia database. - This will consume a lot of memory if you have a large database, - so better use \term{install\_fallback}. -\titem {install\_fallback ejabberd.backup} - The binary backup file is installed as fallback: - it will be used to restore the database at the next ejabberd start. - This means that, after running this command, you have to restart ejabberd. - This command requires less memory than \term{restore}. -\titem {dump ejabberd.dump} - Dump internal Mnesia database to a text file dump. -\titem {load ejabberd.dump} - Restore immediately from a text file dump. - This is not recommended for big databases, as it will consume much time, - memory and processor. In that case it's preferable to use \term{backup} and \term{install\_fallback}. -\titem{import\_piefxis, export\_piefxis, export\_piefxis\_host} \ind{migrate between servers} - These options can be used to migrate accounts - using \xepref{0227} formatted XML files - from/to other Jabber/XMPP servers - or move users of a vhost to another ejabberd installation. - See also \footahref{https://support.process-one.net/doc/display/MESSENGER/ejabberd+migration+kit}{ejabberd migration kit}. -\titem{import\_file, import\_dir} \ind{migration from other software} - These options can be used to migrate accounts - using jabberd1.4 formatted XML files. - from other Jabber/XMPP servers - There exist tutorials to - \footahref{http://www.ejabberd.im/migrate-to-ejabberd}{migrate from other software to ejabberd}. -\titem{set\_master nodename} - Set master node of the clustered Mnesia tables. - If you provide as nodename "self", this node will be set as its own master. -\titem{mnesia\_change\_nodename oldnodename newnodename oldbackup newbackup} - Change the erlang node name in a backup file -\titem{export2odbc virtualhost directory} \ind{export mnesia data to SQL files} - Export virtual host information from Mnesia tables to SQL files. -\titem{update\_list} List modified modules that can be updated -\titem{update module} Update the given module, or use the keyword: all -\titem{reload\_config} Reload ejabberd configuration file into memory -\titem{delete\_expired\_messages} This option can be used to delete old messages - in offline storage. This might be useful when the number of offline messages - is very high. -\titem{delete\_old\_messages days} Delete offline messages older than the given days. -\titem{incoming\_s2s\_number} Number of incoming s2s connections on the node -\titem{outgoing\_s2s\_number} Number of outgoing s2s connections on the node -\titem{register user host password} Register an account in that domain with the given password. -\titem{unregister user host} Unregister the given account. -\titem{registered\_users host} List all registered users in HOST -\titem{connected\_users} List all established sessions -\titem{connected\_users\_number} Get the number of established sessions -\titem{user\_resources user host} List user's connected resources -\titem{kick\_user user host} Disconnect user's active sessions - -\end{description} - -\makesubsection{accesscommands}{Restrict Execution with AccessCommands} - -The frontends can be configured to restrict access to certain commands -using the \term{AccessCommands}. -In that case, authentication information must be provided. - -This option allows quite complex settings, so it does not use the YAML format, -instead it uses the Erlang format. -If you want to set that option, -then you must move the frontend definition to another config file -and include it using the \term{include\_config\_file} option -(see section~\ref{includeconfigfile} and the example below). - -In each frontend the \term{AccessCommands} option is defined -in a different place. But in all cases the option syntax is the same: -\begin{verbatim} -AccessCommands = [ {Access, CommandNames, Arguments}, ...] -Access = atom() -CommandNames = all | [CommandName] -CommandName = atom() -Arguments = [ {ArgumentName, ArgumentValue}, ...] -ArgumentName = atom() -ArgumentValue = any() -\end{verbatim} - -The default value is to not define any restriction: \term{[]}. -The authentication information is provided when executing a command, -and is Username, Hostname and Password of a local XMPP account -that has permission to execute the corresponding command. -This means that the account must be registered in the local ejabberd, -because the information will be verified. - -When one or several access restrictions are defined and the -authentication information is provided, -each restriction is verified until one matches completely: -the account matches the Access rule, -the command name is listed in CommandNames, -and the provided arguments do not contradict Arguments. - -As an example to understand the syntax, let's suppose those options: -\begin{verbatim} -{hosts, ["example.org"]}. -{acl, bots, {user, "robot1", "example.org"}}. -{access, commaccess, [{allow, bots}]}. -\end{verbatim} - -This list of access restrictions allows only \term{robot1@example.org} to execute all commands: -\begin{verbatim} -[{commaccess, all, []}] -\end{verbatim} - -See another list of restrictions (the corresponding ACL and ACCESS are not shown): -\begin{verbatim} -[ - %% This bot can execute all commands: - {bot, all, []}, - %% This bot can only execute the command 'dump'. No argument restriction: - {bot_backups, [dump], []} - %% This bot can execute all commands, - %% but if a 'host' argument is provided, it must be "example.org": - {bot_all_example, all, [{host, "example.org"}]}, - %% This bot can only execute the command 'register', - %% and if argument 'host' is provided, it must be "example.org": - {bot_reg_example, [register], [{host, "example.org"}]}, - %% This bot can execute the commands 'register' and 'unregister', - %% if argument host is provided, it must be "test.org": - {_bot_reg_test, [register, unregister], [{host, "test.org"}]} -] -\end{verbatim} - -In summary, you put the frontends configurations in a CFG file using Erlang format, for example a file called \term{additional.cfg}: -\begin{verbatim} -{ejabberdctl_access_commands, [ {ctlaccess, [registered_users, register], []} ]}. - -{listen, [ - {4560, ejabberd_xmlrpc, [{maxsessions, 10}, {timeout, 5000}, - {access_commands, [ - {ctlaccess, [registered_users], [{host, "localhost"}]} - ]} - ]} - ]}. - -{modules, [ - {mod_rest, [ - {allowed_ips, [ {127,0,0,1}, {192,168,1,12} ]}, - {allowed_destinations, [ "nolan@localhost", "admin@example.com" ]}, - {allowed_stanza_types, [ "message", "presence", "iq" ]}, - {access_commands, [ - {ctlaccess, [registered_users], [{host, "localhost"}]} - ]} - ]} - ]}. -\end{verbatim} -and then add this line at the end of your main ejabberd configuration file, usually called \term{ejabberd.yml}: -\begin{verbatim} -include_config_file: "/etc/ejabberd/additional.cfg" -\end{verbatim} - -\makesection{webadmin}{Web Admin} -\ind{web admin} - -The \ejabberd{} Web Admin allows to administer most of \ejabberd{} using a web browser. - -This feature is enabled by default: -a \term{ejabberd\_http} listener with the option \term{web\_admin} (see -section~\ref{listened}) is included in the listening ports. Then you can open -\verb|http://server:port/admin/| in your favourite web browser. You -will be asked to enter the username (the \emph{full} \Jabber{} ID) and password -of an \ejabberd{} user with administrator rights. After authentication -you will see a page similar to figure~\ref{fig:webadmmain}. - -\begin{figure}[htbp] - \centering - \insimg{webadmmain.png} - \caption{Top page from the Web Admin} - \label{fig:webadmmain} -\end{figure} -Here you can edit access restrictions, manage users, create backups, -manage the database, enable/disable ports listened for, view server -statistics,\ldots - -The access rule \term{configure} determines what accounts can access the Web Admin and modify it. -The access rule \term{webadmin\_view} is to grant only view access: those accounts can browse the Web Admin with read-only access. - -Example configurations: -\begin{itemize} -\item You can serve the Web Admin on the same port as the - \ind{protocols!XEP-0025: HTTP Polling}HTTP Polling interface. In this example - you should point your web browser to \verb|http://example.org:5280/admin/| to - administer all virtual hosts or to - \verb|http://example.org:5280/admin/server/example.com/| to administer only - the virtual host \jid{example.com}. Before you get access to the Web Admin - you need to enter as username, the JID and password from a registered user - that is allowed to configure \ejabberd{}. In this example you can enter as - username `\jid{admin@example.net}' to administer all virtual hosts (first - URL). If you log in with `\jid{admin@example.com}' on \\ - \verb|http://example.org:5280/admin/server/example.com/| you can only - administer the virtual host \jid{example.com}. - The account `\jid{reviewer@example.com}' can browse that vhost in read-only mode. -\begin{verbatim} -acl: - admin: - user: - - "admin": "example.net" - -host_config: - "example.com": - acl: - admin: - user: - - "admin": "example.com" - viewers: - user: - - "reviewer": "example.com" - -access: - configure: - admin: allow - webadmin_view: - viewers: allow - -hosts: - - "example.org" - -listen: - ... - - - port: 5280 - module: ejabberd_http - web_admin: true - http_poll: true - ... -\end{verbatim} -\item For security reasons, you can serve the Web Admin on a secured - connection, on a port differing from the HTTP Polling interface, and bind it - to the internal LAN IP. The Web Admin will be accessible by pointing your - web browser to \verb|https://192.168.1.1:5282/admin/|: -\begin{verbatim} -hosts: - - "example.org" -listen: - ... - - - port: 5280 - module: ejabberd_http - http_poll: true - - - ip: "192.168.1.1" - port: 5282 - module: ejabberd_http - certfile: "/usr/local/etc/server.pem" - tls: true - web_admin: true - ... -\end{verbatim} -\end{itemize} - -Certain pages in the ejabberd Web Admin contain a link to a related -section in the ejabberd Installation and Operation Guide. -In order to view such links, a copy in HTML format of the Guide must -be installed in the system. -The file is searched by default in -\term{"/share/doc/ejabberd/guide.html"}. -The directory of the documentation can be specified in -the environment variable \term{EJABBERD\_DOC\_PATH}. -See section \ref{erlangconfiguration}. - - -\makesection{adhoccommands}{Ad-hoc Commands} - -If you enable \modconfigure\ and \modadhoc, -you can perform several administrative tasks in \ejabberd{} -with an XMPP client. -The client must support Ad-Hoc Commands (\xepref{0050}), -and you must login in the XMPP server with -an account with proper privileges. - - -\makesection{changeerlangnodename}{Change Computer Hostname} - -\ejabberd{} uses the distributed Mnesia database. -Being distributed, Mnesia enforces consistency of its file, -so it stores the name of the Erlang node in it (see section \ref{nodename}). -The name of an Erlang node includes the hostname of the computer. -So, the name of the Erlang node changes -if you change the name of the machine in which \ejabberd{} runs, -or when you move \ejabberd{} to a different machine. - -You have two ways to use the old Mnesia database in an ejabberd with new node name: -put the old node name in \term{ejabberdctl.cfg}, -or convert the database to the new node name. - -Those example steps will backup, convert and load the Mnesia database. -You need to have either the old Mnesia spool dir or a backup of Mnesia. -If you already have a backup file of the old database, you can go directly to step 5. -You also need to know the old node name and the new node name. -If you don't know them, look for them by executing \term{ejabberdctl} -or in the ejabberd log files. - -Before starting, setup some variables: -\begin{verbatim} -OLDNODE=ejabberd@oldmachine -NEWNODE=ejabberd@newmachine -OLDFILE=/tmp/old.backup -NEWFILE=/tmp/new.backup -\end{verbatim} - -\begin{enumerate} -\item Start ejabberd enforcing the old node name: -\begin{verbatim} -ejabberdctl --node $OLDNODE start -\end{verbatim} - -\item Generate a backup file: -\begin{verbatim} -ejabberdctl --node $OLDNODE backup $OLDFILE -\end{verbatim} - -\item Stop the old node: -\begin{verbatim} -ejabberdctl --node $OLDNODE stop -\end{verbatim} - -\item Make sure there aren't files in the Mnesia spool dir. For example: -\begin{verbatim} -mkdir /var/lib/ejabberd/oldfiles -mv /var/lib/ejabberd/*.* /var/lib/ejabberd/oldfiles/ -\end{verbatim} - -\item Start ejabberd. There isn't any need to specify the node name anymore: -\begin{verbatim} -ejabberdctl start -\end{verbatim} - -\item Convert the backup to new node name: -\begin{verbatim} -ejabberdctl mnesia_change_nodename $OLDNODE $NEWNODE $OLDFILE $NEWFILE -\end{verbatim} - -\item Install the backup file as a fallback: -\begin{verbatim} -ejabberdctl install_fallback $NEWFILE -\end{verbatim} - -\item Stop ejabberd: -\begin{verbatim} -ejabberdctl stop -\end{verbatim} -You may see an error message in the log files, it's normal, so don't worry: -\begin{verbatim} -Mnesia(ejabberd@newmachine): -** ERROR ** (ignoring core) -** FATAL ** A fallback is installed and Mnesia must be restarted. - Forcing shutdown after mnesia_down from ejabberd@newmachine... -\end{verbatim} - -\item Now you can finally start ejabberd: -\begin{verbatim} -ejabberdctl start -\end{verbatim} - -\item Check that the information of the old database is available: accounts, rosters... -After you finish, remember to delete the temporary backup files from public directories. -\end{enumerate} - - -\makechapter{secure}{Securing \ejabberd{}} - -\makesection{firewall}{Firewall Settings} -\ind{firewall}\ind{ports}\ind{SASL}\ind{TLS}\ind{clustering!ports} - -You need to take the following TCP ports in mind when configuring your firewall: -\begin{table}[H] - \centering - \begin{tabular}{|l|l|} - \hline {\bf Port} & {\bf Description} \\ - \hline \hline 5222& Standard port for Jabber/XMPP client connections, plain or STARTTLS.\\ - \hline 5223& Standard port for Jabber client connections using the old SSL method.\\ - \hline 5269& Standard port for Jabber/XMPP server connections.\\ - \hline 4369& EPMD (section \ref{epmd}) listens for Erlang node name requests.\\ - \hline port range& Used for connections between Erlang nodes. This range is configurable (see section \ref{epmd}).\\ - \hline - \end{tabular} -\end{table} - -\makesection{epmd}{epmd} - -\footahref{http://www.erlang.org/doc/man/epmd.html}{epmd (Erlang Port Mapper Daemon)} -is a small name server included in Erlang/OTP -and used by Erlang programs when establishing distributed Erlang communications. -\ejabberd{} needs \term{epmd} to use \term{ejabberdctl} and also when clustering \ejabberd{} nodes. -This small program is automatically started by Erlang, and is never stopped. -If \ejabberd{} is stopped, and there aren't any other Erlang programs -running in the system, you can safely stop \term{epmd} if you want. - -\ejabberd{} runs inside an Erlang node. -To communicate with \ejabberd{}, the script \term{ejabberdctl} starts a new Erlang node -and connects to the Erlang node that holds \ejabberd{}. -In order for this communication to work, -\term{epmd} must be running and listening for name requests in the port 4369. -You should block the port 4369 in the firewall in such a way that -only the programs in your machine can access it. -or configure the option \term{ERL\_EPMD\_ADDRESS} in the file \term{ejabberdctl.cfg}. - -If you build a cluster of several \ejabberd{} instances, -each \ejabberd{} instance is called an \ejabberd{} node. -Those \ejabberd{} nodes use a special Erlang communication method to -build the cluster, and EPMD is again needed listening in the port 4369. -So, if you plan to build a cluster of \ejabberd{} nodes -you must open the port 4369 for the machines involved in the cluster. -Remember to block the port so Internet doesn't have access to it. - -Once an Erlang node solved the node name of another Erlang node using EPMD and port 4369, -the nodes communicate directly. -The ports used in this case by default are random, -but can be configured in the file \term{ejabberdctl.cfg}. -The Erlang command-line parameter used internally is, for example: -\begin{verbatim} -erl ... -kernel inet_dist_listen_min 4370 inet_dist_listen_max 4375 -\end{verbatim} -It is also possible to configure in \term{ejabberdctl.cfg} -the network interface where the Erlang node will listen and accept connections. -The Erlang command-line parameter used internally is, for example: -\begin{verbatim} -erl ... -kernel inet_dist_use_interface "{127,0,0,1}" -\end{verbatim} - - -\makesection{cookie}{Erlang Cookie} - -The Erlang cookie is a string with numbers and letters. -An Erlang node reads the cookie at startup from the command-line parameter \term{-setcookie}. -If not indicated, the cookie is read from the cookie file \term{\$HOME/.erlang.cookie}. -If this file does not exist, it is created immediately with a random cookie. -Two Erlang nodes communicate only if they have the same cookie. -Setting a cookie on the Erlang node allows you to structure your Erlang network -and define which nodes are allowed to connect to which. - -Thanks to Erlang cookies, you can prevent access to the Erlang node by mistake, -for example when there are several Erlang nodes running different programs in the same machine. - -Setting a secret cookie is a simple method -to difficult unauthorized access to your Erlang node. -However, the cookie system is not ultimately effective -to prevent unauthorized access or intrusion to an Erlang node. -The communication between Erlang nodes are not encrypted, -so the cookie could be read sniffing the traffic on the network. -The recommended way to secure the Erlang node is to block the port 4369. - - -\makesection{nodename}{Erlang Node Name} - -An Erlang node may have a node name. -The name can be short (if indicated with the command-line parameter \term{-sname}) -or long (if indicated with the parameter \term{-name}). -Starting an Erlang node with -sname limits the communication between Erlang nodes to the LAN. - -Using the option \term{-sname} instead of \term{-name} is a simple method -to difficult unauthorized access to your Erlang node. -However, it is not ultimately effective to prevent access to the Erlang node, -because it may be possible to fake the fact that you are on another network -using a modified version of Erlang \term{epmd}. -The recommended way to secure the Erlang node is to block the port 4369. - - -\makesection{secure-files}{Securing Sensitive Files} - -\ejabberd{} stores sensitive data in the file system either in plain text or binary files. -The file system permissions should be set to only allow the proper user to read, -write and execute those files and directories. - -\begin{description} - \titem{ejabberd configuration file: /etc/ejabberd/ejabberd.yml} - Contains the JID of administrators - and passwords of external components. - The backup files probably contain also this information, - so it is preferable to secure the whole \term{/etc/ejabberd/} directory. - \titem{ejabberd service log: /var/log/ejabberd/ejabberd.log} - Contains IP addresses of clients. - If the loglevel is set to 5, it contains whole conversations and passwords. - If a logrotate system is used, there may be several log files with similar information, - so it is preferable to secure the whole \term{/var/log/ejabberd/} directory. - \titem{Mnesia database spool files in /var/lib/ejabberd/} - The files store binary data, but some parts are still readable. - The files are generated by Mnesia and their permissions cannot be set directly, - so it is preferable to secure the whole \term{/var/lib/ejabberd/} directory. - \titem{Erlang cookie file: /var/lib/ejabberd/.erlang.cookie} - See section \ref{cookie}. -\end{description} - - -\makechapter{clustering}{Clustering} -\ind{clustering} - -\makesection{howitworks}{How it Works} -\ind{clustering!how it works} - -A \XMPP{} domain is served by one or more \ejabberd{} nodes. These nodes can -be run on different machines that are connected via a network. They all -must have the ability to connect to port 4369 of all another nodes, and must -have the same magic cookie (see Erlang/OTP documentation, in other words the -file \term{\~{}ejabberd/.erlang.cookie} must be the same on all nodes). This is -needed because all nodes exchange information about connected users, s2s -connections, registered services, etc\ldots - -Each \ejabberd{} node has the following modules: -\begin{itemize} -\item router, -\item local router, -\item session manager, -\item s2s manager. -\end{itemize} - -\makesubsection{router}{Router} -\ind{clustering!router} - -This module is the main router of \XMPP{} packets on each node. It -routes them based on their destination's domains. It uses a global -routing table. The domain of the packet's destination is searched in the -routing table, and if it is found, the packet is routed to the -appropriate process. If not, it is sent to the s2s manager. - -\makesubsection{localrouter}{Local Router} -\ind{clustering!local router} - -This module routes packets which have a destination domain equal to -one of this server's host names. If the destination JID has a non-empty user -part, it is routed to the session manager, otherwise it is processed depending -on its content. - -\makesubsection{sessionmanager}{Session Manager} -\ind{clustering!session manager} - -This module routes packets to local users. It looks up to which user -resource a packet must be sent via a presence table. Then the packet is -either routed to the appropriate c2s process, or stored in offline -storage, or bounced back. - -\makesubsection{s2smanager}{s2s Manager} -\ind{clustering!s2s manager} - -This module routes packets to other \XMPP{} servers. First, it -checks if an opened s2s connection from the domain of the packet's -source to the domain of the packet's destination exists. If that is the case, -the s2s manager routes the packet to the process -serving this connection, otherwise a new connection is opened. - -\makesection{cluster}{Clustering Setup} -\ind{clustering!setup} - -Suppose you already configured \ejabberd{} on one machine named (\term{first}), -and you need to setup another one to make an \ejabberd{} cluster. Then do -following steps: - -\begin{enumerate} -\item Copy \verb|~ejabberd/.erlang.cookie| file from \term{first} to - \term{second}. - - (alt) You can also add `\verb|-setcookie content_of_.erlang.cookie|' - option to all `\shell{erl}' commands below. - -\item On \term{second} run the following command as the \ejabberd{} daemon user, - in the working directory of \ejabberd{}: - -\begin{verbatim} -erl -sname ejabberd \ - -mnesia dir '"/var/lib/ejabberd/"' \ - -mnesia extra_db_nodes "['ejabberd@first']" \ - -s mnesia -\end{verbatim} - - This will start Mnesia serving the same database as \node{ejabberd@first}. - You can check this by running the command `\verb|mnesia:info().|'. You - should see a lot of remote tables and a line like the following: - - Note: the Mnesia directory may be different in your system. - To know where does ejabberd expect Mnesia to be installed by default, - call \ref{ejabberdctl} without options and it will show some help, - including the Mnesia database spool dir. - -\begin{verbatim} -running db nodes = [ejabberd@first, ejabberd@second] -\end{verbatim} - - -\item Now run the following in the same `\shell{erl}' session: - -\begin{verbatim} -mnesia:change_table_copy_type(schema, node(), disc_copies). -\end{verbatim} - - This will create local disc storage for the database. - - (alt) Change storage type of the \term{scheme} table to `RAM and disc - copy' on the second node via the Web Admin. - - -\item Now you can add replicas of various tables to this node with - `\verb|mnesia:add_table_copy|' or - `\verb|mnesia:change_table_copy_type|' as above (just replace - `\verb|schema|' with another table name and `\verb|disc_copies|' - can be replaced with `\verb|ram_copies|' or - `\verb|disc_only_copies|'). - - Which tables to replicate is very dependant on your needs, you can get - some hints from the command `\verb|mnesia:info().|', by looking at the - size of tables and the default storage type for each table on 'first'. - - Replicating a table makes lookups in this table faster on this node. - Writing, on the other hand, will be slower. And of course if machine with one - of the replicas is down, other replicas will be used. - - Also \footahref{http://www.erlang.org/doc/apps/mnesia/Mnesia\_chap5.html\#5.3} - {section 5.3 (Table Fragmentation) of Mnesia User's Guide} can be helpful. - % The above URL needs update every Erlang release! - - (alt) Same as in previous item, but for other tables. - - -\item Run `\verb|init:stop().|' or just `\verb|q().|' to exit from - the Erlang shell. This probably can take some time if Mnesia has not yet - transfered and processed all data it needed from \term{first}. - - -\item Now run \ejabberd{} on \term{second} with a configuration similar as - on \term{first}: you probably do not need to duplicate `\verb|acl|' - and `\verb|access|' options because they will be taken from - \term{first}; and \verb|mod_irc| should be - enabled only on one machine in the cluster. -\end{enumerate} - -You can repeat these steps for other machines supposed to serve this -domain. - -\makesection{servicelb}{Service Load-Balancing} -\ind{component load-balancing} - -% This section never had content, should it? -% \makesubsection{componentlb}{Components Load-Balancing} - -\makesubsection{domainlb}{Domain Load-Balancing Algorithm} -\ind{options!domain\_balancing} - -\ejabberd{} includes an algorithm to load balance the components that are plugged on an \ejabberd{} cluster. It means that you can plug one or several instances of the same component on each \ejabberd{} cluster and that the traffic will be automatically distributed. - -The default distribution algorithm try to deliver to a local instance of a component. If several local instances are available, one instance is chosen randomly. If no instance is available locally, one instance is chosen randomly among the remote component instances. - -If you need a different behaviour, you can change the load balancing behaviour with the option \option{domain\_balancing}. The syntax of the option is the following: -\esyntax{domain\_balancing: BalancingCriteria} - -Several balancing criteria are available: -\begin{itemize} -\item \term{destination}: the full JID of the packet \term{to} attribute is used. -\item \term{source}: the full JID of the packet \term{from} attribute is used. -\item \term{bare\_destination}: the bare JID (without resource) of the packet \term{to} attribute is used. -\item \term{bare\_source}: the bare JID (without resource) of the packet \term{from} attribute is used. -\end{itemize} - -If the value corresponding to the criteria is the same, the same component instance in the cluster will be used. - -\makesubsection{lbbuckets}{Load-Balancing Buckets} -\ind{options!domain\_balancing\_component\_number} - -When there is a risk of failure for a given component, domain balancing can cause service trouble. If one component is failing the service will not work correctly unless the sessions are rebalanced. - -In this case, it is best to limit the problem to the sessions handled by the failing component. This is what the \term{domain\_balancing\_component\_number} option does, making the load balancing algorithm not dynamic, but sticky on a fix number of component instances. - -The syntax is: -\esyntax{domain\_balancing\_component\_number: Number} - - - -% TODO -% See also the section about ejabberdctl!!!! -%\section{Backup and Restore} -%\label{backup} -%\ind{backup} - -\makechapter{debugging}{Debugging} -\ind{debugging} - -\makesection{logfiles}{Log Files} - -An \ejabberd{} node writes three log files: -\begin{description} - \titem{ejabberd.log} is the ejabberd service log, with the messages reported by \ejabberd{} code - \titem{error.log} is the file accumulating error messages from \term{ejabberd.log} - \titem{crash.log} is the Erlang/OTP log, with the crash messages reported by Erlang/OTP using SASL (System Architecture Support Libraries) -\end{description} - -The option \term{loglevel} modifies the verbosity of the file ejabberd.log. The syntax: -\begin{description} - \titem{loglevel: Level} The standard form to set a global log level. -\end{description} - -The possible \term{Level} are: -\begin{description} - \titem{0} No ejabberd log at all (not recommended) - \titem{1} Critical - \titem{2} Error - \titem{3} Warning - \titem{4} Info - \titem{5} Debug -\end{description} -For example, the default configuration is: -\begin{verbatim} -loglevel: 4 -\end{verbatim} - -Option \term{log\_rate\_limit} is useful if you want to protect the logging -mechanism from being overloaded by excessive amount of log messages. -The syntax is: -\begin{description} - \titem{log\_rate\_limit: N} Where N is a maximum number of log messages per second. - The default value is 100. -\end{description} -When the limit is reached the similar warning message is logged: -\begin{verbatim} -lager_error_logger_h dropped 800 messages in the last second that exceeded the limit of 100 messages/sec -\end{verbatim} - -By default \ejabberd{} rotates the log files when they get grown above a certain size. -The exact value is controlled by \term{log\_rotate\_size} option. -The syntax is: -\begin{description} - \titem{log\_rotate\_size: N} Where N is the maximum size of a log file in bytes. - The default value is 10485760 (10Mb). -\end{description} - -\ejabberd{} can also rotates the log files at given date interval. -The exact value is controlled by \term{log\_rotate\_date} option. -The syntax is: -\begin{description} - \titem{log\_rotate\_date: D} Where D is a string with syntax is taken from the syntax newsyslog uses in newsyslog.conf. - The default value is \term{""} (no rotation triggered by date). -\end{description} - -However, you can rotate the log files manually. -For doing this, set \term{log\_rotate\_size} option to 0 and \term{log\_rotate\_date} -to empty list, then, when you need to rotate the files, rename and then reopen them. -The ejabberdctl command \term{reopen-log} -(please refer to section \ref{ectl-commands}) -reopens the log files, -and also renames the old ones if you didn't rename them. - -The option \term{log\_rotate\_count} defines the number of rotated files to keep -by \term{reopen-log} command. -Every such file has a numeric suffix. The exact format is: -\begin{description} - \titem{log\_rotate\_count: N} The default value is 1, - which means only \term{ejabberd.log.0}, \term{error.log.0} - and \term{crash.log.0} will be kept. -\end{description} - -\makesection{debugconsole}{Debug Console} - -The Debug Console is an Erlang shell attached to an already running \ejabberd{} server. -With this Erlang shell, an experienced administrator can perform complex tasks. - -This shell gives complete control over the \ejabberd{} server, -so it is important to use it with extremely care. -There are some simple and safe examples in the article -\footahref{http://www.ejabberd.im/interconnect-erl-nodes}{Interconnecting Erlang Nodes} - -To exit the shell, close the window or press the keys: control+c control+c. - - -\makesection{watchdog}{Watchdog Alerts} -\ind{debugging!watchdog} - -\ejabberd{} includes a watchdog mechanism that may be useful to developers -when troubleshooting a problem related to memory usage. -If a process in the \ejabberd{} server consumes more memory than the configured threshold, -a message is sent to the XMPP accounts defined with the option -\term{watchdog\_admins} -\ind{options!watchdog\_admins} in the \ejabberd{} configuration file. - -The syntax is: -\esyntax{watchdog\_admins: [JID, ...]} - -The memory consumed is measured in \term{words}: -a word on 32-bit architecture is 4 bytes, -and a word on 64-bit architecture is 8 bytes. -The threshold by default is 1000000 words. -This value can be configured with the option \term{watchdog\_large\_heap}, -or in a conversation with the watchdog alert bot. - -The syntax is: -\esyntax{watchdog\_large\_heap: Number} - -Example configuration: -\begin{verbatim} -watchdog_admins: - - "admin2@localhost" - - "admin2@example.org" -watchdog_large_heap: 30000000 -\end{verbatim} - -To remove watchdog admins, remove them in the option. -To remove all watchdog admins, set the option with an empty list: -\begin{verbatim} -watchdog_admins: [] -\end{verbatim} - -\appendix{} - -\makechapter{i18ni10n}{Internationalization and Localization} -\ind{xml:lang}\ind{internationalization}\ind{localization}\ind{i18n}\ind{l10n} - -The source code of \ejabberd{} supports localization. -The translators can edit the -\footahref{http://www.gnu.org/software/gettext/}{gettext} .po files -using any capable program (KBabel, Lokalize, Poedit...) or a simple text editor. - -Then gettext -is used to extract, update and export those .po files to the .msg format read by \ejabberd{}. -To perform those management tasks, in the \term{src/} directory execute \term{make translations}. -The translatable strings are extracted from source code to generate the file \term{ejabberd.pot}. -This file is merged with each .po file to produce updated .po files. -Finally those .po files are exported to .msg files, that have a format easily readable by \ejabberd{}. - -All built-in modules support the \texttt{xml:lang} attribute inside IQ queries. -Figure~\ref{fig:discorus}, for example, shows the reply to the following query: -\begin{verbatim} - - - -\end{verbatim} - -\begin{figure}[htbp] - \centering - \insimg{discorus.png} - \caption{Service Discovery when \texttt{xml:lang='ru'}} - \label{fig:discorus} -\end{figure} - -The Web Admin also supports the \verb|Accept-Language| HTTP header. - -\begin{figure}[htbp] - \centering - \insimg{webadmmainru.png} - \caption{Web Admin showing a virtual host when the web browser provides the - HTTP header `Accept-Language: ru'} - \label{fig:webadmmainru} -\end{figure} - - -\makechapter{releasenotes}{Release Notes} -\ind{release notes} - -Release notes are available from \footahref{http://www.process-one.net/en/ejabberd/release\_notes/}{ejabberd Home Page} - -\makechapter{acknowledgements}{Acknowledgements} - -Thanks to all people who contributed to this guide: -\begin{itemize} -\item Alexey Shchepin (\ahrefurl{xmpp:aleksey@jabber.ru}) -\item Badlop (\ahrefurl{xmpp:badlop@jabberes.org}) -\item Evgeniy Khramtsov (\ahrefurl{xmpp:xram@jabber.ru}) -\item Florian Zumbiehl (\ahrefurl{xmpp:florz@florz.de}) -\item Ludovic Bocquet (\ahrefurl{xmpp:lbocquet@jabber.org}) -\item Marcin Owsiany (\ahrefurl{xmpp:marcin.owsiany@gmail.com}) -\item Michael Grigutsch (\ahrefurl{xmpp:migri@jabber.i-pobox.net}) -\item Mickael Remond (\ahrefurl{xmpp:mremond@process-one.net}) -\item Sander Devrieze (\ahrefurl{xmpp:s.devrieze@gmail.com}) -\item Sergei Golovan (\ahrefurl{xmpp:sgolovan@nes.ru}) -\item Vsevolod Pelipas (\ahrefurl{xmpp:vsevoload@jabber.ru}) -\end{itemize} - - -\makechapter{copyright}{Copyright Information} - -Ejabberd Installation and Operation Guide.\\ -Copyright \copyright{} 2003 --- 2015 ProcessOne - -This document 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 document 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 document; if not, write to the Free Software Foundation, Inc., 51 Franklin -Street, Fifth Floor, Boston, MA 02110-1301, USA. - -%TODO: a glossary describing common terms -%\makesection{glossary}{Glossary} -%\ind{glossary} - -%\begin{description} -%\titem{c2s} -%\titem{s2s} -%\titem{STARTTLS} -%\titem{XEP} (\XMPP{} Extension Protocol) -%\titem{Resource} -%\titem{Roster} -%\titem{Transport} -%\titem{JID} (\Jabber{} ID) -%\titem{JUD} (\Jabber{} User Directory) -%\titem{vCard} -%\titem{Publish-Subscribe} -%\titem{Namespace} -%\titem{Erlang} -%\titem{Fault-tolerant} -%\titem{Distributed} -%\titem{Node} -%\titem{Tuple} -%\titem{Regular Expression} -%\titem{ACL} (Access Control List) -%\titem{IPv6} -%\titem{XMPP} -%\titem{LDAP} (Lightweight Directory Access Protocol) -%\titem{ODBC} (Open Database Connectivity) -%\titem{Virtual Hosting} - -%\end{description} - - - -% Remove the index from the HTML version to save size and bandwith. -\begin{latexonly} -\printindex -\end{latexonly} - -\end{document} diff --git a/doc/introduction.tex b/doc/introduction.tex deleted file mode 100644 index b6f4b6c934f..00000000000 --- a/doc/introduction.tex +++ /dev/null @@ -1,135 +0,0 @@ -\chapter{Introduction} -\label{intro} - -%% TODO: improve the feature sheet with a nice table to highlight new features. - -\quoting{I just tried out ejabberd and was impressed both by ejabberd itself and the language it is written in, Erlang. --- -Joeri} - -%ejabberd is a free and open source instant messaging server written in Erlang. ejabberd is cross-platform, distributed, fault-tolerant, and based on open standards to achieve real-time communication (Jabber/XMPP). - -\ejabberd{} is a \marking{free and open source} instant messaging server written in \footahref{http://www.erlang.org/}{Erlang/OTP}. - -\ejabberd{} is \marking{cross-platform}, distributed, fault-tolerant, and based on open standards to achieve real-time communication. - -\ejabberd{} is designed to be a \marking{rock-solid and feature rich} XMPP server. - -\ejabberd{} is suitable for small deployments, whether they need to be \marking{scalable} or not, as well as extremely big deployments. - -%\subsection{Layout with example deployment (title needs a better name)} -%\label{layout} - -%In this section there will be a graphical overview like these:\\ -%\verb|http://www.tipic.com/var/timp/timp_dep.gif| \\ -%\verb|http://www.jabber.com/images/jabber_Com_Platform.jpg| \\ -%\verb|http://www.antepo.com/files/OPN45systemdatasheet.pdf| \\ - -%A page full with names of Jabber client that are known to work with ejabberd. \begin{tiny}tiny font\end{tiny} - -%\subsection{Try It Today} -%\label{trytoday} - -%(Not sure if I will include/finish this section for the next version.) - -%\begin{itemize} -%\item Erlang REPOS -%\item Packages in distributions -%\item Windows binary -%\item source tar.gz -%\item Migration from Jabberd14 (and so also Jabberd2 because you can migrate from version 2 back to 14) and Jabber Inc. XCP possible. -%\end{itemize} - -\newpage -\section{Key Features} -\label{keyfeatures} -\ind{features!key features} - -\quoting{Erlang seems to be tailor-made for writing stable, robust servers. --- -Peter Saint-Andr\'e, Executive Director of the Jabber Software Foundation} - -\ejabberd{} is: -\begin{itemize} -\item \marking{Cross-platform:} \ejabberd{} runs under Microsoft Windows and Unix derived systems such as Linux, FreeBSD and NetBSD. - -\item \marking{Distributed:} You can run \ejabberd{} on a cluster of machines and all of them will serve the same \Jabber{} domain(s). When you need more capacity you can simply add a new cheap node to your cluster. Accordingly, you do not need to buy an expensive high-end machine to support tens of thousands concurrent users. - -\item \marking{Fault-tolerant:} You can deploy an \ejabberd{} cluster so that all the information required for a properly working service will be replicated permanently on all nodes. This means that if one of the nodes crashes, the others will continue working without disruption. In addition, nodes also can be added or replaced `on the fly'. - -\item \marking{Administrator Friendly:} \ejabberd{} is built on top of the Open Source Erlang. As a result you do not need to install an external database, an external web server, amongst others because everything is already included, and ready to run out of the box. Other administrator benefits include: -\begin{itemize} -\item Comprehensive documentation. -\item Straightforward installers for Linux, Mac OS X, and Windows. %%\improved{} -\item Web Administration. -\item Shared Roster Groups. -\item Command line administration tool. %%\improved{} -\item Can integrate with existing authentication mechanisms. -\item Capability to send announce messages. -\end{itemize} - -\item \marking{Internationalized:} \ejabberd{} leads in internationalization. Hence it is very well suited in a globalized world. Related features are: -\begin{itemize} -\item Translated to 25 languages. %%\improved{} -\item Support for \footahref{http://tools.ietf.org/html/rfc3490}{IDNA}. -\end{itemize} - -\item \marking{Open Standards:} \ejabberd{} is the first Open Source Jabber server claiming to fully comply to the XMPP standard. -\begin{itemize} -\item Fully XMPP compliant. -\item XML-based protocol. -\item \footahref{http://www.ejabberd.im/protocols}{Many protocols supported}. -\end{itemize} - -\end{itemize} - -\newpage - -\section{Additional Features} -\label{addfeatures} -\ind{features!additional features} - -\quoting{ejabberd is making inroads to solving the "buggy incomplete server" problem --- -Justin Karneges, Founder of the Psi and the Delta projects} - -Moreover, \ejabberd{} comes with a wide range of other state-of-the-art features: -\begin{itemize} -\item Modular -\begin{itemize} -\item Load only the modules you want. -\item Extend \ejabberd{} with your own custom modules. -\end{itemize} -\item Security -\begin{itemize} -\item SASL and STARTTLS for c2s and s2s connections. -\item STARTTLS and Dialback s2s connections. -\item Web Admin accessible via HTTPS secure access. -\end{itemize} -\item Databases -\begin{itemize} -\item Internal database for fast deployment (Mnesia). -\item Native MySQL support. -\item Native PostgreSQL support. -\item ODBC data storage support. -\item Microsoft SQL Server support. %%\new{} -\item Riak NoSQL database support. -\end{itemize} -\item Authentication -\begin{itemize} -\item Internal Authentication. -\item PAM, LDAP, ODBC and Riak. %%\improved{} -\item External Authentication script. -\end{itemize} -\item Others -\begin{itemize} -\item Support for virtual hosting. -\item Compressing XML streams with Stream Compression (\xepref{0138}). -\item Statistics via Statistics Gathering (\xepref{0039}). -\item IPv6 support both for c2s and s2s connections. -\item \txepref{0045}{Multi-User Chat} module with support for clustering and HTML logging. %%\improved{} -\item Users Directory based on users vCards. -\item \txepref{0060}{Publish-Subscribe} component with support for \txepref{0163}{Personal Eventing via Pubsub}. -\item Support for web clients: \txepref{0025}{HTTP Polling} and \txepref{0206}{HTTP Binding (BOSH)} services. -\item IRC transport. -\item SIP support. -\item Component support: interface with networks such as AIM, ICQ and MSN installing special tranports. -\end{itemize} -\end{itemize} diff --git a/doc/logo.png b/doc/logo.png deleted file mode 100644 index b8d17ebfddd3c653e7aa0f19a45139e5c1d51f03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83054 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 diff --git a/doc/msrl-roster-deep.png b/doc/msrl-roster-deep.png deleted file mode 100644 index aa1017ecf4f1ff350f24ca1992cb53501490ec31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23093 zcmc$`WmFttw5|z+V8H?ecMl%iNpN=w?ye04x8Uxs0fL0a-CcsaySuwIOy%5j@0@kk zoi(%WpXt?5O?6du)mQu5^1QnVQyTI73r{f>VH%@Xk_lV(?4Q zNGRmQZiBUqz$!dvvG2|z_O`aBcFs^Dj;4mrrY5AWmd+NW5>j%C8b48SprA;hq(r}| zx-Fe#x$3BDJiV=}7{CSRYSa4rlfr~|Nml(@{9g5&OK!4p(S~!-Y`SKUntCxxDd7cU zT6WQj7yc%Ogx`@V2pcJ^;y6+O~^8k&urqnVf-knYiYtXIsd?PWVMwLq?p& zvOFtf5y&ihOBWm{DJku2+M{IbsudP5dZt~G^Q-%NS8#~MjEjT|E8|+J$v^>QvURG5 z)~TNeq64J6Xuzo7r%Y}?_5(Zb@e8~&FB8~1a+G~y9ho(azXy)SVj}&CwE#aT3$tK< z`tg1$AlX8MIuO0asONDbX)(2AnB`dJ%OO>6Y@^_#6{HGmbkCdsub*;DTi5oNFJ-WM zUH-~e$8j}L)SShbGlNAPTiS>Ww0dbK z)DRLB#GQuFaaWE@UMAz$T4@WzBt=H3Zm&ydk)F~*h;@;_?!B2gOSKE-F|Oi~0mrPH znNxNBqpNMqD4fc;KYptoBMsdwvz5yLW;NiJ@($KzcokdH)L-{Ypc%BHcSCG0_InJ&35@SvC-Xn zb^)wL_787tlzJJdYid}#Cfs!z-ICAHcMvVDcHy1c*qI40~kk!@HK z>QtFF6S$qmXuRP=u34NpafT)BSQrVW#2jy9iO9QQl^##YR~%BJ-A#=$8$zNh{=@1p zuzG*F`FxJ?(WbLU*T*|dJQfoQC*Jp6c3+J>IEYm@(LO}m)ozU0$Z z5liAu?NZLJRMX0*$ziMY&Z4=>Q^bey9;F{Ji+rKklW6&l=Ml(w&8-PoM4BRMcZM== zQ1zz@mQ(ZAF49KrykxC|-y>MKQt4`yV+Ox3GkG#5oyrOTgObBV(unBCl|p>xAaH9u zEzKg!h#>A2p9b14G%97!pDSs+PaFKZ%NpHZ5bIeDm8K)U?!XMEfV72odtLf`Bs7wl z*Lb$q;VSOF$!g)aItaSL4f<4fBEv{Vh%S7wgVu3(TmxtfY3H4Lve`*#9~Rq?Ascp zLE||+JXnAGZL#}u&80aq#{6NET#`C!8bZ@QIM}hWD&nGWTac17v zTs6mKR)tGXHs!rYs%)xuYP`wbU?}0ff~F78ml_Jtr8BI--$VnX8tK?!Q{>hHp}R2` zQTf)i@wGfL?bWy^`-$K&otsH7!qc6^111t~yvirVkJH_mrB@Y#s=YF7MbH=h+HXHg zl;Lixjqk(9aXGit!L4>8OJfbpXA;8Xc4T+a&yO3A93#Ys(bImDKb)pXI{M`DDL=RQ z3!zMG{j%bjvOdKv0}cjOSWwco-Z0TZedqCKQayX``Efi>TRC7@k|%dm)L``XEgb`S zS}l@A)+|Cn8(gHvBHOQJM`8v^s(SjWx4iyxS_*G)Bq!i@8x1|8`=j6L4eW}%ac7v# zm~5@1uip#+($uf2oBV=s8k z`6WTzabRSb1x)y-WJrvurG1XY##T+X?OHI~>nw*K(rxW^e?H)#%yslT(hOpee~S3^ z+p9bI^WwBNy|LePpZxCdFn3?mbjZaA{P2FZ)RQUx;0K9>1W<4f{JmpB44kVc9#R5o zTlua}opb9kPs+uowgLVz9HG)q8%~vM&*0hzW+}nOlv)@fV}e~0oL?3xt8X$^*4D)( zUzBw;rwd#-IK+WJ8N2~AD8bL)ed|9gEBH~H-OovIZe1q3?EzJSf&wc-{Vq**P8e4s zCED+0M!1Bor1($yrm*82NqrrH)j=Zz6bHr+P!< z#KLy@W`hdrd1~|yRT@+CVryHMwHDe0hwtH&uLm21RE*DiHZBl|J&)XB&bfe1EzWttpo+WARD*%#Us$^km8+;7{9r9xy zuS@IW&pSOn=wTr9uxeg!f|cRK0}z{p<*$}7`JXGyLCzq9zV5n}w=0C|4!1;j{paLr zBLewTfq;mBQoyp)q{vVk*HyVp|BguJw=VS_M))fgxEE&%gc1MvFf^6m7L~nvv%}Yj zkpoh=o;TMs+K+#4L8SJu@}ydHJ)6xZ`E3rbe}y-$G}1>k=~K0-3gOQ)x>`CsyY%|` z*d<EjA;OzqeQ81gsExu@OFEd$I;vRgye4%^}F)Y?8crsqsy3uW-#Tgw+?Q~n2-@9 ztnH6^#_h~0R?7Q#X~>!%lz!?k^(d-D$ihj)$0#|1K5^8cs;VtI_)Pl`UCp^7vF9?jGhB6=mo*dhI?hxjc+6U%r zu-Mi@W-;;0Ojg*b-%7w99%?+fcbS<^=l)?T05#tK#I_sH!cTBK9+Glo=PID{s*OmR zG8o%%fsz|L{HN>-DXd$QTSB_hkTIL|#cc`KsWgf0M>Mp^{p;-ngqsqJNp)9p_cg}W z3u~VQ2wed(O`X4@f+wLWYsnbVcFO$u{?|g(tggWPEdR=!lp40Wqw0eplh8zccc;Gl zOvaKf1FS|XELcWuF(WNgnybMtW@p0sYSB7|!^}d=eam7&Sy9N$G*nk+?T%VU3IgZD zrPK7RcQx+bFcOY8SQ=@u(5NmyAj!ifI{cOX_d*bo&yT!JWg(ZZS#1>%1d+M!h6d#9 zjFWZo$K>H5{7jK~VS%5-_%Z@2-OLgnRk}U3?%+KvmedqhQ!!DBC>bSiIi2aOlE#u3(dL+CAI36VxPtB}nZu&Izt*`xJ9J~Qvp{xk-ssb{L&m07K z))v2K^?NBf2|U~7rZ}nk*!h7I(0$VjD3W7HG@7g5>vf2 z4X4SLZt%&F)Y^SDw;?0*szlkO8!lkXPv>({Q5HPazDG56Tc)Eo&s{z9M1{T33LNj{ zp~N!c#g~b7@bicM)UR?aS4|7Uc$4~zdy{uR)HaVxnzy{VVwn5YmlGn)6)rlMh5Cmz zgQPzX%&*qZ_6^+K6%o6_^PHhFu2akm^d$>2)vq3e>ZM=n7Zl74?@!#Sqy5Df$1RhS zdh*N|pKBoLQv{R36k{ub&l zvu;>i5d3pk()q|Qa%26PpkccAMPpVV*V-QO&%o2#C3+<`uUhNmH2mT^9`10~NI{EA zOpSU3M(5;{=(BaDk|fM3w!R&&liG=(pke0^-I((J-gTd$Qp`yGeZiSL14-a3LN_5>Lz6>V?vtrjZ2fwPL{D zx}_fLlsu{+7@^}B0qhe}NGTUfj*N&HW>y}|Nsk+^18nzqiO5hg{@-CM!tRvkmU1joj$~v7g{w%)`>B`U5aE8eV%$oBNWvNrzGa06t*&N2xozT)9N_s zR{~S98sS#7Uy-k^>1iAoPnO@zBpSaJO)3iL`(87Wcs+a>7kYLj&JX}=6F&I;43LuJ zahW}~2%|51wj#ct^O{!b2s@VjQcl|~DWJB`O$OW7N9A?Dt-yaf;#8`4IZT3KsPiFp z)GYa>HF93hJzGG--QL*ckr-icFN_Of&sa~Df*sS-!?yr4y<&~uX|aWHk922*UM5< zoWFI%gc9-uPhxQ&S52Rhax-LpF{Y`s=^JvntGTt^FBi=uByzXt zf7i&(S3?hKQ1h_0Wpvu_kmwDaM2;ft;#&7vFRx8cx6Mv&a3C1}O3w{)bfeTZVKo5eX@UR&R< zvt9Kx%k@TKHG>NmByllhZEwIb25QgCGs5qI zg4ZY3M`^RxX-}V$P;2iSGDYy(b^x~L2GIr0()*a5m!B4^((QG;tfMY*=p86CzJ99P$r|79i4n4Hu!p`Q;qD!e@ZB&_Cg1K~8|v6=jY7Y89?bu` z`qq)d?=kB=v(wlx*${mLv8rvVbNWSLTz+}U?XZDH^2oBxRf~3A=6SukTpYmvwcJ7a5Z9fbq$cAMhAW$o$ zcU~sY3=R%f?P#`{l@;hlYr*SzKL)uJl<9WlO0CbAtxwpk!;H8?a&C?m-|_Kr_-5a- z6e-I$XuVoJ6fbVCiLdic-Gisij;mH3j{l}wd+{GV@9gb$Tfce5)g5m&>jr|vgjSv) zJG=80Nl7W!+gmx0_bZQHZyn6bm1+$YmBk45%nHN%g2{bTcfh4QcL#lt%`}4SkZD3b zsQD=fKKYGzJcP#xJ;RjE{ropCgrdTl@*Y>>^^=u!bh>|C{H1=@_jo0N(qUj|ojEJ? zv0yAKZd{-%i)p|S>k}KjYb!9`KiRQ(EL8`y;764uci;0x1ia%mAmHI-3`cOmkbyr2uCh!NmTU~Yfvuh##g`fFYzUmXlh z%g9(qw|}p99~4}9Fdc+Iwvg7Cq49Q0 z-QsFY+(5KivHZu(Xq+=N#q4GNTc{i^~S-K;#mh3^7O=6HK~=J z0S2qB*NpFO9BnPxt=BsfYRjBkk<_WWYI|GLL#&AB?=s(=5;;Y^*)0@huJEtutTwOO zYU@@XAo_<7A-&$OqCMOmTQB0Ulg8S&L$Z&o1m5EyrC#6hsqYrbX8&#ZuvXOAn3|VI zzBi^lk$V&DtI%;yte11mxwt=O$d3Ogz>#FG@6{LodJ<6)o1Gm!`8@(1CSlQ8Y;)-e zg#eGA7K@n~4GdXZ%MOHt$7}#$k~Tu>|Gez4KJMUPDe5VWtvsGDHxcDcb;PLr@siHCdMMHzJNX0q)JBPO@o0Siex*LeK?x|5#yaQ!KA6n-BBZH%0b zwR`B5O+oNyLOz9Ye;@1Zm}eNSi_<^H09nXq!^0;Yqo^S<|2sO#f4?P!cVF}+`KGEN za_^6CYiF!skNbH*jNAF@n@${a3WIKci1xRDkb2FFz?;@m6a*@gxlp zF2!&$Fffz@fmfh1L~%Ry<{do5FoMk2E|Db~Ttg*eN_#2El?~OT6wXDOw!f0X!g;Hb z{=n8`h{1t@ft3IDjyKThS2qnQ8#)W-Mer5Pu@~)-Hf|#LAl`O;#N`>4+zI{8eLIS0 zW@bh*Uq)CMBeD?J>IQh4m}i;Z9N_Ma>URoddzVW!2a3Axdk_wnA@xUR@nwj@mD%#S zoY}bcot@b+qzaMv?G9_y;`SqwJy>iGz@i|3+ujJx@r62XdxOsFs!%!}_G-8I=<^C) zJaY%U+of(gu-PL4^{|^_x=?cRZvjO~Ljs)XK<9>HL{=7`>lZpR_Aw?qZk`ra_bXM- zfq@2GDh?b+pO?WRU=PJ*%ZtmyVN74o_^YccRFc%W6X!zvD9ttx6jUvmlM|u`ugN@m zE8jK}pC`*Nh9cdd3Es_hp;!e$$P8W1qK(Zk(OTd%aML5A-^_zk6E`A-SBAVP-Sx zbzsu_Yd$w3;dWZ*dpX%1ld&V!+|C|xcvsH<tbd>21&oN$_WR02}OgLow zzKUUcUj|WmcX^&)KONgUjIX*Xsk;4aIcp8zT1)NmJolaWFPA?5DL+^Okt~q5$!)C~ z&+0~98@S@lvoj{ZnnXo_Ux6(xEuk^%GrwiGqh!!tOWwQ$nKec-A48#fPZne9Q^)7$ zHK53MXApraiTLpT5eD7+`Oa3Enwe{$+Wz)P|2?T)i)}hBJtH=Ll=#iTCez93shFiy zTqERe8J2XeRMYfx{;XAybODBE!d+hB0@upcC8o|}I z0rjzvkuU2|+nXrIt5xx@3F~Bqz7Q~Aj^NWHi)UY<1fxaQy_?U_2tq|x(x5FUph?ox1EW}Scpl|R30}DIKwFra;VE?d+>WwAH8PLo0CbA z;#n&tbuF9E*In@Ehj!oaIA85d}w%QG$aTF2= zW$N@MtZ4e}M!Q%NJ{k}JwfD&AEET33IzMw1`+ImYH2?De5To%XAFZ9GrP8j!xO zcwH-g#KR*)=J5FV>C@-#9(xQwTrL-z1Xk06J|ovHrpqzDw~u}Yi}@i`w%h&OhUVrp zzpG7U*bEYF_zyDu3R<$Hsf^_ku1lB7$&x0lK+udBmu z?CzQp8Jd{tB_ZUq4HV?Rw#I`Nv)<>6Xh;EbsnYq-XwBo8F_}r%OKpw;|N3TH0p{We zT%n|;B`zlRo`B2N=xXPWZE_Y%mED;8#Ri#~Yz}H?z9y^IXgSs`uaqWb>!rE;#_Ng8;K{7 zt_D^oPZ@4He}#WIYdLQzg)q0hAO!`9VSV~^eMSFP%j*M$Ccyp9FNlQkcXM-kjNl7` z-(n5PDaNz!Z=nhk9ld*NT)D)e#>yV6*+qmN#eAF`-@8A!>=v<=b#7{#1=K%K}q~hkPgM+fNvO=SyG5G3f zYPrj-bk2iOj>QxeV-;z!@)U9ew-RD-T6VQ#-@y|}r-LJAW8x1Psotx{I0e8xw{7BH0mxD^zUX8LTu zK+efbc`~&bPck7I$6W9l%dfKlfXuI-{-sDeaZJ~;3$g|Fhgie?_LQQeY{n&n1#S(D z!A9rLdA0S#sm-L=11(i6&mBh|AO?9o_K{1mP*UPM))gVGp6<`iUzedwC5j3QZw--0 zKFLS{u7r!}-P65wj)ADCxb#|lY-87F`sNA2E|xj`f1yp1{hL-#EbxF85e7mNP*fsH zvAmwUo1gIyBK`|)lKwPglWMdrJz;=j9@8hzh?1qQIl&RWn4Mo&{Qmu~bw#`5YUT-D z5)xpyFOZke(9o~>RrV=SXJ_w#Lp3845KviKTEfD@e!nXyEHpHBg1l6>y#{jOB4gpC zIGikiUY|$bQXl_{aP#m;QK$jo@eYINli1Xnx4M57&F8Sq$;r}}A4#VAmX@D0wj1J; zl7a?J@+vBrRf^=k8SCFOW+i8j)!QzArlS)E&$2r9Is_vlS}W^oyR4=0#Ykb&RMJ>7 zfBN(Z@PcDApH&WK!R9SP4Z&q)jBTFxd9LSr#j|wv=L>_j(}nfir^Ptwu6tuOFWywA zZO1CWQhG75{eU0z>ZS#@=QRfY+`DjKd-@N z@b#BkyMA(+L3bc%1@z1=OO4s$a%wi5T$YS!ce?aLHk~`}6#|(&bUu+@SuHiFHH9ao z=gW{F_CZgQ?rVp@hb~wC)MO*EbbY*IF_FYw_j&fNnU3xWiHS{5pR;MAw|u+UoU~c2 zj{5m7fI+2GH>?E@`-?2bhp=+Zo6?f0I7i-~-)&MhE3IKs8C-F-Tw#gRpH# zYM74IUqH$eT5_o-rT8xbm;=Rc;O)x%>FLSH*f;=)ZzHL=tgNgIhe$#3LnYET9sDAry z^P{1)b4Z)s_X`p|X# z2TfSZeI>A&Djmo6z^WC;sAUBa6d&J@01j*daLQ$Ek=JuzBa$cIG0r9yHg+{=+pJK? zfrKupWYJM$>Gfkz{$g@v05FgXP4saG2a+~6Hot4c@~-{K0u9dF+Ym?@7?4d2O3TD5 z=E(xTQm1ThZTW*EKBSqCI|{z>Q-s7E)LPIcNe7D|Z#UE(;|lP?6;xYJYrHmxgN*I_ z#w&nNLJH{Wd?xX-kh;IQ*;w;D6Gr&vAr5yu-*-8}22E5yjjf^8o=qVUJvDxQMHHaM zOGK|;ZZx#BppGM4QTyuW2jy}iYw~7mfjiihv@7>$RXXg_gFGeD(0i6>MN)W=8Jk19^&zkN1}^ z%9lWMU0GRS`S9&B=z~t{_fW0(+}i)M7eK3wn)H{D`M6m^da}3y+xo$&shcxaPkz3Z zELU12Z4y$VG?l5TDW%Q2VN$!*ExvdZ;m?SO55fo|-7BB@Y(Z4J*4Ea*eB67u#LSeI zGTfs;)0|3X*6+GFpnbZz1a_HMfR;dxF`GT&0L&{;I5##i_r37D)`R7NcTr_9=6smO zd32KmvNrrlfn$nXL@8-tP?{r-Gy&e1wQ^bInRpE{^SSV|2I`s5UB!UWr)P_Q|Bn0l zbI}B^1tJRKuHqG0q&OxiEpr7a9c#D~&%UIbOn!&2Z#1z$bVvw|7W}B%;Yi|OLfCqB zQgyYOMV%HI#6DDw#l1$q!g`q{AtY?Vn@A!NmrB zB)KO`jbe?=!!|623qql5`gLLg(-bV|c5_8_naKxi-lFTvcROme<%WUigo0jyz!-wpjU?F>9-!CI5#iK9t0CjFRzb=m`uIbK0SBDQY5VT|v zprWQX|IPd88Sj#>40dpK&a0pElP=3^{4I)aI?v*?o;7|ZAO%#-kKyH3tF*K`j@aYw zp>3Wq7io- zQo~^Rz-Cs1M|RYnmi}CiVfGW<>}&9#Np-Uq4d|3?HDL-Q9`p#ZzkxzE*~dI0kybyn z3x;p3rXLkON;{2gw?uF^bzgWIh;^V0_`T3wM9&n;1g-PVrOBr9)dNS2h8 z6p1UCC)NJ3N5Y`^Pi}23a+<8TS`sP_&0(1p#yrWJ4@0v5^q(E|*?2V$3_fj|C*F|i ze6$;v>iyz-%4)W;s$^^lW918zP(6(yxG;oRSizXJ`q<{>tXrKO3DD4<^3 z(EQR;EFi8_hDy@W(J9ggx6YSwc6EJuVWG#OUcW1}$Ou;zE0S zINVHkIPPaeXnw~S$w=T&Lnj`K8I*d^c&vP?d4J=0y5>skD$PPj$PRmlMoK}E;N#(<#S;DY%*?y1@6GrDqfxp}Slbk;AoX(U(LLZ+saGqbYr zI2>VfbIFo#0#Er;zj*TkaUaG&yW54h@y&;y-{ak!t2<{aSVcIG9$k0_f<9r>PmGC{ zn!wX$&Bna5KA0%fG(9|>!oO^#%86uU9Yu@fXu_)5prd-`Y=bq?A>{7vZenf<1g@At zo4kI-fT}qJzk~!#V5m~%{6|V{RO{;lUA9>5##UEXXY=&(j_|%>2fHr&a%{s#eEhy+J<{7j zpTG6a>HMB8^w1rCT%iq(fPerCNvr`gO8!HzEVZ$-EV8-JTNcGY^mL1c0#N%YfoB2a zUQ*($s+t_H@9?v7LQz=6pKmwwcbjJ#H;5ldV4#4s^9yLp4Fl8lUlv2Q#gy&XdP35i-R-AyyFq~!baGH-Qt4am{)U&P|{jb{WIOW-CA+$kFE z%cUp4drK(nL|?5 zuLwZ31^-0^o;*b;SeQ(LsiSq3MI}Diq7F3>4R4AO?E%QK0IPySM%bBG12aCev9j_w z?YV-VIVmZ%Fj0bpL90S=8|fYG(_jsS>hY|e_3`m)W_rHmEACc$m(GIaoeY&{^Ve4_ zR8-U{JOC|)SqoB!hew)h_m2Y9*pM~t@93!UbfH^b`PGMf$jeg|qamM%HwTbqmOk2+ zv1?JH9G@s)frj|BcApP$b{m)z;04tPT|2@I~Un~Fbv_FhMm&HcS1>in*#Q_%*H%)xc zw_29ZQQVwwWTPV>syRmUAeGFa?m=jcImZ{p99goYA=la;evmG z9D2uv{O;G@I*;V6Z%qaDYY~Lrpnx(5c+&t}y?wDs0rhe<%nF>~zXeo$0-7t> zyYNmo^q1l5CUPBJ1LuJ>Pz_l!fr_|hn~mO!HbIyo=|xTkC;3$&kZ zSQykxvsKdUTUg8S+I#IBw2j;l5<_6_y*%`|?&OT`CTZyHU5{gPJO+Q6IasX!@c}S1 zfPjEG51e_UiKPl_e}^`#`$X8cKaz|Kya|UqucrT_8)OkU%$q+C*%ZOErJ6P29Rio4 zDYb76b=Hf`RN199X~;zQW7p#yfAg5zD}OV)oqOx~LQu|{o|(dtm>uS`Trc_woZQYK zXwA;D&iz6}c;;N}|KBkd3cBC!^<%5f7pFZ681x!*p(P_hfb~F!CaTZ`=87{jVeNeQ zdULwmAeGj-LO9$$3-{Q3!dN zo=ZK5^yOt8Tf#q{AO7D$tdsu^vCzVm|JW#FqdPXW&c4&sQl?a;OFEeB(PhxTi-792 z?aN1E_?Ure#&Z2s}wEz*kQgP6>F~b!-+Y*M`paMhSx2+S+1=cZ~+O za!RM_ZCA;~qY24swaQ`#O_E)J6a_U4-FER%cKyf}7%u400vT*B%YmeN{R(jH$+Vgp z!qM3@MvBZrWda z<_2w18X5-Ru{EFJWtYHNW4W$?a6HI1-Jg*S()yvPqy)zG+} z3?YGL@x05|75vXjnZg&>9#YX+FswVW3H%3d0Wn<_8J}J9AEc6ykoW@XhOP2}EOFYB z0Kf_ZJ7;|OA4#SCE5r;`-tS4HN%)MCd;ty(IF?9YB6p9C$%{%zgb^)cYGtZ(l)Lr> z-;&ePO44E>O%^GTTn-L=;QM4)J0LIdJf}l+J6++rp0y0HjlB;2h|bQhhQ`Jet!-_6 z{_n5LuGD~=gQM@J=jP!7P%N^4>oa-mzZcT#^8C*m0SF}mu-~`B|8&f_3A~AS{TFg& zAG%EkyeFK83Fv^0mY7iQ;89z1y>k{;a4`*c>Lc}7ny zDLO{*2{(VzqR#g*JV`w#N}Phkr#7~PPB&y};?wErk)VvE|78eyASury%Xa^&wBwZ_ z7{11ZiyhyywY5!3POj!;`WOr>MT%NpFn8F@eFm0W(D0+$*rkC}I6$yGJOrpx@TwQv z-JQ#Ca}##N+=K+Q>qGMhH`g_of53~DwsFELbk#v$%Y#?n8-j8^rrlYT!?^V~E`M~7 zo{`aX@hYkH{`Jjx?dAUAao<$+(0R1}@#WDA+vnvo(79m|kIm_ZJ`j^r=`}Vu`VHZm zon5r)dX@12A_0G~6akPtA|ft70#-Ppe<27~uc-2W)*{LFAC<=ltoz zg`~y|GLi1|ooCZUBx+gQ0ip(l9uw9o>v_9+o5dm9>C&8`#PsC;<{!stgnVJ0ot@M! zFA&H=r6C2tH}E|@9mjSz09A2+Y!@9J{VM>UahP;E*Vikg7FRvv|Bf?njMtF#&CMl` zUTRA&vE>e+P%INJM%~)u3$CUC+kmSh{R!ceyw@FD( zj&~J|iH$XY@(+Oj_Y$Z8z+RX%vR}coM%LCcswS|HkMB>*MRFCDHPyoODh4Je;|8k| z(ns$f^j~FxfCMlgU|L1uVTy?7TkLP-iuCr`?zDTJ+g`$|(qh5F!#e?(T;`)VQ@(f< zB@I^tQ!}@Z|Hg&^kbWmrOT-WxzdTd{JVBN2Q^N{t@bu>*zS)Yq+JEOxj!XudmX`Lr zuxN94Hz=ft#^?3b?`zStil(O2R<PA~7TMW_>gG)9Yr#7`dH0JpCF$4s18su1K5 zd)S<>Wq5q8wyNrIViTe6$+;Bk9osR_Qg zx~i?+-pDmclrErZ`+^@84DeEM@NE6!dHvJuTD^2_j*4%mjtKQ*I6 zTG;HPJ>h*DUQHkzNKRsiQ1F4lB*=m%w1*+Gb~5fSF9gQY@jzt>^>lkIAuWv*f=Wyd zDEGv@pNG|TX+4gi1?C|oqd-uugA6I}ioAh!vV#QOU`vepiLqkIV@2!#|E>j=w zK^xsTm^40FOPCQ){E`}Yx_o(i3EeqA5Te_Hf#+peRl@^lS~N^{6jW4HKrzRp)7V)u zYn?v2tlq&pr5?72h;p$NtxeI`$Cgay5_5f0HvM>f;HfxBIDvOmxXtRs!K8AQH$dcy zd3}$^;LQ^rP~nb_zwyIZ6jx1+S9y9G;ll?Cs$DECc*b0^T!8ijPFldg?(TjP6%z+B z?Gyg7w7j`LAD_%0xV*R!J^p2>Apnm?L{4p{T4TAnDFT$+MY9Ru>;p#l!BdJ3rJ)6 zA2yt^nf1Z}`FQ5<$I+z^h^S`AbG8ppK;yAK31DVqU0sZK|8S(|!tfTA5I{bD0*9oK zK(^>UQLPu$WHofH#6!K5~As7;eco!vJX}TE4We<+*6Y zZC+CR`(rZ)8~=!t00;lBGZJ+T9#EyA5^_tbny|~uM+2&TrRTUEI*U;+0x+q83XSqq zj+~n^wL2mRn0mp;#0*ijU_W$!*L}u~S>JXBo^78IK$0vxTiwOH^` zZ~HF* z7Zj6|O7Rr0U$Go{BKG-v*V-h)kguqC=2NVU-v_*dNRILJR>>XzDx%pNBEMUHZ+Ofb zi#E4&F@21d7dvc^+*SO+w~JvU1$)NgZhuJ_AyAW4bTuzy(Bx=hS3WHIa%h+t=wnii^Jjkwy=&(UuJMX3BCtn?xk_wp;Wf zPMS(G-B_KOltT*P!OAN00=@pifI~ulx5!=l(cZbj=XTU$6~_C+?cqCJK8GJa#7x0k zUa#&ZtlSP4q*irE(3EFVl#btFAK$+R{D`bL=Kl4E#>c`7rt@AP2>`fu(9sdTp6Bf+ z`AqJ?y$3hI*~<_gCfkOA<-X<+6GCn(Rv!0^u#;i0_b3&p14FKj9Wh?j1WR9Spxbn^ zntzb+QQ@MZ;=??{$Hv7;0m?q>)b!xUNblg_$1-*8dl>~%(7hcX0|1$QLR!-3#)Kjv zQ5{kFIY9g=&(=f$a6C3P7KzW}KQVzW(!bOU-vjXS&7-66MasV;L*k~^G8PU4`X-)x zBj+azO%coX8NneE_G3BY=C|qVl~q-Soqo*(g>>}vj7HEu?zLwk#EdDcVh^mUSTaTd zA6|WUjpne@5wAVt(a#s~j3==E=EHW^<$ZavG~Tv8PFlE6#4mI!_%Caq#afkT=VioY zO^clT@+I>T;u=lJCx5OdP}R^NQKoLpnenG&N=Zpm+NbM%x3CDHQ=BC_0g0*UR_~>o z=R72GZh1K(409kMwJ`(w9Sq~7$hJB6jISL7ItoQ3AWBkDn_)fQol5*sWU-v;9VS;* z>swl%i%ZIi0%)TO^}tk7OoMZYKwL=hN^gMhg{S<-_0wrZ zvyPMRv!2`%-G7R%KqpuIOgUajV+j8ZuaEm zM28L;>lz8ze2e4t7$+Y|@;pHoS$~x;6~lwz0Vq>-*fUQ=j{N6u#KicuRs+1cdWoKqag; z861x!@}yUa`^dEeT~nnLpPXz~$IQWjl4199;1PBv(tu}*mzGuvu_bC)6^!!neugn% z$6u`F$xck1hJuAhGkIyON)Fj-1wJEzTHZimN)O=D0J6yXqf+>txPAIU$;YfFjfl_1 zapyn@Iamwk-Mi2%_K!)@@BIc%$jJ=(1{5-ZmIk0@3n9XS<9>8a=f?5XOK>>3f|Qpx zKGd*h$;Q`7R6;DS)|CVrI%Pex?*CQgx3|As4UWo?l;Vjhi$aN0ij&Jrt1`AX1(=ws zs_MlOxT4mwhKy*Co(xeu#qsF|k8{9&v;Fz3&V%b7k7&I}1{*Iz$Uuy?_vHSG{D9W~J5xTlMB26Q4oEY50x!2qdto+u2UQ{oTK|S#Q;z_y3b2lyeH?b}0U({j74l)wD#He3BF2Wu&6@&yA3x&(1s20@ zZXkoRstX5g_j6Xox!*AihM+ku+s@JSb%}(8MlApJzF)Kc7;#tM@da>sKtBPHC%h-M z9M{Vur%31be!A>R>!J>fp#oWSOT+Oqz_D)l@(ruL~9Pv~l_E6Gp(& zjV>IUmL>)GA3Z%iH#d*1{c|(~XI=q7DFfnM@A^22uTY1)kg|Zwl<3?*AJ8Hd5~Gj< zC#)7!bG;h^0Ti(OY0VFbSy|0pFYASUDc>{ztLRJ7Z&(N(8j=P#+iY7zL|~8{sH`&Cx5#Qv!6bv>j019BxukyE4Df+&54pc4G)vP)?It$-1tw(fASXu8U1m#$DYx{ep|*!>|F@8w|{14z&&QRa|%mwgJ92P;Dj zU+P_m@+Ah?TlW5Ug;bCFv0X&HjSHu}Yd>gZcm|10&yeco19t?=a3{k+&uSXiKwChE zwr}+-eo#{$tlvA~@C}WRxD!qDEAX(e|JosIjCQ5_*F5Nf zI+UE!jr8(TJB`2K%yuDz%bx5vroF~HTweCf#>S{f5+Q6F8XDkh0*h@lVSIKSW%9Lf zXhwioQYaf%S86z;AoD+335v1xoqx|-{l}oxx>>IJA6{7a(ObO%O$Nad5_PF||E09V3H^Nkk(*E=rs z2IB`bq5wT4g(~$S5)xG*Z47!>Y(U>qV^h-?ps7jb>2DmxLcJ}Y{@Xo4AbKPr&s2PJ zMuvo)UG^-WEWSP!$iZQw3%;o4A>IPWyYhgZz|{X zWTHw5&?*g+ni}^Ow*SMP1@w*o!=44a#6~9W*!a;%_u;TGiOi(6=?D=AGtSS*zE<+7!rC}A!+u6DA(`PyO`hp{`D)A$G2=hNaD;;^1L*n-ZtwF zW23p57jSczk6x72RMn=(WPf7)fjQ%kUiydTiazrh z;06(YrS%EFQ9Frgb_`66(C~2N@7P6^uNglUPB@K>2p=GVHZBAMS@Mg+lqtw&31J;0 zZ5j3*5I(W@i#Cko{a}u%3JoUh;rdGB$8}O3lpeL={tKAyEzfI`oW#rhq9Wrne)r!-!M97us0mKlz+vbmYtxEsG- z7Q}NNJtbZ^NCQ2YD}Htv+~{)gRUGYTk!pE~tSdAux_=vFtSk#u&>N0TxL>?_Eg!{^ zNq#D*{Q-j|l(1ILsJ93m<0%IV2At5Mi#*1ChE{!~S2Qq*_kMZWkm;KVhg0}>m`CQ< zJ|O6yUw^URdth1~Lq!y~v0;dcVj3~~09-XtfBUc66}7iV7Yrv?J1;699UoUN+92a; zi2`WbtR^V9U;O`Sx}xri}OUa$(T4iYs%jl77>X=-@@qX!E^UR9G8RS zYdy9tvQR1_FoZ0G$Za1|SGBS8_)2Y@!|_U$ZGNPxnCRHNIt_Oz)^AM{mFwnNq>xNQ z7MLaLt^M}xD?3#luST!U@Yrpg;j1TiC?Y~GEkjSN6x%$_8!2Md0_`0>d( zVVpGpFBO%QnGbVESAHmOdz2=STsq!b18@&N4Kku=NmXs4!=RvxYyYI%^8l)99J|u2 zY)oWWM>EU9yhO?uxp`HM#hx*b19Qux@~dNwdW+f*Lg^S2;Hbq1ipqt2T2(pQpY1+l zUW^~%PyOAw&i!{kNIC~n_jE-vCYHTU4@<;r}4E9+d-?m;?Aj*;m8QF^CE;8KR4}|(W*oEjG za)AX{+n$4;5aRLqh5uIHF5Qh~F3p+PQXqO|Y|p0(7{6v0r--?4G`jk%oYJMIqfXO? zhQ7MZkY_}NNQOOU=}_q5CcEo%&x({ErE-)cT{hYLg|J1rIryw4MRMZd)`(Sq8vdt@ zG)G}30XJV*F-(9&PRb1QAM2o^`Nn+pN3&2WONYHUR5(*T`K#K<_sz{`56D47oB@Z} z_6TUDLC@epXE!N5;Uqmht2v;(@~#LK4jUTs>gkyAPtEzW-ouNFTNC`LBkamOeHijz zygdBmE!GDQSp(N|unxu7gRFiRH6E{3IFd!^n>F0@-ag9qtNU*!bTcVLp@M|Fjz6v^&ns+G)9Y!@>}`Ds1!e)<1_>$%ugy z=m7}~_P^Z-JOyi6*1!fGC;ah*=HHdU>_~FuawDJBc7W96}ZTl8AtenU;Vs2y(K1 zK$ylgG}XI%9?0`%CBaTj>CvciO6UaZM(*w@9v|VQCan)C`R7khe?LWvD0O6hJHV9c z=)Dc^Tl=H~dD8p<`kqwl#_NSY<~ichyf($t-&-rT36;s%KIG1v&>5Ua8o3$)tulBW zb@#7W$VtBTfhrL#VSiN6c-bRIy-1Q{DywrUs9xoVnss4*QM^L~3ftg|_0^{yXPTkH z2z}M0jxlRhU~3GW2HYSZySN$b^XunRNV>cI`xkG;1)U!WFcnb8u-}HD{VDIjmG3@E zt*%I`e)Sd-6Bw396rw}$^MwH<-&jS!U4edYBZ>`@O2!uzG{4L~GZEUZ8wESJ$X|QB zv?)Ol__qXBJar9J)bJXEmTt zk4uwd;lG>+R5KT^NWBh?CF$c zg9}RWTEDnds`VE}t%%1c=Aa}Q5}^nc+A+X9xe1r;IJ;#?`w%?Dcz5W;)?6pT#c9%) z%|-OY%wz)`4u1Vin<%7HdU0vR1mU8GJvEj+eBk)Cg;o3cj8o|M8CjW@6Dh9KYh_1) zjF4PoCdxD=rS4_NvYkZK9*>$!Wg`b$zQ4cec}`duRGeoM`KlwSyTN5hnJxsTLVjd{Z^Clz_uaI(U({ay>tO`?~CU)0vUNF_^kru_#t z-NwIM*M969O@1{uwoT4gyoS=z%;dzWI8XJk`m(2$J|QC~V+MKRiehkeyZb==WW7XGma3PCP)C|#&2W^v zY2i+K*B(0y=j+IJ%TO>GA=u5W{pF&UVk^CH`8a zsT&q~>ke@ecPL0t|9;L`N{Q;O;O#P#Pz-{SdJlkLqsADC0Iy z$ylGKSs5)zf1U>LcQ$eHBtsD!Dppp&m&#soljb9Z-VlJZR{ z9^KD3`oKlpTRbO)7YCv|bp4ELUtrZOt_}|mw?88iM%lAh6Wy!_z3%Jj&GM;Dy06O} z^UWW7$0vU8YCeAv*thmQ3C)oY3Lhs!f+3=U;q`atR}{{rhR40hKC*`|ejSnlA?e#8 z+RaiWi&1K|D{jhIQI|;Mvg8pLO1Z7$T!rN?6Zz^gARcWWPA?sa8G@CD?|&z9?yA|@ zloDP!dh14t%#kp9>@PY`ex`QGWf>z{vk@mndC3X;o%DgIK{e2;(pu;F9ZC1tlhSKA!+dR|KLly=x2Dr&^= ziQxC-7p$vARj7`>Nfb+b*j{?TYeVtWf@MUpyL1t}Q%8?gW&D@tr+JDeV=81&$}TlG zldA^0uAG%7)mY7L1Yzi_Q9tfvF;;&}+~i`YT6y=z`O^??^w$DH7N2p^uk{OF$&#+t1QlDer!h~w$gyx~ zAt9mu%uCVifXcra4#ZYX$sbdc-@Ri~RgFZQ{FafsSZWvV`@52T(~tP*A9+$Enwy*J zd6wG9XIiCTs?-E2=Hc;0dOkW|^nj%=E(R<%|Mvz6naRAfY9L6P0;mf!bhc~UfUOBw zyhF|1!_AsxwG<`}FKtcBoW1O4TNre72pd)DqJA|J`&}N`>b4gjE4ZL|(pEHv$Gq6= zblY(k_GVT0O{h&?PKy8vwh(G11CG?>E6 zGFiUO??mh;((;++P`5ZtVM)vV?ERcq?#u6YaDPpTT9me%m7Tr+vD0P5;hT$YUh=gU zDCn5_rDQnb9Y_;Pj?lN~U?YiNg#}fjDRuS+-9S}sU`a`T2JTKk%B}bvboQ+{`=@6hUi22`Cm0BDo*&Gc;WBVG_!oAMlQmO4zp9AZsYV4 zdqj?@u~}OlRh#YS3`1zvXgS{(Pw6s2?az2+Ro-VmV)~li(>C%+?s63|)_|c}WaWfX zi7gPx8P%ouS-I0jd@V3*RcV>63O_jCwQ(KGOPuuNL7csV>;Ai2^v0_;`RIw@V=+@y z2@5Uv3Q8s-Cu6#sM}*xs{z~XOCV}!R6aN`U~UFf2^gb7?Q~!(TaAOlx0xQ1F)^!Ayd)ubl&K)R ziP@(ibA;XM>Jmk-1yg41%dtNn6B)$)Ek)cpT%EH?mDx%X??WCeY+bFOWd;C+t0^f- z0fF$P@k!GS%;Igm%&dSC?ONG2ia(r!xxZvB8$KgYBjXh(DQiDlnUEdRn2Bxw2pwh2 zo2u{z*OCWeH;IMdE>$8t-jwlAabP7x6w0 z8=~51`>j22BvEpy+j4zFN@cAc^>}=vZN+uvv=LXrqMIGHt%Jks`liuG$fg>6mg0S1 zhV6pt%<>(V*V7-iUZ2T82fLlIHbi@_Lc<@EuTAib0xf#`rzu6C zR}IxHYIqOu?M3`2VhktPgKSOX?Fs*G9QeMU@_gT^ylV>F1Xf@&nZ6UTKIAdhY>OPI zz~)UI)Qmz_Rm16ii#2Dqxw*e$)~6q<{g9l!PT2(+NCZ3i6=p)rZb>r#r030m#d;|BDnfAUU5a`E{Pg(PCA3ig%q41QTv;bpO^?AMyKUyv-8n(stSC zd^dbDJLQ;z)`rim?HlevFXupO5P@Ks`>@R0;joe>R}0Y5zYywPFZ4)#x9p}ma8|~G z`)xtr%>Wok6#Y>%{#pFhOE-;nd+~aFW`SKBC_MKW_~WT`RB;&P$k-}ahAr3iK07CW zNL3YeRh8?Spg{c99UwiTqN)KqUM{th8itdK4Jc8sEC(cB7t6d?_O1EK6&DdY;G*j9 zGEeS%H2g582~UT#*)Xq5SrZhDuj#8Ak~DtTU)33X(VOC|kcIu^?{^EbMpfNQ?q2*9 zytc&AkD-BNXJj;b;rS9ovXKsIxqH?HG3u0!%s{3Ne$LbtlisTTv26ABAKuq#+Zt@~ zHSnFLfAfXSS8d;o3KLNRNWNuF3d6K?B=3m5sHphzsW*Y+A1}{@#^B&i^EStN8X9H| z1;)!!Xxp7ly`hMcetUeBWMqC`F0_)$vA$lCSR_zZhRMhCIdLR0y#wRST&JfD4@Os48kI{CaH`{67Z>uM_|P diff --git a/doc/msrl-roster-flat.png b/doc/msrl-roster-flat.png deleted file mode 100644 index b998d92259a7a6de5d74fc03c77e470ef80517e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21565 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 Z{|~lgNT|Oqx1s<5002ovPDHLkV1jeFBf9_q diff --git a/doc/webadmmain.png b/doc/webadmmain.png deleted file mode 100644 index 2228dcd6865aefce44c1c7f2e9efba9c5b55b3f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6542 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 diff --git a/doc/webadmmainru.png b/doc/webadmmainru.png deleted file mode 100644 index 3fd34ae8c6314938c6e57ce531bc24d29832a468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13085 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 z 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 diff --git a/doc/yozhikheader.png b/doc/yozhikheader.png deleted file mode 100644 index f2a4e4f002db88403decf9ca48700f3ddd9ef6b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 160944 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

    *?Xj;slYCa$s5kW) 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 *QQDvA9h0OHajG1 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

    E)3eP1_*E{q1%;cO-xJ?od~3kR-@1s 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 Date: Wed, 20 May 2015 12:13:15 +0200 Subject: [PATCH 079/695] Fix function specification --- src/jlib.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index c0d5ebd2294..5b51f4f3feb 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -637,8 +637,8 @@ add_delay_info(El, From, Time, Desc) -> xml:append_subtags(NewEl, [NewDelayTag]) end. --spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary(), - binary()) -> xmlel() | error. +-spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary()) + -> xmlel() | error. create_delay_tag(TimeStamp, FromJID, Desc) when is_tuple(FromJID) -> From = jlib:jid_to_string(FromJID), From 05011e6918e3227839681ac464c29620c8221bea Mon Sep 17 00:00:00 2001 From: Evgeny Khramtsov Date: Wed, 20 May 2015 13:57:44 +0300 Subject: [PATCH 080/695] Revert "added sm table to pg.sql" --- sql/pg.sql | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/sql/pg.sql b/sql/pg.sql index 966614f4858..8412c3c6b51 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -288,18 +288,3 @@ CREATE TABLE caps_features ( ); CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode); - -CREATE TABLE sm ( - usec bigint NOT NULL, - pid text NOT NULL, - node text NOT NULL, - username text NOT NULL, - resource text NOT NULL, - priority text NOT NULL, - info text NOT NULL -); - -CREATE UNIQUE INDEX i_sid ON sm USING btree (usec, pid); -CREATE INDEX i_node ON sm USING btree (node); -CREATE INDEX i_username ON sm USING btree (username); - From fcdb5197703c24a033209c0573c3e377ba3c0eb7 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 20 May 2015 13:50:59 +0200 Subject: [PATCH 081/695] Add missing sm table (thanks to Rasim Kalimullin)(EJAB-1740) --- sql/pg.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sql/pg.sql b/sql/pg.sql index 8412c3c6b51..736c4f93259 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -288,3 +288,17 @@ CREATE TABLE caps_features ( ); CREATE INDEX i_caps_features_node_subnode ON caps_features USING btree (node, subnode); + +CREATE TABLE sm ( + usec bigint NOT NULL, + pid text NOT NULL, + node text NOT NULL, + username text NOT NULL, + resource text NOT NULL, + priority text NOT NULL, + info text NOT NULL +); + +CREATE UNIQUE INDEX i_sid ON sm USING btree (usec, pid); +CREATE INDEX i_node ON sm USING btree (node); +CREATE INDEX i_username ON sm USING btree (username); From 3188941af20c020df756e82393649b561d46c984 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 20 May 2015 14:06:03 +0200 Subject: [PATCH 082/695] Add minor robustness on cluster scripts --- tools/joincluster | 6 +++--- tools/leavecluster | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/joincluster b/tools/joincluster index b3516d94df8..ff2e0380f51 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Add the current ejabberd node in a cluster @@ -56,7 +56,7 @@ function error PA=/tmp/clustersetup_$$ CTL=$(which ejabberdctl) -[ "$CTL" == "" ] && { +[ -x "$CTL" ] || { HERE=`which "$0"` BASE=`dirname $HERE`/.. ROOTDIR=`cd $BASE; pwd` @@ -65,7 +65,7 @@ CTL=$(which ejabberdctl) CTL=$(which ejabberdctl) } echo "Using commands:" -[ -x $CTL ] && echo $CTL || error "can't find ejabberdctl" 10 +[ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 . $CTL stop 2>/dev/null >/dev/null ERLC=${ERL}c diff --git a/tools/leavecluster b/tools/leavecluster index 7acc2b46ce8..edac8689eb2 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # Remove the current ejabberd node in a cluster @@ -36,7 +36,7 @@ exit PA=/tmp/clustersetup_$$ CTL=$(which ejabberdctl) -[ "$CTL" == "" ] && { +[ -x "$CTL" ] || { HERE=`which "$0"` BASE=`dirname $HERE`/.. ROOTDIR=`cd $BASE; pwd` @@ -45,7 +45,7 @@ CTL=$(which ejabberdctl) CTL=$(which ejabberdctl) } echo "Using commands:" -[ -x $CTL ] && echo $CTL || error "can't find ejabberdctl" 10 +[ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 . $CTL stop 2>/dev/null >/dev/null ERLC=${ERL}c From 3b24923458397fa19361490c25d1a6b84013421e Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 21 May 2015 12:00:41 +0200 Subject: [PATCH 083/695] Fix dialyzer warning in mod_muc_admin:206 --- include/mod_muc_room.hrl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index 6f170269d4c..5fabbb9e8aa 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -110,8 +110,8 @@ -record(muc_online_users, {us = {<<>>, <<>>} :: {binary(), binary()}, resource = <<>> :: binary() | '_', - room = <<>> :: binary() | '_', - host = <<>> :: binary() | '_'}). + room = <<>> :: binary() | '_' | '$1', + host = <<>> :: binary() | '_' | '$2'}). -type muc_online_users() :: #muc_online_users{}. From 0c725b5fac3fe14a1ba67db36888f1d0a51dceae Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 21 May 2015 17:02:36 +0200 Subject: [PATCH 084/695] Document protocol support (EJABS-1620) --- src/cyrsasl_scram.erl | 2 ++ src/ejabberd_c2s.erl | 4 ++++ src/ejabberd_captcha.erl | 2 ++ src/ejabberd_http_bind.erl | 3 +++ src/ejabberd_piefxis.erl | 2 ++ src/ejabberd_service.erl | 2 ++ src/ejabberd_stun.erl | 2 ++ src/ejabberd_websocket.erl | 2 ++ src/jlib.erl | 4 ++++ src/mod_adhoc.erl | 2 ++ src/mod_blocking.erl | 2 ++ src/mod_caps.erl | 2 ++ src/mod_carboncopy.erl | 1 + src/mod_client_state.erl | 1 + src/mod_configure.erl | 5 ++--- src/mod_disco.erl | 3 +++ src/mod_last.erl | 2 ++ src/mod_muc.erl | 2 ++ src/mod_multicast.erl | 2 ++ src/mod_offline.erl | 5 +++++ src/mod_ping.erl | 2 ++ src/mod_privacy.erl | 2 ++ src/mod_private.erl | 2 ++ src/mod_proxy65.erl | 2 ++ src/mod_pubsub.erl | 3 ++- src/mod_register.erl | 2 ++ src/mod_roster.erl | 3 +++ src/mod_sic.erl | 2 ++ src/mod_sip.erl | 1 + src/mod_stats.erl | 2 ++ src/mod_time.erl | 2 ++ src/mod_vcard.erl | 3 +++ src/mod_version.erl | 2 ++ 33 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl index deef51c5760..1805a16e00c 100644 --- a/src/cyrsasl_scram.erl +++ b/src/cyrsasl_scram.erl @@ -27,6 +27,8 @@ -author('stephen.roettger@googlemail.com'). +-protocol({rfc, 5802}). + -export([start/1, stop/0, mech_new/4, mech_step/2]). -include("ejabberd.hrl"). diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 5cdb8e1c9df..cd77ace2936 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -27,6 +27,10 @@ -author('alexey@process-one.net'). +-protocol({xep, 78, '2.5'}). +-protocol({xep, 138, '2.0'}). +-protocol({xep, 198, '1.3'}). + -update_info({update, 0}). -define(GEN_FSM, p1_fsm). diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 110da1f69fb..fc9f975f53a 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -25,6 +25,8 @@ -module(ejabberd_captcha). +-protocol({xep, 158, '1.0'}). + -behaviour(gen_server). %% API diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index 234ccf35ac4..620c8f1d37e 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -10,6 +10,9 @@ -module(ejabberd_http_bind). +-protocol({xep, 124, '1.11'}). +-protocol({xep, 206, '1.4'}). + -behaviour(gen_fsm). %% External exports diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 641db497b6f..61e6595e342 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -38,6 +38,8 @@ -module(ejabberd_piefxis). +-protocol({xep, 227, '1.0'}). + %% API -export([import_file/1, export_server/1, export_host/2]). diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 1fbc18ff29d..b7cea0c36ba 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 114, '1.6'}). + -define(GEN_FSM, p1_fsm). -behaviour(?GEN_FSM). diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 11347d604a6..9435f7e635d 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -25,6 +25,8 @@ %%%------------------------------------------------------------------- -module(ejabberd_stun). +-protocol({rfc, 5766}). + %% API -export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]). diff --git a/src/ejabberd_websocket.erl b/src/ejabberd_websocket.erl index 9d5f32c33c7..c45d157bbfb 100644 --- a/src/ejabberd_websocket.erl +++ b/src/ejabberd_websocket.erl @@ -38,6 +38,8 @@ -module(ejabberd_websocket). +-protocol({rfc, 6455}). + -author('ecestari@process-one.net'). -export([check/2, socket_handoff/8]). diff --git a/src/jlib.erl b/src/jlib.erl index 5b51f4f3feb..389783b2471 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -27,6 +27,10 @@ -author('alexey@process-one.net'). +-protocol({xep, 59, '1.0'}). +-protocol({xep, 82, '1.1'}). +-protocol({xep, 203, '2.0'}). + -compile({no_auto_import, [atom_to_binary/2, binary_to_integer/1, integer_to_binary/1]}). diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index ec41e73f513..db73ced54d4 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -27,6 +27,8 @@ -author('henoch@dtek.chalmers.se'). +-protocol({xep, 50, '1.2'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 172786810c3..1d3bf3c3483 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -28,6 +28,8 @@ -behaviour(gen_mod). +-protocol({xep, 191, '1.2'}). + -export([start/2, stop/1, process_iq/3, process_iq_set/4, process_iq_get/5]). diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 36c8c0eeddd..10fe2943107 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -29,6 +29,8 @@ -author('henoch@dtek.chalmers.se'). +-protocol({xep, 115, '1.5'}). + -behaviour(gen_server). -behaviour(gen_mod). diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 24c09bffd70..be9e30f9c3f 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -26,6 +26,7 @@ %%%---------------------------------------------------------------------- -module (mod_carboncopy). -author ('ecestari@process-one.net'). +-protocol({xep, 280, '0.8'}). -behavior(gen_mod). diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index fd72c02f6be..c5041ed04c9 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -25,6 +25,7 @@ -module(mod_client_state). -author('holger@zedat.fu-berlin.de'). +-protocol({xep, 352, '0.1'}). -behavior(gen_mod). diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 9e6e83e1c9c..f8ae1258d64 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -23,13 +23,12 @@ %%% %%%---------------------------------------------------------------------- -%%% Implements most of XEP-0133: Service Administration Version 1.1 -%%% (2005-08-19) - -module(mod_configure). -author('alexey@process-one.net'). +-protocol({xep, 133, '1.1'}). + -behaviour(gen_mod). -export([start/2, stop/1, get_local_identity/5, diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 00b65d23edb..c0ab9a9ac5a 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -27,6 +27,9 @@ -author('alexey@process-one.net'). +-protocol({xep, 30, '2.4'}). +-protocol({xep, 157, '1.0'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq_items/3, diff --git a/src/mod_last.erl b/src/mod_last.erl index e079a2d3859..4e96526e7c2 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 12, '2.0'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, export/1, diff --git a/src/mod_muc.erl b/src/mod_muc.erl index a3a8a933178..4fdc0fe1352 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 45, '1.25'}). + -behaviour(gen_server). -behaviour(gen_mod). diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 8a1960088fe..b6699d1039d 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -9,6 +9,8 @@ -author('badlop@process-one.net'). +-protocol({xep, 33, '1.1'}). + -behaviour(gen_server). -behaviour(gen_mod). diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 7f9a81a0daf..7c18a7f9873 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -26,6 +26,11 @@ -module(mod_offline). -author('alexey@process-one.net'). + +-protocol({xep, 22, '1.4'}). +-protocol({xep, 23, '1.3'}). +-protocol({xep, 160, '1.0'}). + -define(GEN_SERVER, p1_server). -behaviour(?GEN_SERVER). diff --git a/src/mod_ping.erl b/src/mod_ping.erl index f493dccb8ed..9ba9833ee9b 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -27,6 +27,8 @@ -author('bjc@kublai.com'). +-protocol({xep, 199, '2.0'}). + -behavior(gen_mod). -behavior(gen_server). diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index fd3f60247c5..35c3ed93b6f 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 16, '1.6'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_iq/3, export/1, import/1, diff --git a/src/mod_private.erl b/src/mod_private.erl index f09c6100ede..09182ded626 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 49, '1.2'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_sm_iq/3, import/3, diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl index 6eced10b859..effe2f784d6 100644 --- a/src/mod_proxy65.erl +++ b/src/mod_proxy65.erl @@ -27,6 +27,8 @@ -author('xram@jabber.ru'). +-protocol({xep, 65, '1.8'}). + -behaviour(gen_mod). -behaviour(supervisor). diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 8553db4e0ed..a61defc33e6 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -47,7 +47,8 @@ -behaviour(gen_mod). -behaviour(gen_server). -author('christophe.romain@process-one.net'). --version('1.13-1'). +-protocol({xep, 60, '1.13-1'}). +-protocol({xep, 163, '1.2'}). -include("ejabberd.hrl"). -include("logger.hrl"). diff --git a/src/mod_register.erl b/src/mod_register.erl index 1c03fb3e93c..6cb6731c15b 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 77, '2.4'}). + -behaviour(gen_mod). -export([start/2, stop/1, stream_feature_register/2, diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 605e8e36702..aa214b4216a 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -34,6 +34,9 @@ -module(mod_roster). +-protocol({xep, 237, '1.3'}). +-protocol({xep, 321, '0.1'}). + -author('alexey@process-one.net'). -behaviour(gen_mod). diff --git a/src/mod_sic.erl b/src/mod_sic.erl index ed44f8500d3..273930ff04d 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -25,6 +25,8 @@ -module(mod_sic). +-protocol({xep, 279, '0.2'}). + -author('karim.gemayel@process-one.net'). -behaviour(gen_mod). diff --git a/src/mod_sip.erl b/src/mod_sip.erl index f7f2b8ed0fd..8790cdfc047 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -24,6 +24,7 @@ %%%------------------------------------------------------------------- -module(mod_sip). +-protocol({rfc, 3261}). -behaviour(gen_mod). -behaviour(esip). diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 4317e9e92c8..4896a3c18b2 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 39, '0.6.0'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3]). diff --git a/src/mod_time.erl b/src/mod_time.erl index 417ee6bb0a4..111428070ca 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -28,6 +28,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 202, '2.0'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3]). diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index ba23d068832..2c700af2f4c 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -27,6 +27,9 @@ -author('alexey@process-one.net'). +-protocol({xep, 54, '1.2'}). +-protocol({xep, 55, '1.3'}). + -behaviour(gen_mod). -export([start/2, init/3, stop/1, get_sm_features/5, diff --git a/src/mod_version.erl b/src/mod_version.erl index e46262a2a6c..669a401d42e 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -27,6 +27,8 @@ -author('alexey@process-one.net'). +-protocol({xep, 92, '1.1'}). + -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3]). From b07cb1ed843497af7d505f83dcc4a83d561812e1 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 21 May 2015 17:03:06 +0200 Subject: [PATCH 085/695] Use namespace definitions when possible --- src/mod_admin_extra.erl | 6 +++--- src/mod_configure.erl | 4 ++-- src/mod_register.erl | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 3687c1edf37..8eae45b6daa 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -1068,7 +1068,7 @@ subscribe(LU, LS, User, Server, Nick, Group, Subscription, _Xattrs) -> mod_roster:set_items( LU, LS, {xmlel, <<"query">>, - [{<<"xmlns">>, <<"jabber:iq:roster">>}], + [{<<"xmlns">>, ?NS_ROSTER}], [ItemEl]}). delete_rosteritem(LocalUser, LocalServer, User, Server) -> @@ -1085,7 +1085,7 @@ unsubscribe(LU, LS, User, Server) -> mod_roster:set_items( LU, LS, {xmlel, <<"query">>, - [{<<"xmlns">>, <<"jabber:iq:roster">>}], + [{<<"xmlns">>, ?NS_ROSTER}], [ItemEl]}). %% ----------------------------- @@ -1250,7 +1250,7 @@ private_get(Username, Host, Element, Ns) -> [{xmlel, Element, [{<<"xmlns">>, Ns}], []}]}}, ResIq = mod_private:process_sm_iq(From, To, IQ), [{xmlel, <<"query">>, - [{<<"xmlns">>, <<"jabber:iq:private">>}], + [{<<"xmlns">>, ?NS_PRIVATE}], [SubEl]}] = ResIq#iq.sub_el, binary_to_list(xml:element_to_binary(SubEl)). diff --git a/src/mod_configure.erl b/src/mod_configure.erl index f8ae1258d64..0941dcf2841 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -2022,14 +2022,14 @@ stop_node(From, Host, ENode, Action, XData) -> #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, - <<"jabber:x:data">>}, + ?NS_XDATA}, {<<"type">>, <<"submit">>}], children = SubEls}, others = [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, - <<"jabber:x:data">>}, + ?NS_XDATA}, {<<"type">>, <<"submit">>}], children = SubEls}]}, To = jlib:make_jid(<<"">>, Host, <<"">>), diff --git a/src/mod_register.erl b/src/mod_register.erl index 6cb6731c15b..1ed950146ef 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -282,7 +282,7 @@ process_iq(From, To, [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, - <<"jabber:iq:register">>}], + ?NS_REGISTER}], children = [TopInstrEl | CaptchaEls]}]}; {error, limit} -> @@ -304,7 +304,7 @@ process_iq(From, To, [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, - <<"jabber:iq:register">>}], + ?NS_REGISTER}], children = [#xmlel{name = <<"instructions">>, attrs = [], From be6ac85f315bd9b371d84b5005a44f56bb395af6 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 22 May 2015 10:40:24 +0200 Subject: [PATCH 086/695] A few more... Fix epmd not in PATH (#484)(thanks to acediac) --- ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 6c131ace024..683f172a3e7 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -410,7 +410,7 @@ ctlexec() # stop epmd if there is no other running node stop_epmd() { - $EPMD -names 2>/dev/null | grep -q name || epmd -kill >/dev/null + $EPMD -names 2>/dev/null | grep -q name || $EPMD -kill >/dev/null } # make sure node not already running and node name unregistered From 0d322d8dabd29af63fd06e7dd14ee8cd9a98e257 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 22 May 2015 12:42:24 +0200 Subject: [PATCH 087/695] Add fold markers to config file for Vim editors --- ejabberd.yml.example | 49 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 5f577d1ad5b..9fc815071d5 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -1,5 +1,5 @@ ### -### ejabberd configuration file +###' ejabberd configuration file ### ### @@ -24,8 +24,8 @@ ### > Art thou not Romeo, ### and a Montague? -### ======= -### LOGGING +###. ======= +###' LOGGING ## ## loglevel: Verbosity of log files generated by ejabberd. @@ -73,8 +73,8 @@ log_rate_limit: 100 ## - "bob@example.com" -### ================ -### SERVED HOSTNAMES +###. ================ +###' SERVED HOSTNAMES ## ## hosts: Domains served by ejabberd. @@ -94,8 +94,8 @@ hosts: ## ## route_subdomains: s2s -### =============== -### LISTENING PORTS +###. =============== +###' LISTENING PORTS ## ## listen: The ports ejabberd will listen on, which service each is handled @@ -169,6 +169,9 @@ listen: ## register: true captcha: true +###. ================== +###' S2S GLOBAL OPTIONS + ## ## s2s_use_starttls: Enable STARTTLS + Dialback for S2S connections. ## Allowed values are: false optional required required_trusted @@ -214,8 +217,8 @@ listen: ## - ipv6 ## outgoing_s2s_timeout: 10000 -### ============== -### AUTHENTICATION +###. ============== +###' AUTHENTICATION ## ## auth_method: Method used to authenticate the users. @@ -305,8 +308,8 @@ auth_method: internal ## - internal ## - anonymous -### ============== -### DATABASE SETUP +###. ============== +###' DATABASE SETUP ## ejabberd by default uses the internal Mnesia database, ## so you do not necessarily need this section. @@ -366,8 +369,8 @@ auth_method: internal ## ## odbc_keepalive_interval: undefined -### =============== -### TRAFFIC SHAPERS +###. =============== +###' TRAFFIC SHAPERS shaper: ## @@ -448,8 +451,8 @@ acl: ## user: ## - "bob-local": "localhost" -### ============ -### ACCESS RULES +###. ============ +###' ACCESS RULES access: ## Maximum number of simultaneous sessions allowed for a single user: max_user_sessions: @@ -518,8 +521,8 @@ access: ## register: ## all: deny -### ================ -### DEFAULT LANGUAGE +###. ================ +###' DEFAULT LANGUAGE ## ## language: Default language used for server messages. @@ -533,8 +536,8 @@ language: "en" ## "localhost": ## language: "ru" -### ======= -### CAPTCHA +###. ======= +###' CAPTCHA ## ## Full path to a script that generates the image. @@ -551,8 +554,8 @@ language: "en" ## ## captcha_limit: 5 -### ======= -### MODULES +###. ======= +###' MODULES ## ## Modules enabled in all ejabberd virtual hosts. @@ -668,7 +671,9 @@ modules: allow_contrib_modules: true +###. +###' ### Local Variables: ### mode: yaml ### End: -### vim: set filetype=yaml tabstop=8 +### vim: set filetype=yaml tabstop=8 foldmarker=###',###. foldmethod=marker: From 90225a4744a90ff65a5fb89a5a3dd2dc51c412d7 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 22 May 2015 17:28:40 +0200 Subject: [PATCH 088/695] Minor cosmetic changes and add ping command --- ejabberdctl.template | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 683f172a3e7..3b3461bbdd3 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -16,9 +16,6 @@ IEX={{bindir}}/iex EPMD={{bindir}}/epmd INSTALLUSER={{installuser}} -# Compatibility in ZSH -#setopt shwordsplit 2>/dev/null - # check the proper system user is used if defined if [ "$INSTALLUSER" != "" ] ; then EXEC_CMD="false" @@ -241,14 +238,6 @@ iexlive() --erl \"$ERLANG_OPTS\" --erl $ARGS --erl \"$@\"" } -etop() -{ - $EXEC_CMD "$ERL \ - $NAME debug-${TTY}-${ERLANG_NODE} \ - -hidden -s etop -s erlang halt -output text -node $ERLANG_NODE" -} - -# TODO: refactor debug warning and livewarning debugwarning() { if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then @@ -270,7 +259,7 @@ debugwarning() echo "Press return to continue" read foo echo "" - fi + fi } livewarning() @@ -297,7 +286,26 @@ livewarning() fi } -# TODO: Make iex command display only if ejabberd Elixir support has been enabled +etop() +{ + TTY=`tty | sed -e 's/.*\///g'` + $EXEC_CMD "$ERL \ + $NAME debug-${TTY}-${ERLANG_NODE} \ + -hidden -s etop -s erlang halt -output text -node $ERLANG_NODE" +} + +ping() +{ + TTY=`tty | sed -e 's/.*\///g'` + $EXEC_CMD "$ERL \ + $NAME ping-${TTY}-${ERLANG_NODE} \ + -hidden \ + -pa $EJABBERD_EBIN_PATH \ + $KERNEL_OPTS $ERLANG_OPTS \ + -eval 'io:format(\"~p~n\",[net_adm:ping($1)])' \ + -s erlang halt -output text -noinput" +} + help() { echo "" @@ -328,9 +336,9 @@ ctl() # flock that can lock a file descriptor. MAXCONNID=100 CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl - FLOCK='/usr/bin/flock' + FLOCK=/usr/bin/flock if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then - JOT='/usr/bin/jot' + JOT=/usr/bin/jot if [ ! -x "$JOT" ] ; then # no flock or jot, simply invoke ctlexec() CTL_CONN="ctl-${ERLANG_NODE}" @@ -470,6 +478,7 @@ case $ARGS in ' iexdebug') iexdebug;; ' live') live;; ' iexlive') iexlive;; + ' ping'*) ping ${ARGS# ping};; ' etop') etop;; ' started') wait_for_status 0 30 2;; # wait 30x2s before timeout ' stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout From e54e556e01ec206b7e104c472270f86955d69fc6 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 22 May 2015 18:47:17 +0200 Subject: [PATCH 089/695] Fix use of publish_only affiliation with odbc backend --- src/node_hometree_odbc.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index b9abac20336..e99ce7247f8 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -1105,6 +1105,7 @@ decode_jid(SJID) -> ). decode_affiliation(<<"o">>) -> owner; decode_affiliation(<<"p">>) -> publisher; +decode_affiliation(<<"u">>) -> publish_only; decode_affiliation(<<"m">>) -> member; decode_affiliation(<<"c">>) -> outcast; decode_affiliation(_) -> none. @@ -1151,6 +1152,7 @@ encode_host(Host) -> ejabberd_odbc:escape(Host). ). encode_affiliation(owner) -> <<"o">>; encode_affiliation(publisher) -> <<"p">>; +encode_affiliation(publish_only) -> <<"u">>; encode_affiliation(member) -> <<"m">>; encode_affiliation(outcast) -> <<"c">>; encode_affiliation(_) -> <<"n">>. From 3af507cc43eadbfdae3347f0c755b7594c3efd81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 25 May 2015 15:23:38 +0200 Subject: [PATCH 090/695] Fix merging of not yaml config files --- src/ejabberd_config.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 4931fe72ed0..fb506377568 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -391,7 +391,9 @@ include_config_files(Terms) -> dict:store(Name, Val, Dict); _ -> dict:update(rest, fun(L1) -> [Pair|L1] end, Dict) - end + end; + (Tuple, Dict2) -> + dict:update(rest, fun(L2) -> [Tuple|L2] end, Dict2) end, dict:from_list([{rest, []}]), L) end, From 9574e71e8db595ce7b2fa2f8fbfc38deec2ad74b Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Tue, 26 May 2015 10:08:46 +0200 Subject: [PATCH 091/695] Include session record from header file instead of duplicating it --- include/ejabberd_sm.hrl | 5 +++++ src/mod_admin_extra.erl | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/ejabberd_sm.hrl b/include/ejabberd_sm.hrl index 756f4b8884e..bae60ccd374 100644 --- a/include/ejabberd_sm.hrl +++ b/include/ejabberd_sm.hrl @@ -1,3 +1,6 @@ +-ifndef(EJABBERD_SM_HRL). +-define(EJABBERD_SM_HRL, true). + -record(session, {sid, usr, us, priority, info}). -record(session_counter, {vhost, count}). -type sid() :: {erlang:timestamp(), pid()}. @@ -5,3 +8,5 @@ -type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()} | {oor, boolean()} | {auth_module, atom()}]. -type prio() :: undefined | integer(). + +-endif. diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 8eae45b6daa..bc49bae47b4 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -89,15 +89,13 @@ stats/1, stats/2 ]). + -include("ejabberd.hrl"). -include("ejabberd_commands.hrl"). -include("mod_roster.hrl"). +-include("ejabberd_sm.hrl"). -include("jlib.hrl"). -%% Copied from ejabberd_sm.erl --record(session, {sid, usr, us, priority, info}). - - %%% %%% gen_mod %%% From b83c07251cbfa97cdc8f69971596e619149838ac Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 26 May 2015 19:19:57 +0200 Subject: [PATCH 092/695] Fix pubsub/odbc crash on remote user unsubscribe (EJAB-1483) --- src/mod_pubsub.erl | 65 ++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index a61defc33e6..1f625cd5d6f 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -733,39 +733,42 @@ in_subscription(_, _, _, _, _, _) -> true. unsubscribe_user(Entity, Owner) -> - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - Host = host(element(2, BJID)), spawn(fun () -> - lists:foreach(fun (PType) -> - {result, Subs} = node_action(Host, PType, - get_entity_subscriptions, - [Host, Entity]), - lists:foreach(fun - ({#pubsub_node{options = Options, - owners = O, - id = Nidx}, - subscribed, _, JID}) -> - case match_option(Options, access_model, presence) of - true -> - Owners = node_owners_action(Host, PType, Nidx, O), - case lists:member(BJID, Owners) of - true -> - node_action(Host, PType, - unsubscribe_node, - [Nidx, Entity, JID, all]); - false -> - {result, ok} - end; - _ -> - {result, ok} - end; - (_) -> - ok - end, - Subs) - end, - plugins(Host)) + [unsubscribe_user(ServerHost, Entity, Owner) || + ServerHost <- lists:usort(lists:foldl( + fun(UserHost, Acc) -> + case gen_mod:is_loaded(UserHost, mod_pubsub) of + true -> [UserHost|Acc]; + false -> Acc + end + end, [], [Entity#jid.lserver, Owner#jid.lserver]))] end). +unsubscribe_user(Host, Entity, Owner) -> + BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + lists:foreach(fun (PType) -> + {result, Subs} = node_action(Host, PType, + get_entity_subscriptions, + [Host, Entity]), + lists:foreach(fun + ({#pubsub_node{options = Options, + owners = O, + id = Nidx}, + subscribed, _, JID}) -> + Unsubscribe = match_option(Options, access_model, presence) + andalso lists:member(BJID, node_owners_action(Host, PType, Nidx, O)), + case Unsubscribe of + true -> + node_action(Host, PType, + unsubscribe_node, [Nidx, Entity, JID, all]); + false -> + ok + end; + (_) -> + ok + end, + Subs) + end, + plugins(Host)). %% ------- %% user remove hook handling function From 5585fb1ecf6f42226f9804cdf113821cbe3fbd1c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 26 May 2015 21:06:04 +0200 Subject: [PATCH 093/695] New options: dhfile and s2s_dhfile Let admins specify a file that contains custom parameters for Diffie-Hellman key exchange. --- src/ejabberd_c2s.erl | 1 + src/ejabberd_http.erl | 1 + src/ejabberd_s2s_in.erl | 9 +++++++-- src/ejabberd_s2s_out.erl | 9 +++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 5112db7dede..9c02899c793 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -292,6 +292,7 @@ init([{SockMod, Socket}, Opts]) -> StartTLSRequired orelse TLSEnabled, TLSOpts1 = lists:filter(fun ({certfile, _}) -> true; ({ciphers, _}) -> true; + ({dhfile, _}) -> true; (_) -> false end, Opts), diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 4e7f4b554eb..4e3fe8e0eac 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -95,6 +95,7 @@ init({SockMod, Socket}, Opts) -> TLSEnabled = proplists:get_bool(tls, Opts), TLSOpts1 = lists:filter(fun ({certfile, _}) -> true; ({ciphers, _}) -> true; + ({dhfile, _}) -> true; (_) -> false end, Opts), diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 1b40f03c230..c51314c362d 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -184,9 +184,14 @@ init([{SockMod, Socket}, Opts]) -> undefined -> TLSOpts2; ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2] end, + TLSOpts4 = case ejabberd_config:get_option( + s2s_dhfile, fun iolist_to_binary/1) of + undefined -> TLSOpts3; + DHFile -> [{dhfile, DHFile} | TLSOpts3] + end, TLSOpts = case proplists:get_bool(tls_compression, Opts) of - false -> [compression_none | TLSOpts3]; - true -> TLSOpts3 + false -> [compression_none | TLSOpts4]; + true -> TLSOpts4 end, Timer = erlang:start_timer(?S2STIMEOUT, self(), []), {ok, wait_for_stream, diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 6196f136f2d..44287632b1a 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -207,13 +207,18 @@ init([From, Server, Type]) -> undefined -> TLSOpts2; ProtocolOpts -> [{protocol_options, ProtocolOpts} | TLSOpts2] end, + TLSOpts4 = case ejabberd_config:get_option( + s2s_dhfile, fun iolist_to_binary/1) of + undefined -> TLSOpts3; + DHFile -> [{dhfile, DHFile} | TLSOpts3] + end, TLSOpts = case ejabberd_config:get_option( {s2s_tls_compression, From}, fun(true) -> true; (false) -> false end, true) of - false -> [compression_none | TLSOpts3]; - true -> TLSOpts3 + false -> [compression_none | TLSOpts4]; + true -> TLSOpts4 end, {New, Verify} = case Type of {new, Key} -> {Key, false}; From d0443bb7148961470d6ed43ed607b80026cb32ad Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 27 May 2015 13:10:15 +0200 Subject: [PATCH 094/695] An auth external module requires ext_mod to be started first (#578) --- src/ejabberd_app.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index fabe2d3e099..daf8919a6fd 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -59,13 +59,13 @@ start(normal, _Args) -> ejabberd_rdbms:start(), ejabberd_riak_sup:start(), ejabberd_sm:start(), - ejabberd_auth:start(), cyrsasl:start(), % Profiling %ejabberd_debug:eprof_start(), %ejabberd_debug:fprof_start(), maybe_add_nameservers(), ext_mod:start(), + ejabberd_auth:start(), start_modules(), ejabberd_listener:start_listeners(), ?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]), From e8ffbbb0b479ef2c70912d3e892c13f26752bdbe Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 28 May 2015 11:37:27 +0300 Subject: [PATCH 095/695] Validate MUC room options from the configuration file --- src/mod_muc.erl | 61 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 4fdc0fe1352..c283f9c8af6 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -307,13 +307,60 @@ init([Host, Opts]) -> catch ets:new(muc_online_users, [bag, named_table, public, {keypos, 2}]), clean_table_from_bad_node(node(), MyHost), mnesia:subscribe(system), - Access = gen_mod:get_opt(access, Opts, fun(A) -> A end, all), - AccessCreate = gen_mod:get_opt(access_create, Opts, fun(A) -> A end, all), - AccessAdmin = gen_mod:get_opt(access_admin, Opts, fun(A) -> A end, none), - AccessPersistent = gen_mod:get_opt(access_persistent, Opts, fun(A) -> A end, all), - HistorySize = gen_mod:get_opt(history_size, Opts, fun(A) -> A end, 20), - DefRoomOpts = gen_mod:get_opt(default_room_options, Opts, fun(A) -> A end, []), - RoomShaper = gen_mod:get_opt(room_shaper, Opts, fun(A) -> A end, none), + Access = gen_mod:get_opt(access, Opts, + fun(A) when is_atom(A) -> A end, all), + AccessCreate = gen_mod:get_opt(access_create, Opts, + fun(A) when is_atom(A) -> A end, all), + AccessAdmin = gen_mod:get_opt(access_admin, Opts, + fun(A) when is_atom(A) -> A end, + none), + AccessPersistent = gen_mod:get_opt(access_persistent, Opts, + fun(A) when is_atom(A) -> A end, + all), + HistorySize = gen_mod:get_opt(history_size, Opts, + fun(I) when is_integer(I), I>=0 -> I end, + 20), + DefRoomOpts1 = gen_mod:get_opt(default_room_options, Opts, + fun(L) when is_list(L) -> L end, + []), + DefRoomOpts = + lists:filter( + fun({Opt, Val}) -> + VFun = case Opt of + allow_change_subj -> fun is_boolean/1; + allow_private_messages -> fun is_boolean/1; + allow_query_users -> fun is_boolean/1; + allow_user_invites -> fun is_boolean/1; + allow_visitor_nickchange -> fun is_boolean/1; + allow_visitor_status -> fun is_boolean/1; + anonymous -> fun is_boolean/1; + captcha_protected -> fun is_boolean/1; + logging -> fun is_boolean/1; + members_by_default -> fun is_boolean/1; + members_only -> fun is_boolean/1; + moderated -> fun is_boolean/1; + password_protected -> fun is_boolean/1; + persistent -> fun is_boolean/1; + public -> fun is_boolean/1; + public_list -> fun is_boolean/1; + password -> fun iolist_to_binary/1; + title -> fun iolist_to_binary/1; + allow_private_messages_from_visitors -> + fun(anyone) -> anyone; + (moderators) -> moderators; + (nobody) -> nobody + end; + max_users -> + fun(I) when is_integer(I), I > 0 -> I end; + _ -> + ?ERROR_MSG("unknown option ~p with value ~p", + [Opt, Val]) + end, + Val == gen_mod:get_opt(Opt, [{Opt, Val}], VFun) + end, DefRoomOpts1), + RoomShaper = gen_mod:get_opt(room_shaper, Opts, + fun(A) when is_atom(A) -> A end, + none), ejabberd_router:register_route(MyHost), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, From 6cba7bf83459be24e384e016c017c639ecc8226c Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 29 May 2015 09:30:16 +0200 Subject: [PATCH 096/695] Add correct package version for mix (#577) --- .gitignore | 1 + configure.ac | 3 ++- mix.exs => mix.exs.in | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) rename mix.exs => mix.exs.in (97%) diff --git a/.gitignore b/.gitignore index 21f8cfadaa3..d44a41f3f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ XmppAddr.hrl /test/*.beam /logs/ /priv/sql +mix.exs diff --git a/configure.ac b/configure.ac index a3e26384bf2..6ae0a2455b1 100644 --- a/configure.ac +++ b/configure.ac @@ -235,7 +235,8 @@ esac],[if test "x$lager" = "x"; then lager=true; fi]) AC_CONFIG_FILES([Makefile vars.config - src/ejabberd.app.src]) + src/ejabberd.app.src + mix.exs]) ENABLEUSER="" AC_ARG_ENABLE(user, diff --git a/mix.exs b/mix.exs.in similarity index 97% rename from mix.exs rename to mix.exs.in index c5236473733..d7b236e0177 100644 --- a/mix.exs +++ b/mix.exs.in @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.03.0", + version: "@PACKAGE_VERSION@", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", @@ -65,7 +65,7 @@ defmodule Mix.Tasks.Compile.Asn1 do options = options ++ [:noobj, outdir: Erlang.to_erl_file(Path.dirname(output))] case :asn1ct.compile(Erlang.to_erl_file(input), options) do :ok -> {:ok, :done} - error -> error + error -> error end end) end From a291e7d4e6b8666b86bc1362e5d22326fd36d774 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 29 May 2015 12:08:13 +0300 Subject: [PATCH 097/695] Fix MUC room options vaildation --- src/mod_muc.erl | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index c283f9c8af6..0d9ed97500f 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -324,25 +324,26 @@ init([Host, Opts]) -> fun(L) when is_list(L) -> L end, []), DefRoomOpts = - lists:filter( + lists:flatmap( fun({Opt, Val}) -> + Bool = fun(B) when is_boolean(B) -> B end, VFun = case Opt of - allow_change_subj -> fun is_boolean/1; - allow_private_messages -> fun is_boolean/1; - allow_query_users -> fun is_boolean/1; - allow_user_invites -> fun is_boolean/1; - allow_visitor_nickchange -> fun is_boolean/1; - allow_visitor_status -> fun is_boolean/1; - anonymous -> fun is_boolean/1; - captcha_protected -> fun is_boolean/1; - logging -> fun is_boolean/1; - members_by_default -> fun is_boolean/1; - members_only -> fun is_boolean/1; - moderated -> fun is_boolean/1; - password_protected -> fun is_boolean/1; - persistent -> fun is_boolean/1; - public -> fun is_boolean/1; - public_list -> fun is_boolean/1; + allow_change_subj -> Bool; + allow_private_messages -> Bool; + allow_query_users -> Bool; + allow_user_invites -> Bool; + allow_visitor_nickchange -> Bool; + allow_visitor_status -> Bool; + anonymous -> Bool; + captcha_protected -> Bool; + logging -> Bool; + members_by_default -> Bool; + members_only -> Bool; + moderated -> Bool; + password_protected -> Bool; + persistent -> Bool; + public -> Bool; + public_list -> Bool; password -> fun iolist_to_binary/1; title -> fun iolist_to_binary/1; allow_private_messages_from_visitors -> @@ -354,9 +355,13 @@ init([Host, Opts]) -> fun(I) when is_integer(I), I > 0 -> I end; _ -> ?ERROR_MSG("unknown option ~p with value ~p", - [Opt, Val]) + [Opt, Val]), + fun(_) -> undefined end end, - Val == gen_mod:get_opt(Opt, [{Opt, Val}], VFun) + case gen_mod:get_opt(Opt, [{Opt, Val}], VFun) of + undefined -> []; + NewVal -> [{Opt, NewVal}] + end end, DefRoomOpts1), RoomShaper = gen_mod:get_opt(room_shaper, Opts, fun(A) when is_atom(A) -> A end, From 100827ec6eda7e78e3145f9fdc4a28491e25cf98 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 29 May 2015 15:48:43 +0200 Subject: [PATCH 098/695] In xmlrpc use process_unicode_codepoints instead of list_to_binary --- src/ejabberd_xmlrpc.erl | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 7e437104993..c852114506d 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -2,8 +2,26 @@ %%% File : ejabberd_xmlrpc.erl %%% Author : Badlop %%% Purpose : XML-RPC server that frontends ejabberd commands -%%% Created : 21 Aug 2007 by Badlop -%%% Id : $Id: ejabberd_xmlrpc.erl 595 2008-05-20 11:39:31Z badlop $ +%%% Created : 21 Aug 2007 by Badlop +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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 +%%% %%%---------------------------------------------------------------------- %%% TODO: Implement a command in ejabberdctl 'help COMMAND LANGUAGE' that shows @@ -440,7 +458,7 @@ format_arg({array, Elements}, {list, ElementsDef}) [format_arg(Element, ElementsDef) || Element <- Elements]; format_arg(Arg, integer) when is_integer(Arg) -> Arg; -format_arg(Arg, binary) when is_list(Arg) -> list_to_binary(Arg); +format_arg(Arg, binary) when is_list(Arg) -> process_unicode_codepoints(Arg); format_arg(Arg, binary) when is_binary(Arg) -> Arg; format_arg(Arg, string) when is_list(Arg) -> Arg; format_arg(Arg, string) when is_binary(Arg) -> binary_to_list(Arg); @@ -448,7 +466,12 @@ format_arg(undefined, binary) -> <<>>; format_arg(undefined, string) -> ""; format_arg(Arg, Format) -> ?ERROR_MSG("don't know how to format Arg ~p for format ~p", [Arg, Format]), - throw({error_formatting_argument, Arg, Format}). + error. + +process_unicode_codepoints(Str) -> + iolist_to_binary(lists:map(fun(X) when X > 255 -> unicode:characters_to_binary([X]); + (Y) -> Y + end, Str)). %% ----------------------------- %% Result From 22d9011c0c1d72637ea7510a9e8c05da91f4fbd0 Mon Sep 17 00:00:00 2001 From: Cor Cornelisse Date: Mon, 1 Jun 2015 13:30:26 +0200 Subject: [PATCH 099/695] These arguments should be binary instead of strings, otherwise it won't work properly --- src/mod_admin_extra.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index bc49bae47b4..a4b78604638 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -418,12 +418,12 @@ commands() -> #ejabberd_commands{name = push_roster, tags = [roster], desc = "Push template roster from file to a user", module = ?MODULE, function = push_roster, - args = [{file, string}, {user, string}, {host, string}], + args = [{file, binary}, {user, binary}, {host, binary}], result = {res, rescode}}, #ejabberd_commands{name = push_roster_all, tags = [roster], desc = "Push template roster from file to all those users", module = ?MODULE, function = push_roster_all, - args = [{file, string}], + args = [{file, binary}], result = {res, rescode}}, #ejabberd_commands{name = push_alltoall, tags = [roster], desc = "Add all the users to all the users of Host in Group", From 48213b09ce1d28bdf398523926ad83cedac54596 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 31 May 2015 17:56:16 +0300 Subject: [PATCH 100/695] Get rid of some fuzzy macros as it makes syntax tools getting mad --- src/ejabberd_c2s.erl | 12 ++++++------ src/mod_muc_admin.erl | 34 ++++++++++++++++------------------ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 5112db7dede..b4cd2857687 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -173,14 +173,14 @@ %% XEP-0198: -define(IS_STREAM_MGMT_TAG(Name), - Name == <<"enable">>; - Name == <<"resume">>; - Name == <<"a">>; - Name == <<"r">>). + (Name == <<"enable">>) or + (Name == <<"resume">>) or + (Name == <<"a">>) or + (Name == <<"r">>)). -define(IS_SUPPORTED_MGMT_XMLNS(Xmlns), - Xmlns == ?NS_STREAM_MGMT_2; - Xmlns == ?NS_STREAM_MGMT_3). + (Xmlns == ?NS_STREAM_MGMT_2) or + (Xmlns == ?NS_STREAM_MGMT_3)). -define(MGMT_FAILED(Condition, Xmlns), #xmlel{name = <<"failed">>, diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 1a6d8a865c8..1f8efe241db 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -876,27 +876,25 @@ set_room_affiliation(Name, Service, JID, AffiliationString) -> error end. --define(MAKE_CONFIG_OPT(Opt), {Opt, Config#config.Opt}). - make_opts(StateData) -> Config = StateData#state.config, [ - ?MAKE_CONFIG_OPT(title), - ?MAKE_CONFIG_OPT(allow_change_subj), - ?MAKE_CONFIG_OPT(allow_query_users), - ?MAKE_CONFIG_OPT(allow_private_messages), - ?MAKE_CONFIG_OPT(public), - ?MAKE_CONFIG_OPT(public_list), - ?MAKE_CONFIG_OPT(persistent), - ?MAKE_CONFIG_OPT(moderated), - ?MAKE_CONFIG_OPT(members_by_default), - ?MAKE_CONFIG_OPT(members_only), - ?MAKE_CONFIG_OPT(allow_user_invites), - ?MAKE_CONFIG_OPT(password_protected), - ?MAKE_CONFIG_OPT(password), - ?MAKE_CONFIG_OPT(anonymous), - ?MAKE_CONFIG_OPT(logging), - ?MAKE_CONFIG_OPT(max_users), + {title, Config#config.title}, + {allow_change_subj, Config#config.allow_change_subj}, + {allow_query_users, Config#config.allow_query_users}, + {allow_private_messages, Config#config.allow_private_messages}, + {public, Config#config.public}, + {public_list, Config#config.public_list}, + {persistent, Config#config.persistent}, + {moderated, Config#config.moderated}, + {members_by_default, Config#config.members_by_default}, + {members_only, Config#config.members_only}, + {allow_user_invites, Config#config.allow_user_invites}, + {password_protected, Config#config.password_protected}, + {password, Config#config.password}, + {anonymous, Config#config.anonymous}, + {logging, Config#config.logging}, + {max_users, Config#config.max_users}, {affiliations, ?DICT:to_list(StateData#state.affiliations)}, {subject, StateData#state.subject}, {subject_author, StateData#state.subject_author} From ea7de2097f514d8720875526faef0c0430b73d36 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 1 Jun 2015 13:19:01 +0300 Subject: [PATCH 101/695] Reorganize get_opt() code in some modules --- src/mod_sip_registrar.erl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl index a534c61ceff..58ffa5029c1 100644 --- a/src/mod_sip_registrar.erl +++ b/src/mod_sip_registrar.erl @@ -490,15 +490,18 @@ need_ob_hdrs(Contacts, _IsOutboundSupported = true) -> end, Contacts). get_flow_timeout(LServer, #sip_socket{type = Type}) -> - {Option, Default} = - case Type of - udp -> {flow_timeout_udp, ?FLOW_TIMEOUT_UDP}; - _ -> {flow_timeout_tcp, ?FLOW_TIMEOUT_TCP} - end, - gen_mod:get_module_opt( - LServer, mod_sip, Option, - fun(I) when is_integer(I), I>0 -> I end, - Default). + case Type of + udp -> + gen_mod:get_module_opt( + LServer, mod_sip, flow_timeout_udp, + fun(I) when is_integer(I), I>0 -> I end, + ?FLOW_TIMEOUT_UDP); + _ -> + gen_mod:get_module_opt( + LServer, mod_sip, flow_timeout_tcp, + fun(I) when is_integer(I), I>0 -> I end, + ?FLOW_TIMEOUT_TCP) + end. update_table() -> Fields = record_info(fields, sip_session), From a9f7d9481f778e982c3f20ef82e41d66c6179f1c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 31 May 2015 16:14:57 +0300 Subject: [PATCH 102/695] Do not try to fetch module options via eldap_utils --- src/ejabberd_auth_ldap.erl | 8 +++---- src/eldap_utils.erl | 42 ++++++++++------------------------ src/gen_mod.erl | 11 +++++++-- src/mod_shared_roster_ldap.erl | 16 ++++++------- src/mod_vcard_ldap.erl | 4 ++-- 5 files changed, 35 insertions(+), 46 deletions(-) diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index 3055d1044b5..d08151e60e4 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -360,7 +360,7 @@ parse_options(Host) -> Eldap_ID = jlib:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)), Bind_Eldap_ID = jlib:atom_to_binary( gen_mod:get_module_proc(Host, bind_ejabberd_auth_ldap)), - UIDsTemp = eldap_utils:get_opt( + UIDsTemp = gen_mod:get_opt( {ldap_uids, Host}, [], fun(Us) -> lists:map( @@ -375,7 +375,7 @@ parse_options(Host) -> end, [{<<"uid">>, <<"%u">>}]), UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp), SubFilter = eldap_utils:generate_subfilter(UIDs), - UserFilter = case eldap_utils:get_opt( + UserFilter = case gen_mod:get_opt( {ldap_filter, Host}, [], fun check_filter/1, <<"">>) of <<"">> -> @@ -386,7 +386,7 @@ parse_options(Host) -> SearchFilter = eldap_filter:do_sub(UserFilter, [{<<"%u">>, <<"*">>}]), {DNFilter, DNFilterAttrs} = - eldap_utils:get_opt({ldap_dn_filter, Host}, [], + gen_mod:get_opt({ldap_dn_filter, Host}, [], fun([{DNF, DNFA}]) -> NewDNFA = case DNFA of undefined -> @@ -398,7 +398,7 @@ parse_options(Host) -> NewDNF = check_filter(DNF), {NewDNF, NewDNFA} end, {undefined, []}), - LocalFilter = eldap_utils:get_opt( + LocalFilter = gen_mod:get_opt( {ldap_local_filter, Host}, [], fun(V) -> V end), #state{host = Host, eldap_id = Eldap_ID, bind_eldap_id = Bind_Eldap_ID, diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index eb6601623f6..bdc98c202fd 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -33,8 +33,6 @@ make_filter/2, get_state/2, case_insensitive_match/2, - get_opt/3, - get_opt/4, get_config/2, decode_octet_string/3, uids_domain_subst/2]). @@ -171,64 +169,48 @@ uids_domain_subst(Host, UIDs) -> end, UIDs). --spec get_opt({atom(), binary()}, list(), fun()) -> any(). - -get_opt({Key, Host}, Opts, F) -> - get_opt({Key, Host}, Opts, F, undefined). - --spec get_opt({atom(), binary()}, list(), fun(), any()) -> any(). - -get_opt({Key, Host}, Opts, F, Default) -> - case gen_mod:get_opt(Key, Opts, F, undefined) of - undefined -> - ejabberd_config:get_option( - {Key, Host}, F, Default); - Val -> - Val - end. - -spec get_config(binary(), list()) -> eldap_config(). get_config(Host, Opts) -> - Servers = get_opt({ldap_servers, Host}, Opts, + Servers = gen_mod:get_opt({ldap_servers, Host}, Opts, fun(L) -> [iolist_to_binary(H) || H <- L] end, [<<"localhost">>]), - Backups = get_opt({ldap_backups, Host}, Opts, + Backups = gen_mod:get_opt({ldap_backups, Host}, Opts, fun(L) -> [iolist_to_binary(H) || H <- L] end, []), - Encrypt = get_opt({ldap_encrypt, Host}, Opts, + Encrypt = gen_mod:get_opt({ldap_encrypt, Host}, Opts, fun(tls) -> tls; (starttls) -> starttls; (none) -> none end, none), - TLSVerify = get_opt({ldap_tls_verify, Host}, Opts, + TLSVerify = gen_mod:get_opt({ldap_tls_verify, Host}, Opts, fun(hard) -> hard; (soft) -> soft; (false) -> false end, false), - TLSCAFile = get_opt({ldap_tls_cacertfile, Host}, Opts, + TLSCAFile = gen_mod:get_opt({ldap_tls_cacertfile, Host}, Opts, fun iolist_to_binary/1), - TLSDepth = get_opt({ldap_tls_depth, Host}, Opts, + TLSDepth = gen_mod:get_opt({ldap_tls_depth, Host}, Opts, fun(I) when is_integer(I), I>=0 -> I end), - Port = get_opt({ldap_port, Host}, Opts, + Port = gen_mod:get_opt({ldap_port, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, case Encrypt of tls -> ?LDAPS_PORT; starttls -> ?LDAP_PORT; _ -> ?LDAP_PORT end), - RootDN = get_opt({ldap_rootdn, Host}, Opts, + RootDN = gen_mod:get_opt({ldap_rootdn, Host}, Opts, fun iolist_to_binary/1, <<"">>), - Password = get_opt({ldap_password, Host}, Opts, + Password = gen_mod:get_opt({ldap_password, Host}, Opts, fun iolist_to_binary/1, <<"">>), - Base = get_opt({ldap_base, Host}, Opts, + Base = gen_mod:get_opt({ldap_base, Host}, Opts, fun iolist_to_binary/1, <<"">>), - OldDerefAliases = get_opt({deref_aliases, Host}, Opts, + OldDerefAliases = gen_mod:get_opt({deref_aliases, Host}, Opts, fun(never) -> never; (searching) -> searching; (finding) -> finding; @@ -236,7 +218,7 @@ get_config(Host, Opts) -> end, unspecified), DerefAliases = if OldDerefAliases == unspecified -> - get_opt({ldap_deref_aliases, Host}, Opts, + gen_mod:get_opt({ldap_deref_aliases, Host}, Opts, fun(never) -> never; (searching) -> searching; (finding) -> finding; diff --git a/src/gen_mod.erl b/src/gen_mod.erl index b8e155a0493..29d5dfb784d 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -155,13 +155,20 @@ wait_for_stop1(MonitorReference) -> -type check_fun() :: fun((any()) -> any()) | {module(), atom()}. --spec get_opt(atom(), opts(), check_fun()) -> any(). +-spec get_opt(atom() | {atom(), binary()|global}, opts(), check_fun()) -> any(). get_opt(Opt, Opts, F) -> get_opt(Opt, Opts, F, undefined). --spec get_opt(atom(), opts(), check_fun(), any()) -> any(). +-spec get_opt(atom() | {atom(), binary()|global}, opts(), check_fun(), any()) -> any(). +get_opt({Opt, Host}, Opts, F, Default) -> + case lists:keysearch(Opt, 1, Opts) of + false -> + ejabberd_config:get_option({Opt, Host}, F, Default); + {value, {_, Val}} -> + ejabberd_config:prepare_opt_val(Opt, Val, F, Default) + end; get_opt(Opt, Opts, F, Default) -> case lists:keysearch(Opt, 1, Opts) of false -> diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index af85e4d401f..a2d6f2fff5e 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -521,29 +521,29 @@ parse_options(Host, Opts) -> (false) -> false; (true) -> true end, true), - UserCacheValidity = eldap_utils:get_opt( + UserCacheValidity = gen_mod:get_opt( {ldap_user_cache_validity, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?USER_CACHE_VALIDITY), - GroupCacheValidity = eldap_utils:get_opt( + GroupCacheValidity = gen_mod:get_opt( {ldap_group_cache_validity, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?GROUP_CACHE_VALIDITY), - UserCacheSize = eldap_utils:get_opt( + UserCacheSize = gen_mod:get_opt( {ldap_user_cache_size, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?CACHE_SIZE), - GroupCacheSize = eldap_utils:get_opt( + GroupCacheSize = gen_mod:get_opt( {ldap_group_cache_size, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?CACHE_SIZE), - ConfigFilter = eldap_utils:get_opt({ldap_filter, Host}, Opts, + ConfigFilter = gen_mod:get_opt({ldap_filter, Host}, Opts, fun check_filter/1, <<"">>), - ConfigUserFilter = eldap_utils:get_opt({ldap_ufilter, Host}, Opts, + ConfigUserFilter = gen_mod:get_opt({ldap_ufilter, Host}, Opts, fun check_filter/1, <<"">>), - ConfigGroupFilter = eldap_utils:get_opt({ldap_gfilter, Host}, Opts, + ConfigGroupFilter = gen_mod:get_opt({ldap_gfilter, Host}, Opts, fun check_filter/1, <<"">>), - RosterFilter = eldap_utils:get_opt({ldap_rfilter, Host}, Opts, + RosterFilter = gen_mod:get_opt({ldap_rfilter, Host}, Opts, fun check_filter/1, <<"">>), SubFilter = <<"(&(", UIDAttr/binary, "=", UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>, diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 61db3897617..a5cafc5e54a 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -739,7 +739,7 @@ parse_options(Host, Opts) -> end, 30), Eldap_ID = jlib:atom_to_binary(gen_mod:get_module_proc(Host, ?PROCNAME)), Cfg = eldap_utils:get_config(Host, Opts), - UIDsTemp = eldap_utils:get_opt( + UIDsTemp = gen_mod:get_opt( {ldap_uids, Host}, Opts, fun(Us) -> lists:map( @@ -752,7 +752,7 @@ parse_options(Host, Opts) -> end, [{<<"uid">>, <<"%u">>}]), UIDs = eldap_utils:uids_domain_subst(Host, UIDsTemp), SubFilter = eldap_utils:generate_subfilter(UIDs), - UserFilter = case eldap_utils:get_opt( + UserFilter = case gen_mod:get_opt( {ldap_filter, Host}, Opts, fun check_filter/1, <<"">>) of <<"">> -> From 9a802185ad1dd05295a0e679fcb9f9df6163feaa Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 1 Jun 2015 14:34:49 +0200 Subject: [PATCH 103/695] Fix anonymous user login, it wasn't stored in anonymous mnesia table --- src/ejabberd_auth_anonymous.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index cb320dea557..2193794520c 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -141,7 +141,7 @@ remove_connection(SID, LUser, LServer) -> %% Register connection register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) -> - AuthModule = list_to_atom(binary_to_list(xml:get_attr_s(<<"auth_module">>, Info))), + AuthModule = xml:get_attr_s(auth_module, Info), case AuthModule == (?MODULE) of true -> ejabberd_hooks:run(register_user, LServer, From fb6267f38ee47f3f725f88324d132741c85dfb6a Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 1 Jun 2015 15:38:27 +0300 Subject: [PATCH 104/695] Add config validation at startup --- src/acl.erl | 11 +++- src/cyrsasl.erl | 12 +++- src/cyrsasl_digest.erl | 8 ++- src/ejabberd_app.erl | 18 +++++- src/ejabberd_auth.erl | 11 +++- src/ejabberd_auth_anonymous.erl | 21 +++++-- src/ejabberd_auth_external.erl | 15 ++++- src/ejabberd_auth_internal.erl | 8 ++- src/ejabberd_auth_ldap.erl | 100 +++++++++++++++++++++++++++++-- src/ejabberd_auth_odbc.erl | 11 ++-- src/ejabberd_auth_pam.erl | 24 +++++--- src/ejabberd_c2s.erl | 37 ++++++------ src/ejabberd_c2s_config.erl | 7 ++- src/ejabberd_captcha.erl | 15 ++++- src/ejabberd_config.erl | 59 +++++++++++++++++- src/ejabberd_ctl.erl | 15 +++-- src/ejabberd_http.erl | 17 +++++- src/ejabberd_http_ws.erl | 16 +++-- src/ejabberd_listener.erl | 22 ++++--- src/ejabberd_node_groups.erl | 14 ++++- src/ejabberd_odbc.erl | 27 ++++++++- src/ejabberd_odbc_sup.erl | 19 +++++- src/ejabberd_piefxis.erl | 9 ++- src/ejabberd_rdbms.erl | 12 +++- src/ejabberd_riak_sup.erl | 28 ++++++--- src/ejabberd_router.erl | 9 ++- src/ejabberd_s2s.erl | 14 ++++- src/ejabberd_s2s_in.erl | 33 ++++++++++- src/ejabberd_s2s_out.erl | 81 ++++++++++++++++++------- src/ejabberd_service.erl | 13 +++- src/ejabberd_sm.erl | 13 +++- src/ejabberd_sm_redis.erl | 27 ++++++--- src/ejabberd_stun.erl | 13 +++- src/ejabberd_system_monitor.erl | 14 ++++- src/ejabberd_web_admin.erl | 8 ++- src/ejabberd_xmlrpc.erl | 13 +++- src/ejd2odbc.erl | 6 +- src/eldap.erl | 24 +++++++- src/eldap_utils.erl | 56 ++++++++++++++---- src/ext_mod.erl | 21 ++++--- src/extauth.erl | 8 ++- src/gen_mod.erl | 92 +++++++++++++++++++++------- src/mod_adhoc.erl | 7 ++- src/mod_admin_extra.erl | 79 +++++++------------------ src/mod_announce.erl | 24 ++++---- src/mod_blocking.erl | 5 +- src/mod_caps.erl | 11 +++- src/mod_carboncopy.erl | 13 ++-- src/mod_client_state.erl | 15 ++++- src/mod_configure.erl | 4 +- src/mod_configure2.erl | 23 ++++++- src/mod_disco.erl | 17 +++++- src/mod_echo.erl | 7 ++- src/mod_fail2ban.erl | 15 ++++- src/mod_http_bind.erl | 8 ++- src/mod_http_fileserver.erl | 17 +++++- src/mod_ip_blacklist.erl | 5 +- src/mod_irc.erl | 13 +++- src/mod_last.erl | 17 +++++- src/mod_muc.erl | 30 +++++++++- src/mod_muc_admin.erl | 26 ++++---- src/mod_muc_log.erl | 47 ++++++++++++++- src/mod_multicast.erl | 9 ++- src/mod_offline.erl | 12 +++- src/mod_ping.erl | 15 ++++- src/mod_pres_counter.erl | 9 ++- src/mod_privacy.erl | 9 ++- src/mod_private.erl | 7 ++- src/mod_proxy65.erl | 5 +- src/mod_proxy65_service.erl | 22 ++++++- src/mod_proxy65_sm.erl | 10 +++- src/mod_proxy65_stream.erl | 15 ++++- src/mod_pubsub.erl | 25 +++++++- src/mod_register.erl | 39 +++++++++++- src/mod_register_web.erl | 4 +- src/mod_roster.erl | 23 +++++-- src/mod_service_log.erl | 17 ++++-- src/mod_shared_roster.erl | 24 ++++---- src/mod_shared_roster_ldap.erl | 100 ++++++++++++++++++++++++++++++- src/mod_sic.erl | 5 +- src/mod_sip.erl | 47 ++++++++++++++- src/mod_sip_proxy.erl | 14 +++-- src/mod_stats.erl | 6 +- src/mod_time.erl | 6 +- src/mod_vcard.erl | 20 ++++++- src/mod_vcard_ldap.erl | 102 +++++++++++++++++++++++++++++++- src/mod_vcard_xupdate.erl | 7 ++- src/mod_version.erl | 8 ++- src/odbc_queries.erl | 53 ++++++++++------- src/shaper.erl | 10 +++- 90 files changed, 1597 insertions(+), 390 deletions(-) diff --git a/src/acl.erl b/src/acl.erl index 8d9692ffbd7..021e4e2d43a 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -25,11 +25,14 @@ -module(acl). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -export([start/0, to_record/3, add/3, add_list/3, - add_local/3, add_list_local/3, load_from_config/0, - match_rule/3, match_acl/3, transform_options/1]). + add_local/3, add_list_local/3, load_from_config/0, + match_rule/3, match_acl/3, transform_options/1, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -476,3 +479,7 @@ transform_options({access, Name, Rules}, Opts) -> [{access, [{Name, NewRules}]}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. + +opt_type(access) -> fun (V) -> V end; +opt_type(acl) -> fun (V) -> V end; +opt_type(_) -> [access, acl]. diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 764473bab09..970da5bb9bc 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -25,10 +25,13 @@ -module(cyrsasl). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -export([start/0, register_mechanism/3, listmech/1, - server_new/7, server_start/3, server_step/2]). + server_new/7, server_start/3, server_step/2, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -237,3 +240,10 @@ is_disabled(Mechanism) -> [str:to_upper(V)] end, []), lists:member(Mechanism, Disabled). + +opt_type(disable_sasl_mechanisms) -> + fun (V) when is_list(V) -> + lists:map(fun (M) -> str:to_upper(M) end, V); + (V) -> [str:to_upper(V)] + end; +opt_type(_) -> [disable_sasl_mechanisms]. diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 10f9641308d..4b14bafd35a 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -25,9 +25,12 @@ -module(cyrsasl_digest). +-behaviour(ejabberd_config). + -author('alexey@sevcom.net'). --export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]). +-export([start/1, stop/0, mech_new/4, mech_step/2, + parse/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -256,3 +259,6 @@ response(KeyVals, User, Passwd, Nonce, AuthzId, ":", NC/binary, ":", CNonce/binary, ":", QOP/binary, ":", (hex((erlang:md5(A2))))/binary>>, hex((erlang:md5(T))). + +opt_type(fqdn) -> fun iolist_to_binary/1; +opt_type(_) -> [fqdn]. diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index daf8919a6fd..46fbf81dc9e 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -24,11 +24,14 @@ %%%---------------------------------------------------------------------- -module(ejabberd_app). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(application). --export([start_modules/0,start/2, prep_stop/1, stop/1, init/0]). +-export([start_modules/0, start/2, prep_stop/1, stop/1, + init/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -248,3 +251,16 @@ start_apps() -> ejabberd:start_app(p1_stringprep), ejabberd:start_app(p1_zlib), ejabberd:start_app(p1_cache_tab). + +opt_type(cluster_nodes) -> + fun (Ns) -> true = lists:all(fun is_atom/1, Ns), Ns end; +opt_type(loglevel) -> + fun (P) when P >= 0, P =< 5 -> P end; +opt_type(modules) -> + fun (Mods) -> + lists:map(fun ({M, A}) when is_atom(M), is_list(A) -> + {M, A} + end, + Mods) + end; +opt_type(_) -> [cluster_nodes, loglevel, modules]. diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 991cb664b91..03c117b6c65 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -27,6 +27,8 @@ -module(ejabberd_auth). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). %% External exports @@ -42,7 +44,7 @@ remove_user/2, remove_user/3, plain_password_required/1, store_type/1, entropy/1]). --export([auth_modules/1]). +-export([auth_modules/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -453,3 +455,10 @@ import(Server, riak, Passwd) -> ejabberd_auth_riak:import(Server, riak, Passwd); import(_, _, _) -> pass. + +opt_type(auth_method) -> + fun (V) when is_list(V) -> + true = lists:all(fun is_atom/1, V), V; + (V) when is_atom(V) -> [V] + end; +opt_type(_) -> [auth_method]. diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index cb320dea557..c00fff0bd47 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -24,6 +24,8 @@ %%%---------------------------------------------------------------------- -module(ejabberd_auth_anonymous). + +-behaviour(ejabberd_config). -author('mickael.remond@process-one.net'). -export([start/1, @@ -36,16 +38,15 @@ unregister_connection/3 ]). - -%% Function used by ejabberd_auth: -export([login/2, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, get_vh_registered_users_number/1, - get_vh_registered_users_number/2, get_password_s/2, + get_vh_registered_users/2, + get_vh_registered_users_number/1, + get_vh_registered_users_number/2, get_password_s/2, get_password/2, get_password/3, is_user_exists/2, remove_user/2, remove_user/3, store_type/0, - plain_password_required/0]). + plain_password_required/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -269,3 +270,13 @@ plain_password_required() -> false. store_type() -> plain. + +opt_type(allow_multiple_connections) -> + fun (V) when is_boolean(V) -> V end; +opt_type(anonymous_protocol) -> + fun (sasl_anon) -> sasl_anon; + (login_anon) -> login_anon; + (both) -> both + end; +opt_type(_) -> + [allow_multiple_connections, anonymous_protocol]. diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 0aa825f73bf..67477f27aaf 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -25,11 +25,12 @@ -module(ejabberd_auth_external). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -%% External exports -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, @@ -37,8 +38,8 @@ get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, - plain_password_required/0]). + remove_user/3, store_type/0, plain_password_required/0, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -311,3 +312,11 @@ get_mod_last_configured(Server) -> is_configured(Host, Module) -> gen_mod:is_loaded(Host, Module). + +opt_type(extauth_cache) -> + fun (false) -> undefined; + (I) when is_integer(I), I >= 0 -> I + end; +opt_type(extauth_program) -> + fun (V) -> binary_to_list(iolist_to_binary(V)) end; +opt_type(_) -> [extauth_cache, extauth_program]. diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index fc128ac5a54..d7f2a5ae5af 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -25,11 +25,12 @@ -module(ejabberd_auth_internal). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -%% External exports -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, @@ -38,7 +39,7 @@ get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, remove_user/3, store_type/0, export/1, import/1, - import/3, plain_password_required/0]). + import/3, plain_password_required/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -484,3 +485,6 @@ import(_LServer, mnesia, #passwd{} = P) -> mnesia:dirty_write(P); import(_, _, _) -> pass. + +opt_type(auth_password_format) -> fun (V) -> V end; +opt_type(_) -> [auth_password_format]. diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index d08151e60e4..f2122805aea 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -25,6 +25,8 @@ -module(ejabberd_auth_ldap). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -34,16 +36,15 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% External exports -export([start/1, stop/1, start_link/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, - get_vh_registered_users_number/1, + get_vh_registered_users/2, + get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, - plain_password_required/0]). + remove_user/3, store_type/0, plain_password_required/0, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -418,3 +419,92 @@ check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. + +mod_opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(ldap_password) -> fun iolist_to_binary/1; +mod_opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +mod_opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_tls_cacertfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_certfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(ldap_dn_filter) -> + fun ([{DNF, DNFA}]) -> + NewDNFA = case DNFA of + undefined -> []; + _ -> [iolist_to_binary(A) || A <- DNFA] + end, + NewDNF = check_filter(DNF), + {NewDNF, NewDNFA} + end; +mod_opt_type(ldap_filter) -> fun check_filter/1; +mod_opt_type(ldap_local_filter) -> fun (V) -> V end; +mod_opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)}; + (U) -> {iolist_to_binary(U)} + end, + lists:flatten(Us)) + end; +mod_opt_type(_) -> + [ldap_dn_filter, ldap_filter, ldap_local_filter, + ldap_uids, deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. + +opt_type(ldap_dn_filter) -> + fun ([{DNF, DNFA}]) -> + NewDNFA = case DNFA of + undefined -> []; + _ -> [iolist_to_binary(A) || A <- DNFA] + end, + NewDNF = check_filter(DNF), + {NewDNF, NewDNFA} + end; +opt_type(ldap_filter) -> fun check_filter/1; +opt_type(ldap_local_filter) -> fun (V) -> V end; +opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)}; + (U) -> {iolist_to_binary(U)} + end, + lists:flatten(Us)) + end; +opt_type(_) -> + [ldap_dn_filter, ldap_filter, ldap_local_filter, + ldap_uids]. diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index 881b86ccad9..45ff4d7786c 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -25,11 +25,12 @@ -module(ejabberd_auth_odbc). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(ejabberd_auth). -%% External exports -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, @@ -37,9 +38,8 @@ get_vh_registered_users_number/1, get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, - remove_user/3, store_type/0, - plain_password_required/0, - convert_to_scram/1]). + remove_user/3, store_type/0, plain_password_required/0, + convert_to_scram/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -467,3 +467,6 @@ convert_to_scram(Server) -> Error -> Error end end. + +opt_type(auth_password_format) -> fun (V) -> V end; +opt_type(_) -> [auth_password_format]. diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl index f3fdf628dd4..312bcf46eca 100644 --- a/src/ejabberd_auth_pam.erl +++ b/src/ejabberd_auth_pam.erl @@ -24,22 +24,21 @@ %%%------------------------------------------------------------------- -module(ejabberd_auth_pam). +-behaviour(ejabberd_config). + -author('xram@jabber.ru'). -behaviour(ejabberd_auth). -%% External exports -%%==================================================================== -%% API -%%==================================================================== -export([start/1, set_password/3, check_password/3, check_password/5, try_register/3, dirty_get_registered_users/0, get_vh_registered_users/1, - get_vh_registered_users/2, get_vh_registered_users_number/1, - get_vh_registered_users_number/2, - get_password/2, get_password_s/2, is_user_exists/2, - remove_user/2, remove_user/3, store_type/0, - plain_password_required/0]). + get_vh_registered_users/2, + get_vh_registered_users_number/1, + get_vh_registered_users_number/2, get_password/2, + get_password_s/2, is_user_exists/2, remove_user/2, + remove_user/3, store_type/0, plain_password_required/0, + opt_type/1]). start(_Host) -> ejabberd:start_app(p1_pam). @@ -118,3 +117,10 @@ get_pam_userinfotype(Host) -> (jid) -> jid end, username). + +opt_type(pam_service) -> fun iolist_to_binary/1; +opt_type(pam_userinfotype) -> + fun (username) -> username; + (jid) -> jid + end; +opt_type(_) -> [pam_service, pam_userinfotype]. diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b4cd2857687..330660925fa 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -25,6 +25,8 @@ -module(ejabberd_c2s). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 78, '2.5'}). @@ -54,23 +56,12 @@ get_subscribed/1, transform_listen_option/2]). -%% gen_fsm callbacks --export([init/1, - wait_for_stream/2, - wait_for_auth/2, - wait_for_feature_request/2, - wait_for_bind/2, - wait_for_session/2, - wait_for_sasl_response/2, - wait_for_resume/2, - session_established/2, - handle_event/3, - handle_sync_event/4, - code_change/4, - handle_info/3, - terminate/3, - print_state/1 - ]). +-export([init/1, wait_for_stream/2, wait_for_auth/2, + wait_for_feature_request/2, wait_for_bind/2, + wait_for_session/2, wait_for_sasl_response/2, + wait_for_resume/2, session_established/2, + handle_event/3, handle_sync_event/4, code_change/4, + handle_info/3, terminate/3, print_state/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -3126,3 +3117,15 @@ pack_string(String, Pack) -> transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(resource_conflict) -> + fun (setresource) -> setresource; + (closeold) -> closeold; + (closenew) -> closenew; + (acceptnew) -> acceptnew + end; +opt_type(_) -> + [domain_certfile, max_fsm_queue, resource_conflict]. diff --git a/src/ejabberd_c2s_config.erl b/src/ejabberd_c2s_config.erl index a971f0af4f7..43bba6726ca 100644 --- a/src/ejabberd_c2s_config.erl +++ b/src/ejabberd_c2s_config.erl @@ -26,9 +26,11 @@ -module(ejabberd_c2s_config). +-behaviour(ejabberd_config). + -author('mremond@process-one.net'). --export([get_c2s_limits/0]). +-export([get_c2s_limits/0, opt_type/1]). %% Get first c2s configuration limitations to apply it to other c2s %% connectors. @@ -63,3 +65,6 @@ select_opts_values([{max_stanza_size, Value} | Opts], [{max_stanza_size, Value} | SelectedValues]); select_opts_values([_Opt | Opts], SelectedValues) -> select_opts_values(Opts, SelectedValues). + +opt_type(listen) -> fun (V) -> V end; +opt_type(_) -> [listen]. diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index fc9f975f53a..8a1de2ede8d 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -25,6 +25,8 @@ -module(ejabberd_captcha). +-behaviour(ejabberd_config). + -protocol({xep, 158, '1.0'}). -behaviour(gen_server). @@ -39,7 +41,7 @@ -export([create_captcha/6, build_captcha_html/2, check_captcha/2, process_reply/1, process/2, is_feature_available/0, create_captcha_x/5, - create_captcha_x/6]). + create_captcha_x/6, opt_type/1]). -include("jlib.hrl"). @@ -695,3 +697,14 @@ clean_treap(Treap, CleanPriority) -> now_priority() -> {MSec, Sec, USec} = now(), -((MSec * 1000000 + Sec) * 1000000 + USec). + +opt_type(captcha_cmd) -> + fun (FileName) -> + F = iolist_to_binary(FileName), if F /= <<"">> -> F end + end; +opt_type(captcha_host) -> fun iolist_to_binary/1; +opt_type(captcha_limit) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(listen) -> fun (V) -> V end; +opt_type(_) -> + [captcha_cmd, captcha_host, captcha_limit, listen]. diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index fb506377568..efc70ed5789 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -36,13 +36,14 @@ prepare_opt_val/4, convert_table_to_binary/5, transform_options/1, collect_options/1, convert_to_yaml/1, convert_to_yaml/2, - env_binary_to_list/2]). + env_binary_to_list/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_config.hrl"). -include_lib("kernel/include/file.hrl"). +-callback opt_type(atom()) -> function() | [atom()]. %% @type macro() = {macro_key(), macro_value()} @@ -65,7 +66,8 @@ start() -> {attributes, record_info(fields, local_config)}]), mnesia:add_table_copy(local_config, node(), ram_copies), Config = get_ejabberd_config_path(), - State = read_file(Config), + State0 = read_file(Config), + State = validate_opts(State0), %% This start time is used by mod_last: {MegaSecs, Secs, _} = now(), UnixTime = MegaSecs*1000000 + Secs, @@ -712,6 +714,47 @@ get_option(Opt, F, Default) -> end end. +get_modules_with_options() -> + {ok, Mods} = application:get_key(ejabberd, modules), + lists:foldl( + fun(Mod, D) -> + Attrs = Mod:module_info(attributes), + Behavs = proplists:get_value(behaviour, Attrs, []), + case lists:member(ejabberd_config, Behavs) or (Mod == ?MODULE) of + true -> + Opts = Mod:opt_type(''), + lists:foldl( + fun(Opt, Acc) -> + dict:append(Opt, Mod, Acc) + end, D, Opts); + false -> + D + end + end, dict:new(), [?MODULE|Mods]). + +validate_opts(#state{opts = Opts} = State) -> + ModOpts = get_modules_with_options(), + NewOpts = lists:filter( + fun(#local_config{key = {Opt, _Host}, value = Val}) -> + case dict:find(Opt, ModOpts) of + {ok, [Mod|_]} -> + VFun = Mod:opt_type(Opt), + case catch VFun(Val) of + {'EXIT', _} -> + ?ERROR_MSG("ignoring option '~s' with " + "invalid value: ~p", + [Opt, Val]), + false; + _ -> + true + end; + _ -> + ?ERROR_MSG("ignoring uknown option '~s'", [Opt]), + false + end + end, Opts), + State#state{opts = NewOpts}. + -spec get_vh_by_auth_method(atom()) -> [binary()]. %% Return the list of hosts handled by a given module @@ -1098,3 +1141,15 @@ emit_deprecation_warning(Module, NewModule) -> ?WARNING_MSG("Module ~s is deprecated, use ~s instead", [Module, NewModule]) end. + +opt_type(hosts) -> + fun(L) when is_list(L) -> + lists:map( + fun(H) -> + iolist_to_binary(H) + end, L) + end; +opt_type(language) -> + fun iolist_to_binary/1; +opt_type(_) -> + [hosts, language]. diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 1eae7f758ed..82ac6b134f9 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -44,14 +44,13 @@ -module(ejabberd_ctl). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). --export([start/0, - init/0, - process/1, - process2/2, - register_commands/3, - unregister_commands/3]). +-export([start/0, init/0, process/1, process2/2, + register_commands/3, unregister_commands/3, + opt_type/1]). -include("ejabberd_ctl.hrl"). -include("ejabberd_commands.hrl"). @@ -801,3 +800,7 @@ print(Format, Args) -> %%format_usage_xmlrpc(ArgsDef, ResultDef) -> %% ["aaaa bbb ccc"]. + +opt_type(ejabberdctl_access_commands) -> + fun (V) when is_list(V) -> V end; +opt_type(_) -> [ejabberdctl_access_commands]. diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 4e7f4b554eb..b4de38c02ee 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -25,6 +25,8 @@ -module(ejabberd_http). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). %% External exports @@ -32,8 +34,7 @@ socket_type/0, receive_headers/1, url_encode/1, transform_listen_option/2]). -%% Callbacks --export([init/2]). +-export([init/2, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -870,3 +871,15 @@ transform_listen_option({request_handlers, Hs}, Opts) -> [{request_handlers, Hs1} | Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(default_host) -> fun (A) -> A end; +mod_opt_type(request_handlers) -> + fun (Hs) -> + [{str:tokens(iolist_to_binary(Path), <<"/">>), Mod} + || {Path, Mod} <- Hs] + end; +mod_opt_type(_) -> [default_host, request_handlers]. + +opt_type(trusted_proxies) -> + fun (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end; +opt_type(_) -> [trusted_proxies]. diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index a0cc31e2a00..66a0542d4ac 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -24,16 +24,17 @@ %%%---------------------------------------------------------------------- -module(ejabberd_http_ws). +-behaviour(ejabberd_config). + -author('ecestari@process-one.net'). -behaviour(gen_fsm). -% External exports -export([start/1, start_link/1, init/1, handle_event/3, handle_sync_event/4, code_change/4, handle_info/3, - terminate/3, send_xml/2, setopts/2, sockname/1, peername/1, - controlling_process/2, become_controller/2, close/1, - socket_handoff/6]). + terminate/3, send_xml/2, setopts/2, sockname/1, + peername/1, controlling_process/2, become_controller/2, + close/1, socket_handoff/6, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -353,3 +354,10 @@ parsed_items(List) -> after 0 -> lists:reverse(List) end. + +opt_type(websocket_ping_interval) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(websocket_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> + [websocket_ping_interval, websocket_timeout]. diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 0cfca0aa0b2..81256cc1852 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -24,20 +24,15 @@ %%%---------------------------------------------------------------------- -module(ejabberd_listener). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). --export([start_link/0, init/1, start/3, - init/3, - start_listeners/0, - start_listener/3, - stop_listeners/0, - stop_listener/2, - parse_listener_portip/2, - add_listener/3, - delete_listener/2, - transform_options/1, - validate_cfg/1 - ]). +-export([start_link/0, init/1, start/3, init/3, + start_listeners/0, start_listener/3, stop_listeners/0, + stop_listener/2, parse_listener_portip/2, + add_listener/3, delete_listener/2, transform_options/1, + validate_cfg/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -660,3 +655,6 @@ prepare_mod(sip) -> esip_socket; prepare_mod(Mod) when is_atom(Mod) -> Mod. + +opt_type(listen) -> fun validate_cfg/1; +opt_type(_) -> [listen]. diff --git a/src/ejabberd_node_groups.erl b/src/ejabberd_node_groups.erl index da0bffe997d..87942b7937b 100644 --- a/src/ejabberd_node_groups.erl +++ b/src/ejabberd_node_groups.erl @@ -24,6 +24,8 @@ %%%---------------------------------------------------------------------- -module(ejabberd_node_groups). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). -behaviour(gen_server). @@ -35,9 +37,8 @@ get_members/1, get_closest_node/1]). -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, + handle_info/2, terminate/2, code_change/3, opt_type/1]). -define(PG2, pg2). @@ -163,3 +164,10 @@ code_change(_OldVsn, State, _Extra) -> %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- + +opt_type(node_type) -> + fun (frontend) -> frontend; + (backend) -> backend; + (generic) -> generic + end; +opt_type(_) -> [node_type]. diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index dbae9f49b5c..eca781951f4 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -25,6 +25,8 @@ -module(ejabberd_odbc). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -define(GEN_FSM, p1_fsm). @@ -51,9 +53,9 @@ handle_info/3, terminate/3, print_state/1, code_change/4]). -%% gen_fsm states -export([connecting/2, connecting/3, - session_established/2, session_established/3]). + session_established/2, session_established/3, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -692,3 +694,24 @@ fsm_limit_opts() -> N when is_integer(N) -> [{max_queue, N}]; _ -> [] end. + +opt_type(max_fsm_queue) -> + fun (N) when is_integer(N), N > 0 -> N end; +opt_type(odbc_database) -> fun iolist_to_binary/1; +opt_type(odbc_keepalive_interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(odbc_password) -> fun iolist_to_binary/1; +opt_type(odbc_port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +opt_type(odbc_server) -> fun iolist_to_binary/1; +opt_type(odbc_type) -> + fun (mysql) -> mysql; + (pgsql) -> pgsql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(odbc_username) -> fun iolist_to_binary/1; +opt_type(_) -> + [max_fsm_queue, odbc_database, odbc_keepalive_interval, + odbc_password, odbc_port, odbc_server, odbc_type, + odbc_username]. diff --git a/src/ejabberd_odbc_sup.erl b/src/ejabberd_odbc_sup.erl index 37128e26575..4a1498964d5 100644 --- a/src/ejabberd_odbc_sup.erl +++ b/src/ejabberd_odbc_sup.erl @@ -25,11 +25,13 @@ -module(ejabberd_odbc_sup). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -%% API -export([start_link/1, init/1, add_pid/2, remove_pid/2, - get_pids/1, get_random_pid/1, transform_options/1]). + get_pids/1, get_random_pid/1, transform_options/1, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -205,3 +207,16 @@ read_lines(Fd, File, Acc) -> ?ERROR_MSG("Failed read from lite.sql, reason: ~p", [Err]), [] end. + +opt_type(odbc_pool_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(odbc_start_interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(odbc_type) -> + fun (mysql) -> mysql; + (pgsql) -> pgsql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(_) -> + [odbc_pool_size, odbc_start_interval, odbc_type]. diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 61e6595e342..3b29aeefe5a 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -38,10 +38,12 @@ -module(ejabberd_piefxis). +-behaviour(ejabberd_config). + -protocol({xep, 227, '1.0'}). -%% API --export([import_file/1, export_server/1, export_host/2]). +-export([import_file/1, export_server/1, export_host/2, + opt_type/1]). -define(CHUNK_SIZE, 1024*20). %20k @@ -737,3 +739,6 @@ print(Fd, String) -> %%%================================== %%% vim: set filetype=erlang tabstop=8 foldmarker=%%%%,%%%= foldmethod=marker: file:write(Fd, String). + +opt_type(auth_password_format) -> fun (X) -> X end; +opt_type(_) -> [auth_password_format]. diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl index 93bd9fc494a..23f1a857e1a 100644 --- a/src/ejabberd_rdbms.erl +++ b/src/ejabberd_rdbms.erl @@ -25,9 +25,11 @@ -module(ejabberd_rdbms). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). --export([start/0]). +-export([start/0, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -83,3 +85,11 @@ needs_odbc(Host) -> odbc -> {true, odbc}; undefined -> false end. + +opt_type(odbc_type) -> + fun (mysql) -> mysql; + (pgsql) -> pgsql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(_) -> [odbc_type]. diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index bb36eb44d1e..8b6a8064ddb 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -24,17 +24,13 @@ %%%---------------------------------------------------------------------- -module(ejabberd_riak_sup). + +-behaviour(ejabberd_config). -author('alexey@process-one.net'). -%% API --export([start/0, - start_link/0, - init/1, - get_pids/0, - transform_options/1, - get_random_pid/0, - get_random_pid/1 - ]). +-export([start/0, start_link/0, init/1, get_pids/0, + transform_options/1, get_random_pid/0, get_random_pid/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -158,3 +154,17 @@ transform_options({riak_server, {S, P}}, Opts) -> [{riak_server, S}, {riak_port, P}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. + +opt_type(modules) -> fun (L) when is_list(L) -> L end; +opt_type(riak_pool_size) -> + fun (N) when is_integer(N), N >= 1 -> N end; +opt_type(riak_port) -> fun (_) -> true end; +opt_type(riak_server) -> fun (_) -> true end; +opt_type(riak_start_interval) -> + fun (N) when is_integer(N), N >= 1 -> N end; +opt_type(_) -> + [modules, riak_pool_size, riak_port, riak_server, + riak_start_interval]. diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 76ef71dc477..6a56a22eae2 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -25,6 +25,8 @@ -module(ejabberd_router). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -43,9 +45,8 @@ -export([start_link/0]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -406,3 +407,7 @@ update_tables() -> false -> ok end. + +opt_type(domain_balancing_component_number) -> + fun (N) when is_integer(N), N > 1 -> N end; +opt_type(_) -> [domain_balancing_component_number]. diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index a7b3234fd55..d6729dd46e0 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -44,8 +46,8 @@ -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -%% ejabberd API --export([get_info_s2s_connections/1, transform_options/1]). +-export([get_info_s2s_connections/1, + transform_options/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -771,3 +773,11 @@ match_labels([DL | DLabels], [PL | PLabels]) -> end; false -> false end. + +opt_type(route_subdomains) -> + fun (s2s) -> s2s; + (local) -> local + end; +opt_type(s2s_access) -> + fun (A) when is_atom(A) -> A end; +opt_type(_) -> [route_subdomains, s2s_access]. diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 1b40f03c230..067eb98b23f 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s_in). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(p1_fsm). @@ -32,11 +34,10 @@ %% External exports -export([start/2, start_link/2, socket_type/0]). -%% gen_fsm callbacks -export([init/1, wait_for_stream/2, wait_for_feature_request/2, stream_established/2, handle_event/3, handle_sync_event/4, code_change/4, - handle_info/3, print_state/1, terminate/3]). + handle_info/3, print_state/1, terminate/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -710,3 +711,31 @@ fsm_limit_opts(Opts) -> N -> [{max_queue, N}] end end. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(s2s_certfile) -> fun iolist_to_binary/1; +opt_type(s2s_ciphers) -> fun iolist_to_binary/1; +opt_type(s2s_protocol_options) -> + fun (Options) -> + [_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] + || Opt <- Options, is_binary(Opt)]), + iolist_to_binary(O) + end; +opt_type(s2s_tls_compression) -> + fun (true) -> true; + (false) -> false + end; +opt_type(s2s_use_starttls) -> + fun (false) -> false; + (true) -> true; + (optional) -> optional; + (required) -> required; + (required_trusted) -> required_trusted + end; +opt_type(_) -> + [domain_certfile, max_fsm_queue, s2s_certfile, + s2s_ciphers, s2s_protocol_options, s2s_tls_compression, + s2s_use_starttls]. diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 6196f136f2d..733dbe0a703 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s_out). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(p1_fsm). @@ -37,26 +39,14 @@ stop_connection/1, transform_options/1]). -%% p1_fsm callbacks (same as gen_fsm) --export([init/1, - open_socket/2, - wait_for_stream/2, - wait_for_validation/2, - wait_for_features/2, - wait_for_auth_result/2, - wait_for_starttls_proceed/2, - relay_to_bridge/2, - reopen_socket/2, - wait_before_retry/2, - stream_established/2, - handle_event/3, - handle_sync_event/4, - handle_info/3, - terminate/3, - print_state/1, - code_change/4, - test_get_addr_port/1, - get_addr_port/1]). +-export([init/1, open_socket/2, wait_for_stream/2, + wait_for_validation/2, wait_for_features/2, + wait_for_auth_result/2, wait_for_starttls_proceed/2, + relay_to_bridge/2, reopen_socket/2, wait_before_retry/2, + stream_established/2, handle_event/3, + handle_sync_event/4, handle_info/3, terminate/3, + print_state/1, code_change/4, test_get_addr_port/1, + get_addr_port/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1365,3 +1355,54 @@ fsm_limit_opts() -> undefined -> []; N -> [{max_queue, N}] end. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(outgoing_s2s_families) -> + fun (Families) -> + true = lists:all(fun (ipv4) -> true; + (ipv6) -> true + end, + Families), + Families + end; +opt_type(outgoing_s2s_port) -> + fun (I) when is_integer(I), I > 0, I =< 65536 -> I end; +opt_type(outgoing_s2s_timeout) -> + fun (TimeOut) when is_integer(TimeOut), TimeOut > 0 -> + TimeOut; + (infinity) -> infinity + end; +opt_type(s2s_certfile) -> fun iolist_to_binary/1; +opt_type(s2s_ciphers) -> fun iolist_to_binary/1; +opt_type(s2s_dns_retries) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(s2s_dns_timeout) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(s2s_max_retry_delay) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(s2s_protocol_options) -> + fun (Options) -> + [_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [], + [["|" | binary_to_list(Opt)] + || Opt <- Options, is_binary(Opt)]), + iolist_to_binary(O) + end; +opt_type(s2s_tls_compression) -> + fun (true) -> true; + (false) -> false + end; +opt_type(s2s_use_starttls) -> + fun (true) -> true; + (false) -> false; + (optional) -> optional; + (required) -> required; + (required_trusted) -> required_trusted + end; +opt_type(_) -> + [domain_certfile, max_fsm_queue, outgoing_s2s_families, + outgoing_s2s_port, outgoing_s2s_timeout, s2s_certfile, + s2s_ciphers, s2s_dns_retries, s2s_dns_timeout, + s2s_max_retry_delay, s2s_protocol_options, + s2s_tls_compression, s2s_use_starttls]. diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index b7cea0c36ba..3e283a0a211 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -25,6 +25,8 @@ -module(ejabberd_service). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 114, '1.6'}). @@ -37,11 +39,11 @@ -export([start/2, start_link/2, send_text/2, send_element/2, socket_type/0, transform_listen_option/2]). -%% gen_fsm callbacks -export([init/1, wait_for_stream/2, wait_for_handshake/2, stream_established/2, handle_event/3, handle_sync_event/4, code_change/4, - handle_info/3, terminate/3, print_state/1]). + handle_info/3, terminate/3, print_state/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -404,3 +406,10 @@ fsm_limit_opts(Opts) -> N -> [{max_queue, N}] end end. + +mod_opt_type(password) -> fun iolist_to_binary/1; +mod_opt_type(_) -> [password]. + +opt_type(max_fsm_queue) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> [max_fsm_queue]. diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index bfe6e934f95..e2590237441 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -25,6 +25,8 @@ -module(ejabberd_sm). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -64,9 +66,8 @@ is_existing_resource/3 ]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -805,3 +806,11 @@ kick_user(User, Server) -> PID ! kick end, Resources), length(Resources). + +opt_type(sm_db_type) -> + fun (mnesia) -> mnesia; + (internal) -> mnesia; + (odbc) -> odbc; + (redis) -> redis + end; +opt_type(_) -> [sm_db_type]. diff --git a/src/ejabberd_sm_redis.erl b/src/ejabberd_sm_redis.erl index 0283f9c3e33..a92845b81c2 100644 --- a/src/ejabberd_sm_redis.erl +++ b/src/ejabberd_sm_redis.erl @@ -8,16 +8,13 @@ %%%------------------------------------------------------------------- -module(ejabberd_sm_redis). +-behaviour(ejabberd_config). + -behaviour(ejabberd_sm). -%% API --export([init/0, - set_session/1, - delete_session/4, - get_sessions/0, - get_sessions/1, - get_sessions/2, - get_sessions/3]). +-export([init/0, set_session/1, delete_session/4, + get_sessions/0, get_sessions/1, get_sessions/2, + get_sessions/3, opt_type/1]). -include("ejabberd.hrl"). -include("ejabberd_sm.hrl"). @@ -207,3 +204,17 @@ clean_table() -> "server ~s: ~p", [LServer, Err]) end end, ?MYHOSTS). + +opt_type(redis_connect_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(redis_db) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(redis_password) -> fun iolist_to_list/1; +opt_type(redis_port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +opt_type(redis_reconnect_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(redis_server) -> fun iolist_to_list/1; +opt_type(_) -> + [redis_connect_timeout, redis_db, redis_password, + redis_port, redis_reconnect_timeout, redis_server]. diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 9435f7e635d..3d5ab6bd71c 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -27,8 +27,8 @@ -protocol({rfc, 5766}). -%% API --export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]). +-export([tcp_init/2, udp_init/2, udp_recv/5, start/2, + socket_type/0, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -100,3 +100,12 @@ prepare_turn_opts(Opts, _UseTurn = true) -> MaxRate = shaper:get_max_rate(Shaper), Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} | lists:keydelete(shaper, 1, Opts)]. + +mod_opt_type(auth_realm) -> fun iolist_to_binary/1; +mod_opt_type(auth_type) -> + fun (anonymous) -> anonymous; + (user) -> user + end; +mod_opt_type(shaper) -> + fun (S) when is_atom(S) -> S end; +mod_opt_type(_) -> [auth_realm, auth_type, shaper]. diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index df8d9d51a44..fe8c1d2bbbb 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -25,6 +25,8 @@ -module(ejabberd_system_monitor). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -33,9 +35,8 @@ -export([start_link/0, process_command/3, process_remote_command/1]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -331,3 +332,12 @@ process_remote_command([setlh, NewValue]) -> io_lib:format("Result of set large heap: ~p --> ~p", [OldLH, NewLH]); process_remote_command(_) -> throw(unknown_command). + +opt_type(watchdog_admins) -> + fun (JIDs) -> + [jlib:jid_tolower(jlib:string_to_jid(iolist_to_binary(S))) + || S <- JIDs] + end; +opt_type(watchdog_large_heap) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> [watchdog_admins, watchdog_large_heap]. diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 29ecb7346ea..239c8bac556 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -27,12 +27,13 @@ -module(ejabberd_web_admin). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -%% External exports -export([process/2, list_users/4, list_users_in_diapason/4, pretty_print_xml/1, - term_to_id/1]). + term_to_id/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -2877,3 +2878,6 @@ make_menu_item(item, 3, URI, Name, Lang) -> %%%================================== %%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: + +opt_type(access) -> fun (V) -> V end; +opt_type(_) -> [access]. diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index c852114506d..0a74fd47b69 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -36,7 +36,7 @@ -author('badlop@process-one.net'). -export([start/2, handler/2, process/2, socket_type/0, - transform_listen_option/2]). + transform_listen_option/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -541,3 +541,14 @@ transform_listen_option({access_commands, ACOpts}, Opts) -> [{access_commands, NewACOpts}|Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(access_commands) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(commands) -> + fun (A) when is_atom(A) -> A; + (L) when is_list(L) -> + true = lists:all(fun is_atom/1, L), L + end; +mod_opt_type(options) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(_) -> [access_commands, commands, options]. diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index 90781481332..cc6241925e2 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -29,7 +29,8 @@ -include("logger.hrl"). --export([export/2, export/3, import_file/2, import/2, import/3]). +-export([export/2, export/3, import_file/2, import/2, + import/3, mod_opt_type/1]). -define(MAX_RECORDS_PER_TRANSACTION, 100). @@ -279,3 +280,6 @@ flatten1([H|T], Acc) -> flatten1(T, [[H, $\n]|Acc]); flatten1([], Acc) -> Acc. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. diff --git a/src/eldap.erl b/src/eldap.erl index a9edebdf03c..f8f6d04a99e 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -80,11 +80,10 @@ -export([get_status/1]). -%% gen_fsm callbacks -export([init/1, connecting/2, connecting/3, wait_bind_response/3, active/3, active_bind/3, handle_event/3, handle_sync_event/4, handle_info/3, - terminate/3, code_change/4]). + terminate/3, code_change/4, mod_opt_type/1]). -export_type([filter/0]). @@ -1194,3 +1193,24 @@ bump_id(#eldap{id = Id}) when Id > (?MAX_TRANSACTION_ID) -> ?MIN_TRANSACTION_ID; bump_id(#eldap{id = Id}) -> Id + 1. + +mod_opt_type(encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(tls_cacertfile) -> + fun (S) when is_binary(S) -> binary_to_list(S); + (undefined) -> undefined + end; +mod_opt_type(tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I; + (undefined) -> undefined + end; +mod_opt_type(tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(_) -> + [encrypt, tls_cacertfile, tls_depth, tls_verify]. diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index bdc98c202fd..3c475e20b76 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -24,18 +24,14 @@ %%%---------------------------------------------------------------------- -module(eldap_utils). + +-behaviour(ejabberd_config). -author('mremond@process-one.net'). --export([generate_subfilter/1, - find_ldap_attrs/2, - get_ldap_attr/2, - get_user_part/2, - make_filter/2, - get_state/2, - case_insensitive_match/2, - get_config/2, - decode_octet_string/3, - uids_domain_subst/2]). +-export([generate_subfilter/1, find_ldap_attrs/2, + get_ldap_attr/2, get_user_part/2, make_filter/2, + get_state/2, case_insensitive_match/2, get_config/2, + decode_octet_string/3, uids_domain_subst/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -349,3 +345,43 @@ collect_parts_bit([{?N_BIT_STRING,<>}|Rest],Acc,Uacc) -> collect_parts_bit(Rest,[Bits|Acc],Unused+Uacc); collect_parts_bit([],Acc,Uacc) -> list_to_binary([Uacc|lists:reverse(Acc)]). + +opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +opt_type(ldap_base) -> fun iolist_to_binary/1; +opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +opt_type(ldap_password) -> fun iolist_to_binary/1; +opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +opt_type(ldap_tls_cacertfile) -> fun iolist_to_binary/1; +opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +opt_type(_) -> + [deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_depth, ldap_tls_verify]. diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 473aeb4ebee..bfc448dcfa1 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -24,16 +24,16 @@ %%%---------------------------------------------------------------------- -module(ext_mod). + +-behaviour(ejabberd_config). -author("Christophe Romain "). -%% Packaging service -export([start/0, stop/0, update/0, check/1, - available_command/0, available/0, available/1, - installed_command/0, installed/0, installed/1, - install/1, uninstall/1, - upgrade/0, upgrade/1, - add_sources/2, del_sources/1, - modules_dir/0]). + available_command/0, available/0, available/1, + installed_command/0, installed/0, installed/1, + install/1, uninstall/1, upgrade/0, upgrade/1, + add_sources/2, del_sources/1, modules_dir/0, + opt_type/1]). -include("ejabberd_commands.hrl"). @@ -517,3 +517,10 @@ format({Key, Val}) when is_binary(Val) -> {Key, binary_to_list(Val)}; format({Key, Val}) -> % TODO: improve Yaml parsing {Key, Val}. + +opt_type(allow_contrib_modules) -> + fun (false) -> false; + (no) -> false; + (_) -> true + end; +opt_type(_) -> [allow_contrib_modules]. diff --git a/src/extauth.erl b/src/extauth.erl index eb936ddf953..766d43340c0 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -25,11 +25,13 @@ -module(extauth). +-behaviour(ejabberd_config). + -author('leifj@it.su.se'). -export([start/2, stop/1, init/2, check_password/3, set_password/3, try_register/3, remove_user/2, - remove_user/3, is_user_exists/2]). + remove_user/3, is_user_exists/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -157,3 +159,7 @@ encode(L) -> str:join(L, <<":">>). decode([0, 0]) -> false; decode([0, 1]) -> true. + +opt_type(extauth_instances) -> + fun (V) when is_integer(V), V > 0 -> V end; +opt_type(_) -> [extauth_instances]. diff --git a/src/gen_mod.erl b/src/gen_mod.erl index 29d5dfb784d..2f9d3dd9ee5 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -1,7 +1,6 @@ %%%---------------------------------------------------------------------- %%% File : gen_mod.erl %%% Author : Alexey Shchepin -%%% Purpose : %%% Purpose : %%% Created : 24 Jan 2003 by Alexey Shchepin %%% @@ -18,22 +17,26 @@ %%% 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., -%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% 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(gen_mod). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). --export([start/0, start_module/2, start_module/3, stop_module/2, - stop_module_keep_config/2, get_opt/3, get_opt/4, - get_opt_host/3, db_type/1, db_type/2, get_module_opt/5, - get_module_opt_host/3, loaded_modules/1, - loaded_modules_with_opts/1, get_hosts/2, - get_module_proc/2, is_loaded/2, default_db/1]). +-export([start/0, start_module/2, start_module/3, + stop_module/2, stop_module_keep_config/2, get_opt/3, + get_opt/4, get_opt_host/3, db_type/1, db_type/2, + get_module_opt/4, get_module_opt/5, get_module_opt_host/3, + loaded_modules/1, loaded_modules_with_opts/1, + get_hosts/2, get_module_proc/2, is_loaded/2, + start_modules/1, default_db/1, v_db/1, opt_type/1]). %%-export([behaviour_info/1]). @@ -45,11 +48,13 @@ opts = [] :: opts() | '_' | '$2'}). -type opts() :: [{atom(), any()}]. +-type db_type() :: odbc | mnesia | riak. -callback start(binary(), opts()) -> any(). -callback stop(binary()) -> any(). -export_type([opts/0]). +-export_type([db_type/0]). %%behaviour_info(callbacks) -> [{start, 2}, {stop, 1}]; %%behaviour_info(_Other) -> undefined. @@ -60,6 +65,17 @@ start() -> {keypos, #ejabberd_module.module_host}]), ok. +-spec start_modules(binary()) -> any(). + +start_modules(Host) -> + Modules = ejabberd_config:get_option( + {modules, Host}, + fun(L) when is_list(L) -> L end, []), + lists:foreach( + fun({Module, Opts}) -> + start_module(Host, Module, Opts) + end, Modules). + -spec start_module(binary(), atom()) -> any(). start_module(Host, Module) -> @@ -75,7 +91,8 @@ start_module(Host, Module) -> -spec start_module(binary(), atom(), opts()) -> any(). -start_module(Host, Module, Opts) -> +start_module(Host, Module, Opts0) -> + Opts = validate_opts(Module, Opts0), ets:insert(ejabberd_modules, #ejabberd_module{module_host = {Module, Host}, opts = Opts}), @@ -107,18 +124,12 @@ is_app_running(AppName) -> -spec stop_module(binary(), atom()) -> error | {aborted, any()} | {atomic, any()}. -%% @doc Stop the module in a host, and forget its configuration. stop_module(Host, Module) -> case stop_module_keep_config(Host, Module) of error -> error; ok -> ok end. -%% @doc Stop the module in a host, but keep its configuration. -%% As the module configuration is kept in the Mnesia local_config table, -%% when ejabberd is restarted the module will be started again. -%% This function is useful when ejabberd is being stopped -%% and it stops all modules. -spec stop_module_keep_config(binary(), atom()) -> error | ok. stop_module_keep_config(Host, Module) -> @@ -177,6 +188,11 @@ get_opt(Opt, Opts, F, Default) -> ejabberd_config:prepare_opt_val(Opt, Val, F, Default) end. +-spec get_module_opt(global | binary(), atom(), atom(), check_fun()) -> any(). + +get_module_opt(Host, Module, Opt, F) -> + get_module_opt(Host, Module, Opt, F, undefined). + -spec get_module_opt(global | binary(), atom(), atom(), check_fun(), any()) -> any(). get_module_opt(global, Module, Opt, F, Default) -> @@ -216,26 +232,56 @@ get_opt_host(Host, Opts, Default) -> Val = get_opt(host, Opts, fun iolist_to_binary/1, Default), ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host). --spec v_db(odbc | mnesia | riak | internal) -> odbc | mnesia | riak. +validate_opts(Module, Opts) -> + lists:filter( + fun({Opt, Val}) -> + case catch Module:mod_opt_type(Opt) of + VFun when is_function(VFun) -> + case catch VFun(Val) of + {'EXIT', _} -> + ?ERROR_MSG("ignoring invalid value '~p' for " + "option '~s' of module '~s'", + [Val, Opt, Module]), + false; + _ -> + true + end; + L when is_list(L) -> + SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>), + ?ERROR_MSG("ignoring unknown option '~s' for module '~s'," + " available options are: ~s", [Opt, Module, SOpts]), + false; + {'EXIT', {undef, _}} -> + ?WARNING_MSG("module '~s' doesn't export mod_opt_type/1", + [Module]), + true + end; + (Junk) -> + ?ERROR_MSG("failed to understand option ~p for module '~s'", + [Junk, Module]), + false + end, Opts). + +-spec v_db(db_type() | internal) -> db_type(). v_db(odbc) -> odbc; v_db(internal) -> mnesia; v_db(mnesia) -> mnesia; v_db(riak) -> riak. --spec db_type(opts()) -> odbc | mnesia | riak. +-spec db_type(opts()) -> db_type(). db_type(Opts) -> db_type(global, Opts). --spec db_type(binary() | global, atom() | opts()) -> odbc | mnesia | riak. +-spec db_type(binary() | global, atom() | opts()) -> db_type(). db_type(Host, Module) when is_atom(Module) -> get_module_opt(Host, Module, db_type, fun v_db/1, default_db(Host)); db_type(Host, Opts) when is_list(Opts) -> get_opt(db_type, Opts, fun v_db/1, default_db(Host)). --spec default_db(binary() | global) -> odbc | mnesia | riak. +-spec default_db(binary() | global) -> db_type(). default_db(Host) -> ejabberd_config:get_option({default_db, Host}, fun v_db/1, mnesia). @@ -285,3 +331,7 @@ get_module_proc(Host, Base) -> is_loaded(Host, Module) -> ets:member(ejabberd_modules, {Module, Host}). + +opt_type(default_db) -> fun v_db/1; +opt_type(modules) -> fun (L) when is_list(L) -> L end; +opt_type(_) -> [default_db, modules]. diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index db73ced54d4..f5480483171 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -35,7 +35,7 @@ process_sm_iq/3, get_local_commands/5, get_local_identity/5, get_local_features/5, get_sm_commands/5, get_sm_identity/5, get_sm_features/5, - ping_item/4, ping_command/4]). + ping_item/4, ping_command/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -280,3 +280,8 @@ ping_command(_Acc, _From, _To, true -> {error, ?ERR_BAD_REQUEST} end; ping_command(Acc, _From, _To, _Request) -> Acc. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(report_commands_node) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> [iqdisc, report_commands_node]. diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index bc49bae47b4..c213efe4221 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -30,64 +30,24 @@ -include("logger.hrl"). --export([start/2, stop/1, - %% Node - compile/1, - get_cookie/0, - remove_node/1, - export2odbc/2, - %% Accounts - set_password/3, - check_password_hash/4, - delete_old_users/1, - delete_old_users_vhost/2, - ban_account/3, - num_active_users/2, - %% Sessions - num_resources/2, - resource_num/3, - kick_session/4, - status_num/2, status_num/1, - status_list/2, status_list/1, - connected_users_info/0, - connected_users_vhost/1, - set_presence/7, - user_sessions_info/2, - %% Vcard - set_nickname/3, - get_vcard/3, - get_vcard/4, - get_vcard_multi/4, - set_vcard/4, - set_vcard/5, - %% Roster - add_rosteritem/7, - delete_rosteritem/4, - process_rosteritems/5, - get_roster/2, - push_roster/3, - push_roster_all/1, - push_alltoall/2, - %% mod_last - get_last/2, - %% mod_private - private_get/4, - private_set/3, - %% mod_shared_roster - srg_create/5, - srg_delete/2, - srg_list/1, - srg_get_info/2, - srg_get_members/2, - srg_user_add/4, - srg_user_del/4, - %% Stanza - send_message/5, - send_stanza_c2s/4, - privacy_set/3, - %% Stats - stats/1, stats/2 - ]). +-export([start/2, stop/1, compile/1, get_cookie/0, + remove_node/1, export2odbc/2, set_password/3, + check_password_hash/4, delete_old_users/1, + delete_old_users_vhost/2, ban_account/3, + num_active_users/2, num_resources/2, resource_num/3, + kick_session/4, status_num/2, status_num/1, + status_list/2, status_list/1, connected_users_info/0, + connected_users_vhost/1, set_presence/7, + user_sessions_info/2, set_nickname/3, get_vcard/3, + get_vcard/4, get_vcard_multi/4, set_vcard/4, + set_vcard/5, add_rosteritem/7, delete_rosteritem/4, + process_rosteritems/5, get_roster/2, push_roster/3, + push_roster_all/1, push_alltoall/2, get_last/2, + private_get/4, private_set/3, srg_create/5, + srg_delete/2, srg_list/1, srg_get_info/2, + srg_get_members/2, srg_user_add/4, srg_user_del/4, + send_message/5, send_stanza_c2s/4, privacy_set/3, + stats/1, stats/2, mod_opt_type/1]). -include("ejabberd.hrl"). @@ -1557,3 +1517,6 @@ is_glob_match(String, <<"!", Glob/binary>>) -> not is_regexp_match(String, ejabberd_regexp:sh_to_awk(Glob)); 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]. diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 542417ff378..8049dd4f638 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -31,20 +31,11 @@ -behaviour(gen_mod). --export([start/2, - init/0, - stop/1, - export/1, - import/1, - import/3, - announce/3, - send_motd/1, - disco_identity/5, - disco_features/5, - disco_items/5, - send_announcement_to_all/3, - announce_commands/4, - announce_items/4]). +-export([start/2, init/0, stop/1, export/1, import/1, + import/3, announce/3, send_motd/1, disco_identity/5, + disco_features/5, disco_items/5, + send_announcement_to_all/3, announce_commands/4, + announce_items/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1152,3 +1143,8 @@ import(_LServer, riak, #motd_users{us = {_, S}} = Users) -> [{'2i', [{<<"server">>, S}]}]); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [access, db_type]. diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 1d3bf3c3483..609f1664c53 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -31,7 +31,7 @@ -protocol({xep, 191, '1.2'}). -export([start/2, stop/1, process_iq/3, - process_iq_set/4, process_iq_get/5]). + process_iq_set/4, process_iq_get/5, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -451,3 +451,6 @@ process_blocklist_get(LUser, LServer, odbc) -> end; {'EXIT', _} -> error end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 10fe2943107..f10ed66c7b5 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -47,10 +47,9 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% hook handlers -export([user_send_packet/3, user_receive_packet/4, c2s_presence_in/2, c2s_filter_packet/6, - c2s_broadcast_recipients/6]). + c2s_broadcast_recipients/6, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -754,3 +753,11 @@ import_next(LServer, DBType, NodePair) -> ok end, import_next(LServer, DBType, ets:next(caps_features_tmp, NodePair)). + +mod_opt_type(cache_life_time) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> + [cache_life_time, cache_size, db_type]. diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index be9e30f9c3f..2cc495aecde 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -34,13 +34,9 @@ -export([start/2, stop/1]). -%% Hooks: --export([user_send_packet/3, - user_receive_packet/4, - iq_handler2/3, - iq_handler1/3, - remove_connection/4, - is_carbon_copy/1]). +-export([user_send_packet/3, user_receive_packet/4, + iq_handler2/3, iq_handler1/3, remove_connection/4, + is_carbon_copy/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -288,3 +284,6 @@ is_chat_or_normal_message(_Packet) -> false. list(User, Server)-> mnesia:dirty_select(?TABLE, [{#carboncopy{us = {User, Server}, resource = '$2', version = '$3'}, [], [{{'$2','$3'}}]}]). + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index c5041ed04c9..1287d5687b5 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -29,8 +29,9 @@ -behavior(gen_mod). --export([start/2, stop/1, add_stream_feature/2, filter_presence/2, - filter_chat_states/2]). +-export([start/2, stop/1, add_stream_feature/2, + filter_presence/2, filter_chat_states/2, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -108,3 +109,13 @@ filter_chat_states(_Action, #xmlel{name = <<"message">>} = Stanza) -> {stop, send} end; filter_chat_states(Action, _Stanza) -> Action. + +mod_opt_type(drop_chat_states) -> + fun (true) -> true; + (false) -> false + end; +mod_opt_type(queue_presence) -> + fun (true) -> true; + (false) -> false + end; +mod_opt_type(_) -> [drop_chat_states, queue_presence]. diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 0941dcf2841..8faf7be735c 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -35,7 +35,7 @@ get_local_features/5, get_local_items/5, adhoc_local_items/4, adhoc_local_commands/4, get_sm_identity/5, get_sm_features/5, get_sm_items/5, - adhoc_sm_items/4, adhoc_sm_commands/4]). + adhoc_sm_items/4, adhoc_sm_commands/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -2148,3 +2148,5 @@ set_sm_form(User, Server, <<"config">>, end; set_sm_form(_User, _Server, _Node, _Request, _Fields) -> {error, ?ERR_SERVICE_UNAVAILABLE}. + +mod_opt_type(_) -> []. diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index b70f8fe5195..efe665d2305 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -25,11 +25,14 @@ -module(mod_configure2). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -195,3 +198,21 @@ process_get(#xmlel{name = <<"last">>, attrs = Attrs}) -> %%process_get({xmlelement, Name, Attrs, SubEls}) -> %% {result, }; process_get(_) -> {error, ?ERR_BAD_REQUEST}. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. + +opt_type(registration_watchers) -> + fun (JIDs) when is_list(JIDs) -> + lists:map(fun (J) -> + #xmlel{name = <<"jid">>, attrs = [], + children = + [{xmlcdata, iolist_to_binary(J)}]} + end, + JIDs) + end; +opt_type(welcome_message) -> + fun ({Subj, Body}) -> + {iolist_to_binary(Subj), iolist_to_binary(Body)} + end; +opt_type(_) -> [registration_watchers, welcome_message]. diff --git a/src/mod_disco.erl b/src/mod_disco.erl index c0ab9a9ac5a..afa7d39081e 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -39,7 +39,7 @@ get_sm_identity/5, get_sm_features/5, get_sm_items/5, get_info/5, register_feature/2, unregister_feature/2, register_extra_domain/2, unregister_extra_domain/2, - transform_module_options/1]). + transform_module_options/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -519,3 +519,18 @@ values_to_xml(Values) -> children = [{xmlcdata, Value}]} end, Values). + +mod_opt_type(extra_domains) -> + fun (Hs) -> [iolist_to_binary(H) || H <- Hs] end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(server_info) -> + fun (L) -> + lists:map(fun (Opts) -> + Mods = proplists:get_value(modules, Opts, all), + Name = proplists:get_value(name, Opts, <<>>), + URLs = proplists:get_value(urls, Opts, []), + {Mods, Name, URLs} + end, + L) + end; +mod_opt_type(_) -> [extra_domains, iqdisc, server_info]. diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 63dc8c81bcc..cdd9a8856d7 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -35,9 +35,9 @@ -export([start_link/2, start/2, stop/1, do_client_version/3]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -196,3 +196,6 @@ do_client_version(enabled, From, To) -> Values_string2 = iolist_to_binary(Values_string1), ?INFO_MSG("Information of the client: ~s~s", [ToS, Values_string2]). + +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(_) -> [host]. diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 63c09db26f5..67b705d9a0b 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -31,9 +31,9 @@ %% API -export([start_link/2, start/2, stop/1, c2s_auth_result/4, check_bl_c2s/3]). -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). +-export([init/1, handle_call/3, handle_cast/2, + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include_lib("stdlib/include/ms_transform.hrl"). -include("ejabberd.hrl"). @@ -187,3 +187,12 @@ is_loaded_at_other_hosts(Host) -> format_date({{Year, Month, Day}, {Hour, Minute, Second}}) -> io_lib:format("~2..0w:~2..0w:~2..0w ~2..0w.~2..0w.~4..0w", [Hour, Minute, Second, Day, Month, Year]). + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(c2s_auth_ban_lifetime) -> + fun (T) when is_integer(T), T > 0 -> T end; +mod_opt_type(c2s_max_auth_failures) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> + [access, c2s_auth_ban_lifetime, c2s_max_auth_failures]. diff --git a/src/mod_http_bind.erl b/src/mod_http_bind.erl index 773ef241fdb..1c772ce1738 100644 --- a/src/mod_http_bind.erl +++ b/src/mod_http_bind.erl @@ -37,7 +37,7 @@ -behaviour(gen_mod). --export([start/2, stop/1, process/2]). +-export([start/2, stop/1, process/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -142,3 +142,9 @@ migrate_database() -> %% of actually migrating data, let's just destroy the table mnesia:delete_table(http_bind) end. + +mod_opt_type(max_inactivity) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(max_pause) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> [max_inactivity, max_pause]. diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 97738355e04..68ebf8835b2 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -43,8 +43,7 @@ %% request_handlers callbacks -export([process/2]). -%% ejabberd_hooks callbacks --export([reopen_log/1]). +-export([reopen_log/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -448,3 +447,17 @@ ip_to_string(Address) when size(Address) == 4 -> ip_to_string(Address) when size(Address) == 8 -> Parts = lists:map(fun (Int) -> io_lib:format("~.16B", [Int]) end, tuple_to_list(Address)), string:to_lower(lists:flatten(join(Parts, ":"))). + +mod_opt_type(accesslog) -> fun iolist_to_binary/1; +mod_opt_type(content_types) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(custom_headers) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(default_content_type) -> + fun iolist_to_binary/1; +mod_opt_type(directory_indices) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(docroot) -> fun (A) -> A end; +mod_opt_type(_) -> + [accesslog, content_types, custom_headers, + default_content_type, directory_indices, docroot]. diff --git a/src/mod_ip_blacklist.erl b/src/mod_ip_blacklist.erl index 6225343c02e..b0777d28ec6 100644 --- a/src/mod_ip_blacklist.erl +++ b/src/mod_ip_blacklist.erl @@ -36,8 +36,7 @@ -export([update_bl_c2s/0]). -%% Hooks: --export([is_ip_in_c2s_blacklist/3]). +-export([is_ip_in_c2s_blacklist/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -129,3 +128,5 @@ is_ip_in_c2s_blacklist(_Val, _IP, _Lang) -> false. %% - For now, we do not kick user already logged on a given IP after %% we update the blacklist. + +mod_opt_type(_) -> []. diff --git a/src/mod_irc.erl b/src/mod_irc.erl index e96fc4dc139..25511848306 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -35,9 +35,9 @@ -export([start_link/2, start/2, stop/1, export/1, import/1, import/3, closed_connection/3, get_connection_params/3]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1345,3 +1345,12 @@ import(_LServer, riak, #irc_custom{} = R) -> ejabberd_riak:put(R, irc_custom_schema()); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(default_encoding) -> + fun iolist_to_binary/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(_) -> + [access, db_type, default_encoding, host]. diff --git a/src/mod_last.erl b/src/mod_last.erl index 4e96526e7c2..8904f78ce6c 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -25,6 +25,8 @@ -module(mod_last). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 12, '2.0'}). @@ -32,9 +34,10 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, export/1, - process_sm_iq/3, on_presence_update/4, import/1, import/3, - store_last_info/4, get_last_info/2, remove_user/2, - transform_options/1]). + process_sm_iq/3, on_presence_update/4, import/1, + import/3, store_last_info/4, get_last_info/2, + remove_user/2, transform_options/1, mod_opt_type/1, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -351,3 +354,11 @@ transform_options({node_start, {_, _, _} = Now}, Opts) -> [{node_start, now_to_seconds(Now)}|Opts]; transform_options(Opt, Opts) -> [Opt|Opts]. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [db_type, iqdisc]. + +opt_type(node_start) -> + fun (S) when is_integer(S), S >= 0 -> S end; +opt_type(_) -> [node_start]. diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 0d9ed97500f..81d232be74d 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -50,9 +50,9 @@ import/3, can_use_nick/4]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1343,3 +1343,29 @@ import(_LServer, riak, [{'2i', [{<<"nick_host">>, {Nick, Host}}]}]); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_admin) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_create) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_persistent) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(default_room_options) -> + fun (L) when is_list(L) -> L end; +mod_opt_type(history_size) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(max_room_id) -> + fun (infinity) -> infinity; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(persist_history) -> fun (X) -> X end; +mod_opt_type(room_shaper) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(_) -> + [access, access_admin, access_create, access_persistent, + db_type, default_room_options, history_size, host, + max_room_id, persist_history, room_shaper]. diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 1f8efe241db..371b5e41514 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -11,24 +11,16 @@ -behaviour(gen_mod). --export([ - start/2, stop/1, % gen_mod API - muc_online_rooms/1, - muc_unregister_nick/1, - create_room/3, destroy_room/3, +-export([start/2, stop/1, muc_online_rooms/1, + muc_unregister_nick/1, create_room/3, destroy_room/3, create_rooms_file/1, destroy_rooms_file/1, rooms_unused_list/2, rooms_unused_destroy/2, - get_user_rooms/2, - get_room_occupants/2, - get_room_occupants_number/2, - send_direct_invitation/4, - change_room_option/4, - get_room_options/2, - set_room_affiliation/4, - get_room_affiliations/2, - web_menu_main/2, web_page_main/2, % Web Admin API - web_menu_host/3, web_page_host/3 - ]). + get_user_rooms/2, get_room_occupants/2, + get_room_occupants_number/2, send_direct_invitation/4, + change_room_option/4, get_room_options/2, + set_room_affiliation/4, get_room_affiliations/2, + web_menu_main/2, web_page_main/2, web_menu_host/3, + web_page_host/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -918,3 +910,5 @@ find_host(ServerHost) when is_list(ServerHost) -> find_host(list_to_binary(ServerHost)); find_host(ServerHost) -> gen_mod:get_module_opt_host(ServerHost, mod_muc, <<"conference.@HOST@">>). + +mod_opt_type(_) -> []. diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index d94151418db..14aef01e91c 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -25,6 +25,8 @@ -module(mod_muc_log). +-behaviour(ejabberd_config). + -author('badlop@process-one.net'). -behaviour(gen_server). @@ -35,9 +37,9 @@ -export([start_link/2, start/2, stop/1, transform_module_options/1, check_access_log/2, add_to_log/5]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1252,3 +1254,44 @@ calc_hour_offset(TimeHere) -> fjoin(FileList) -> list_to_binary(filename:join([binary_to_list(File) || File <- FileList])). + +mod_opt_type(access_log) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(cssfile) -> fun iolist_to_binary/1; +mod_opt_type(dirname) -> + fun (room_jid) -> room_jid; + (room_name) -> room_name + end; +mod_opt_type(dirtype) -> + fun (subdirs) -> subdirs; + (plain) -> plain + end; +mod_opt_type(file_format) -> + fun (html) -> html; + (plaintext) -> plaintext + end; +mod_opt_type(file_permissions) -> + fun (SubOpts) -> + F = fun ({mode, Mode}, {_M, G}) -> {Mode, G}; + ({group, Group}, {M, _G}) -> {M, Group} + end, + lists:foldl(F, {644, 33}, SubOpts) + end; +mod_opt_type(outdir) -> fun iolist_to_binary/1; +mod_opt_type(spam_prevention) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(timezone) -> + fun (local) -> local; + (universal) -> universal + end; +mod_opt_type(top_link) -> + fun ([{S1, S2}]) -> + {iolist_to_binary(S1), iolist_to_binary(S2)} + end; +mod_opt_type(_) -> + [access_log, cssfile, dirname, dirtype, file_format, + file_permissions, outdir, spam_prevention, timezone, + top_link]. + +opt_type(language) -> fun iolist_to_binary/1; +opt_type(_) -> [language]. diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index b6699d1039d..b39a391be4a 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -22,7 +22,7 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). --export([purge_loop/1]). +-export([purge_loop/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1162,3 +1162,10 @@ make_reply(forbidden, Lang, ErrText) -> stj(String) -> jlib:string_to_jid(String). jts(String) -> jlib:jid_to_string(String). + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(limits) -> + fun (A) when is_list(A) -> A end; +mod_opt_type(_) -> [access, host, limits]. diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 7c18a7f9873..280f39f6c4d 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -57,9 +57,9 @@ webadmin_user/4, webadmin_user_parse_query/5]). -%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, - handle_info/2, terminate/2, code_change/3]). + handle_info/2, terminate/2, code_change/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1140,3 +1140,11 @@ import(_LServer, riak, #offline_msg{us = US, timestamp = TS} = M) -> [{i, TS}, {'2i', [{<<"us">>, US}]}]); import(_, _, _) -> pass. + +mod_opt_type(access_max_user_messages) -> + fun (A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(store_empty_body) -> + fun (V) when is_boolean(V) -> V end; +mod_opt_type(_) -> + [access_max_user_messages, db_type, store_empty_body]. diff --git a/src/mod_ping.erl b/src/mod_ping.erl index 9ba9833ee9b..0b332edec3b 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -56,9 +56,8 @@ -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2, code_change/3]). -%% Hook callbacks -export([iq_ping/3, user_online/3, user_offline/3, - user_send/3]). + user_send/3, mod_opt_type/1]). -record(state, {host = <<"">>, @@ -246,3 +245,15 @@ cancel_timer(TRef) -> receive {timeout, TRef, _} -> ok after 0 -> ok end; _ -> ok end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(ping_interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(send_pings) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(timeout_action) -> + fun (none) -> none; + (kill) -> kill + end; +mod_opt_type(_) -> + [iqdisc, ping_interval, send_pings, timeout_action]. diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index e904ab95f4c..840c3aaea2c 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -27,7 +27,8 @@ -behavior(gen_mod). --export([start/2, stop/1, check_packet/6]). +-export([start/2, stop/1, check_packet/6, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -119,3 +120,9 @@ update(Server, JID, Dir) -> read(K) -> get({pres_counter, K}). write(K, V) -> put({pres_counter, K}, V). + +mod_opt_type(count) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(interval) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> [count, interval]. diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 35c3ed93b6f..81ea3dfcfe9 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -37,15 +37,14 @@ raw_to_item/1, is_list_needdb/1, updated_list/3, item_to_xml/1, get_user_lists/2, import/3]). -%% For mod_blocking -export([sql_add_privacy_list/2, sql_get_default_privacy_list/2, sql_get_default_privacy_list_t/1, sql_get_privacy_list_data/3, sql_get_privacy_list_data_by_id_t/1, sql_get_privacy_list_id_t/2, - sql_set_default_privacy_list/2, - sql_set_privacy_list/2, privacy_schema/0]). + sql_set_default_privacy_list/2, sql_set_privacy_list/2, + privacy_schema/0, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1257,3 +1256,7 @@ import(_LServer, riak, #privacy{} = P) -> ejabberd_riak:put(P, privacy_schema()); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [db_type, iqdisc]. diff --git a/src/mod_private.erl b/src/mod_private.erl index 09182ded626..56d4b493719 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -32,7 +32,8 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_sm_iq/3, import/3, - remove_user/2, get_data/2, export/1, import/1]). + remove_user/2, get_data/2, export/1, import/1, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -321,3 +322,7 @@ import(_LServer, riak, #private_storage{usns = {LUser, LServer, _}} = PS) -> [{'2i', [{<<"us">>, {LUser, LServer}}]}]); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [db_type, iqdisc]. diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl index effe2f784d6..621189db216 100644 --- a/src/mod_proxy65.erl +++ b/src/mod_proxy65.erl @@ -39,8 +39,7 @@ %% supervisor callbacks. -export([init/1]). -%% API. --export([start_link/2]). +-export([start_link/2, mod_opt_type/1]). -define(PROCNAME, ejabberd_mod_proxy65). @@ -84,3 +83,5 @@ init([Host, Opts]) -> {ok, {{one_for_one, 10, 1}, [StreamManager, StreamSupervisor, Service]}}. + +mod_opt_type(_) -> []. diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 1e7735c586c..32cd4443d49 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -33,9 +33,9 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% API. --export([start_link/2, add_listener/2, transform_module_options/1, - delete_listener/1]). +-export([start_link/2, add_listener/2, + transform_module_options/1, delete_listener/1, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -292,3 +292,19 @@ get_my_ip() -> {ok, Addr} -> Addr; {error, _} -> {127, 0, 0, 1} end. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(hostname) -> fun iolist_to_binary/1; +mod_opt_type(ip) -> + fun (S) -> + {ok, Addr} = + inet_parse:address(binary_to_list(iolist_to_binary(S))), + Addr + end; +mod_opt_type(name) -> fun iolist_to_binary/1; +mod_opt_type(port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +mod_opt_type(_) -> + [access, host, hostname, ip, name, port]. diff --git a/src/mod_proxy65_sm.erl b/src/mod_proxy65_sm.erl index 367f7f0bdda..895dd7d57dd 100644 --- a/src/mod_proxy65_sm.erl +++ b/src/mod_proxy65_sm.erl @@ -33,9 +33,9 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). -%% API. -export([start_link/2, register_stream/1, - unregister_stream/1, activate_stream/4]). + unregister_stream/1, activate_stream/4, + mod_opt_type/1]). -record(state, {max_connections = infinity :: non_neg_integer() | infinity}). @@ -171,3 +171,9 @@ activate_stream(SHA1, IJid, TJid, Host) {atomic, false} -> false; _ -> error end. + +mod_opt_type(max_connections) -> + fun (I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end; +mod_opt_type(_) -> [max_connections]. diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 663fbf72989..972faa76b60 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -37,9 +37,8 @@ wait_for_request/2, wait_for_activation/2, stream_established/2]). -%% API. -export([start/2, stop/1, start_link/3, activate/2, - relay/3, socket_type/0]). + relay/3, socket_type/0, mod_opt_type/1]). -include("mod_proxy65.hrl"). @@ -289,3 +288,15 @@ find_maxrate(Shaper, JID1, JID2, Host) -> if MaxRate1 == none; MaxRate2 == none -> none; true -> lists:max([MaxRate1, MaxRate2]) end. + +mod_opt_type(auth_type) -> + fun (plain) -> plain; + (anonymous) -> anonymous + end; +mod_opt_type(recbuf) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(shaper) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(sndbuf) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(_) -> [auth_type, recbuf, shaper, sndbuf]. diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 1f625cd5d6f..a5e90531caa 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -89,8 +89,7 @@ handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -%% calls for parallel sending of last items --export([send_loop/1]). +-export([send_loop/1, mod_opt_type/1]). -define(PROCNAME, ejabberd_mod_pubsub). -define(LOOPNAME, ejabberd_mod_pubsub_loop). @@ -4347,3 +4346,25 @@ purge_offline(Host, LJID, Node) -> Error -> Error end. + +mod_opt_type(access_createnode) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(ignore_pep_from_offline) -> + fun (A) when is_boolean(A) -> A end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(last_item_cache) -> + fun (A) when is_boolean(A) -> A end; +mod_opt_type(max_items_node) -> + fun (A) when is_integer(A) andalso A >= 0 -> A end; +mod_opt_type(nodetree) -> + fun (A) when is_binary(A) -> A end; +mod_opt_type(pep_mapping) -> + fun (A) when is_list(A) -> A end; +mod_opt_type(plugins) -> + fun (A) when is_list(A) -> A end; +mod_opt_type(_) -> + [access_createnode, db_type, host, + ignore_pep_from_offline, iqdisc, last_item_cache, + max_items_node, nodetree, pep_mapping, plugins]. diff --git a/src/mod_register.erl b/src/mod_register.erl index 1ed950146ef..bb2a8fbe97f 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -25,6 +25,8 @@ -module(mod_register). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -protocol({xep, 77, '2.4'}). @@ -34,7 +36,8 @@ -export([start/2, stop/1, stream_feature_register/2, unauthenticated_iq_register/4, try_register/5, process_iq/3, send_registration_notifications/3, - transform_options/1, transform_module_options/1]). + transform_options/1, transform_module_options/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -687,3 +690,37 @@ check_ip_access(undefined, _IPAccess) -> deny; check_ip_access(IPAddress, IPAccess) -> acl:match_rule(global, IPAccess, IPAddress). + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(access_from) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(captcha_protected) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(ip_access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(password_strength) -> + fun (N) when is_number(N), N >= 0 -> N end; +mod_opt_type(registration_watchers) -> + fun (Ss) -> + [#jid{} = jlib:string_to_jid(iolist_to_binary(S)) + || S <- Ss] + end; +mod_opt_type(welcome_message) -> + fun (Opts) -> + S = proplists:get_value(subject, Opts, <<>>), + B = proplists:get_value(body, Opts, <<>>), + {iolist_to_binary(S), iolist_to_binary(B)} + end; +mod_opt_type(_) -> + [access, access_from, captcha_protected, ip_access, + iqdisc, password_strength, registration_watchers, + welcome_message]. + +opt_type(registration_timeout) -> + fun (TO) when is_integer(TO), TO > 0 -> TO; + (infinity) -> infinity; + (unlimited) -> infinity + end; +opt_type(_) -> [registration_timeout]. diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index b9f799b41b9..32e06f142b3 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -55,7 +55,7 @@ -behaviour(gen_mod). --export([start/2, stop/1, process/2]). +-export([start/2, stop/1, process/2, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -574,3 +574,5 @@ get_error_text({error, passwords_not_identical}) -> <<"The passwords are different">>; get_error_text({error, wrong_parameters}) -> <<"Wrong parameters in the web formulary">>. + +mod_opt_type(_) -> []. diff --git a/src/mod_roster.erl b/src/mod_roster.erl index aa214b4216a..31fbeb1d26e 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -41,15 +41,16 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_iq/3, export/1, import/1, - process_local_iq/3, get_user_roster/2, import/3, - get_subscription_lists/3, get_roster/2, +-export([start/2, stop/1, process_iq/3, export/1, + import/1, process_local_iq/3, get_user_roster/2, + import/3, get_subscription_lists/3, get_roster/2, get_in_pending_subscriptions/3, in_subscription/6, out_subscription/4, set_items/3, remove_user/2, get_jid_info/4, item_to_xml/1, webadmin_page/3, webadmin_user/4, get_versioning_feature/2, roster_versioning_enabled/1, roster_version/2, - record_to_string/1, groups_to_string/1]). + record_to_string/1, groups_to_string/1, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1767,3 +1768,17 @@ import(_LServer, riak, #roster_version{} = RV) -> ejabberd_riak:put(RV, roster_version_schema()); import(_, _, _) -> pass. + +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(managers) -> + fun (B) when is_list(B) -> B end; +mod_opt_type(store_current_id) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(versioning) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [access, db_type, iqdisc, managers, store_current_id, + versioning]. diff --git a/src/mod_service_log.erl b/src/mod_service_log.erl index 7a23b40131a..e145c5ce6b0 100644 --- a/src/mod_service_log.erl +++ b/src/mod_service_log.erl @@ -29,10 +29,8 @@ -behaviour(gen_mod). --export([start/2, - stop/1, - log_user_send/3, - log_user_receive/4]). +-export([start/2, stop/1, log_user_send/3, + log_user_receive/4, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -95,3 +93,14 @@ log_packet(From, To, [FixedPacket]}) end, Loggers). + +mod_opt_type(loggers) -> + fun (L) -> + lists:map(fun (S) -> + B = iolist_to_binary(S), + N = jlib:nameprep(B), + if N /= error -> N end + end, + L) + end; +mod_opt_type(_) -> [loggers]. diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 4c3f177efa4..ac285bfd9c0 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -29,16 +29,17 @@ -behaviour(gen_mod). --export([start/2, stop/1, item_to_xml/1, export/1, import/1, - webadmin_menu/3, webadmin_page/3, get_user_roster/2, - get_subscription_lists/3, get_jid_info/4, import/3, - process_item/2, in_subscription/6, out_subscription/4, - user_available/1, unset_presence/4, register_user/2, - remove_user/2, list_groups/1, create_group/2, - create_group/3, delete_group/2, get_group_opts/2, - set_group_opts/3, get_group_users/2, - get_group_explicit_users/2, is_user_in_group/3, - add_user_to_group/3, remove_user_from_group/3]). +-export([start/2, stop/1, item_to_xml/1, export/1, + import/1, webadmin_menu/3, webadmin_page/3, + get_user_roster/2, get_subscription_lists/3, + get_jid_info/4, import/3, process_item/2, + in_subscription/6, out_subscription/4, user_available/1, + unset_presence/4, register_user/2, remove_user/2, + list_groups/1, create_group/2, create_group/3, + delete_group/2, get_group_opts/2, set_group_opts/3, + get_group_users/2, get_group_explicit_users/2, + is_user_in_group/3, add_user_to_group/3, + remove_user_from_group/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1506,3 +1507,6 @@ import(_LServer, riak, #sr_user{us = US, group_host = {Group, Host}} = User) -> {<<"group_host">>, {Group, Host}}]}]); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index a2d6f2fff5e..653c83ee254 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -26,6 +26,8 @@ %%%------------------------------------------------------------------- -module(mod_shared_roster_ldap). +-behaviour(ejabberd_config). + -behaviour(gen_server). -behaviour(gen_mod). @@ -39,7 +41,7 @@ -export([get_user_roster/2, get_subscription_lists/3, get_jid_info/4, process_item/2, in_subscription/6, - out_subscription/4]). + out_subscription/4, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -599,3 +601,99 @@ check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. + +mod_opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(ldap_password) -> fun iolist_to_binary/1; +mod_opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +mod_opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_tls_cacertfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_certfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(ldap_auth_check) -> + fun (on) -> true; + (off) -> false; + (false) -> false; + (true) -> true + end; +mod_opt_type(ldap_filter) -> fun check_filter/1; +mod_opt_type(ldap_gfilter) -> fun check_filter/1; +mod_opt_type(ldap_group_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_group_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_groupattr) -> fun iolist_to_binary/1; +mod_opt_type(ldap_groupdesc) -> fun iolist_to_binary/1; +mod_opt_type(ldap_memberattr) -> fun iolist_to_binary/1; +mod_opt_type(ldap_memberattr_format) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_memberattr_format_re) -> + fun (S) -> + Re = iolist_to_binary(S), {ok, MP} = re:compile(Re), MP + end; +mod_opt_type(ldap_rfilter) -> fun check_filter/1; +mod_opt_type(ldap_ufilter) -> fun check_filter/1; +mod_opt_type(ldap_user_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_user_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_userdesc) -> fun iolist_to_binary/1; +mod_opt_type(ldap_useruid) -> fun iolist_to_binary/1; +mod_opt_type(_) -> + [ldap_auth_check, ldap_filter, ldap_gfilter, + ldap_group_cache_size, ldap_group_cache_validity, + ldap_groupattr, ldap_groupdesc, ldap_memberattr, + ldap_memberattr_format, ldap_memberattr_format_re, + ldap_rfilter, ldap_ufilter, ldap_user_cache_size, + ldap_user_cache_validity, ldap_userdesc, ldap_useruid, + deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. + +opt_type(ldap_filter) -> fun check_filter/1; +opt_type(ldap_gfilter) -> fun check_filter/1; +opt_type(ldap_group_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_group_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_rfilter) -> fun check_filter/1; +opt_type(ldap_ufilter) -> fun check_filter/1; +opt_type(ldap_user_cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(ldap_user_cache_validity) -> + fun (I) when is_integer(I), I > 0 -> I end; +opt_type(_) -> + [ldap_filter, ldap_gfilter, ldap_group_cache_size, + ldap_group_cache_validity, ldap_rfilter, ldap_ufilter, + ldap_user_cache_size, ldap_user_cache_validity]. diff --git a/src/mod_sic.erl b/src/mod_sic.erl index 273930ff04d..3f5bf0dab08 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -32,7 +32,7 @@ -behaviour(gen_mod). -export([start/2, stop/1, process_local_iq/3, - process_sm_iq/3]). + process_sm_iq/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -91,3 +91,6 @@ get_ip({User, Server, Resource}, IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 8790cdfc047..7e7d2f30739 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -32,9 +32,9 @@ %% API -export([start/2, stop/1, make_response/2, is_my_host/1, at_my_host/1]). -%% esip_callbacks --export([data_in/2, data_out/2, message_in/2, message_out/2, - request/2, request/3, response/2, locate/1]). +-export([data_in/2, data_out/2, message_in/2, + message_out/2, request/2, request/3, response/2, + locate/1, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -299,3 +299,44 @@ at_my_host(#uri{host = Host}) -> is_my_host(LServer) -> gen_mod:is_loaded(LServer, ?MODULE). + +mod_opt_type(always_record_route) -> + fun (true) -> true; + (false) -> false + end; +mod_opt_type(flow_timeout_tcp) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(flow_timeout_udp) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(record_route) -> + fun (IOList) -> + S = iolist_to_binary(IOList), + #uri{} = esip:decode_uri(S) + end; +mod_opt_type(routes) -> + fun (L) -> + lists:map(fun (IOList) -> + S = iolist_to_binary(IOList), + #uri{} = esip:decode_uri(S) + end, + L) + end; +mod_opt_type(via) -> + fun (L) -> + lists:map(fun (Opts) -> + Type = proplists:get_value(type, Opts), + Host = proplists:get_value(host, Opts), + Port = proplists:get_value(port, Opts), + true = (Type == tcp) or (Type == tls) or + (Type == udp), + true = is_binary(Host) and (Host /= <<"">>), + true = is_integer(Port) and (Port > 0) and + (Port < 65536) + or (Port == undefined), + {Type, {Host, Port}} + end, + L) + end; +mod_opt_type(_) -> + [always_record_route, flow_timeout_tcp, + flow_timeout_udp, record_route, routes, via]. diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index 6168d997c27..1dcf264ede6 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -25,16 +25,18 @@ %%%------------------------------------------------------------------- -module(mod_sip_proxy). +-behaviour(ejabberd_config). + -define(GEN_FSM, p1_fsm). -behaviour(?GEN_FSM). %% API -export([start/2, start_link/2, route/3, route/4]). -%% gen_fsm callbacks --export([init/1, wait_for_request/2, wait_for_response/2, - handle_event/3, handle_sync_event/4, - handle_info/3, terminate/3, code_change/4]). +-export([init/1, wait_for_request/2, + wait_for_response/2, handle_event/3, + handle_sync_event/4, handle_info/3, terminate/3, + code_change/4, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -456,3 +458,7 @@ safe_nameprep(S) -> error -> S; S1 -> S1 end. + +opt_type(domain_certfile) -> fun iolist_to_binary/1; +opt_type(shared_key) -> fun (V) -> V end; +opt_type(_) -> [domain_certfile, shared_key]. diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 4896a3c18b2..ce97dbdf09b 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -31,7 +31,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -265,3 +266,6 @@ search_running_node(SNode, [Node | Nodes]) -> SNode -> Node; _ -> search_running_node(SNode, Nodes) end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_time.erl b/src/mod_time.erl index 111428070ca..e1146840093 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -32,7 +32,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -84,3 +85,6 @@ process_local_iq(_From, _To, sign(N) when N < 0 -> <<"-">>; sign(_) -> <<"+">>. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(_) -> [iqdisc]. diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 2c700af2f4c..306bd84458e 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -34,7 +34,8 @@ -export([start/2, init/3, stop/1, get_sm_features/5, process_local_iq/3, process_sm_iq/3, reindex_vcards/0, - remove_user/2, export/1, import/1, import/3]). + remove_user/2, export/1, import/1, import/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1162,3 +1163,20 @@ import(_LServer, riak, #vcard_search{}) -> ok; import(_, _, _) -> pass. + +mod_opt_type(allow_return_all) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(matches) -> + fun (infinity) -> infinity; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(search) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(search_all_hosts) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [allow_return_all, db_type, host, iqdisc, matches, + search, search_all_hosts]. diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index a5cafc5e54a..f75bb07124f 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -25,6 +25,8 @@ -module(mod_vcard_ldap). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). -behaviour(gen_server). @@ -37,7 +39,8 @@ -export([start/2, start_link/2, stop/1, get_sm_features/5, process_local_iq/3, process_sm_iq/3, - remove_user/1, route/4, transform_module_options/1]). + remove_user/1, route/4, transform_module_options/1, + mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -840,3 +843,100 @@ check_filter(F) -> NewF = iolist_to_binary(F), {ok, _} = eldap_filter:parse(NewF), NewF. + +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(ldap_filter) -> fun check_filter/1; +mod_opt_type(ldap_search_fields) -> + fun (Ls) -> + [{iolist_to_binary(S), iolist_to_binary(P)} + || {S, P} <- Ls] + end; +mod_opt_type(ldap_search_reported) -> + fun (Ls) -> + [{iolist_to_binary(S), iolist_to_binary(P)} + || {S, P} <- Ls] + end; +mod_opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)} + end, + Us) + end; +mod_opt_type(ldap_vcard_map) -> + fun (Ls) -> + lists:map(fun ({S, [{P, L}]}) -> + {iolist_to_binary(S), iolist_to_binary(P), + [iolist_to_binary(E) || E <- L]} + end, + Ls) + end; +mod_opt_type(matches) -> + fun (infinity) -> 0; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(search) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_backups) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_deref_aliases) -> + fun (never) -> never; + (searching) -> searching; + (finding) -> finding; + (always) -> always + end; +mod_opt_type(ldap_encrypt) -> + fun (tls) -> tls; + (starttls) -> starttls; + (none) -> none + end; +mod_opt_type(ldap_password) -> fun iolist_to_binary/1; +mod_opt_type(ldap_port) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; +mod_opt_type(ldap_servers) -> + fun (L) -> [iolist_to_binary(H) || H <- L] end; +mod_opt_type(ldap_tls_cacertfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_certfile) -> + fun iolist_to_binary/1; +mod_opt_type(ldap_tls_depth) -> + fun (I) when is_integer(I), I >= 0 -> I end; +mod_opt_type(ldap_tls_verify) -> + fun (hard) -> hard; + (soft) -> soft; + (false) -> false + end; +mod_opt_type(_) -> + [host, iqdisc, ldap_filter, ldap_search_fields, + ldap_search_reported, ldap_uids, ldap_vcard_map, + matches, search, deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. + +opt_type(ldap_filter) -> fun check_filter/1; +opt_type(ldap_uids) -> + fun (Us) -> + lists:map(fun ({U, P}) -> + {iolist_to_binary(U), iolist_to_binary(P)}; + ({U}) -> {iolist_to_binary(U)} + end, + Us) + end; +opt_type(_) -> + [ldap_filter, ldap_uids, deref_aliases, ldap_backups, ldap_base, + ldap_deref_aliases, ldap_encrypt, ldap_password, + ldap_port, ldap_rootdn, ldap_servers, + ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, + ldap_tls_verify]. diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 41a07bbc3db..96ee09d8730 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -12,8 +12,8 @@ %% gen_mod callbacks -export([start/2, stop/1]). -%% hooks --export([update_presence/3, vcard_set/3, export/1, import/1, import/3]). +-export([update_presence/3, vcard_set/3, export/1, + import/1, import/3, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -231,3 +231,6 @@ import(_LServer, riak, #vcard_xupdate{} = R) -> ejabberd_riak:put(R, vcard_xupdate_schema()); import(_, _, _) -> pass. + +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(_) -> [db_type]. diff --git a/src/mod_version.erl b/src/mod_version.erl index 669a401d42e..55609d1ea04 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -31,7 +31,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, process_local_iq/3]). +-export([start/2, stop/1, process_local_iq/3, + mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -90,3 +91,8 @@ get_os() -> OS = <>, #xmlel{name = <<"os">>, attrs = [], children = [{xmlcdata, OS}]}. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(show_os) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> [iqdisc, show_os]. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 7dee1a047e2..6d76610af87 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -25,41 +25,38 @@ -module(odbc_queries). +-behaviour(ejabberd_config). + -author("mremond@process-one.net"). --export([get_db_type/0, update/5, update_t/4, sql_transaction/2, - get_last/2, set_last_t/4, del_last/2, - get_password/2, get_password_scram/2, - set_password_t/3, set_password_scram_t/6, - add_user/3, add_user_scram/6, del_user/2, - del_user_return_password/3, list_users/1, list_users/2, - users_number/1, users_number/2, add_spool_sql/2, - add_spool/2, get_and_del_spool_msg_t/2, del_spool_msg/2, - get_roster/2, get_roster_jid_groups/2, +-export([get_db_type/0, update/5, update_t/4, + sql_transaction/2, get_last/2, set_last_t/4, del_last/2, + get_password/2, get_password_scram/2, set_password_t/3, + set_password_scram_t/6, add_user/3, add_user_scram/6, + del_user/2, del_user_return_password/3, list_users/1, + list_users/2, users_number/1, users_number/2, + add_spool_sql/2, add_spool/2, get_and_del_spool_msg_t/2, + del_spool_msg/2, get_roster/2, get_roster_jid_groups/2, get_roster_groups/3, del_user_roster_t/2, get_roster_by_jid/3, get_rostergroup_by_jid/3, del_roster/3, del_roster_sql/2, update_roster/5, update_roster_sql/4, roster_subscribe/4, get_subscription/3, set_private_data/4, - set_private_data_sql/3, get_private_data/3, get_private_data/2, - del_user_private_storage/2, get_default_privacy_list/2, + set_private_data_sql/3, get_private_data/3, + get_private_data/2, del_user_private_storage/2, + get_default_privacy_list/2, get_default_privacy_list_t/1, get_privacy_list_names/2, get_privacy_list_names_t/1, get_privacy_list_id/3, get_privacy_list_id_t/2, get_privacy_list_data/3, - get_privacy_list_data_by_id/2, get_privacy_list_data_t/2, + get_privacy_list_data_by_id/2, + get_privacy_list_data_t/2, get_privacy_list_data_by_id_t/1, set_default_privacy_list/2, - unset_default_privacy_list/2, - remove_privacy_list/2, - add_privacy_list/2, - set_privacy_list/2, - del_privacy_lists/3, - set_vcard/26, - get_vcard/2, - escape/1, - count_records_where/3, - get_roster_version/2, - set_roster_version/2]). + unset_default_privacy_list/2, remove_privacy_list/2, + add_privacy_list/2, set_privacy_list/2, + del_privacy_lists/3, set_vcard/26, get_vcard/2, + escape/1, count_records_where/3, get_roster_version/2, + set_roster_version/2, opt_type/1]). %% We have only two compile time options for db queries: %-define(generic, true). @@ -990,3 +987,13 @@ set_roster_version(Username, Version) -> <<"', '">>, Version, <<"'">>]). -endif. + +opt_type(odbc_type) -> + fun (pgsql) -> pgsql; + (mysql) -> mysql; + (sqlite) -> sqlite; + (odbc) -> odbc + end; +opt_type(pgsql_users_number_estimate) -> + fun (V) when is_boolean(V) -> V end; +opt_type(_) -> [odbc_type, pgsql_users_number_estimate]. diff --git a/src/shaper.erl b/src/shaper.erl index a85c4f11187..c8140703c35 100644 --- a/src/shaper.erl +++ b/src/shaper.erl @@ -25,10 +25,13 @@ -module(shaper). +-behaviour(ejabberd_config). + -author('alexey@process-one.net'). --export([start/0, new/1, new1/1, update/2, get_max_rate/1, - transform_options/1, load_from_config/0]). +-export([start/0, new/1, new1/1, update/2, + get_max_rate/1, transform_options/1, load_from_config/0, + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -140,3 +143,6 @@ transform_options(Opt, Opts) -> now_to_usec({MSec, Sec, USec}) -> (MSec * 1000000 + Sec) * 1000000 + USec. + +opt_type(shaper) -> fun (V) -> V end; +opt_type(_) -> [shaper]. From 4ed6a3d78f40f03d55045a6dd3f0c4c9b688e1b5 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 2 Jun 2015 12:52:15 +0200 Subject: [PATCH 105/695] Fix commands export2odbc, connected_users_vhost and push_alltoall (#586) --- src/ejabberd_admin.erl | 20 +------------------- src/ejd2odbc.erl | 2 +- src/mod_admin_extra.erl | 30 +++--------------------------- 3 files changed, 5 insertions(+), 47 deletions(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 8b6e27b8285..89421d99622 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -42,7 +42,6 @@ %% Purge DB delete_expired_messages/0, delete_old_messages/1, %% Mnesia - export2odbc/2, set_master/1, backup_mnesia/1, restore_mnesia/1, dump_mnesia/1, dump_table/2, load_mnesia/1, @@ -191,7 +190,7 @@ commands() -> #ejabberd_commands{name = export2odbc, tags = [mnesia], desc = "Export virtual host information from Mnesia tables to SQL files", - module = ?MODULE, function = export2odbc, + module = ejd2odbc, function = export, args = [{host, string}, {directory, string}], result = {res, rescode}}, #ejabberd_commands{name = set_master, tags = [mnesia], @@ -408,23 +407,6 @@ delete_old_messages(Days) -> %%% Mnesia management %%% -export2odbc(Host, Directory) -> - Tables = [{export_last, last}, - {export_offline, offline}, - {export_private_storage, private_storage}, - {export_roster, roster}, - {export_vcard, vcard}, - {export_vcard_search, vcard_search}, - {export_passwd, passwd}], - Export = fun({TableFun, Table}) -> - Filename = filename:join([Directory, atom_to_list(Table)++".txt"]), - io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]), - Res = (catch ejd2odbc:TableFun(Host, Filename)), - io:format(" Result: ~p~n", [Res]) - end, - lists:foreach(Export, Tables), - ok. - set_master("self") -> set_master(node()); set_master(NodeString) when is_list(NodeString) -> diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index cc6241925e2..81c4b0fded4 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -55,7 +55,7 @@ modules() -> mod_offline, mod_privacy, mod_private, - mod_pubsub, + %% mod_pubsub, mod_roster, mod_shared_roster, mod_vcard, diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 0cb763bd99c..6fbf762eb73 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -31,7 +31,7 @@ -include("logger.hrl"). -export([start/2, stop/1, compile/1, get_cookie/0, - remove_node/1, export2odbc/2, set_password/3, + remove_node/1, set_password/3, check_password_hash/4, delete_old_users/1, delete_old_users_vhost/2, ban_account/3, num_active_users/2, num_resources/2, resource_num/3, @@ -112,11 +112,6 @@ commands() -> module = ?MODULE, function = remove_node, args = [{node, string}], result = {res, rescode}}, - #ejabberd_commands{name = export2odbc, tags = [mnesia], %% Copied to ejabberd 2.1.x after 11 - desc = "Export Mnesia tables to files in directory", - module = ?MODULE, function = export2odbc, - args = [{host, string}, {path, string}], - result = {res, rescode}}, #ejabberd_commands{name = num_active_users, tags = [accounts, stats], desc = "Get number of users active in the last days", @@ -233,7 +228,7 @@ commands() -> tags = [session], desc = "Get the list of established sessions in a vhost", module = ?MODULE, function = connected_users_vhost, - args = [{host, string}], + args = [{host, binary}], result = {connected_users_vhost, {list, {sessions, string}}}}, #ejabberd_commands{name = user_sessions_info, tags = [session], @@ -388,7 +383,7 @@ commands() -> #ejabberd_commands{name = push_alltoall, tags = [roster], desc = "Add all the users to all the users of Host in Group", module = ?MODULE, function = push_alltoall, - args = [{host, string}, {group, string}], + args = [{host, binary}, {group, binary}], result = {res, rescode}}, #ejabberd_commands{name = get_last, tags = [last], @@ -505,25 +500,6 @@ remove_node(Node) -> mnesia:del_table_copy(schema, list_to_atom(Node)), ok. -export2odbc(Host, Directory) -> - Tables = [ - {export_last, last}, - {export_offline, offline}, - {export_passwd, passwd}, - {export_private_storage, private_storage}, - {export_roster, roster}, - {export_vcard, vcard}, - {export_vcard_search, vcard_search}], - Export = fun({TableFun, Table}) -> - Filename = filename:join([Directory, atom_to_list(Table)++".txt"]), - io:format("Trying to export Mnesia table '~p' on Host '~s' to file '~s'~n", [Table, Host, Filename]), - Res = (catch ejd2odbc:TableFun(Host, Filename)), - io:format(" Result: ~p~n", [Res]) - end, - lists:foreach(Export, Tables), - ok. - - %%% %%% Accounts %%% From 83faff37e555cf2bdf8f57c1c07e8c2d9d6ea9e6 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 3 Jun 2015 15:18:09 +0300 Subject: [PATCH 106/695] Add missing options of mod_muc to validator --- src/mod_muc.erl | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 81d232be74d..6226ca3b220 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -1358,14 +1358,41 @@ mod_opt_type(default_room_options) -> mod_opt_type(history_size) -> fun (I) when is_integer(I), I >= 0 -> I end; mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(max_room_desc) -> + fun (infinity) -> infinity; + (I) when is_integer(I), I > 0 -> I + end; mod_opt_type(max_room_id) -> fun (infinity) -> infinity; (I) when is_integer(I), I > 0 -> I end; -mod_opt_type(persist_history) -> fun (X) -> X end; +mod_opt_type(max_room_name) -> + fun (infinity) -> infinity; + (I) when is_integer(I), I > 0 -> I + end; +mod_opt_type(max_user_conferences) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(max_users) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(max_users_admin_threshold) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(max_users_presence) -> + fun (MUP) when is_integer(MUP) -> MUP end; +mod_opt_type(min_message_interval) -> + fun (MMI) when is_number(MMI) -> MMI end; +mod_opt_type(min_presence_interval) -> + fun (I) when is_number(I), I >= 0 -> I end; mod_opt_type(room_shaper) -> fun (A) when is_atom(A) -> A end; +mod_opt_type(user_message_shaper) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(user_presence_shaper) -> + fun (A) when is_atom(A) -> A end; mod_opt_type(_) -> [access, access_admin, access_create, access_persistent, db_type, default_room_options, history_size, host, - max_room_id, persist_history, room_shaper]. + max_room_desc, max_room_id, max_room_name, + max_user_conferences, max_users, + max_users_admin_threshold, max_users_presence, + min_message_interval, min_presence_interval, + room_shaper, user_message_shaper, user_presence_shaper]. From 0ae9ef2b416e8b8ded0c6631a53d2e268df124d2 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 3 Jun 2015 15:25:20 +0300 Subject: [PATCH 107/695] Add missing options of ejabberd_logger to validator --- src/ejabberd_logger.erl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index a00ac9942a3..067f80f2845 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -25,8 +25,10 @@ %%%------------------------------------------------------------------- -module(ejabberd_logger). +-behaviour(ejabberd_config). + %% API --export([start/0, reopen_log/0, get/0, set/1, get_log_path/0]). +-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0, opt_type/1]. -include("ejabberd.hrl"). @@ -184,6 +186,17 @@ get() -> set(LogLevel) -> p1_loglevel:set(LogLevel). +opt_type(log_rotate_date) -> + fun(S) -> binary_to_list(iolist_to_binary(S)) end; +opt_type(log_rotate_size) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(log_rotate_count) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(log_rate_limit) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(_) -> + [log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit]. + %%%=================================================================== %%% Internal functions %%%=================================================================== From 730fd55ec9a07735186f1bd852fc80974076ece4 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 3 Jun 2015 15:45:15 +0300 Subject: [PATCH 108/695] Fix typo --- src/ejabberd_logger.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 067f80f2845..8c13be07fce 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -28,7 +28,7 @@ -behaviour(ejabberd_config). %% API --export([start/0, reopen_log/0, get/0, set/1, get_log_path/0, opt_type/1]. +-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0, opt_type/1]). -include("ejabberd.hrl"). From ab196b4b02ac2cbe7114ecb466cc10aea55bc112 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 3 Jun 2015 15:52:19 +0300 Subject: [PATCH 109/695] Move opt_type/1 function out of if-else block --- src/ejabberd_logger.erl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 8c13be07fce..3bfe37c80aa 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -63,6 +63,17 @@ get_log_path() -> end end. +opt_type(log_rotate_date) -> + fun(S) -> binary_to_list(iolist_to_binary(S)) end; +opt_type(log_rotate_size) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(log_rotate_count) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(log_rate_limit) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(_) -> + [log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit]. + -ifdef(LAGER). get_integer_env(Name, Default) -> @@ -186,17 +197,6 @@ get() -> set(LogLevel) -> p1_loglevel:set(LogLevel). -opt_type(log_rotate_date) -> - fun(S) -> binary_to_list(iolist_to_binary(S)) end; -opt_type(log_rotate_size) -> - fun(I) when is_integer(I), I >= 0 -> I end; -opt_type(log_rotate_count) -> - fun(I) when is_integer(I), I >= 0 -> I end; -opt_type(log_rate_limit) -> - fun(I) when is_integer(I), I >= 0 -> I end; -opt_type(_) -> - [log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit]. - %%%=================================================================== %%% Internal functions %%%=================================================================== From c1119b1f3945a37f656934ef530f8c7bf158530f Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 3 Jun 2015 16:05:17 +0300 Subject: [PATCH 110/695] Remove unused validation code --- src/ejabberd_auth_ldap.erl | 67 +------------------------------------ src/ejabberd_http.erl | 10 +----- src/ejabberd_riak_sup.erl | 5 +-- src/ejabberd_service.erl | 6 +--- src/ejabberd_stun.erl | 11 +----- src/ejabberd_xmlrpc.erl | 13 +------ src/ejd2odbc.erl | 5 +-- src/eldap.erl | 23 +------------ src/mod_proxy65.erl | 32 +++++++++++++++++- src/mod_proxy65_service.erl | 19 +---------- src/mod_proxy65_sm.erl | 9 +---- src/mod_proxy65_stream.erl | 14 +------- 12 files changed, 42 insertions(+), 172 deletions(-) diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index f2122805aea..4fdb87b2079 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -44,7 +44,7 @@ get_vh_registered_users_number/2, get_password/2, get_password_s/2, is_user_exists/2, remove_user/2, remove_user/3, store_type/0, plain_password_required/0, - mod_opt_type/1, opt_type/1]). + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -420,71 +420,6 @@ check_filter(F) -> {ok, _} = eldap_filter:parse(NewF), NewF. -mod_opt_type(deref_aliases) -> - fun (never) -> never; - (searching) -> searching; - (finding) -> finding; - (always) -> always - end; -mod_opt_type(ldap_backups) -> - fun (L) -> [iolist_to_binary(H) || H <- L] end; -mod_opt_type(ldap_base) -> fun iolist_to_binary/1; -mod_opt_type(ldap_deref_aliases) -> - fun (never) -> never; - (searching) -> searching; - (finding) -> finding; - (always) -> always - end; -mod_opt_type(ldap_encrypt) -> - fun (tls) -> tls; - (starttls) -> starttls; - (none) -> none - end; -mod_opt_type(ldap_password) -> fun iolist_to_binary/1; -mod_opt_type(ldap_port) -> - fun (I) when is_integer(I), I > 0 -> I end; -mod_opt_type(ldap_rootdn) -> fun iolist_to_binary/1; -mod_opt_type(ldap_servers) -> - fun (L) -> [iolist_to_binary(H) || H <- L] end; -mod_opt_type(ldap_tls_cacertfile) -> - fun iolist_to_binary/1; -mod_opt_type(ldap_tls_certfile) -> - fun iolist_to_binary/1; -mod_opt_type(ldap_tls_depth) -> - fun (I) when is_integer(I), I >= 0 -> I end; -mod_opt_type(ldap_tls_verify) -> - fun (hard) -> hard; - (soft) -> soft; - (false) -> false - end; -mod_opt_type(ldap_dn_filter) -> - fun ([{DNF, DNFA}]) -> - NewDNFA = case DNFA of - undefined -> []; - _ -> [iolist_to_binary(A) || A <- DNFA] - end, - NewDNF = check_filter(DNF), - {NewDNF, NewDNFA} - end; -mod_opt_type(ldap_filter) -> fun check_filter/1; -mod_opt_type(ldap_local_filter) -> fun (V) -> V end; -mod_opt_type(ldap_uids) -> - fun (Us) -> - lists:map(fun ({U, P}) -> - {iolist_to_binary(U), iolist_to_binary(P)}; - ({U}) -> {iolist_to_binary(U)}; - (U) -> {iolist_to_binary(U)} - end, - lists:flatten(Us)) - end; -mod_opt_type(_) -> - [ldap_dn_filter, ldap_filter, ldap_local_filter, - ldap_uids, deref_aliases, ldap_backups, ldap_base, - ldap_deref_aliases, ldap_encrypt, ldap_password, - ldap_port, ldap_rootdn, ldap_servers, - ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, - ldap_tls_verify]. - opt_type(ldap_dn_filter) -> fun ([{DNF, DNFA}]) -> NewDNFA = case DNFA of diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index b4de38c02ee..5f98063bbd6 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -34,7 +34,7 @@ socket_type/0, receive_headers/1, url_encode/1, transform_listen_option/2]). --export([init/2, mod_opt_type/1, opt_type/1]). +-export([init/2, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -872,14 +872,6 @@ transform_listen_option({request_handlers, Hs}, Opts) -> transform_listen_option(Opt, Opts) -> [Opt|Opts]. -mod_opt_type(default_host) -> fun (A) -> A end; -mod_opt_type(request_handlers) -> - fun (Hs) -> - [{str:tokens(iolist_to_binary(Path), <<"/">>), Mod} - || {Path, Mod} <- Hs] - end; -mod_opt_type(_) -> [default_host, request_handlers]. - opt_type(trusted_proxies) -> fun (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end; opt_type(_) -> [trusted_proxies]. diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index 8b6a8064ddb..a971a4a3276 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -30,7 +30,7 @@ -export([start/0, start_link/0, init/1, get_pids/0, transform_options/1, get_random_pid/0, get_random_pid/1, - mod_opt_type/1, opt_type/1]). + opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -155,9 +155,6 @@ transform_options({riak_server, {S, P}}, Opts) -> transform_options(Opt, Opts) -> [Opt|Opts]. -mod_opt_type(db_type) -> fun gen_mod:v_db/1; -mod_opt_type(_) -> [db_type]. - opt_type(modules) -> fun (L) when is_list(L) -> L end; opt_type(riak_pool_size) -> fun (N) when is_integer(N), N >= 1 -> N end; diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 3e283a0a211..febede8d97e 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -42,8 +42,7 @@ -export([init/1, wait_for_stream/2, wait_for_handshake/2, stream_established/2, handle_event/3, handle_sync_event/4, code_change/4, - handle_info/3, terminate/3, print_state/1, - mod_opt_type/1, opt_type/1]). + handle_info/3, terminate/3, print_state/1, opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -407,9 +406,6 @@ fsm_limit_opts(Opts) -> end end. -mod_opt_type(password) -> fun iolist_to_binary/1; -mod_opt_type(_) -> [password]. - opt_type(max_fsm_queue) -> fun (I) when is_integer(I), I > 0 -> I end; opt_type(_) -> [max_fsm_queue]. diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index 3d5ab6bd71c..a69b731c5f2 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -28,7 +28,7 @@ -protocol({rfc, 5766}). -export([tcp_init/2, udp_init/2, udp_recv/5, start/2, - socket_type/0, mod_opt_type/1]). + socket_type/0]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -100,12 +100,3 @@ prepare_turn_opts(Opts, _UseTurn = true) -> MaxRate = shaper:get_max_rate(Shaper), Realm ++ [{auth_fun, AuthFun},{shaper, MaxRate} | lists:keydelete(shaper, 1, Opts)]. - -mod_opt_type(auth_realm) -> fun iolist_to_binary/1; -mod_opt_type(auth_type) -> - fun (anonymous) -> anonymous; - (user) -> user - end; -mod_opt_type(shaper) -> - fun (S) when is_atom(S) -> S end; -mod_opt_type(_) -> [auth_realm, auth_type, shaper]. diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 0a74fd47b69..c852114506d 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -36,7 +36,7 @@ -author('badlop@process-one.net'). -export([start/2, handler/2, process/2, socket_type/0, - transform_listen_option/2, mod_opt_type/1]). + transform_listen_option/2]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -541,14 +541,3 @@ transform_listen_option({access_commands, ACOpts}, Opts) -> [{access_commands, NewACOpts}|Opts]; transform_listen_option(Opt, Opts) -> [Opt|Opts]. - -mod_opt_type(access_commands) -> - fun (L) when is_list(L) -> L end; -mod_opt_type(commands) -> - fun (A) when is_atom(A) -> A; - (L) when is_list(L) -> - true = lists:all(fun is_atom/1, L), L - end; -mod_opt_type(options) -> - fun (L) when is_list(L) -> L end; -mod_opt_type(_) -> [access_commands, commands, options]. diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index 81c4b0fded4..8e83fb5b0b3 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -30,7 +30,7 @@ -include("logger.hrl"). -export([export/2, export/3, import_file/2, import/2, - import/3, mod_opt_type/1]). + import/3]). -define(MAX_RECORDS_PER_TRANSACTION, 100). @@ -280,6 +280,3 @@ flatten1([H|T], Acc) -> flatten1(T, [[H, $\n]|Acc]); flatten1([], Acc) -> Acc. - -mod_opt_type(db_type) -> fun gen_mod:v_db/1; -mod_opt_type(_) -> [db_type]. diff --git a/src/eldap.erl b/src/eldap.erl index f8f6d04a99e..20a5b6139b3 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -83,7 +83,7 @@ -export([init/1, connecting/2, connecting/3, wait_bind_response/3, active/3, active_bind/3, handle_event/3, handle_sync_event/4, handle_info/3, - terminate/3, code_change/4, mod_opt_type/1]). + terminate/3, code_change/4]). -export_type([filter/0]). @@ -1193,24 +1193,3 @@ bump_id(#eldap{id = Id}) when Id > (?MAX_TRANSACTION_ID) -> ?MIN_TRANSACTION_ID; bump_id(#eldap{id = Id}) -> Id + 1. - -mod_opt_type(encrypt) -> - fun (tls) -> tls; - (starttls) -> starttls; - (none) -> none - end; -mod_opt_type(tls_cacertfile) -> - fun (S) when is_binary(S) -> binary_to_list(S); - (undefined) -> undefined - end; -mod_opt_type(tls_depth) -> - fun (I) when is_integer(I), I >= 0 -> I; - (undefined) -> undefined - end; -mod_opt_type(tls_verify) -> - fun (hard) -> hard; - (soft) -> soft; - (false) -> false - end; -mod_opt_type(_) -> - [encrypt, tls_cacertfile, tls_depth, tls_verify]. diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl index 621189db216..8d58c891868 100644 --- a/src/mod_proxy65.erl +++ b/src/mod_proxy65.erl @@ -84,4 +84,34 @@ init([Host, Opts]) -> {{one_for_one, 10, 1}, [StreamManager, StreamSupervisor, Service]}}. -mod_opt_type(_) -> []. +mod_opt_type(auth_type) -> + fun (plain) -> plain; + (anonymous) -> anonymous + end; +mod_opt_type(recbuf) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(shaper) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(sndbuf) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(access) -> + fun (A) when is_atom(A) -> A end; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(hostname) -> fun iolist_to_binary/1; +mod_opt_type(ip) -> + fun (S) -> + {ok, Addr} = + inet_parse:address(binary_to_list(iolist_to_binary(S))), + Addr + end; +mod_opt_type(name) -> fun iolist_to_binary/1; +mod_opt_type(port) -> + fun (P) when is_integer(P), P > 0, P < 65536 -> P end; +mod_opt_type(max_connections) -> + fun (I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end; +mod_opt_type(_) -> + [auth_type, recbuf, shaper, sndbuf, + access, host, hostname, ip, name, port, + max_connections]. diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 32cd4443d49..3c360942a4a 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -34,8 +34,7 @@ handle_cast/2, terminate/2, code_change/3]). -export([start_link/2, add_listener/2, - transform_module_options/1, delete_listener/1, - mod_opt_type/1]). + transform_module_options/1, delete_listener/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -292,19 +291,3 @@ get_my_ip() -> {ok, Addr} -> Addr; {error, _} -> {127, 0, 0, 1} end. - -mod_opt_type(access) -> - fun (A) when is_atom(A) -> A end; -mod_opt_type(host) -> fun iolist_to_binary/1; -mod_opt_type(hostname) -> fun iolist_to_binary/1; -mod_opt_type(ip) -> - fun (S) -> - {ok, Addr} = - inet_parse:address(binary_to_list(iolist_to_binary(S))), - Addr - end; -mod_opt_type(name) -> fun iolist_to_binary/1; -mod_opt_type(port) -> - fun (P) when is_integer(P), P > 0, P < 65536 -> P end; -mod_opt_type(_) -> - [access, host, hostname, ip, name, port]. diff --git a/src/mod_proxy65_sm.erl b/src/mod_proxy65_sm.erl index 895dd7d57dd..ce997154e91 100644 --- a/src/mod_proxy65_sm.erl +++ b/src/mod_proxy65_sm.erl @@ -34,8 +34,7 @@ handle_cast/2, terminate/2, code_change/3]). -export([start_link/2, register_stream/1, - unregister_stream/1, activate_stream/4, - mod_opt_type/1]). + unregister_stream/1, activate_stream/4]). -record(state, {max_connections = infinity :: non_neg_integer() | infinity}). @@ -171,9 +170,3 @@ activate_stream(SHA1, IJid, TJid, Host) {atomic, false} -> false; _ -> error end. - -mod_opt_type(max_connections) -> - fun (I) when is_integer(I), I > 0 -> I; - (infinity) -> infinity - end; -mod_opt_type(_) -> [max_connections]. diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 972faa76b60..722a782c56b 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -38,7 +38,7 @@ stream_established/2]). -export([start/2, stop/1, start_link/3, activate/2, - relay/3, socket_type/0, mod_opt_type/1]). + relay/3, socket_type/0]). -include("mod_proxy65.hrl"). @@ -288,15 +288,3 @@ find_maxrate(Shaper, JID1, JID2, Host) -> if MaxRate1 == none; MaxRate2 == none -> none; true -> lists:max([MaxRate1, MaxRate2]) end. - -mod_opt_type(auth_type) -> - fun (plain) -> plain; - (anonymous) -> anonymous - end; -mod_opt_type(recbuf) -> - fun (I) when is_integer(I), I > 0 -> I end; -mod_opt_type(shaper) -> - fun (A) when is_atom(A) -> A end; -mod_opt_type(sndbuf) -> - fun (I) when is_integer(I), I > 0 -> I end; -mod_opt_type(_) -> [auth_type, recbuf, shaper, sndbuf]. From 9a9633dbc50430185a49cfda489bc87bed838d7c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 3 Jun 2015 16:21:07 +0300 Subject: [PATCH 111/695] Do not ignore unknown options so far --- src/ejabberd_config.erl | 5 +++-- src/gen_mod.erl | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index efc70ed5789..2ea35ed83c9 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -749,8 +749,9 @@ validate_opts(#state{opts = Opts} = State) -> true end; _ -> - ?ERROR_MSG("ignoring uknown option '~s'", [Opt]), - false + ?ERROR_MSG("unknown option '~s' will be likely" + " ignored", [Opt]), + true end end, Opts), State#state{opts = NewOpts}. diff --git a/src/gen_mod.erl b/src/gen_mod.erl index 2f9d3dd9ee5..3dcf4fcfd86 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -248,9 +248,10 @@ validate_opts(Module, Opts) -> end; L when is_list(L) -> SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>), - ?ERROR_MSG("ignoring unknown option '~s' for module '~s'," - " available options are: ~s", [Opt, Module, SOpts]), - false; + ?ERROR_MSG("unknown option '~s' for module '~s' will be" + " likely ignored, available options are: ~s", + [Opt, Module, SOpts]), + true; {'EXIT', {undef, _}} -> ?WARNING_MSG("module '~s' doesn't export mod_opt_type/1", [Module]), From 6f48f22c713b083ee4a85b4a6f8d0583d1ef3eed Mon Sep 17 00:00:00 2001 From: jpegger Date: Wed, 3 Jun 2015 18:11:35 +0200 Subject: [PATCH 112/695] Authmodule using old style XML:get_attr_s() --- src/ejabberd_auth_anonymous.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index 41126e56fa2..7533565217a 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -142,7 +142,7 @@ remove_connection(SID, LUser, LServer) -> %% Register connection register_connection(SID, #jid{luser = LUser, lserver = LServer}, Info) -> - AuthModule = xml:get_attr_s(auth_module, Info), + AuthModule = proplists:get_value(auth_module, Info, undefined), case AuthModule == (?MODULE) of true -> ejabberd_hooks:run(register_user, LServer, From 6c712b6caaaed35471452612d643f785bfdf11ee Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 4 Jun 2015 09:55:38 +0200 Subject: [PATCH 113/695] Don't add body element to MUC subject messages --- src/mod_muc_room.erl | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index c52b4e320d5..f28fe00413d 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1883,7 +1883,7 @@ add_new_user(From, Nick, Shift = count_stanza_shift(Nick, Els, NewState), case send_history(From, Shift, NewState) of true -> ok; - _ -> send_subject(From, Lang, StateData) + _ -> send_subject(From, StateData) end, case NewState#state.just_created of true -> NewState#state{just_created = false}; @@ -2502,25 +2502,15 @@ send_history(JID, Shift, StateData) -> lists:nthtail(Shift, lqueue_to_list(StateData#state.history))). -send_subject(JID, Lang, StateData) -> - case StateData#state.subject_author of - <<"">> -> ok; - Nick -> - Subject = StateData#state.subject, - Packet = #xmlel{name = <<"message">>, - attrs = [{<<"type">>, <<"groupchat">>}], - children = - [#xmlel{name = <<"subject">>, attrs = [], - children = [{xmlcdata, Subject}]}, - #xmlel{name = <<"body">>, attrs = [], - children = - [{xmlcdata, - <>))/binary, - Subject/binary>>}]}]}, - ejabberd_router:route(StateData#state.jid, JID, Packet) - end. +send_subject(_JID, #state{subject_author = <<"">>}) -> ok; +send_subject(JID, StateData) -> + Subject = StateData#state.subject, + Packet = #xmlel{name = <<"message">>, + attrs = [{<<"type">>, <<"groupchat">>}], + children = + [#xmlel{name = <<"subject">>, attrs = [], + children = [{xmlcdata, Subject}]}]}, + ejabberd_router:route(StateData#state.jid, JID, Packet). check_subject(Packet) -> case xml:get_subtag(Packet, <<"subject">>) of From fe10c6f6f2e28cb116f9e6f37cfb5927e49546ba Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 4 Jun 2015 12:13:10 +0200 Subject: [PATCH 114/695] Pick first local multicast service, otherwise remote (ejabberd-contrib#105) --- src/ejabberd_router_multicast.erl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index 9cd7dd3dd67..373d92272d1 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -202,14 +202,18 @@ do_route(From, Domain, Destinations, Packet) -> %% If no multicast service is available in this server, send manually [] -> do_route_normal(From, Destinations, Packet); - %% If available, send the packet using multicast service - [R] -> - case R#route_multicast.pid of - Pid when is_pid(Pid) -> - Pid ! {route_trusted, From, Destinations, Packet}; - _ -> do_route_normal(From, Destinations, Packet) - end + %% If some is available, send the packet using multicast service + Rs when is_list(Rs) -> + Pid = pick_multicast_pid(Rs), + Pid ! {route_trusted, From, Destinations, Packet} end. +pick_multicast_pid(Rs) -> + List = case [R || R <- Rs, node(R#route_multicast.pid) == node()] of + [] -> Rs; + RLocals -> RLocals + end, + (hd(List))#route_multicast.pid. + do_route_normal(From, Destinations, Packet) -> [ejabberd_router:route(From, To, Packet) || To <- Destinations]. From c04053cfae85e2a7038f2cab5e6b51b56b701f4b Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 4 Jun 2015 13:12:49 +0200 Subject: [PATCH 115/695] Use https instead of git in rebar file for dependencies url (#589) --- rebar.config.script | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index 2c42c961d32..b4dfaa3ed93 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -54,15 +54,15 @@ SrcDirs = lists:foldl( Acc end, [], Cfg), -Deps = [{p1_cache_tab, ".*", {git, "git://github.com/processone/cache_tab"}}, - {p1_tls, ".*", {git, "git://github.com/processone/tls"}}, - {p1_stringprep, ".*", {git, "git://github.com/processone/stringprep"}}, - {p1_xml, ".*", {git, "git://github.com/processone/xml"}}, - {esip, ".*", {git, "git://github.com/processone/p1_sip"}}, - {p1_stun, ".*", {git, "git://github.com/processone/stun"}}, - {p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}}, +Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, + {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, + {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}}, + {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, + {esip, ".*", {git, "https://github.com/processone/p1_sip"}}, + {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, + {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, {ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}}, - {p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}], + {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}], ConfigureCmd = fun(Pkg, Flags) -> {'get-deps', @@ -87,32 +87,32 @@ PostHooks = [ConfigureCmd("p1_tls", ""), CfgDeps = lists:flatmap( fun({mysql, true}) -> - [{p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}]; + [{p1_mysql, ".*", {git, "https://github.com/processone/mysql"}}]; ({pgsql, true}) -> - [{p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}]; + [{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql"}}]; ({sqlite, true}) -> - [{sqlite3, ".*", {git, "git://github.com/alexeyr/erlang-sqlite3"}}]; + [{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3"}}]; ({pam, true}) -> - [{p1_pam, ".*", {git, "git://github.com/processone/epam"}}]; + [{p1_pam, ".*", {git, "https://github.com/processone/epam"}}]; ({zlib, true}) -> - [{p1_zlib, ".*", {git, "git://github.com/processone/zlib"}}]; + [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; ({riak, true}) -> - [{riakc, ".*", {git, "git://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; + [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; ({json, true}) -> - [{jiffy, ".*", {git, "git://github.com/davisp/jiffy"}}]; + [{jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}]; ({elixir, true}) -> - [{rebar_elixir_plugin, ".*", {git, "git://github.com/yrashk/rebar_elixir_plugin"}}, - {elixir, ".*", {git, "git://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; + [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, + {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; ({iconv, true}) -> - [{p1_iconv, ".*", {git, "git://github.com/processone/eiconv"}}]; + [{p1_iconv, ".*", {git, "https://github.com/processone/eiconv"}}]; ({lager, true}) -> - [{lager, ".*", {git, "git://github.com/basho/lager"}}]; + [{lager, ".*", {git, "https://github.com/basho/lager"}}]; ({lager, false}) -> - [{p1_logger, ".*", {git, "git://github.com/processone/p1_logger"}}]; + [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}]; ({tools, true}) -> [{meck, "0.*", {git, "https://github.com/eproxus/meck"}}]; - ({redis, true}) -> - [{eredis, ".*", {git, "git://github.com/wooga/eredis"}}]; + ({redis, true}) -> + [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; (_) -> [] end, Cfg), From 357ff6c8f791781553a74e5ac4268546aa4efb2e Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 4 Jun 2015 15:47:02 +0200 Subject: [PATCH 116/695] Fix bug introduced in commit b88fa6f6174 --- src/mod_shared_roster.erl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index ac285bfd9c0..83ecade91ef 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -985,11 +985,11 @@ push_user_to_displayed(LUser, LServer, Group, Host, Subscription, DisplayedToGro GroupName = proplists:get_value(name, GroupOpts, Group), [push_user_to_group(LUser, LServer, GroupD, Host, GroupName, Subscription) - || {GroupD, _Opts} <- DisplayedToGroupsOpts]. + || GroupD <- DisplayedToGroupsOpts]. broadcast_user_to_displayed(LUser, LServer, Host, Subscription, DisplayedToGroupsOpts) -> [broadcast_user_to_group(LUser, LServer, GroupD, Host, Subscription) - || {GroupD, _Opts} <- DisplayedToGroupsOpts]. + || GroupD <- DisplayedToGroupsOpts]. push_user_to_group(LUser, LServer, Group, Host, GroupName, Subscription) -> @@ -1012,12 +1012,13 @@ broadcast_user_to_group(LUser, LServer, Group, Host, Subscription) -> %% Get list of groups to which this group is displayed displayed_to_groups(GroupName, LServer) -> GroupsOpts = groups_with_opts(LServer), - lists:filter(fun ({_Group, Opts}) -> + Gs = lists:filter(fun ({_Group, Opts}) -> lists:member(GroupName, proplists:get_value(displayed_groups, Opts, [])) end, - GroupsOpts). + GroupsOpts), + [Name || {Name, _} <- Gs]. push_item(User, Server, Item) -> Stanza = jlib:iq_to_xml(#iq{type = set, From dcf5aefea0363cc96d404591696e306fc323d8f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 15 Jun 2015 14:57:07 +0200 Subject: [PATCH 117/695] Add option to set net_ticktime (EJAB-1742) --- ejabberd.yml.example | 9 +++++++++ src/ejabberd_app.erl | 15 +++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 9fc815071d5..c57ef4657d4 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -72,6 +72,15 @@ log_rate_limit: 100 ## watchdog_admins: ## - "bob@example.com" +###. =============== +###' NODE PARAMETERS + +## +## net_ticktime: Specifies net_kernel tick time in seconds. This options must have +## identical value on all nodes, and in most cases shouldn't be changed at all from +## default value. +## +## net_ticktime: 60 ###. ================ ###' SERVED HOSTNAMES diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 46fbf81dc9e..30f34aff4ca 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -54,7 +54,7 @@ start(normal, _Args) -> ejabberd_admin:start(), gen_mod:start(), ejabberd_config:start(), - set_loglevel_from_config(), + set_settings_from_config(), acl:start(), shaper:start(), connect_nodes(), @@ -234,12 +234,17 @@ delete_pid_file() -> file:delete(PidFilename) end. -set_loglevel_from_config() -> +set_settings_from_config() -> Level = ejabberd_config:get_option( loglevel, fun(P) when P>=0, P=<5 -> P end, 4), - ejabberd_logger:set(Level). + ejabberd_logger:set(Level), + Ticktime = ejabberd_config:get_option( + net_ticktime, + opt_type(net_ticktime), + 60), + net_kernel:set_net_ticktime(Ticktime). start_apps() -> crypto:start(), @@ -252,6 +257,8 @@ start_apps() -> ejabberd:start_app(p1_zlib), ejabberd:start_app(p1_cache_tab). +opt_type(net_ticktime) -> + fun (P) when is_integer(P), P > 0 -> P end; opt_type(cluster_nodes) -> fun (Ns) -> true = lists:all(fun is_atom/1, Ns), Ns end; opt_type(loglevel) -> @@ -263,4 +270,4 @@ opt_type(modules) -> end, Mods) end; -opt_type(_) -> [cluster_nodes, loglevel, modules]. +opt_type(_) -> [cluster_nodes, loglevel, modules, net_ticktime]. From e6082742435bc18392aea785a3e9b667fce689c0 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 16 Jun 2015 15:18:34 +0200 Subject: [PATCH 118/695] Add s2s_dhfile option to configuration validator --- src/ejabberd_s2s_in.erl | 1 + src/ejabberd_s2s_out.erl | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index d890f0bce59..be5532cd0dd 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -722,6 +722,7 @@ opt_type(max_fsm_queue) -> fun (I) when is_integer(I), I > 0 -> I end; opt_type(s2s_certfile) -> fun iolist_to_binary/1; opt_type(s2s_ciphers) -> fun iolist_to_binary/1; +opt_type(s2s_dhfile) -> fun iolist_to_binary/1; opt_type(s2s_protocol_options) -> fun (Options) -> [_ | O] = lists:foldl(fun (X, Acc) -> X ++ Acc end, [], diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 7abc817755a..b512232db3b 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -1381,6 +1381,7 @@ opt_type(outgoing_s2s_timeout) -> end; opt_type(s2s_certfile) -> fun iolist_to_binary/1; opt_type(s2s_ciphers) -> fun iolist_to_binary/1; +opt_type(s2s_dhfile) -> fun iolist_to_binary/1; opt_type(s2s_dns_retries) -> fun (I) when is_integer(I), I >= 0 -> I end; opt_type(s2s_dns_timeout) -> From 3c47a5bb7504213eca4e86610d3adcc8f893110f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 17 Jun 2015 08:59:09 +0200 Subject: [PATCH 119/695] Allow password with ';' passed in ejabberdctl (#599) --- ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 3b3461bbdd3..095653e1b68 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -405,7 +405,7 @@ ctl() ctlexec() { CONN_NAME=$1; shift - COMMAND=$@ + COMMAND=$(echo $@ | sed 's/;/\\;/') $EXEC_CMD "$ERL \ $NAME ${CONN_NAME} \ -noinput \ From 1cf2dfe63afe0994988e756dfbb82524f50f6af8 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 17 Jun 2015 11:32:42 +0200 Subject: [PATCH 120/695] New hide_sensitive_log_data option to hide client IP in log (#452 #471) --- src/ejabberd_c2s.erl | 16 ++++++++-------- src/ejabberd_config.erl | 17 ++++++++++++++++- src/ejabberd_listener.erl | 2 +- src/ejabberd_web_admin.erl | 4 ++-- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 563a7df3504..9655a2ab1bc 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -639,7 +639,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> ?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s", [StateData#state.socket, jlib:jid_to_string(JID), AuthModule, - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [true, U, StateData#state.server, StateData#state.ip]), @@ -680,7 +680,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> ?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s", [StateData#state.socket, jlib:jid_to_string(JID), - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, U, StateData#state.server, StateData#state.ip]), @@ -701,7 +701,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> "for ~s from ~s", [StateData#state.socket, jlib:jid_to_string(JID), - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, U, StateData#state.server, StateData#state.ip]), @@ -756,7 +756,7 @@ wait_for_feature_request({xmlstreamelement, El}, ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", [StateData#state.socket, U, AuthModule, - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [true, U, StateData#state.server, StateData#state.ip]), @@ -783,7 +783,7 @@ wait_for_feature_request({xmlstreamelement, El}, ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s", [StateData#state.socket, Username, StateData#state.server, - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, Username, StateData#state.server, StateData#state.ip]), @@ -909,7 +909,7 @@ wait_for_sasl_response({xmlstreamelement, El}, ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", [StateData#state.socket, U, AuthModule, - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [true, U, StateData#state.server, StateData#state.ip]), @@ -932,7 +932,7 @@ wait_for_sasl_response({xmlstreamelement, El}, ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", [StateData#state.socket, U, AuthModule, - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [true, U, StateData#state.server, StateData#state.ip]), @@ -961,7 +961,7 @@ wait_for_sasl_response({xmlstreamelement, El}, ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s", [StateData#state.socket, Username, StateData#state.server, - jlib:ip_to_list(StateData#state.ip)]), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, Username, StateData#state.server, StateData#state.ip]), diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 2ea35ed83c9..d049e411247 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -36,7 +36,7 @@ prepare_opt_val/4, convert_table_to_binary/5, transform_options/1, collect_options/1, convert_to_yaml/1, convert_to_yaml/2, - env_binary_to_list/2, opt_type/1]). + env_binary_to_list/2, opt_type/1, may_hide_data/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1154,3 +1154,18 @@ opt_type(language) -> fun iolist_to_binary/1; opt_type(_) -> [hosts, language]. + +-spec may_hide_data(string()) -> string(). + +may_hide_data(Data) -> + case ejabberd_config:get_option( + hide_sensitive_log_data, + fun(false) -> false; + (true) -> true + end, + false) of + false -> + Data; + true -> + "hidden_by_ejabberd" + end. diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 81256cc1852..8660cc2f8af 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -297,7 +297,7 @@ accept(ListenSocket, Module, Opts) -> case {inet:sockname(Socket), inet:peername(Socket)} of {{ok, {Addr, Port}}, {ok, {PAddr, PPort}}} -> ?INFO_MSG("(~w) Accepted connection ~s:~p -> ~s:~p", - [Socket, inet_parse:ntoa(PAddr), PPort, + [Socket, ejabberd_config:may_hide_data(inet_parse:ntoa(PAddr)), PPort, inet_parse:ntoa(Addr), Port]); _ -> ok diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 239c8bac556..da166581c40 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -203,7 +203,7 @@ process([<<"server">>, SHost | RPath] = Path, {unauthorized, Error} -> {BadUser, _BadPass} = Auth, {IPT, _Port} = Request#request.ip, - IPS = jlib:ip_to_list(IPT), + IPS = ejabberd_config:may_hide_data(jlib:ip_to_list(IPT)), ?WARNING_MSG("Access of ~p from ~p failed with error: ~p", [BadUser, IPS, Error]), {401, @@ -235,7 +235,7 @@ process(RPath, {unauthorized, Error} -> {BadUser, _BadPass} = Auth, {IPT, _Port} = Request#request.ip, - IPS = jlib:ip_to_list(IPT), + IPS = ejabberd_config:may_hide_data(jlib:ip_to_list(IPT)), ?WARNING_MSG("Access of ~p from ~p failed with error: ~p", [BadUser, IPS, Error]), {401, From e5a98b100dfff0803278d1f46e68872621447c35 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 18 Jun 2015 12:06:29 +0200 Subject: [PATCH 121/695] Fix max_items and don't let PEP depends on item cache --- src/mod_pubsub.erl | 10 +++++----- src/node_pep.erl | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index a5e90531caa..f127ca12bb6 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3636,9 +3636,9 @@ max_items(Host, Options) -> case get_option(Options, persist_items) of true -> case get_option(Options, max_items) of - false -> unlimited; - Result when Result < 0 -> 0; - Result -> Result + I when is_integer(I), I < 0 -> 0; + I when is_integer(I) -> I; + _ -> ?MAXITEMS end; false -> case get_option(Options, send_last_published_item) of @@ -3646,8 +3646,8 @@ max_items(Host, Options) -> 0; _ -> case is_last_item_cache_enabled(Host) of - true -> 0; - false -> 1 + true -> 1; + false -> 0 end end end. diff --git a/src/node_pep.erl b/src/node_pep.erl index 8eeb28f0e81..34a841d3ed1 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -62,7 +62,7 @@ options() -> {notify_delete, false}, {notify_retract, false}, {purge_offline, false}, - {persist_items, false}, + {persist_items, true}, {max_items, 1}, {subscribe, true}, {access_model, presence}, From d528457ba51a656798cdacec7827f9912db6a753 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 18 Jun 2015 12:54:46 +0200 Subject: [PATCH 122/695] Don't force persistence if cache enabled (fix previous commit) --- src/mod_pubsub.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index f127ca12bb6..4969ac187f9 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3646,8 +3646,8 @@ max_items(Host, Options) -> 0; _ -> case is_last_item_cache_enabled(Host) of - true -> 1; - false -> 0 + true -> 0; + false -> 1 end end end. From 36a96ae3f52b0417855e174b406d84a8e9b15d99 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 18 Jun 2015 13:13:49 +0200 Subject: [PATCH 123/695] change_room_option misses handling some room options #604 --- src/mod_muc_admin.erl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 371b5e41514..1804ba7e521 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -785,9 +785,14 @@ change_option(Option, Value, Config) -> case Option of allow_change_subj -> Config#config{allow_change_subj = Value}; allow_private_messages -> Config#config{allow_private_messages = Value}; + allow_private_messages_from_visitors -> Config#config{allow_private_messages_from_visitors = Value}; allow_query_users -> Config#config{allow_query_users = Value}; allow_user_invites -> Config#config{allow_user_invites = Value}; + allow_visitor_nickchange -> Config#config{allow_visitor_nickchange = Value}; + allow_visitor_status -> Config#config{allow_visitor_status = Value}; + allow_voice_requests -> Config#config{allow_voice_requests = Value}; anonymous -> Config#config{anonymous = Value}; + captcha_protected -> Config#config{captcha_protected = Value}; description -> Config#config{description = Value}; logging -> Config#config{logging = Value}; max_users -> Config#config{max_users = Value}; @@ -799,7 +804,9 @@ change_option(Option, Value, Config) -> persistent -> Config#config{persistent = Value}; public -> Config#config{public = Value}; public_list -> Config#config{public_list = Value}; - title -> Config#config{title = Value} + title -> Config#config{title = Value}; + vcard -> Config#config{vcard = Value}; + voice_request_min_interval -> Config#config{voice_request_min_interval = Value} end. %%---------------------------- From 4dc23a5d810cd8ef1cb9897778d8b4660caf290a Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 18 Jun 2015 14:59:00 +0200 Subject: [PATCH 124/695] Allow several ';' passed in commands (#599) --- ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 095653e1b68..79f443890c2 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -405,7 +405,7 @@ ctl() ctlexec() { CONN_NAME=$1; shift - COMMAND=$(echo $@ | sed 's/;/\\;/') + COMMAND=$(echo $@ | sed 's/;/\\;/g') $EXEC_CMD "$ERL \ $NAME ${CONN_NAME} \ -noinput \ From 04038c01f76fd36bcd8f6252d8f37254f1d2fbf7 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 19 Jun 2015 00:50:08 +0200 Subject: [PATCH 125/695] PubSub: Check for node subscription of bare JID Don't just check whether the full JID is subscribed when a node subscription is required to list or publish items. If the bare JID is subscribed, these requests are now also accepted. --- src/node_hometree.erl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/node_hometree.erl b/src/node_hometree.erl index 296fbdde7a8..01eeccdd9c3 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -373,7 +373,8 @@ publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> end, Affiliation = GenState#pubsub_state.affiliation, Subscribed = case PublishModel of - subscribers -> is_subscribed(SubState#pubsub_state.subscriptions); + subscribers -> is_subscribed(GenState#pubsub_state.subscriptions) orelse + is_subscribed(SubState#pubsub_state.subscriptions); _ -> undefined end, if not ((PublishModel == open) or @@ -738,8 +739,10 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RS GenState = get_state(Nidx, GenKey), SubState = get_state(Nidx, SubKey), Affiliation = GenState#pubsub_state.affiliation, - Subscriptions = SubState#pubsub_state.subscriptions, - Whitelisted = can_fetch_item(Affiliation, Subscriptions), + BareSubscriptions = GenState#pubsub_state.subscriptions, + FullSubscriptions = SubState#pubsub_state.subscriptions, + Whitelisted = can_fetch_item(Affiliation, BareSubscriptions) orelse + can_fetch_item(Affiliation, FullSubscriptions), if %%SubId == "", ?? -> %% Entity has multiple subscriptions to the node but does not specify a subscription ID %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; From 73a0fb418cd7f2d7850e4e0d795dab4303dade17 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 19 Jun 2015 23:13:36 +0200 Subject: [PATCH 126/695] Update comment that explains how to set up node_mb Specify settings that make sense with current ejabberd versions, and use the YAML configuration format. Also, specify the "urn:xmpp:microblog:0" namespace, as that's the microblogging node name currently defined by XEP-0277. --- src/node_mb.erl | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/node_mb.erl b/src/node_mb.erl index e48fd7967f8..9dc4bf81f7a 100644 --- a/src/node_mb.erl +++ b/src/node_mb.erl @@ -31,13 +31,17 @@ -include("jlib.hrl"). %%% @doc The module {@module} is the pep microblog PubSub plugin. -%%%

    To be used, mod_pubsub must be configured : -%%% {mod_pubsub, [ % requires mod_caps -%%% {access_createnode, pubsub_createnode}, -%%% {plugins, ["default", "pep","mb"]}, -%%% {pep_mapping, [{"urn:xmpp:microblog", "mb"}]} -%%% ]}, -%%%

    +%%%

    To be used, mod_pubsub must be configured:

    +%%% mod_pubsub:
    +%%%   access_createnode: pubsub_createnode
    +%%%   ignore_pep_from_offline: false
    +%%%   plugins:
    +%%%     - "flat"
    +%%%     - "hometree"
    +%%%     - "pep" # Requires mod_caps.
    +%%%   pep_mapping:
    +%%%     "urn:xmpp:microblog:0": "mb"
    +%%% 

    %%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    -export([init/3, terminate/2, options/0, features/0, From fc0754c609cfecf567a712602c94716fbacc5712 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 20 Jun 2015 00:14:54 +0200 Subject: [PATCH 127/695] Add s2s_dhfile to list of known options --- src/ejabberd_s2s_in.erl | 4 ++-- src/ejabberd_s2s_out.erl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index be5532cd0dd..99a313ef6b1 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -743,5 +743,5 @@ opt_type(s2s_use_starttls) -> end; opt_type(_) -> [domain_certfile, max_fsm_queue, s2s_certfile, - s2s_ciphers, s2s_protocol_options, s2s_tls_compression, - s2s_use_starttls]. + s2s_ciphers, s2s_dhfile, s2s_protocol_options, + s2s_tls_compression, s2s_use_starttls]. diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index b512232db3b..77e159cdc6c 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -1409,6 +1409,6 @@ opt_type(s2s_use_starttls) -> opt_type(_) -> [domain_certfile, max_fsm_queue, outgoing_s2s_families, outgoing_s2s_port, outgoing_s2s_timeout, s2s_certfile, - s2s_ciphers, s2s_dns_retries, s2s_dns_timeout, + s2s_ciphers, s2s_dhfile, s2s_dns_retries, s2s_dns_timeout, s2s_max_retry_delay, s2s_protocol_options, s2s_tls_compression, s2s_use_starttls]. From 66310788848ef185f3831648b2abf67ab6ded7fa Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 22 Jun 2015 13:11:11 +0200 Subject: [PATCH 128/695] Document a few more supported protocols --- src/cyrsasl_anonymous.erl | 2 ++ src/ejabberd.erl | 10 ++++++++++ src/ejabberd_s2s.erl | 2 ++ src/ejabberd_stun.erl | 1 + src/mod_client_state.erl | 1 + src/mod_pubsub.erl | 1 + 6 files changed, 17 insertions(+) diff --git a/src/cyrsasl_anonymous.erl b/src/cyrsasl_anonymous.erl index 51d5db9d8d7..af403645ab2 100644 --- a/src/cyrsasl_anonymous.erl +++ b/src/cyrsasl_anonymous.erl @@ -26,6 +26,8 @@ -module(cyrsasl_anonymous). +-protocol({xep, 175, '1.2'}). + -export([start/1, stop/0, mech_new/4, mech_step/2]). -behaviour(cyrsasl). diff --git a/src/ejabberd.erl b/src/ejabberd.erl index 64ac5a0da1f..14404cd4c31 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -26,6 +26,16 @@ -module(ejabberd). -author('alexey@process-one.net'). +-protocol({xep, 4, '2.9'}). +-protocol({xep, 86, '1.0'}). +-protocol({xep, 106, '1.1'}). +-protocol({xep, 170, '1.0'}). +-protocol({xep, 205, '1.0'}). +-protocol({xep, 212, '1.0'}). +-protocol({xep, 216, '1.0'}). +-protocol({xep, 243, '1.0'}). +-protocol({xep, 270, '1.0'}). + -export([start/0, stop/0, start_app/1, start_app/2, get_pid_file/0, check_app/1]). diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index d6729dd46e0..74831fffb9a 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -25,6 +25,8 @@ -module(ejabberd_s2s). +-protocol({xep, 220, '1.1'}). + -behaviour(ejabberd_config). -author('alexey@process-one.net'). diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index a69b731c5f2..b609da5bdf2 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -26,6 +26,7 @@ -module(ejabberd_stun). -protocol({rfc, 5766}). +-protocol({xep, 176, '1.0'}). -export([tcp_init/2, udp_init/2, udp_recv/5, start/2, socket_type/0]). diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 1287d5687b5..bb0d962ff05 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -25,6 +25,7 @@ -module(mod_client_state). -author('holger@zedat.fu-berlin.de'). +-protocol({xep, 85, '2.1'}). -protocol({xep, 352, '0.1'}). -behavior(gen_mod). diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 4969ac187f9..f572c33d175 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -49,6 +49,7 @@ -author('christophe.romain@process-one.net'). -protocol({xep, 60, '1.13-1'}). -protocol({xep, 163, '1.2'}). +-protocol({xep, 248, '0.2'}). -include("ejabberd.hrl"). -include("logger.hrl"). From 83cce468a573d3ca58a0c6653a2ccc17c7b4dbc3 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 22 Jun 2015 16:56:08 +0300 Subject: [PATCH 129/695] Add MAM (XEP-0313) support --- include/ns.hrl | 2 + sql/lite.sql | 24 + sql/mysql.sql | 25 + sql/pg.sql | 29 +- src/ejabberd_c2s.erl | 32 +- src/mod_caps.erl | 24 +- src/mod_carboncopy.erl | 13 +- src/mod_mam.erl | 823 +++++++++++++++++ src/mod_ping.erl | 7 +- src/mod_service_log.erl | 14 +- test/ejabberd_SUITE.erl | 280 ++++++ test/ejabberd_SUITE_data/ejabberd.yml | 8 + tools/xmpp_codec.erl | 1200 +++++++++++++++++++++++++ tools/xmpp_codec.hrl | 35 + tools/xmpp_codec.spec | 150 ++++ 15 files changed, 2624 insertions(+), 42 deletions(-) create mode 100644 src/mod_mam.erl diff --git a/include/ns.hrl b/include/ns.hrl index f4c8bf3b0bc..71f454cadf8 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -141,6 +141,8 @@ -define(NS_CAPTCHA, <<"urn:xmpp:captcha">>). -define(NS_MEDIA, <<"urn:xmpp:media-element">>). -define(NS_BOB, <<"urn:xmpp:bob">>). +-define(NS_MAM_TMP, <<"urn:xmpp:mam:tmp">>). +-define(NS_MAM_0, <<"urn:xmpp:mam:0">>). -define(NS_PING, <<"urn:xmpp:ping">>). -define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>). -define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>). diff --git a/sql/lite.sql b/sql/lite.sql index 21e4df92998..461686d1a04 100644 --- a/sql/lite.sql +++ b/sql/lite.sql @@ -270,3 +270,27 @@ CREATE TABLE caps_features ( ); CREATE INDEX i_caps_features_node_subnode ON caps_features (node, subnode); + +CREATE TABLE archive ( + username text NOT NULL, + timestamp BIGINT UNSIGNED NOT NULL, + peer text NOT NULL, + bare_peer text NOT NULL, + xml text NOT NULL, + txt text, + id INTEGER PRIMARY KEY AUTOINCREMENT, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX i_username ON archive(username); +CREATE INDEX i_timestamp ON archive(timestamp); +CREATE INDEX i_peer ON archive(peer); +CREATE INDEX i_bare_peer ON archive(bare_peer); + +CREATE TABLE archive_prefs ( + username text NOT NULL PRIMARY KEY, + def text NOT NULL, + always text NOT NULL, + never text NOT NULL, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +); diff --git a/sql/mysql.sql b/sql/mysql.sql index 9596afa7cf0..fab76b9a2a8 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -85,6 +85,31 @@ CREATE TABLE spool ( CREATE INDEX i_despool USING BTREE ON spool(username); CREATE INDEX i_spool_created_at USING BTREE ON spool(created_at); +CREATE TABLE archive ( + username varchar(250) NOT NULL, + timestamp BIGINT UNSIGNED NOT NULL, + peer varchar(250) NOT NULL, + bare_peer varchar(250) NOT NULL, + xml text NOT NULL, + txt text, + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB CHARACTER SET utf8; + +CREATE FULLTEXT INDEX i_text ON archive(txt); +CREATE INDEX i_username USING BTREE ON archive(username); +CREATE INDEX i_timestamp USING BTREE ON archive(timestamp); +CREATE INDEX i_peer USING BTREE ON archive(peer); +CREATE INDEX i_bare_peer USING BTREE ON archive(bare_peer); + +CREATE TABLE archive_prefs ( + username varchar(250) NOT NULL PRIMARY KEY, + def text NOT NULL, + always text NOT NULL, + never text NOT NULL, + created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB CHARACTER SET utf8; + CREATE TABLE vcard ( username varchar(250) PRIMARY KEY, vcard mediumtext NOT NULL, diff --git a/sql/pg.sql b/sql/pg.sql index 736c4f93259..2a052d33793 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -85,6 +85,29 @@ CREATE TABLE spool ( CREATE INDEX i_despool ON spool USING btree (username); +CREATE TABLE archive ( + username text NOT NULL, + timestamp BIGINT NOT NULL, + peer text NOT NULL, + bare_peer text NOT NULL, + xml text NOT NULL, + txt text, + id SERIAL, + created_at TIMESTAMP NOT NULL DEFAULT now() +); + +CREATE INDEX i_username ON archive USING btree (username); +CREATE INDEX i_timestamp ON archive USING btree (timestamp); +CREATE INDEX i_peer ON archive USING btree (peer); +CREATE INDEX i_bare_peer ON archive USING btree (bare_peer); + +CREATE TABLE archive_prefs ( + username text NOT NULL PRIMARY KEY, + def text NOT NULL, + always text NOT NULL, + never text NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now() +); CREATE TABLE vcard ( username text PRIMARY KEY, @@ -299,6 +322,6 @@ CREATE TABLE sm ( info text NOT NULL ); -CREATE UNIQUE INDEX i_sid ON sm USING btree (usec, pid); -CREATE INDEX i_node ON sm USING btree (node); -CREATE INDEX i_username ON sm USING btree (username); +CREATE UNIQUE INDEX i_sm_sid ON sm USING btree (usec, pid); +CREATE INDEX i_sm_node ON sm USING btree (node); +CREATE INDEX i_sm_username ON sm USING btree (username); diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 9655a2ab1bc..3869bd54e50 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1260,12 +1260,14 @@ session_established2(El, StateData) -> _ -> case Name of <<"presence">> -> - PresenceEl = + PresenceEl0 = ejabberd_hooks:run_fold(c2s_update_presence, Server, NewEl, [User, Server]), - ejabberd_hooks:run(user_send_packet, Server, - [FromJID, ToJID, PresenceEl]), + PresenceEl = + ejabberd_hooks:run_fold( + user_send_packet, Server, PresenceEl0, + [NewStateData, FromJID, ToJID]), case ToJID of #jid{user = User, server = Server, resource = <<"">>} -> @@ -1285,16 +1287,18 @@ session_established2(El, StateData) -> process_privacy_iq(FromJID, ToJID, IQ, NewStateData); _ -> - ejabberd_hooks:run(user_send_packet, Server, - [FromJID, ToJID, NewEl]), + NewEl0 = ejabberd_hooks:run_fold( + user_send_packet, Server, NewEl, + [NewStateData, FromJID, ToJID]), check_privacy_route(FromJID, NewStateData, - FromJID, ToJID, NewEl) + FromJID, ToJID, NewEl0) end; <<"message">> -> - ejabberd_hooks:run(user_send_packet, Server, - [FromJID, ToJID, NewEl]), + NewEl0 = ejabberd_hooks:run_fold( + user_send_packet, Server, NewEl, + [NewStateData, FromJID, ToJID]), check_privacy_route(FromJID, NewStateData, FromJID, - ToJID, NewEl); + ToJID, NewEl0); _ -> NewStateData end end, @@ -1692,11 +1696,13 @@ handle_info({route, From, To, Attrs2 = jlib:replace_from_to_attrs(jlib:jid_to_string(From), jlib:jid_to_string(To), NewAttrs), - FixedPacket = #xmlel{name = Name, attrs = Attrs2, children = Els}, + FixedPacket0 = #xmlel{name = Name, attrs = Attrs2, children = Els}, + FixedPacket = ejabberd_hooks:run_fold( + user_receive_packet, + NewState#state.server, + FixedPacket0, + [NewState, NewState#state.jid, From, To]), SentStateData = send_packet(NewState, FixedPacket), - ejabberd_hooks:run(user_receive_packet, - SentStateData#state.server, - [SentStateData#state.jid, From, To, FixedPacket]), ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]), fsm_next_state(StateName, SentStateData); true -> diff --git a/src/mod_caps.erl b/src/mod_caps.erl index f10ed66c7b5..4d166ce70ed 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -47,7 +47,7 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, terminate/2, code_change/3]). --export([user_send_packet/3, user_receive_packet/4, +-export([user_send_packet/4, user_receive_packet/5, c2s_presence_in/2, c2s_filter_packet/6, c2s_broadcast_recipients/6, mod_opt_type/1]). @@ -143,11 +143,12 @@ read_caps([_ | Tail], Result) -> read_caps(Tail, Result); read_caps([], Result) -> Result. -user_send_packet(#jid{luser = User, lserver = Server} = From, +user_send_packet(#xmlel{name = <<"presence">>, attrs = Attrs, + children = Els} = Pkt, + _C2SState, + #jid{luser = User, lserver = Server} = From, #jid{luser = User, lserver = Server, - lresource = <<"">>}, - #xmlel{name = <<"presence">>, attrs = Attrs, - children = Els} = Pkt) -> + lresource = <<"">>}) -> Type = xml:get_attr_s(<<"type">>, Attrs), if Type == <<"">>; Type == <<"available">> -> case read_caps(Els) of @@ -158,13 +159,14 @@ user_send_packet(#jid{luser = User, lserver = Server} = From, true -> ok end, Pkt; -user_send_packet( _From, _To, Pkt) -> +user_send_packet(Pkt, _C2SState, _From, _To) -> Pkt. -user_receive_packet(#jid{lserver = Server}, - From, _To, - #xmlel{name = <<"presence">>, attrs = Attrs, - children = Els} = Pkt) -> +user_receive_packet(#xmlel{name = <<"presence">>, attrs = Attrs, + children = Els} = Pkt, + _C2SState, + #jid{lserver = Server}, + From, _To) -> Type = xml:get_attr_s(<<"type">>, Attrs), IsRemote = not lists:member(From#jid.lserver, ?MYHOSTS), if IsRemote and @@ -177,7 +179,7 @@ user_receive_packet(#jid{lserver = Server}, true -> ok end, Pkt; -user_receive_packet( _JID, _From, _To, Pkt) -> +user_receive_packet(Pkt, _C2SState, _JID, _From, _To) -> Pkt. -spec caps_stream_features([xmlel()], binary()) -> [xmlel()]. diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 2cc495aecde..186aca5e374 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -34,7 +34,7 @@ -export([start/2, stop/1]). --export([user_send_packet/3, user_receive_packet/4, +-export([user_send_packet/4, user_receive_packet/5, iq_handler2/3, iq_handler1/3, remove_connection/4, is_carbon_copy/1, mod_opt_type/1]). @@ -124,10 +124,10 @@ iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children iq_handler(_From, _To, IQ, _CC)-> IQ#iq{type=error, sub_el = [?ERR_NOT_ALLOWED]}. -user_send_packet(From, To, Packet) -> +user_send_packet(Packet, _C2SState, From, To) -> check_and_forward(From, To, Packet, sent). -user_receive_packet(JID, _From, To, Packet) -> +user_receive_packet(Packet, _C2SState, JID, _From, To) -> check_and_forward(JID, To, Packet, received). % verifier si le trafic est local @@ -142,14 +142,15 @@ check_and_forward(JID, To, Packet, Direction)-> true -> case is_carbon_copy(Packet) of false -> - send_copies(JID, To, Packet, Direction); + send_copies(JID, To, Packet, Direction), + Packet; true -> %% stop the hook chain, we don't want mod_logdb to register %% this message (duplicate) - stop + {stop, Packet} end; _ -> - ok + Packet end. remove_connection(User, Server, Resource, _Status)-> diff --git a/src/mod_mam.erl b/src/mod_mam.erl new file mode 100644 index 00000000000..1de1d9a9548 --- /dev/null +++ b/src/mod_mam.erl @@ -0,0 +1,823 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeniy Khramtsov +%%% @doc +%%% Message Archive Management (XEP-0313) +%%% @end +%%% Created : 4 Jul 2013 by Evgeniy Khramtsov +%%% +%%% +%%% ejabberd, Copyright (C) 2013-2015 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_mam). + +-behaviour(gen_mod). + +%% API +-export([start/2, stop/1]). + +-export([user_send_packet/4, user_receive_packet/5, + process_iq/3, remove_user/2, mod_opt_type/1]). + +-include_lib("stdlib/include/ms_transform.hrl"). +-include("jlib.hrl"). +-include("logger.hrl"). + +-record(archive_msg, + {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', + id = <<>> :: binary() | '_', + timestamp = now() :: erlang:timestamp() | '_' | '$1', + peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', + bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', + packet = #xmlel{} :: xmlel() | '_'}). + +-record(archive_prefs, + {us = {<<"">>, <<"">>} :: {binary(), binary()}, + default = never :: never | always | roster, + always = [] :: [ljid()], + never = [] :: [ljid()]}). + +%%%=================================================================== +%%% API +%%%=================================================================== +start(Host, Opts) -> + IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, + one_queue), + DBType = gen_mod:db_type(Host, Opts), + init_db(DBType, Host), + init_cache(DBType, Opts), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_MAM_TMP, ?MODULE, process_iq, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_MAM_TMP, ?MODULE, process_iq, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_MAM_0, ?MODULE, process_iq, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_MAM_0, ?MODULE, process_iq, IQDisc), + ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, + user_receive_packet, 500), + ejabberd_hooks:add(user_send_packet, Host, ?MODULE, + user_send_packet, 500), + ejabberd_hooks:add(remove_user, Host, ?MODULE, + remove_user, 50), + ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, + remove_user, 50), + ok. + +init_db(odbc, Host) -> + Muchost = gen_mod:get_module_opt_host(Host, mod_muc, + <<"conference.@HOST@">>), + ets:insert(ejabberd_modules, {ejabberd_module, {mod_mam, Muchost}, + [{db_type, odbc}]}), + mnesia:dirty_write({local_config, {modules,Muchost}, + [{mod_mam, [{db_type, odbc}]}]}); +init_db(mnesia, _Host) -> + mnesia:create_table(archive_msg, + [{disc_only_copies, [node()]}, + {type, bag}, + {attributes, record_info(fields, archive_msg)}]), + mnesia:create_table(archive_prefs, + [{disc_only_copies, [node()]}, + {attributes, record_info(fields, archive_prefs)}]); +init_db(_, _) -> + ok. + +init_cache(_DBType, Opts) -> + MaxSize = gen_mod:get_opt(cache_size, Opts, + fun(I) when is_integer(I), I>0 -> I end, + 1000), + LifeTime = gen_mod:get_opt(cache_life_time, Opts, + fun(I) when is_integer(I), I>0 -> I end, + timer:hours(1) div 1000), + cache_tab:new(archive_prefs, [{max_size, MaxSize}, + {life_time, LifeTime}]). + +stop(Host) -> + ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, + user_send_packet, 500), + ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, + user_receive_packet, 500), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_TMP), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_0), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_0), + ejabberd_hooks:delete(remove_user, Host, ?MODULE, + remove_user, 50), + ejabberd_hooks:delete(anonymous_purge_hook, Host, + ?MODULE, remove_user, 50), + ok. + +remove_user(User, Server) -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + remove_user(LUser, LServer, + gen_mod:db_type(LServer, ?MODULE)). + +remove_user(LUser, LServer, mnesia) -> + US = {LUser, LServer}, + F = fun () -> + mnesia:delete({archive_msg, US}), + mnesia:delete({archive_prefs, US}) + end, + mnesia:transaction(F); +remove_user(LUser, LServer, odbc) -> + SUser = ejabberd_odbc:escape(LUser), + ejabberd_odbc:sql_query( + LServer, + [<<"delete from archive where username='">>, SUser, <<"';">>]), + ejabberd_odbc:sql_query( + LServer, + [<<"delete from archive_prefs where username='">>, SUser, <<"';">>]). + +user_receive_packet(Pkt, C2SState, JID, Peer, _To) -> + LUser = JID#jid.luser, + LServer = JID#jid.lserver, + case should_archive(Pkt) of + true -> + NewPkt = strip_my_archived_tag(Pkt, LServer), + case store(C2SState, NewPkt, LUser, LServer, + Peer, true, recv) of + {ok, ID} -> + Archived = #xmlel{name = <<"archived">>, + attrs = [{<<"by">>, LServer}, + {<<"xmlns">>, ?NS_MAM_TMP}, + {<<"id">>, ID}]}, + NewEls = [Archived|NewPkt#xmlel.children], + NewPkt#xmlel{children = NewEls}; + _ -> + NewPkt + end; + muc -> + Pkt; + false -> + Pkt + end. + +user_send_packet(Pkt, C2SState, JID, Peer) -> + LUser = JID#jid.luser, + LServer = JID#jid.lserver, + case should_archive(Pkt) of + S when (S==true) -> + NewPkt = strip_my_archived_tag(Pkt, LServer), + store0(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), + LUser, LServer, Peer, S, send), + NewPkt; + S when (S==muc) -> + NewPkt = strip_my_archived_tag(Pkt, LServer), + case store0(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), + LUser, LServer, Peer, S, send) of + {ok, ID} -> + By = jlib:jid_to_string(Peer), + Archived = #xmlel{name = <<"archived">>, + attrs = [{<<"by">>, By}, {<<"xmlns">>, ?NS_MAM_TMP}, + {<<"id">>, ID}]}, + NewEls = [Archived|NewPkt#xmlel.children], + NewPkt#xmlel{children = NewEls}; + _ -> + NewPkt + end; + false -> + Pkt + end. + +process_iq(#jid{lserver = LServer} = From, + #jid{lserver = LServer} = To, + #iq{type = get, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> + NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), + Fs = case NS of + ?NS_MAM_TMP -> + lists:flatmap( + fun(#xmlel{name = <<"start">>} = El) -> + [{<<"start">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"end">>} = El) -> + [{<<"end">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"with">>} = El) -> + [{<<"with">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"withroom">>} = El) -> + [{<<"withroom">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"withtext">>} = El) -> + [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"set">>}) -> + [{<<"set">>, SubEl}]; + (_) -> + [] + end, SubEl#xmlel.children); + ?NS_MAM_0 -> + case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), + xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of + {#xmlel{} = XData, false} -> + jlib:parse_xdata_submit(XData); + {#xmlel{} = XData, #xmlel{}} -> + [{<<"set">>, SubEl} | jlib:parse_xdata_submit(XData)]; + {false, #xmlel{}} -> + [{<<"set">>, SubEl}]; + {false, false} -> + [] + end + end, + case catch lists:foldl( + fun({<<"start">>, [Data|_]}, {_, End, With, RSM}) -> + {{_, _, _} = jlib:datetime_string_to_timestamp(Data), + End, With, RSM}; + ({<<"end">>, [Data|_]}, {Start, _, With, RSM}) -> + {Start, + {_, _, _} = jlib:datetime_string_to_timestamp(Data), + With, RSM}; + ({<<"with">>, [Data|_]}, {Start, End, _, RSM}) -> + {Start, End, jlib:jid_tolower(jlib:string_to_jid(Data)), RSM}; + ({<<"withroom">>, [Data|_]}, {Start, End, _, RSM}) -> + {Start, End, + {room, jlib:jid_tolower(jlib:string_to_jid(Data))}, + RSM}; + ({<<"withtext">>, [Data|_]}, {Start, End, _, RSM}) -> + {Start, End, {text, Data}, RSM}; + ({<<"set">>, El}, {Start, End, With, _}) -> + {Start, End, With, jlib:rsm_decode(El)}; + (_, Acc) -> + Acc + end, {none, [], none, none}, Fs) of + {'EXIT', _} -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; + {Start, End, With, RSM} -> + select_and_send(From, To, Start, End, With, RSM, IQ) + end; +process_iq(#jid{luser = LUser, lserver = LServer}, + #jid{lserver = LServer}, + #iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> + try {case xml:get_tag_attr_s(<<"default">>, SubEl) of + <<"always">> -> always; + <<"never">> -> never; + <<"roster">> -> roster + end, + lists:foldl( + fun(#xmlel{name = <<"always">>, children = Els}, {A, N}) -> + {get_jids(Els) ++ A, N}; + (#xmlel{name = <<"never">>, children = Els}, {A, N}) -> + {A, get_jids(Els) ++ N}; + (_, {A, N}) -> + {A, N} + end, {[], []}, SubEl#xmlel.children)} of + {Default, {Always, Never}} -> + case write_prefs(LUser, LServer, LServer, Default, + lists:usort(Always), lists:usort(Never)) of + ok -> + IQ#iq{type = result, sub_el = []}; + _Err -> + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} + end + catch _:_ -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} + end; +process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +should_archive(#xmlel{name = <<"message">>} = Pkt) -> + case {xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs), + xml:get_subtag_cdata(Pkt, <<"body">>)} of + {<<"error">>, _} -> + false; + {<<"groupchat">>, _} -> + To = xml:get_attr_s(<<"to">>, Pkt#xmlel.attrs), + case (jlib:string_to_jid(To))#jid.resource of + <<"">> -> muc; + _ -> false + end; + {_, <<>>} -> + %% Empty body + false; + _ -> + true + end; +should_archive(#xmlel{}) -> + false. + +strip_my_archived_tag(Pkt, LServer) -> + NewEls = lists:filter( + fun(#xmlel{name = <<"archived">>, + attrs = Attrs}) -> + case catch jlib:nameprep( + xml:get_attr_s( + <<"by">>, Attrs)) of + LServer -> + false; + _ -> + true + end; + (_) -> + true + end, Pkt#xmlel.children), + Pkt#xmlel{children = NewEls}. + +should_archive_peer(C2SState, + #archive_prefs{default = Default, + always = Always, + never = Never}, + Peer) -> + LPeer = jlib:jid_tolower(Peer), + case lists:member(LPeer, Always) of + true -> + true; + false -> + case lists:member(LPeer, Never) of + true -> + false; + false -> + case Default of + always -> true; + never -> false; + roster -> + case ejabberd_c2s:get_subscription( + LPeer, C2SState) of + both -> true; + from -> true; + to -> true; + _ -> false + end + end + end + end. + +store0(C2SState, Pkt, LUser, LServer, Peer, Type, Dir) -> + case Type of + muc -> store(C2SState, Pkt, Peer#jid.luser, LServer, + jlib:jid_replace_resource(Peer, LUser), Type, Dir); + true -> store(C2SState, Pkt, LUser, LServer, Peer, Type, Dir) + end. + +store(C2SState, Pkt, LUser, LServer, Peer, Type, Dir) -> + Prefs = get_prefs(LUser, LServer), + case should_archive_peer(C2SState, Prefs, Peer) of + true -> + do_store(Pkt, LUser, LServer, Peer, Type, Dir, + gen_mod:db_type(LServer, ?MODULE)); + false -> + pass + end. + +do_store(Pkt, LUser, LServer, Peer, Type, _Dir, mnesia) -> + LPeer = {PUser, PServer, _} = jlib:jid_tolower(Peer), + LServer2 = case Type of muc -> Peer#jid.lserver; _ -> LServer end, + TS = now(), + ID = jlib:integer_to_binary(now_to_usec(TS)), + case mnesia:dirty_write( + #archive_msg{us = {LUser, LServer2}, + id = ID, + timestamp = TS, + peer = LPeer, + bare_peer = {PUser, PServer, <<>>}, + packet = Pkt}) of + ok -> + {ok, ID}; + Err -> + Err + end; +do_store(Pkt, LUser, LServer, Peer, _Type, _Dir, odbc) -> + TSinteger = now_to_usec(now()), + ID = TS = jlib:integer_to_binary(TSinteger), + BarePeer = jlib:jid_to_string( + jlib:jid_tolower( + jlib:jid_remove_resource(Peer))), + LPeer = jlib:jid_to_string( + jlib:jid_tolower(Peer)), + XML = xml:element_to_binary(Pkt), + Body = xml:get_subtag_cdata(Pkt, <<"body">>), + case ejabberd_odbc:sql_query( + LServer, + [<<"insert into archive (username, timestamp, " + "peer, bare_peer, xml, txt) values (">>, + <<"'">>, ejabberd_odbc:escape(LUser), <<"', ">>, + <<"'">>, TS, <<"', ">>, + <<"'">>, ejabberd_odbc:escape(LPeer), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(BarePeer), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(XML), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(Body), <<"');">>]) of + {updated, _} -> + {ok, ID}; + Err -> + Err + end. + +write_prefs(LUser, LServer, Host, Default, Always, Never) -> + DBType = case gen_mod:db_type(Host, ?MODULE) of + odbc -> {odbc, Host}; + DB -> DB + end, + Prefs = #archive_prefs{us = {LUser, LServer}, + default = Default, + always = Always, + never = Never}, + cache_tab:dirty_insert( + archive_prefs, {LUser, LServer}, Prefs, + fun() -> write_prefs(LUser, LServer, Prefs, DBType) end). + +write_prefs(_LUser, _LServer, Prefs, mnesia) -> + mnesia:dirty_write(Prefs); +write_prefs(LUser, _LServer, #archive_prefs{default = Default, + never = Never, + always = Always}, + {odbc, Host}) -> + SUser = ejabberd_odbc:escape(LUser), + SDefault = erlang:atom_to_binary(Default, utf8), + SAlways = ejabberd_odbc:encode_term(Always), + SNever = ejabberd_odbc:encode_term(Never), + case update(Host, <<"archive_prefs">>, + [<<"username">>, <<"def">>, <<"always">>, <<"never">>], + [SUser, SDefault, SAlways, SNever], + [<<"username='">>, SUser, <<"'">>]) of + {updated, _} -> + ok; + Err -> + Err + end. + +get_prefs(LUser, LServer) -> + DBType = gen_mod:db_type(LServer, ?MODULE), + Res = cache_tab:lookup(archive_prefs, {LUser, LServer}, + fun() -> get_prefs(LUser, LServer, + DBType) + end), + case Res of + {ok, Prefs} -> + Prefs; + error -> + Default = gen_mod:get_module_opt( + LServer, ?MODULE, default, + fun(always) -> always; + (never) -> never; + (roster) -> roster + end, never), + #archive_prefs{us = {LUser, LServer}, default = Default} + end. + +get_prefs(LUser, LServer, mnesia) -> + case mnesia:dirty_read(archive_prefs, {LUser, LServer}) of + [Prefs] -> + {ok, Prefs}; + _ -> + error + end; +get_prefs(LUser, LServer, odbc) -> + case ejabberd_odbc:sql_query( + LServer, + [<<"select def, always, never from archive_prefs ">>, + <<"where username='">>, + ejabberd_odbc:escape(LUser), <<"';">>]) of + {selected, _, [[SDefault, SAlways, SNever]]} -> + Default = erlang:binary_to_existing_atom(SDefault, utf8), + Always = ejabberd_odbc:decode_term(SAlways), + Never = ejabberd_odbc:decode_term(SNever), + {ok, #archive_prefs{us = {LUser, LServer}, + default = Default, + always = Always, + never = Never}}; + _ -> + error + end. + +select_and_send(#jid{lserver = LServer} = From, + To, Start, End, With, RSM, IQ) -> + DBType = case gen_mod:db_type(LServer, ?MODULE) of + odbc -> {odbc, LServer}; + DB -> DB + end, + select_and_send(From, To, Start, End, With, RSM, IQ, + DBType). + +select_and_send(From, To, Start, End, With, RSM, IQ, DBType) -> + {Msgs, Count} = select_and_start(From, To, Start, End, With, + RSM, DBType), + SortedMsgs = lists:keysort(2, Msgs), + send(From, To, SortedMsgs, RSM, Count, IQ). + +select_and_start(From, _To, StartUser, End, With, RSM, DB) -> + {JidRequestor, Start, With2} = case With of + {room, {LUserRoom, LServerRoom, <<>>} = WithJid} -> + JR = jlib:make_jid(LUserRoom,LServerRoom,<<>>), + St = StartUser, + {JR, St, WithJid}; + _ -> + {From, StartUser, With} + end, + select(JidRequestor, Start, End, With2, RSM, DB). + +select(#jid{luser = LUser, lserver = LServer} = JidRequestor, + Start, End, With, RSM, mnesia) -> + MS = make_matchspec(LUser, LServer, Start, End, With), + Msgs = mnesia:dirty_select(archive_msg, MS), + FilteredMsgs = filter_by_rsm(Msgs, RSM), + Count = length(Msgs), + {lists:map( + fun(Msg) -> + {Msg#archive_msg.id, + jlib:binary_to_integer(Msg#archive_msg.id), + msg_to_el(Msg, JidRequestor)} + end, FilteredMsgs), Count}; +select(#jid{luser = LUser, lserver = LServer} = JidRequestor, + Start, End, With, RSM, {odbc, Host}) -> + {Query, CountQuery} = make_sql_query(LUser, LServer, + Start, End, With, RSM), + case {ejabberd_odbc:sql_query(Host, Query), + ejabberd_odbc:sql_query(Host, CountQuery)} of + {{selected, _, Res}, {selected, _, [[Count]]}} -> + {lists:map( + fun([TS, XML, PeerBin]) -> + #xmlel{} = El = xml_stream:parse_element(XML), + Now = usec_to_now(jlib:binary_to_integer(TS)), + PeerJid = jlib:jid_tolower(jlib:string_to_jid(PeerBin)), + {TS, jlib:binary_to_integer(TS), + msg_to_el(#archive_msg{timestamp = Now, + packet = El, + peer = PeerJid}, + JidRequestor)} + end, Res), jlib:binary_to_integer(Count)}; + _ -> + {[], 0} + end. + +msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, peer = Peer}, + JidRequestor) -> + Delay = jlib:now_to_utc_string(TS), + Pkt = maybe_update_from_to(Pkt1, JidRequestor, Peer), + #xmlel{name = <<"forwarded">>, + attrs = [{<<"xmlns">>, ?NS_FORWARD}], + children = [#xmlel{name = <<"delay">>, + attrs = [{<<"xmlns">>, ?NS_DELAY}, + {<<"stamp">>, Delay}]}, + xml:replace_tag_attr( + <<"xmlns">>, <<"jabber:client">>, Pkt)]}. + +maybe_update_from_to(Pkt, _JIDRequestor, undefined) -> + Pkt; +maybe_update_from_to(Pkt, JidRequestor, Peer) -> + case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of + <<"groupchat">> -> + Pkt2 = xml:replace_tag_attr(<<"to">>, + jlib:jid_to_string(JidRequestor), + Pkt), + xml:replace_tag_attr(<<"from">>, jlib:jid_to_string(Peer), + Pkt2); + _ -> Pkt + end. + +send(From, To, Msgs, RSM, Count, #iq{sub_el = SubEl} = IQ) -> + QID = xml:get_tag_attr_s(<<"queryid">>, SubEl), + NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), + QIDAttr = if QID /= <<>> -> + [{<<"queryid">>, QID}]; + true -> + [] + end, + Els = lists:map( + fun({ID, _IDInt, El}) -> + #xmlel{name = <<"message">>, + children = [#xmlel{name = <<"result">>, + attrs = [{<<"xmlns">>, NS}, + {<<"id">>, ID}|QIDAttr], + children = [El]}]} + end, Msgs), + RSMOut = make_rsm_out(Msgs, RSM, Count, QIDAttr, NS), + case NS of + ?NS_MAM_TMP -> + lists:foreach( + fun(El) -> + ejabberd_router:route(To, From, El) + end, Els), + IQ#iq{type = result, sub_el = RSMOut}; + ?NS_MAM_0 -> + ejabberd_router:route( + To, From, jlib:iq_to_xml(IQ#iq{type = result, sub_el = []})), + lists:foreach( + fun(El) -> + ejabberd_router:route(To, From, El) + end, Els), + ejabberd_router:route( + To, From, #xmlel{name = <<"message">>, + children = RSMOut}), + ignore + end. + + +make_rsm_out(_Msgs, none, _Count, _QIDAttr, ?NS_MAM_TMP) -> + []; +make_rsm_out(_Msgs, none, _Count, QIDAttr, ?NS_MAM_0) -> + [#xmlel{name = <<"fin">>, attrs = [{<<"xmlns">>, ?NS_MAM_0}|QIDAttr]}]; +make_rsm_out([], #rsm_in{}, Count, QIDAttr, NS) -> + Tag = if NS == ?NS_MAM_TMP -> <<"query">>; + true -> <<"fin">> + end, + [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|QIDAttr], + children = jlib:rsm_encode(#rsm_out{count = Count})}]; +make_rsm_out([{FirstID, _, _}|_] = Msgs, #rsm_in{}, Count, QIDAttr, NS) -> + {LastID, _, _} = lists:last(Msgs), + Tag = if NS == ?NS_MAM_TMP -> <<"query">>; + true -> <<"fin">> + end, + [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|QIDAttr], + children = jlib:rsm_encode( + #rsm_out{first = FirstID, count = Count, + last = LastID})}]. + +filter_by_rsm(Msgs, none) -> + Msgs; +filter_by_rsm(_Msgs, #rsm_in{max = Max}) when Max =< 0 -> + []; +filter_by_rsm(Msgs, #rsm_in{max = Max, direction = Direction, id = ID}) -> + NewMsgs = case Direction of + aft -> + lists:filter( + fun(#archive_msg{id = I}) -> + I > ID + end, Msgs); + before -> + lists:foldl( + fun(#archive_msg{id = I} = Msg, Acc) when I < ID -> + [Msg|Acc]; + (_, Acc) -> + Acc + end, [], Msgs); + _ -> + Msgs + end, + filter_by_max(NewMsgs, Max). + +filter_by_max(Msgs, undefined) -> + Msgs; +filter_by_max(Msgs, Len) when is_integer(Len), Len >= 0 -> + lists:sublist(Msgs, Len); +filter_by_max(_Msgs, _Junk) -> + []. + +make_matchspec(LUser, LServer, Start, End, {_, _, <<>>} = With) -> + ets:fun2ms( + fun(#archive_msg{timestamp = TS, + us = US, + bare_peer = BPeer} = Msg) + when Start =< TS, End >= TS, + US == {LUser, LServer}, + BPeer == With -> + Msg + end); +make_matchspec(LUser, LServer, Start, End, {_, _, _} = With) -> + ets:fun2ms( + fun(#archive_msg{timestamp = TS, + us = US, + peer = Peer} = Msg) + when Start =< TS, End >= TS, + US == {LUser, LServer}, + Peer == With -> + Msg + end); +make_matchspec(LUser, LServer, Start, End, none) -> + ets:fun2ms( + fun(#archive_msg{timestamp = TS, + us = US, + peer = Peer} = Msg) + when Start =< TS, End >= TS, + US == {LUser, LServer} -> + Msg + end). + +make_sql_query(LUser, _LServer, Start, End, With, RSM) -> + {Max, Direction, ID} = case RSM of + #rsm_in{} -> + {RSM#rsm_in.max, + RSM#rsm_in.direction, + RSM#rsm_in.id}; + none -> + {none, none, none} + end, + LimitClause = if is_integer(Max), Max >= 0 -> + [<<" limit ">>, jlib:integer_to_binary(Max)]; + true -> + [] + end, + WithClause = case With of + {text, <<>>} -> + []; + {text, Txt} -> + [<<" and match (txt) against ('">>, + ejabberd_odbc:escape(Txt), <<"')">>]; + {_, _, <<>>} -> + [<<" and bare_peer='">>, + ejabberd_odbc:escape(jlib:jid_to_string(With)), + <<"'">>]; + {_, _, _} -> + [<<" and peer='">>, + ejabberd_odbc:escape(jlib:jid_to_string(With)), + <<"'">>]; + none -> + [] + end, + DirectionClause = case catch jlib:binary_to_integer(ID) of + I when is_integer(I), I >= 0 -> + case Direction of + before -> + [<<" and timestamp < ">>, ID, + <<" order by timestamp desc">>]; + aft -> + [<<" and timestamp > ">>, ID, + <<" order by timestamp asc">>]; + _ -> + [] + end; + _ -> + [] + end, + StartClause = case Start of + {_, _, _} -> + [<<" and timestamp >= ">>, + jlib:integer_to_binary(now_to_usec(Start))]; + _ -> + [] + end, + EndClause = case End of + {_, _, _} -> + [<<" and timestamp <= ">>, + jlib:integer_to_binary(now_to_usec(End))]; + _ -> + [] + end, + SUser = ejabberd_odbc:escape(LUser), + {[<<"select timestamp, xml, peer from archive where username='">>, + SUser, <<"'">>] ++ WithClause ++ StartClause ++ EndClause ++ + DirectionClause ++ LimitClause ++ [<<";">>], + [<<"select count(*) from archive where username='">>, + SUser, <<"'">>] ++ WithClause ++ StartClause ++ EndClause ++ [<<";">>]}. + +now_to_usec({MSec, Sec, USec}) -> + (MSec*1000000 + Sec)*1000000 + USec. + +usec_to_now(Int) -> + Secs = Int div 1000000, + USec = Int rem 1000000, + MSec = Secs div 1000000, + Sec = Secs rem 1000000, + {MSec, Sec, USec}. + +get_jids(Els) -> + lists:flatmap( + fun(#xmlel{name = <<"jid">>} = El) -> + J = jlib:string_to_jid(xml:get_tag_cdata(El)), + [jlib:jid_tolower(jlib:jid_remove_resource(J)), + jlib:jid_tolower(J)]; + (_) -> + [] + end, Els). + +update(LServer, Table, Fields, Vals, Where) -> + UPairs = lists:zipwith(fun (A, B) -> + <
    > + end, + Fields, Vals), + case ejabberd_odbc:sql_query(LServer, + [<<"update ">>, Table, <<" set ">>, + join(UPairs, <<", ">>), <<" where ">>, Where, + <<";">>]) + of + {updated, 1} -> {updated, 1}; + _ -> + ejabberd_odbc:sql_query(LServer, + [<<"insert into ">>, Table, <<"(">>, + join(Fields, <<", ">>), <<") values ('">>, + join(Vals, <<"', '">>), <<"');">>]) + end. + +%% Almost a copy of string:join/2. +join([], _Sep) -> []; +join([H | T], Sep) -> [H, [[Sep, X] || X <- T]]. + +mod_opt_type(cache_life_time) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(cache_size) -> + fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(db_type) -> fun gen_mod:v_db/1; +mod_opt_type(default) -> + fun (always) -> always; + (never) -> never; + (roster) -> roster + end; +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(store_body_only) -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [cache_life_time, cache_size, db_type, default, iqdisc, + store_body_only]. diff --git a/src/mod_ping.erl b/src/mod_ping.erl index 0b332edec3b..7d030685cd0 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -57,7 +57,7 @@ handle_cast/2, handle_info/2, code_change/3]). -export([iq_ping/3, user_online/3, user_offline/3, - user_send/3, mod_opt_type/1]). + user_send/4, mod_opt_type/1]). -record(state, {host = <<"">>, @@ -214,8 +214,9 @@ user_online(_SID, JID, _Info) -> user_offline(_SID, JID, _Info) -> stop_ping(JID#jid.lserver, JID). -user_send(JID, _From, _Packet) -> - start_ping(JID#jid.lserver, JID). +user_send(Packet, _C2SState, JID, _From) -> + start_ping(JID#jid.lserver, JID), + Packet. %%==================================================================== %% Internal functions diff --git a/src/mod_service_log.erl b/src/mod_service_log.erl index e145c5ce6b0..db0f3df3b59 100644 --- a/src/mod_service_log.erl +++ b/src/mod_service_log.erl @@ -29,8 +29,8 @@ -behaviour(gen_mod). --export([start/2, stop/1, log_user_send/3, - log_user_receive/4, mod_opt_type/1]). +-export([start/2, stop/1, log_user_send/4, + log_user_receive/5, mod_opt_type/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -51,11 +51,13 @@ stop(Host) -> ?MODULE, log_user_receive, 50), ok. -log_user_send(From, To, Packet) -> - log_packet(From, To, Packet, From#jid.lserver). +log_user_send(Packet, _C2SState, From, To) -> + log_packet(From, To, Packet, From#jid.lserver), + Packet. -log_user_receive(_JID, From, To, Packet) -> - log_packet(From, To, Packet, To#jid.lserver). +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}, diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 4f082332339..4d1a1fc7b43 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -247,6 +247,10 @@ db_tests(mnesia) -> roster_subscribe_slave]}, {test_offline, [sequence], [offline_master, offline_slave]}, + {test_old_mam, [parallel], + [mam_old_master, mam_old_slave]}, + {test_new_mam, [parallel], + [mam_new_master, mam_new_slave]}, {test_carbons, [parallel], [carbons_master, carbons_slave]}, {test_client_state, [parallel], @@ -283,6 +287,10 @@ db_tests(_) -> roster_subscribe_slave]}, {test_offline, [sequence], [offline_master, offline_slave]}, + {test_old_mam, [parallel], + [mam_old_master, mam_old_slave]}, + {test_new_mam, [parallel], + [mam_new_master, mam_new_slave]}, {test_muc, [parallel], [muc_master, muc_slave]}, {test_announce, [sequence], @@ -1567,6 +1575,278 @@ carbons_slave(Config) -> ?recv1(#presence{from = Peer, type = unavailable}), disconnect(Config). +mam_old_master(Config) -> + mam_master(Config, ?NS_MAM_TMP). + +mam_new_master(Config) -> + mam_master(Config, ?NS_MAM_0). + +mam_master(Config, NS) -> + true = is_feature_advertised(Config, NS), + MyJID = my_jid(Config), + BareMyJID = jlib:jid_remove_resource(MyJID), + Peer = ?config(slave, Config), + send(Config, #presence{}), + ?recv1(#presence{}), + wait_for_slave(Config), + ?recv1(#presence{from = Peer}), + #iq{type = result, sub_els = []} = + send_recv(Config, + #iq{type = set, + sub_els = [#mam_prefs{xmlns = NS, + default = roster, + never = [MyJID]}]}), + if NS == ?NS_MAM_TMP -> + FakeArchived = #mam_archived{id = randoms:get_string(), + by = server_jid(Config)}, + send(Config, #message{to = MyJID, + sub_els = [FakeArchived], + body = [#text{data = <<"a">>}]}), + send(Config, #message{to = BareMyJID, + sub_els = [FakeArchived], + body = [#text{data = <<"b">>}]}), + %% NOTE: The server should strip fake archived tags, + %% i.e. the sub_els received should be []. + ?recv2(#message{body = [#text{data = <<"a">>}], sub_els = []}, + #message{body = [#text{data = <<"b">>}], sub_els = []}); + true -> + ok + end, + wait_for_slave(Config), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + send(Config, + #message{to = Peer, body = [Text]}) + end, lists:seq(1, 5)), + ?recv1(#presence{type = unavailable, from = Peer}), + mam_query_all(Config, NS), + mam_query_with(Config, Peer, NS), + %% mam_query_with(Config, jlib:jid_remove_resource(Peer)), + mam_query_rsm(Config, NS), + #iq{type = result, sub_els = []} = + send_recv(Config, #iq{type = set, + sub_els = [#mam_prefs{xmlns = NS, + default = never}]}), + disconnect(Config). + +mam_old_slave(Config) -> + mam_slave(Config, ?NS_MAM_TMP). + +mam_new_slave(Config) -> + mam_slave(Config, ?NS_MAM_0). + +mam_slave(Config, NS) -> + Peer = ?config(master, Config), + ServerJID = server_jid(Config), + wait_for_master(Config), + send(Config, #presence{}), + ?recv2(#presence{}, #presence{from = Peer}), + #iq{type = result, sub_els = []} = + send_recv(Config, + #iq{type = set, + sub_els = [#mam_prefs{xmlns = NS, default = always}]}), + wait_for_master(Config), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{from = Peer, body = [Text], + sub_els = [#mam_archived{by = ServerJID}]}) + end, lists:seq(1, 5)), + #iq{type = result, sub_els = []} = + send_recv(Config, #iq{type = set, + sub_els = [#mam_prefs{xmlns = NS, default = never}]}), + disconnect(Config). + +mam_query_all(Config, NS) -> + QID = randoms:get_string(), + MyJID = my_jid(Config), + Peer = ?config(slave, Config), + I = send(Config, #iq{type = get, sub_els = [#mam_query{xmlns = NS, id = QID}]}), + maybe_recv_iq_result(NS, I), + Iter = if NS == ?NS_MAM_TMP -> lists:seq(1, 5); + true -> lists:seq(1, 5) ++ lists:seq(1, 5) + end, + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{to = MyJID, + sub_els = + [#mam_result{ + queryid = QID, + sub_els = + [#forwarded{ + delay = #delay{}, + sub_els = + [#message{ + from = MyJID, to = Peer, + body = [Text]}]}]}]}) + end, Iter), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I, sub_els = []}); + true -> + ?recv1(#message{sub_els = [#mam_fin{id = QID}]}) + end. + +mam_query_with(Config, JID, NS) -> + MyJID = my_jid(Config), + Peer = ?config(slave, Config), + Query = if NS == ?NS_MAM_TMP -> + #mam_query{xmlns = NS, with = JID}; + true -> + Fs = [#xdata_field{var = <<"jid">>, + values = [jlib:jid_to_string(JID)]}], + #mam_query{xmlns = NS, + xdata = #xdata{type = submit, fields = Fs}} + end, + I = send(Config, #iq{type = get, sub_els = [Query]}), + Iter = if NS == ?NS_MAM_TMP -> lists:seq(1, 5); + true -> lists:seq(1, 5) ++ lists:seq(1, 5) + end, + maybe_recv_iq_result(NS, I), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{to = MyJID, + sub_els = + [#mam_result{ + sub_els = + [#forwarded{ + delay = #delay{}, + sub_els = + [#message{ + from = MyJID, to = Peer, + body = [Text]}]}]}]}) + end, Iter), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I, sub_els = []}); + true -> + ?recv1(#message{sub_els = [#mam_fin{}]}) + end. + +maybe_recv_iq_result(?NS_MAM_0, I1) -> + ?recv1(#iq{type = result, id = I1}); +maybe_recv_iq_result(_, _) -> + ok. + +mam_query_rsm(Config, NS) -> + MyJID = my_jid(Config), + Peer = ?config(slave, Config), + %% Get the first 3 items out of 5 + I1 = send(Config, + #iq{type = get, + sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 3}}]}), + maybe_recv_iq_result(NS, I1), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{to = MyJID, + sub_els = + [#mam_result{ + xmlns = NS, + sub_els = + [#forwarded{ + delay = #delay{}, + sub_els = + [#message{ + from = MyJID, to = Peer, + body = [Text]}]}]}]}) + end, lists:seq(1, 3)), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I1, + sub_els = [#mam_query{xmlns = NS, + rsm = #rsm_set{last = Last, count = 5}}]}); + true -> + ?recv1(#message{sub_els = [#mam_fin{ + rsm = #rsm_set{last = Last, count = 10}}]}) + end, + %% Get the next items starting from the `Last`. + %% Limit the response to 2 items. + I2 = send(Config, + #iq{type = get, + sub_els = [#mam_query{xmlns = NS, + rsm = #rsm_set{max = 2, + 'after' = Last}}]}), + maybe_recv_iq_result(NS, I2), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{to = MyJID, + sub_els = + [#mam_result{ + xmlns = NS, + sub_els = + [#forwarded{ + delay = #delay{}, + sub_els = + [#message{ + from = MyJID, to = Peer, + body = [Text]}]}]}]}) + end, lists:seq(4, 5)), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I2, + sub_els = [#mam_query{ + xmlns = NS, + rsm = #rsm_set{ + count = 5, + first = #rsm_first{data = First}}}]}); + true -> + ?recv1(#message{ + sub_els = [#mam_fin{ + rsm = #rsm_set{ + count = 10, + first = #rsm_first{data = First}}}]}) + end, + %% Paging back. Should receive 2 elements: 2, 3. + I3 = send(Config, + #iq{type = get, + sub_els = [#mam_query{xmlns = NS, + rsm = #rsm_set{max = 2, + before = First}}]}), + maybe_recv_iq_result(NS, I3), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{to = MyJID, + sub_els = + [#mam_result{ + xmlns = NS, + sub_els = + [#forwarded{ + delay = #delay{}, + sub_els = + [#message{ + from = MyJID, to = Peer, + body = [Text]}]}]}]}) + end, lists:seq(2, 3)), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I3, + sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{count = 5}}]}); + true -> + ?recv1(#message{ + sub_els = [#mam_fin{rsm = #rsm_set{count = 10}}]}) + end, + %% Getting the item count. Should be 5 (or 10). + I4 = send(Config, + #iq{type = get, + sub_els = [#mam_query{xmlns = NS, + rsm = #rsm_set{max = 0}}]}), + maybe_recv_iq_result(NS, I4), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I4, + sub_els = [#mam_query{ + xmlns = NS, + rsm = #rsm_set{count = 5, + first = undefined, + last = undefined}}]}); + true -> + ?recv1(#message{ + sub_els = [#mam_fin{ + rsm = #rsm_set{count = 10, + first = undefined, + last = undefined}}]}) + end. + client_state_master(Config) -> true = ?config(csi, Config), Peer = ?config(slave, Config), diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 0a836b8051e..b1c95ffdf4c 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -39,6 +39,8 @@ host_config: versioning: true store_current_id: true db_type: odbc + mod_mam: + db_type: odbc mod_vcard: db_type: odbc mod_vcard_xupdate: @@ -90,6 +92,8 @@ Welcome to this XMPP server." versioning: true store_current_id: true db_type: odbc + mod_mam: + db_type: odbc mod_vcard: db_type: odbc mod_vcard_xupdate: @@ -147,6 +151,8 @@ Welcome to this XMPP server." versioning: true store_current_id: true db_type: odbc + mod_mam: + db_type: odbc mod_vcard: db_type: odbc mod_vcard_xupdate: @@ -196,6 +202,8 @@ Welcome to this XMPP server." versioning: true store_current_id: true db_type: internal + mod_mam: + db_type: internal mod_vcard: db_type: internal mod_vcard_xupdate: diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 187098abc95..0dbc6280850 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -73,6 +73,65 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> {<<"forwarded">>, <<"urn:xmpp:forward:0">>} -> decode_forwarded(<<"urn:xmpp:forward:0">>, IgnoreEls, _el); + {<<"fin">>, <<"urn:xmpp:mam:0">>} -> + decode_mam_fin(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); + {<<"prefs">>, <<"urn:xmpp:mam:0">>} -> + decode_mam_prefs(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); + {<<"prefs">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_prefs(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"always">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_always(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"never">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_never(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"jid">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_jid(<<"urn:xmpp:mam:tmp">>, IgnoreEls, _el); + {<<"result">>, <<"urn:xmpp:mam:0">>} -> + decode_mam_result(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); + {<<"result">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_result(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"archived">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_archived(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"query">>, <<"urn:xmpp:mam:0">>} -> + decode_mam_query(<<"urn:xmpp:mam:0">>, IgnoreEls, _el); + {<<"query">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_query(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"with">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_with(<<"urn:xmpp:mam:tmp">>, IgnoreEls, _el); + {<<"end">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_end(<<"urn:xmpp:mam:tmp">>, IgnoreEls, _el); + {<<"start">>, <<"urn:xmpp:mam:tmp">>} -> + decode_mam_start(<<"urn:xmpp:mam:tmp">>, IgnoreEls, + _el); + {<<"set">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_set(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"first">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_first(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"max">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_max(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"index">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_index(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"count">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_count(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"last">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_last(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"before">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_before(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); + {<<"after">>, <<"http://jabber.org/protocol/rsm">>} -> + decode_rsm_after(<<"http://jabber.org/protocol/rsm">>, + IgnoreEls, _el); {<<"x">>, <<"http://jabber.org/protocol/muc">>} -> decode_muc(<<"http://jabber.org/protocol/muc">>, IgnoreEls, _el); @@ -1038,6 +1097,36 @@ is_known_tag({xmlel, _name, _attrs, _} = _el) -> {<<"enable">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"disable">>, <<"urn:xmpp:carbons:2">>} -> true; {<<"forwarded">>, <<"urn:xmpp:forward:0">>} -> true; + {<<"fin">>, <<"urn:xmpp:mam:0">>} -> true; + {<<"prefs">>, <<"urn:xmpp:mam:0">>} -> true; + {<<"prefs">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"always">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"never">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"jid">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"result">>, <<"urn:xmpp:mam:0">>} -> true; + {<<"result">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"archived">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"query">>, <<"urn:xmpp:mam:0">>} -> true; + {<<"query">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"with">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"end">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"start">>, <<"urn:xmpp:mam:tmp">>} -> true; + {<<"set">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"first">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"max">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"index">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"count">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"last">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"before">>, <<"http://jabber.org/protocol/rsm">>} -> + true; + {<<"after">>, <<"http://jabber.org/protocol/rsm">>} -> + true; {<<"x">>, <<"http://jabber.org/protocol/muc">>} -> true; {<<"query">>, <<"http://jabber.org/protocol/muc#admin">>} -> @@ -1978,6 +2067,24 @@ encode({muc_admin, _} = Query) -> encode({muc, _, _} = X) -> encode_muc(X, [{<<"xmlns">>, <<"http://jabber.org/protocol/muc">>}]); +encode({rsm_first, _, _} = First) -> + encode_rsm_first(First, + [{<<"xmlns">>, <<"http://jabber.org/protocol/rsm">>}]); +encode({rsm_set, _, _, _, _, _, _, _} = Set) -> + encode_rsm_set(Set, + [{<<"xmlns">>, <<"http://jabber.org/protocol/rsm">>}]); +encode({mam_query, _, _, _, _, _, _, _} = Query) -> + encode_mam_query(Query, []); +encode({mam_archived, _, _} = Archived) -> + encode_mam_archived(Archived, + [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}]); +encode({mam_result, _, _, _, _} = Result) -> + encode_mam_result(Result, []); +encode({mam_prefs, _, _, _, _} = Prefs) -> + encode_mam_prefs(Prefs, []); +encode({mam_fin, _, _} = Fin) -> + encode_mam_fin(Fin, + [{<<"xmlns">>, <<"urn:xmpp:mam:0">>}]); encode({forwarded, _, _} = Forwarded) -> encode_forwarded(Forwarded, [{<<"xmlns">>, <<"urn:xmpp:forward:0">>}]); @@ -2196,6 +2303,12 @@ get_ns({muc_admin, _}) -> <<"http://jabber.org/protocol/muc#admin">>; get_ns({muc, _, _}) -> <<"http://jabber.org/protocol/muc">>; +get_ns({rsm_first, _, _}) -> + <<"http://jabber.org/protocol/rsm">>; +get_ns({rsm_set, _, _, _, _, _, _, _}) -> + <<"http://jabber.org/protocol/rsm">>; +get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>; +get_ns({mam_fin, _, _}) -> <<"urn:xmpp:mam:0">>; get_ns({forwarded, _, _}) -> <<"urn:xmpp:forward:0">>; get_ns({carbons_disable}) -> <<"urn:xmpp:carbons:2">>; get_ns({carbons_enable}) -> <<"urn:xmpp:carbons:2">>; @@ -2384,6 +2497,15 @@ pp(muc_item, 7) -> pp(muc_actor, 2) -> [jid, nick]; pp(muc_admin, 1) -> [items]; pp(muc, 2) -> [history, password]; +pp(rsm_first, 2) -> [index, data]; +pp(rsm_set, 7) -> + ['after', before, count, first, index, last, max]; +pp(mam_query, 7) -> + [xmlns, id, start, 'end', with, rsm, xdata]; +pp(mam_archived, 2) -> [by, id]; +pp(mam_result, 4) -> [xmlns, queryid, id, sub_els]; +pp(mam_prefs, 4) -> [xmlns, default, always, never]; +pp(mam_fin, 2) -> [id, rsm]; pp(forwarded, 2) -> [delay, sub_els]; pp(carbons_disable, 0) -> []; pp(carbons_enable, 0) -> []; @@ -3583,6 +3705,1084 @@ encode_forwarded({forwarded, Delay, __Els}, [{<<"xmlns">>, <<"urn:xmpp:delay">>}]) | _acc]. +decode_mam_fin(__TopXMLNS, __IgnoreEls, + {xmlel, <<"fin">>, _attrs, _els}) -> + Rsm = decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, + undefined), + Id = decode_mam_fin_attrs(__TopXMLNS, _attrs, + undefined), + {mam_fin, Id, Rsm}. + +decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [], Rsm) -> + Rsm; +decode_mam_fin_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"set">>, _attrs, _} = _el | _els], Rsm) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<"http://jabber.org/protocol/rsm">> -> + decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, + decode_rsm_set(_xmlns, __IgnoreEls, _el)); + true -> + decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm) + end; +decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Rsm) -> + decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm). + +decode_mam_fin_attrs(__TopXMLNS, + [{<<"queryid">>, _val} | _attrs], _Id) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, _val); +decode_mam_fin_attrs(__TopXMLNS, [_ | _attrs], Id) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id); +decode_mam_fin_attrs(__TopXMLNS, [], Id) -> + decode_mam_fin_attr_queryid(__TopXMLNS, Id). + +encode_mam_fin({mam_fin, Id, Rsm}, _xmlns_attrs) -> + _els = lists:reverse('encode_mam_fin_$rsm'(Rsm, [])), + _attrs = encode_mam_fin_attr_queryid(Id, _xmlns_attrs), + {xmlel, <<"fin">>, _attrs, _els}. + +'encode_mam_fin_$rsm'(undefined, _acc) -> _acc; +'encode_mam_fin_$rsm'(Rsm, _acc) -> + [encode_rsm_set(Rsm, + [{<<"xmlns">>, <<"http://jabber.org/protocol/rsm">>}]) + | _acc]. + +decode_mam_fin_attr_queryid(__TopXMLNS, undefined) -> + undefined; +decode_mam_fin_attr_queryid(__TopXMLNS, _val) -> _val. + +encode_mam_fin_attr_queryid(undefined, _acc) -> _acc; +encode_mam_fin_attr_queryid(_val, _acc) -> + [{<<"queryid">>, _val} | _acc]. + +decode_mam_prefs(__TopXMLNS, __IgnoreEls, + {xmlel, <<"prefs">>, _attrs, _els}) -> + {Never, Always} = decode_mam_prefs_els(__TopXMLNS, + __IgnoreEls, _els, [], []), + {Default, Xmlns} = decode_mam_prefs_attrs(__TopXMLNS, + _attrs, undefined, undefined), + {mam_prefs, Xmlns, Default, Always, Never}. + +decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, [], Never, + Always) -> + {Never, Always}; +decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"always">>, _attrs, _} = _el | _els], Never, + Always) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els, + Never, + decode_mam_always(__TopXMLNS, __IgnoreEls, + _el)); + true -> + decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els, + Never, Always) + end; +decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"never">>, _attrs, _} = _el | _els], Never, + Always) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els, + decode_mam_never(__TopXMLNS, __IgnoreEls, _el), + Always); + true -> + decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els, + Never, Always) + end; +decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Never, Always) -> + decode_mam_prefs_els(__TopXMLNS, __IgnoreEls, _els, + Never, Always). + +decode_mam_prefs_attrs(__TopXMLNS, + [{<<"default">>, _val} | _attrs], _Default, Xmlns) -> + decode_mam_prefs_attrs(__TopXMLNS, _attrs, _val, Xmlns); +decode_mam_prefs_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], Default, _Xmlns) -> + decode_mam_prefs_attrs(__TopXMLNS, _attrs, Default, + _val); +decode_mam_prefs_attrs(__TopXMLNS, [_ | _attrs], + Default, Xmlns) -> + decode_mam_prefs_attrs(__TopXMLNS, _attrs, Default, + Xmlns); +decode_mam_prefs_attrs(__TopXMLNS, [], Default, + Xmlns) -> + {decode_mam_prefs_attr_default(__TopXMLNS, Default), + decode_mam_prefs_attr_xmlns(__TopXMLNS, Xmlns)}. + +encode_mam_prefs({mam_prefs, Xmlns, Default, Always, + Never}, + _xmlns_attrs) -> + _els = lists:reverse('encode_mam_prefs_$never'(Never, + 'encode_mam_prefs_$always'(Always, + []))), + _attrs = encode_mam_prefs_attr_xmlns(Xmlns, + encode_mam_prefs_attr_default(Default, + _xmlns_attrs)), + {xmlel, <<"prefs">>, _attrs, _els}. + +'encode_mam_prefs_$never'([], _acc) -> _acc; +'encode_mam_prefs_$never'(Never, _acc) -> + [encode_mam_never(Never, + [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}]) + | _acc]. + +'encode_mam_prefs_$always'([], _acc) -> _acc; +'encode_mam_prefs_$always'(Always, _acc) -> + [encode_mam_always(Always, + [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}]) + | _acc]. + +decode_mam_prefs_attr_default(__TopXMLNS, undefined) -> + undefined; +decode_mam_prefs_attr_default(__TopXMLNS, _val) -> + case catch dec_enum(_val, [always, never, roster]) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"default">>, <<"prefs">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_mam_prefs_attr_default(undefined, _acc) -> _acc; +encode_mam_prefs_attr_default(_val, _acc) -> + [{<<"default">>, enc_enum(_val)} | _acc]. + +decode_mam_prefs_attr_xmlns(__TopXMLNS, undefined) -> + undefined; +decode_mam_prefs_attr_xmlns(__TopXMLNS, _val) -> _val. + +encode_mam_prefs_attr_xmlns(undefined, _acc) -> _acc; +encode_mam_prefs_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + +decode_mam_always(__TopXMLNS, __IgnoreEls, + {xmlel, <<"always">>, _attrs, _els}) -> + Jids = decode_mam_always_els(__TopXMLNS, __IgnoreEls, + _els, []), + Jids. + +decode_mam_always_els(__TopXMLNS, __IgnoreEls, [], + Jids) -> + lists:reverse(Jids); +decode_mam_always_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"jid">>, _attrs, _} = _el | _els], Jids) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els, + case decode_mam_jid(__TopXMLNS, __IgnoreEls, + _el) + of + [] -> Jids; + _new_el -> [_new_el | Jids] + end); + true -> + decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els, + Jids) + end; +decode_mam_always_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Jids) -> + decode_mam_always_els(__TopXMLNS, __IgnoreEls, _els, + Jids). + +encode_mam_always(Jids, _xmlns_attrs) -> + _els = lists:reverse('encode_mam_always_$jids'(Jids, + [])), + _attrs = _xmlns_attrs, + {xmlel, <<"always">>, _attrs, _els}. + +'encode_mam_always_$jids'([], _acc) -> _acc; +'encode_mam_always_$jids'([Jids | _els], _acc) -> + 'encode_mam_always_$jids'(_els, + [encode_mam_jid(Jids, []) | _acc]). + +decode_mam_never(__TopXMLNS, __IgnoreEls, + {xmlel, <<"never">>, _attrs, _els}) -> + Jids = decode_mam_never_els(__TopXMLNS, __IgnoreEls, + _els, []), + Jids. + +decode_mam_never_els(__TopXMLNS, __IgnoreEls, [], + Jids) -> + lists:reverse(Jids); +decode_mam_never_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"jid">>, _attrs, _} = _el | _els], Jids) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els, + case decode_mam_jid(__TopXMLNS, __IgnoreEls, + _el) + of + [] -> Jids; + _new_el -> [_new_el | Jids] + end); + true -> + decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els, + Jids) + end; +decode_mam_never_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Jids) -> + decode_mam_never_els(__TopXMLNS, __IgnoreEls, _els, + Jids). + +encode_mam_never(Jids, _xmlns_attrs) -> + _els = lists:reverse('encode_mam_never_$jids'(Jids, + [])), + _attrs = _xmlns_attrs, + {xmlel, <<"never">>, _attrs, _els}. + +'encode_mam_never_$jids'([], _acc) -> _acc; +'encode_mam_never_$jids'([Jids | _els], _acc) -> + 'encode_mam_never_$jids'(_els, + [encode_mam_jid(Jids, []) | _acc]). + +decode_mam_jid(__TopXMLNS, __IgnoreEls, + {xmlel, <<"jid">>, _attrs, _els}) -> + Cdata = decode_mam_jid_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_mam_jid_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_mam_jid_cdata(__TopXMLNS, Cdata); +decode_mam_jid_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_mam_jid_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_mam_jid_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_mam_jid_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_mam_jid(Cdata, _xmlns_attrs) -> + _els = encode_mam_jid_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"jid">>, _attrs, _els}. + +decode_mam_jid_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"jid">>, __TopXMLNS}}); +decode_mam_jid_cdata(__TopXMLNS, _val) -> + case catch dec_jid(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"jid">>, __TopXMLNS}}); + _res -> _res + end. + +encode_mam_jid_cdata(_val, _acc) -> + [{xmlcdata, enc_jid(_val)} | _acc]. + +decode_mam_result(__TopXMLNS, __IgnoreEls, + {xmlel, <<"result">>, _attrs, _els}) -> + __Els = decode_mam_result_els(__TopXMLNS, __IgnoreEls, + _els, []), + {Queryid, Xmlns, Id} = + decode_mam_result_attrs(__TopXMLNS, _attrs, undefined, + undefined, undefined), + {mam_result, Xmlns, Queryid, Id, __Els}. + +decode_mam_result_els(__TopXMLNS, __IgnoreEls, [], + __Els) -> + lists:reverse(__Els); +decode_mam_result_els(__TopXMLNS, __IgnoreEls, + [{xmlel, _, _, _} = _el | _els], __Els) -> + if __IgnoreEls -> + decode_mam_result_els(__TopXMLNS, __IgnoreEls, _els, + [_el | __Els]); + true -> + case is_known_tag(_el) of + true -> + decode_mam_result_els(__TopXMLNS, __IgnoreEls, _els, + [decode(_el) | __Els]); + false -> + decode_mam_result_els(__TopXMLNS, __IgnoreEls, _els, + __Els) + end + end; +decode_mam_result_els(__TopXMLNS, __IgnoreEls, + [_ | _els], __Els) -> + decode_mam_result_els(__TopXMLNS, __IgnoreEls, _els, + __Els). + +decode_mam_result_attrs(__TopXMLNS, + [{<<"queryid">>, _val} | _attrs], _Queryid, Xmlns, + Id) -> + decode_mam_result_attrs(__TopXMLNS, _attrs, _val, Xmlns, + Id); +decode_mam_result_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], Queryid, _Xmlns, Id) -> + decode_mam_result_attrs(__TopXMLNS, _attrs, Queryid, + _val, Id); +decode_mam_result_attrs(__TopXMLNS, + [{<<"id">>, _val} | _attrs], Queryid, Xmlns, _Id) -> + decode_mam_result_attrs(__TopXMLNS, _attrs, Queryid, + Xmlns, _val); +decode_mam_result_attrs(__TopXMLNS, [_ | _attrs], + Queryid, Xmlns, Id) -> + decode_mam_result_attrs(__TopXMLNS, _attrs, Queryid, + Xmlns, Id); +decode_mam_result_attrs(__TopXMLNS, [], Queryid, Xmlns, + Id) -> + {decode_mam_result_attr_queryid(__TopXMLNS, Queryid), + decode_mam_result_attr_xmlns(__TopXMLNS, Xmlns), + decode_mam_result_attr_id(__TopXMLNS, Id)}. + +encode_mam_result({mam_result, Xmlns, Queryid, Id, + __Els}, + _xmlns_attrs) -> + _els = [encode(_el) || _el <- __Els], + _attrs = encode_mam_result_attr_id(Id, + encode_mam_result_attr_xmlns(Xmlns, + encode_mam_result_attr_queryid(Queryid, + _xmlns_attrs))), + {xmlel, <<"result">>, _attrs, _els}. + +decode_mam_result_attr_queryid(__TopXMLNS, undefined) -> + undefined; +decode_mam_result_attr_queryid(__TopXMLNS, _val) -> + _val. + +encode_mam_result_attr_queryid(undefined, _acc) -> _acc; +encode_mam_result_attr_queryid(_val, _acc) -> + [{<<"queryid">>, _val} | _acc]. + +decode_mam_result_attr_xmlns(__TopXMLNS, undefined) -> + undefined; +decode_mam_result_attr_xmlns(__TopXMLNS, _val) -> _val. + +encode_mam_result_attr_xmlns(undefined, _acc) -> _acc; +encode_mam_result_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + +decode_mam_result_attr_id(__TopXMLNS, undefined) -> + undefined; +decode_mam_result_attr_id(__TopXMLNS, _val) -> _val. + +encode_mam_result_attr_id(undefined, _acc) -> _acc; +encode_mam_result_attr_id(_val, _acc) -> + [{<<"id">>, _val} | _acc]. + +decode_mam_archived(__TopXMLNS, __IgnoreEls, + {xmlel, <<"archived">>, _attrs, _els}) -> + {Id, By} = decode_mam_archived_attrs(__TopXMLNS, _attrs, + undefined, undefined), + {mam_archived, By, Id}. + +decode_mam_archived_attrs(__TopXMLNS, + [{<<"id">>, _val} | _attrs], _Id, By) -> + decode_mam_archived_attrs(__TopXMLNS, _attrs, _val, By); +decode_mam_archived_attrs(__TopXMLNS, + [{<<"by">>, _val} | _attrs], Id, _By) -> + decode_mam_archived_attrs(__TopXMLNS, _attrs, Id, _val); +decode_mam_archived_attrs(__TopXMLNS, [_ | _attrs], Id, + By) -> + decode_mam_archived_attrs(__TopXMLNS, _attrs, Id, By); +decode_mam_archived_attrs(__TopXMLNS, [], Id, By) -> + {decode_mam_archived_attr_id(__TopXMLNS, Id), + decode_mam_archived_attr_by(__TopXMLNS, By)}. + +encode_mam_archived({mam_archived, By, Id}, + _xmlns_attrs) -> + _els = [], + _attrs = encode_mam_archived_attr_by(By, + encode_mam_archived_attr_id(Id, + _xmlns_attrs)), + {xmlel, <<"archived">>, _attrs, _els}. + +decode_mam_archived_attr_id(__TopXMLNS, undefined) -> + undefined; +decode_mam_archived_attr_id(__TopXMLNS, _val) -> _val. + +encode_mam_archived_attr_id(undefined, _acc) -> _acc; +encode_mam_archived_attr_id(_val, _acc) -> + [{<<"id">>, _val} | _acc]. + +decode_mam_archived_attr_by(__TopXMLNS, undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"by">>, <<"archived">>, __TopXMLNS}}); +decode_mam_archived_attr_by(__TopXMLNS, _val) -> + case catch dec_jid(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"by">>, <<"archived">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_mam_archived_attr_by(_val, _acc) -> + [{<<"by">>, enc_jid(_val)} | _acc]. + +decode_mam_query(__TopXMLNS, __IgnoreEls, + {xmlel, <<"query">>, _attrs, _els}) -> + {Xdata, End, Start, With, Rsm} = + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + undefined, undefined, undefined, undefined, + undefined), + {Id, Xmlns} = decode_mam_query_attrs(__TopXMLNS, _attrs, + undefined, undefined), + {mam_query, Xmlns, Id, Start, End, With, Rsm, Xdata}. + +decode_mam_query_els(__TopXMLNS, __IgnoreEls, [], Xdata, + End, Start, With, Rsm) -> + {Xdata, End, Start, With, Rsm}; +decode_mam_query_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"start">>, _attrs, _} = _el | _els], Xdata, + End, Start, With, Rsm) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, + decode_mam_start(__TopXMLNS, __IgnoreEls, _el), + With, Rsm); + true -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, Rsm) + end; +decode_mam_query_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"end">>, _attrs, _} = _el | _els], Xdata, + End, Start, With, Rsm) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, + decode_mam_end(__TopXMLNS, __IgnoreEls, _el), + Start, With, Rsm); + true -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, Rsm) + end; +decode_mam_query_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"with">>, _attrs, _} = _el | _els], Xdata, + End, Start, With, Rsm) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, + decode_mam_with(__TopXMLNS, __IgnoreEls, _el), + Rsm); + true -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, Rsm) + end; +decode_mam_query_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"set">>, _attrs, _} = _el | _els], Xdata, + End, Start, With, Rsm) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<"http://jabber.org/protocol/rsm">> -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, + decode_rsm_set(_xmlns, __IgnoreEls, _el)); + true -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, Rsm) + end; +decode_mam_query_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"x">>, _attrs, _} = _el | _els], Xdata, End, + Start, With, Rsm) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<"jabber:x:data">> -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + decode_xdata(_xmlns, __IgnoreEls, _el), End, + Start, With, Rsm); + true -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, Rsm) + end; +decode_mam_query_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Xdata, End, Start, With, Rsm) -> + decode_mam_query_els(__TopXMLNS, __IgnoreEls, _els, + Xdata, End, Start, With, Rsm). + +decode_mam_query_attrs(__TopXMLNS, + [{<<"queryid">>, _val} | _attrs], _Id, Xmlns) -> + decode_mam_query_attrs(__TopXMLNS, _attrs, _val, Xmlns); +decode_mam_query_attrs(__TopXMLNS, + [{<<"xmlns">>, _val} | _attrs], Id, _Xmlns) -> + decode_mam_query_attrs(__TopXMLNS, _attrs, Id, _val); +decode_mam_query_attrs(__TopXMLNS, [_ | _attrs], Id, + Xmlns) -> + decode_mam_query_attrs(__TopXMLNS, _attrs, Id, Xmlns); +decode_mam_query_attrs(__TopXMLNS, [], Id, Xmlns) -> + {decode_mam_query_attr_queryid(__TopXMLNS, Id), + decode_mam_query_attr_xmlns(__TopXMLNS, Xmlns)}. + +encode_mam_query({mam_query, Xmlns, Id, Start, End, + With, Rsm, Xdata}, + _xmlns_attrs) -> + _els = lists:reverse('encode_mam_query_$xdata'(Xdata, + 'encode_mam_query_$end'(End, + 'encode_mam_query_$start'(Start, + 'encode_mam_query_$with'(With, + 'encode_mam_query_$rsm'(Rsm, + [])))))), + _attrs = encode_mam_query_attr_xmlns(Xmlns, + encode_mam_query_attr_queryid(Id, + _xmlns_attrs)), + {xmlel, <<"query">>, _attrs, _els}. + +'encode_mam_query_$xdata'(undefined, _acc) -> _acc; +'encode_mam_query_$xdata'(Xdata, _acc) -> + [encode_xdata(Xdata, + [{<<"xmlns">>, <<"jabber:x:data">>}]) + | _acc]. + +'encode_mam_query_$end'(undefined, _acc) -> _acc; +'encode_mam_query_$end'(End, _acc) -> + [encode_mam_end(End, + [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}]) + | _acc]. + +'encode_mam_query_$start'(undefined, _acc) -> _acc; +'encode_mam_query_$start'(Start, _acc) -> + [encode_mam_start(Start, + [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}]) + | _acc]. + +'encode_mam_query_$with'(undefined, _acc) -> _acc; +'encode_mam_query_$with'(With, _acc) -> + [encode_mam_with(With, + [{<<"xmlns">>, <<"urn:xmpp:mam:tmp">>}]) + | _acc]. + +'encode_mam_query_$rsm'(undefined, _acc) -> _acc; +'encode_mam_query_$rsm'(Rsm, _acc) -> + [encode_rsm_set(Rsm, + [{<<"xmlns">>, <<"http://jabber.org/protocol/rsm">>}]) + | _acc]. + +decode_mam_query_attr_queryid(__TopXMLNS, undefined) -> + undefined; +decode_mam_query_attr_queryid(__TopXMLNS, _val) -> _val. + +encode_mam_query_attr_queryid(undefined, _acc) -> _acc; +encode_mam_query_attr_queryid(_val, _acc) -> + [{<<"queryid">>, _val} | _acc]. + +decode_mam_query_attr_xmlns(__TopXMLNS, undefined) -> + undefined; +decode_mam_query_attr_xmlns(__TopXMLNS, _val) -> _val. + +encode_mam_query_attr_xmlns(undefined, _acc) -> _acc; +encode_mam_query_attr_xmlns(_val, _acc) -> + [{<<"xmlns">>, _val} | _acc]. + +decode_mam_with(__TopXMLNS, __IgnoreEls, + {xmlel, <<"with">>, _attrs, _els}) -> + Cdata = decode_mam_with_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_mam_with_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_mam_with_cdata(__TopXMLNS, Cdata); +decode_mam_with_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_mam_with_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_mam_with_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_mam_with_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_mam_with(Cdata, _xmlns_attrs) -> + _els = encode_mam_with_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"with">>, _attrs, _els}. + +decode_mam_with_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"with">>, __TopXMLNS}}); +decode_mam_with_cdata(__TopXMLNS, _val) -> + case catch dec_jid(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"with">>, __TopXMLNS}}); + _res -> _res + end. + +encode_mam_with_cdata(_val, _acc) -> + [{xmlcdata, enc_jid(_val)} | _acc]. + +decode_mam_end(__TopXMLNS, __IgnoreEls, + {xmlel, <<"end">>, _attrs, _els}) -> + Cdata = decode_mam_end_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_mam_end_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_mam_end_cdata(__TopXMLNS, Cdata); +decode_mam_end_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_mam_end_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_mam_end_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_mam_end_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_mam_end(Cdata, _xmlns_attrs) -> + _els = encode_mam_end_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"end">>, _attrs, _els}. + +decode_mam_end_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"end">>, __TopXMLNS}}); +decode_mam_end_cdata(__TopXMLNS, _val) -> + case catch dec_utc(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"end">>, __TopXMLNS}}); + _res -> _res + end. + +encode_mam_end_cdata(_val, _acc) -> + [{xmlcdata, enc_utc(_val)} | _acc]. + +decode_mam_start(__TopXMLNS, __IgnoreEls, + {xmlel, <<"start">>, _attrs, _els}) -> + Cdata = decode_mam_start_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_mam_start_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_mam_start_cdata(__TopXMLNS, Cdata); +decode_mam_start_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_mam_start_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_mam_start_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Cdata) -> + decode_mam_start_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_mam_start(Cdata, _xmlns_attrs) -> + _els = encode_mam_start_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"start">>, _attrs, _els}. + +decode_mam_start_cdata(__TopXMLNS, <<>>) -> + erlang:error({xmpp_codec, + {missing_cdata, <<>>, <<"start">>, __TopXMLNS}}); +decode_mam_start_cdata(__TopXMLNS, _val) -> + case catch dec_utc(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"start">>, __TopXMLNS}}); + _res -> _res + end. + +encode_mam_start_cdata(_val, _acc) -> + [{xmlcdata, enc_utc(_val)} | _acc]. + +decode_rsm_set(__TopXMLNS, __IgnoreEls, + {xmlel, <<"set">>, _attrs, _els}) -> + {After, Last, First, Count, Before, Max, Index} = + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, + undefined, undefined, undefined, undefined, + undefined, undefined, undefined), + {rsm_set, After, Before, Count, First, Index, Last, + Max}. + +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, [], After, + Last, First, Count, Before, Max, Index) -> + {After, Last, First, Count, Before, Max, Index}; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"after">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, + decode_rsm_after(__TopXMLNS, __IgnoreEls, _el), + Last, First, Count, Before, Max, Index); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"before">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, + decode_rsm_before(__TopXMLNS, __IgnoreEls, _el), + Max, Index); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"count">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, + decode_rsm_count(__TopXMLNS, __IgnoreEls, _el), + Before, Max, Index); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"first">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, + decode_rsm_first(__TopXMLNS, __IgnoreEls, _el), + Count, Before, Max, Index); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"index">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, + decode_rsm_index(__TopXMLNS, __IgnoreEls, _el)); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"last">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + decode_rsm_last(__TopXMLNS, __IgnoreEls, _el), + First, Count, Before, Max, Index); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"max">>, _attrs, _} = _el | _els], After, + Last, First, Count, Before, Max, Index) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, + decode_rsm_max(__TopXMLNS, __IgnoreEls, _el), + Index); + true -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index) + end; +decode_rsm_set_els(__TopXMLNS, __IgnoreEls, [_ | _els], + After, Last, First, Count, Before, Max, Index) -> + decode_rsm_set_els(__TopXMLNS, __IgnoreEls, _els, After, + Last, First, Count, Before, Max, Index). + +encode_rsm_set({rsm_set, After, Before, Count, First, + Index, Last, Max}, + _xmlns_attrs) -> + _els = lists:reverse('encode_rsm_set_$after'(After, + 'encode_rsm_set_$last'(Last, + 'encode_rsm_set_$first'(First, + 'encode_rsm_set_$count'(Count, + 'encode_rsm_set_$before'(Before, + 'encode_rsm_set_$max'(Max, + 'encode_rsm_set_$index'(Index, + [])))))))), + _attrs = _xmlns_attrs, + {xmlel, <<"set">>, _attrs, _els}. + +'encode_rsm_set_$after'(undefined, _acc) -> _acc; +'encode_rsm_set_$after'(After, _acc) -> + [encode_rsm_after(After, []) | _acc]. + +'encode_rsm_set_$last'(undefined, _acc) -> _acc; +'encode_rsm_set_$last'(Last, _acc) -> + [encode_rsm_last(Last, []) | _acc]. + +'encode_rsm_set_$first'(undefined, _acc) -> _acc; +'encode_rsm_set_$first'(First, _acc) -> + [encode_rsm_first(First, []) | _acc]. + +'encode_rsm_set_$count'(undefined, _acc) -> _acc; +'encode_rsm_set_$count'(Count, _acc) -> + [encode_rsm_count(Count, []) | _acc]. + +'encode_rsm_set_$before'(undefined, _acc) -> _acc; +'encode_rsm_set_$before'(Before, _acc) -> + [encode_rsm_before(Before, []) | _acc]. + +'encode_rsm_set_$max'(undefined, _acc) -> _acc; +'encode_rsm_set_$max'(Max, _acc) -> + [encode_rsm_max(Max, []) | _acc]. + +'encode_rsm_set_$index'(undefined, _acc) -> _acc; +'encode_rsm_set_$index'(Index, _acc) -> + [encode_rsm_index(Index, []) | _acc]. + +decode_rsm_first(__TopXMLNS, __IgnoreEls, + {xmlel, <<"first">>, _attrs, _els}) -> + Data = decode_rsm_first_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Index = decode_rsm_first_attrs(__TopXMLNS, _attrs, + undefined), + {rsm_first, Index, Data}. + +decode_rsm_first_els(__TopXMLNS, __IgnoreEls, [], + Data) -> + decode_rsm_first_cdata(__TopXMLNS, Data); +decode_rsm_first_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Data) -> + decode_rsm_first_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_first_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Data) -> + decode_rsm_first_els(__TopXMLNS, __IgnoreEls, _els, + Data). + +decode_rsm_first_attrs(__TopXMLNS, + [{<<"index">>, _val} | _attrs], _Index) -> + decode_rsm_first_attrs(__TopXMLNS, _attrs, _val); +decode_rsm_first_attrs(__TopXMLNS, [_ | _attrs], + Index) -> + decode_rsm_first_attrs(__TopXMLNS, _attrs, Index); +decode_rsm_first_attrs(__TopXMLNS, [], Index) -> + decode_rsm_first_attr_index(__TopXMLNS, Index). + +encode_rsm_first({rsm_first, Index, Data}, + _xmlns_attrs) -> + _els = encode_rsm_first_cdata(Data, []), + _attrs = encode_rsm_first_attr_index(Index, + _xmlns_attrs), + {xmlel, <<"first">>, _attrs, _els}. + +decode_rsm_first_attr_index(__TopXMLNS, undefined) -> + undefined; +decode_rsm_first_attr_index(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, infinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"index">>, <<"first">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_rsm_first_attr_index(undefined, _acc) -> _acc; +encode_rsm_first_attr_index(_val, _acc) -> + [{<<"index">>, enc_int(_val)} | _acc]. + +decode_rsm_first_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_first_cdata(__TopXMLNS, _val) -> _val. + +encode_rsm_first_cdata(undefined, _acc) -> _acc; +encode_rsm_first_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_rsm_max(__TopXMLNS, __IgnoreEls, + {xmlel, <<"max">>, _attrs, _els}) -> + Cdata = decode_rsm_max_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_rsm_max_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_rsm_max_cdata(__TopXMLNS, Cdata); +decode_rsm_max_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_rsm_max_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_max_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_rsm_max_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_rsm_max(Cdata, _xmlns_attrs) -> + _els = encode_rsm_max_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"max">>, _attrs, _els}. + +decode_rsm_max_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_max_cdata(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, infinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"max">>, __TopXMLNS}}); + _res -> _res + end. + +encode_rsm_max_cdata(undefined, _acc) -> _acc; +encode_rsm_max_cdata(_val, _acc) -> + [{xmlcdata, enc_int(_val)} | _acc]. + +decode_rsm_index(__TopXMLNS, __IgnoreEls, + {xmlel, <<"index">>, _attrs, _els}) -> + Cdata = decode_rsm_index_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_rsm_index_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_rsm_index_cdata(__TopXMLNS, Cdata); +decode_rsm_index_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_rsm_index_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_index_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Cdata) -> + decode_rsm_index_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_rsm_index(Cdata, _xmlns_attrs) -> + _els = encode_rsm_index_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"index">>, _attrs, _els}. + +decode_rsm_index_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_index_cdata(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, infinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"index">>, __TopXMLNS}}); + _res -> _res + end. + +encode_rsm_index_cdata(undefined, _acc) -> _acc; +encode_rsm_index_cdata(_val, _acc) -> + [{xmlcdata, enc_int(_val)} | _acc]. + +decode_rsm_count(__TopXMLNS, __IgnoreEls, + {xmlel, <<"count">>, _attrs, _els}) -> + Cdata = decode_rsm_count_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_rsm_count_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_rsm_count_cdata(__TopXMLNS, Cdata); +decode_rsm_count_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_rsm_count_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_count_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Cdata) -> + decode_rsm_count_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_rsm_count(Cdata, _xmlns_attrs) -> + _els = encode_rsm_count_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"count">>, _attrs, _els}. + +decode_rsm_count_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_count_cdata(__TopXMLNS, _val) -> + case catch dec_int(_val, 0, infinity) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_cdata_value, <<>>, <<"count">>, __TopXMLNS}}); + _res -> _res + end. + +encode_rsm_count_cdata(undefined, _acc) -> _acc; +encode_rsm_count_cdata(_val, _acc) -> + [{xmlcdata, enc_int(_val)} | _acc]. + +decode_rsm_last(__TopXMLNS, __IgnoreEls, + {xmlel, <<"last">>, _attrs, _els}) -> + Cdata = decode_rsm_last_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_rsm_last_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_rsm_last_cdata(__TopXMLNS, Cdata); +decode_rsm_last_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_rsm_last_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_last_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Cdata) -> + decode_rsm_last_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_rsm_last(Cdata, _xmlns_attrs) -> + _els = encode_rsm_last_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"last">>, _attrs, _els}. + +decode_rsm_last_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_last_cdata(__TopXMLNS, _val) -> _val. + +encode_rsm_last_cdata(undefined, _acc) -> _acc; +encode_rsm_last_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_rsm_before(__TopXMLNS, __IgnoreEls, + {xmlel, <<"before">>, _attrs, _els}) -> + Cdata = decode_rsm_before_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_rsm_before_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_rsm_before_cdata(__TopXMLNS, Cdata); +decode_rsm_before_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_rsm_before_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_before_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Cdata) -> + decode_rsm_before_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_rsm_before(Cdata, _xmlns_attrs) -> + _els = encode_rsm_before_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"before">>, _attrs, _els}. + +decode_rsm_before_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_before_cdata(__TopXMLNS, _val) -> _val. + +encode_rsm_before_cdata(undefined, _acc) -> _acc; +encode_rsm_before_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + +decode_rsm_after(__TopXMLNS, __IgnoreEls, + {xmlel, <<"after">>, _attrs, _els}) -> + Cdata = decode_rsm_after_els(__TopXMLNS, __IgnoreEls, + _els, <<>>), + Cdata. + +decode_rsm_after_els(__TopXMLNS, __IgnoreEls, [], + Cdata) -> + decode_rsm_after_cdata(__TopXMLNS, Cdata); +decode_rsm_after_els(__TopXMLNS, __IgnoreEls, + [{xmlcdata, _data} | _els], Cdata) -> + decode_rsm_after_els(__TopXMLNS, __IgnoreEls, _els, + <>); +decode_rsm_after_els(__TopXMLNS, __IgnoreEls, + [_ | _els], Cdata) -> + decode_rsm_after_els(__TopXMLNS, __IgnoreEls, _els, + Cdata). + +encode_rsm_after(Cdata, _xmlns_attrs) -> + _els = encode_rsm_after_cdata(Cdata, []), + _attrs = _xmlns_attrs, + {xmlel, <<"after">>, _attrs, _els}. + +decode_rsm_after_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_after_cdata(__TopXMLNS, _val) -> _val. + +encode_rsm_after_cdata(undefined, _acc) -> _acc; +encode_rsm_after_cdata(_val, _acc) -> + [{xmlcdata, _val} | _acc]. + decode_muc(__TopXMLNS, __IgnoreEls, {xmlel, <<"x">>, _attrs, _els}) -> History = decode_muc_els(__TopXMLNS, __IgnoreEls, _els, diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index af5903c93a7..567946fe2e6 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -9,6 +9,14 @@ -record(sasl_success, {text :: any()}). +-record(mam_result, {xmlns :: binary(), + queryid :: binary(), + id :: binary(), + sub_els = [] :: [any()]}). + +-record(rsm_first, {index :: non_neg_integer(), + data :: binary()}). + -record(text, {lang :: binary(), data :: binary()}). @@ -176,6 +184,11 @@ -record(shim, {headers = [] :: [{binary(),'undefined' | binary()}]}). +-record(mam_prefs, {xmlns :: binary(), + default :: 'always' | 'never' | 'roster', + always = [] :: [any()], + never = [] :: [any()]}). + -record(caps, {hash :: binary(), node :: binary(), ver :: any()}). @@ -194,6 +207,9 @@ -record(carbons_sent, {forwarded :: #forwarded{}}). +-record(mam_archived, {by :: any(), + id :: binary()}). + -record(p1_rebind, {}). -record(compress_failure, {reason :: 'processing-failed' | 'setup-failed' | 'unsupported-method'}). @@ -263,6 +279,17 @@ -record(vcard_org, {name :: binary(), units = [] :: [binary()]}). +-record(rsm_set, {'after' :: binary(), + before :: binary(), + count :: non_neg_integer(), + first :: #rsm_first{}, + index :: non_neg_integer(), + last :: binary(), + max :: non_neg_integer()}). + +-record(mam_fin, {id :: binary(), + rsm :: #rsm_set{}}). + -record(vcard_tel, {home = false :: boolean(), work = false :: boolean(), voice = false :: boolean(), @@ -343,6 +370,14 @@ items = [] :: [[#xdata_field{}]], fields = [] :: [#xdata_field{}]}). +-record(mam_query, {xmlns :: binary(), + id :: binary(), + start :: any(), + 'end' :: any(), + with :: any(), + rsm :: #rsm_set{}, + xdata :: #xdata{}}). + -record(muc_owner, {destroy :: #muc_owner_destroy{}, config :: #xdata{}}). diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index e8cf0612b76..dfa516ef5df 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2063,6 +2063,156 @@ refs = [#ref{name = muc_history, min = 0, max = 1, label = '$history'}]}). +-xml(rsm_after, + #elem{name = <<"after">>, + xmlns = <<"http://jabber.org/protocol/rsm">>, + result = '$cdata'}). + +-xml(rsm_before, + #elem{name = <<"before">>, + xmlns = <<"http://jabber.org/protocol/rsm">>, + result = '$cdata'}). + +-xml(rsm_last, + #elem{name = <<"last">>, + xmlns = <<"http://jabber.org/protocol/rsm">>, + result = '$cdata'}). + +-xml(rsm_count, + #elem{name = <<"count">>, result = '$cdata', + xmlns = <<"http://jabber.org/protocol/rsm">>, + cdata = #cdata{dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}}). + +-xml(rsm_index, + #elem{name = <<"index">>, result = '$cdata', + xmlns = <<"http://jabber.org/protocol/rsm">>, + cdata = #cdata{dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}}). + +-xml(rsm_max, + #elem{name = <<"max">>, result = '$cdata', + xmlns = <<"http://jabber.org/protocol/rsm">>, + cdata = #cdata{dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}}). + +-xml(rsm_first, + #elem{name = <<"first">>, + xmlns = <<"http://jabber.org/protocol/rsm">>, + result = {rsm_first, '$index', '$data'}, + cdata = #cdata{label = '$data'}, + attrs = [#attr{name = <<"index">>, + dec = {dec_int, [0, infinity]}, + enc = {enc_int, []}}]}). + +-xml(rsm_set, + #elem{name = <<"set">>, + xmlns = <<"http://jabber.org/protocol/rsm">>, + result = {rsm_set, '$after', '$before', '$count', + '$first', '$index', '$last', '$max'}, + refs = [#ref{name = rsm_after, label = '$after', min = 0, max = 1}, + #ref{name = rsm_before, label = '$before', min = 0, max = 1}, + #ref{name = rsm_count, label = '$count', min = 0, max = 1}, + #ref{name = rsm_first, label = '$first', min = 0, max = 1}, + #ref{name = rsm_index, label = '$index', min = 0, max = 1}, + #ref{name = rsm_last, label = '$last', min = 0, max = 1}, + #ref{name = rsm_max, label = '$max', min = 0, max = 1}]}). + +-xml(mam_start, + #elem{name = <<"start">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = '$cdata', + cdata = #cdata{required = true, + dec = {dec_utc, []}, + enc = {enc_utc, []}}}). + +-xml(mam_end, + #elem{name = <<"end">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = '$cdata', + cdata = #cdata{required = true, + dec = {dec_utc, []}, + enc = {enc_utc, []}}}). + +-xml(mam_with, + #elem{name = <<"with">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = '$cdata', + cdata = #cdata{required = true, + dec = {dec_jid, []}, + enc = {enc_jid, []}}}). + +-xml(mam_query, + #elem{name = <<"query">>, + xmlns = [<<"urn:xmpp:mam:0">>, <<"urn:xmpp:mam:tmp">>], + result = {mam_query, '$xmlns', '$id', '$start', '$end', '$with', + '$rsm', '$xdata'}, + attrs = [#attr{name = <<"queryid">>, label = '$id'}, + #attr{name = <<"xmlns">>}], + refs = [#ref{name = mam_start, min = 0, max = 1, label = '$start'}, + #ref{name = mam_end, min = 0, max = 1, label = '$end'}, + #ref{name = mam_with, min = 0, max = 1, label = '$with'}, + #ref{name = rsm_set, min = 0, max = 1, label = '$rsm'}, + #ref{name = xdata, min = 0, max = 1, label = '$xdata'}]}). + +-xml(mam_archived, + #elem{name = <<"archived">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = {mam_archived, '$by', '$id'}, + attrs = [#attr{name = <<"id">>}, + #attr{name = <<"by">>, + required = true, + dec = {dec_jid, []}, + enc = {enc_jid, []}}]}). + +-xml(mam_result, + #elem{name = <<"result">>, + xmlns = [<<"urn:xmpp:mam:0">>, <<"urn:xmpp:mam:tmp">>], + result = {mam_result, '$xmlns', '$queryid', '$id', '$_els'}, + attrs = [#attr{name = <<"queryid">>}, + #attr{name = <<"xmlns">>}, + #attr{name = <<"id">>}]}). + +-xml(mam_jid, + #elem{name = <<"jid">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = '$cdata', + cdata = #cdata{required = true, + dec = {dec_jid, []}, + enc = {enc_jid, []}}}). + +-xml(mam_never, + #elem{name = <<"never">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = '$jids', + refs = [#ref{name = mam_jid, label = '$jids', default = []}]}). + +-xml(mam_always, + #elem{name = <<"always">>, + xmlns = <<"urn:xmpp:mam:tmp">>, + result = '$jids', + refs = [#ref{name = mam_jid, label = '$jids', default = []}]}). + +-xml(mam_prefs, + #elem{name = <<"prefs">>, + xmlns = [<<"urn:xmpp:mam:0">>, <<"urn:xmpp:mam:tmp">>], + result = {mam_prefs, '$xmlns', '$default', '$always', '$never'}, + attrs = [#attr{name = <<"default">>, + dec = {dec_enum, [[always, never, roster]]}, + enc = {enc_enum, []}}, + #attr{name = <<"xmlns">>}], + refs = [#ref{name = mam_always, label = '$always', + min = 0, max = 1, default = []}, + #ref{name = mam_never, label = '$never', + min = 0, max = 1, default = []}]}). + +-xml(mam_fin, + #elem{name = <<"fin">>, + xmlns = <<"urn:xmpp:mam:0">>, + result = {mam_fin, '$id', '$rsm'}, + attrs = [#attr{name = <<"queryid">>, label = '$id'}], + refs = [#ref{name = rsm_set, min = 0, max = 1, label = '$rsm'}]}). + -xml(forwarded, #elem{name = <<"forwarded">>, xmlns = <<"urn:xmpp:forward:0">>, From 72f35a6dc635cac3099d3ab29bc8e2e9629d8d0f Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 24 Jun 2015 11:58:37 +0200 Subject: [PATCH 130/695] Add xep definition to mod_mam --- src/mod_mam.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 1de1d9a9548..edbc4f91ae3 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -26,6 +26,8 @@ %%%------------------------------------------------------------------- -module(mod_mam). +-protocol({xep, 313, '0.3'}). + -behaviour(gen_mod). %% API From 4ae1b4db03f4cea0fd1d7639ac58eb58cbb19efd Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 25 Jun 2015 13:39:45 +0200 Subject: [PATCH 131/695] When passwords are scrammed, report check_password_hash cannot work (#559) --- src/mod_admin_extra.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 6fbf762eb73..436108ead4f 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -515,12 +515,16 @@ set_password(User, Host, Password) -> %% Copied some code from ejabberd_commands.erl check_password_hash(User, Host, PasswordHash, HashMethod) -> AccountPass = ejabberd_auth:get_password_s(User, Host), - AccountPassHash = case HashMethod of - "md5" -> get_md5(AccountPass); - "sha" -> get_sha(AccountPass); + AccountPassHash = case {AccountPass, HashMethod} of + {A, _} when is_tuple(A) -> scrammed; + {_, "md5"} -> get_md5(AccountPass); + {_, "sha"} -> get_sha(AccountPass); _ -> undefined end, case AccountPassHash of + scrammed -> + ?ERROR_MSG("Passwords are scrammed, and check_password_hash can not work.", []), + throw(passwords_scrammed_command_cannot_work); undefined -> error; PasswordHash -> ok; _ -> error From 7c7e51b6e8d2cee4fb9ed29bcbd5e58081df1bd9 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 28 Jun 2015 14:05:55 +0200 Subject: [PATCH 132/695] Omit warning message regarding non-anonymous room Previous versions of XEP-0045 suggested sending a warning message to new occupants of a non-anonymous MUC room. The current revision (1.25) says that a status code of "100" must be returned with the user's initial presence, instead. We already do this (in addition to generating the warning message). Receiving the warning message each time the client joins the room can become annoying, especially when reconnections occur frequently (e.g., on mobile devices). So, we omit it, now. --- src/mod_muc_room.erl | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index f28fe00413d..ff2ab565305 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1853,31 +1853,6 @@ add_new_user(From, Nick, NewState = add_user_presence(From, Packet, add_online_user(From, Nick, Role, StateData)), - if not (NewState#state.config)#config.anonymous -> - WPacket = #xmlel{name = <<"message">>, - attrs = [{<<"type">>, <<"groupchat">>}], - children = - [#xmlel{name = <<"body">>, - attrs = [], - children = - [{xmlcdata, - translate:translate(Lang, - <<"This room is not anonymous">>)}]}, - #xmlel{name = <<"x">>, - attrs = - [{<<"xmlns">>, - ?NS_MUC_USER}], - children = - [#xmlel{name = - <<"status">>, - attrs = - [{<<"code">>, - <<"100">>}], - children = - []}]}]}, - ejabberd_router:route(StateData#state.jid, From, WPacket); - true -> ok - end, send_existing_presences(From, NewState), send_new_presence(From, NewState), Shift = count_stanza_shift(Nick, Els, NewState), From 3c12d1a9603af01e57ba45ecef498ec8f1e7a0c6 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 29 Jun 2015 22:50:15 +0300 Subject: [PATCH 133/695] Do not rely on behaviour info when doing config validation --- src/ejabberd_config.erl | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index d049e411247..43e4154d5a5 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -718,16 +718,13 @@ get_modules_with_options() -> {ok, Mods} = application:get_key(ejabberd, modules), lists:foldl( fun(Mod, D) -> - Attrs = Mod:module_info(attributes), - Behavs = proplists:get_value(behaviour, Attrs, []), - case lists:member(ejabberd_config, Behavs) or (Mod == ?MODULE) of - true -> - Opts = Mod:opt_type(''), + case catch Mod:opt_type('') of + Opts when is_list(Opts) -> lists:foldl( fun(Opt, Acc) -> dict:append(Opt, Mod, Acc) end, D, Opts); - false -> + {'EXIT', {undef, _}} -> D end end, dict:new(), [?MODULE|Mods]). From df57a07dd5d760d7956500caa3262ff84538a560 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 29 Jun 2015 23:14:18 +0200 Subject: [PATCH 134/695] Keep the version hardcoded in mix.exs file Generated the mix.exs file through configure is not possible when using mix, as it does not run configure after having downloaded the dependencies. #621 --- .gitignore | 1 - configure.ac | 3 +-- mix.exs.in => mix.exs | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) rename mix.exs.in => mix.exs (98%) diff --git a/.gitignore b/.gitignore index d44a41f3f5a..21f8cfadaa3 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,3 @@ XmppAddr.hrl /test/*.beam /logs/ /priv/sql -mix.exs diff --git a/configure.ac b/configure.ac index 6ae0a2455b1..a3e26384bf2 100644 --- a/configure.ac +++ b/configure.ac @@ -235,8 +235,7 @@ esac],[if test "x$lager" = "x"; then lager=true; fi]) AC_CONFIG_FILES([Makefile vars.config - src/ejabberd.app.src - mix.exs]) + src/ejabberd.app.src]) ENABLEUSER="" AC_ARG_ENABLE(user, diff --git a/mix.exs.in b/mix.exs similarity index 98% rename from mix.exs.in rename to mix.exs index d7b236e0177..c93a0881133 100644 --- a/mix.exs.in +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "@PACKAGE_VERSION@", + version: "15.06", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", From 56034e6ed52f5944287c5049182e30b418219183 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 29 Jun 2015 23:23:31 +0200 Subject: [PATCH 135/695] Use https url for git dependencies for consistency --- mix.exs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/mix.exs b/mix.exs index c93a0881133..f4bd4ccf7ed 100644 --- a/mix.exs +++ b/mix.exs @@ -25,21 +25,21 @@ defmodule Ejabberd.Mixfile do defp deps do [ - {:p1_xml, github: "processone/xml"}, - {:p1_logger, github: "processone/p1_logger"}, - {:p1_yaml, github: "processone/p1_yaml"}, - {:p1_tls, github: "processone/tls"}, - {:p1_stringprep, github: "processone/stringprep"}, - {:p1_zlib, github: "processone/zlib"}, - {:p1_cache_tab, github: "processone/cache_tab"}, - {:p1_utils, github: "processone/p1_utils"}, - {:p1_iconv, github: "processone/eiconv"}, - {:esip, github: "processone/p1_sip"}, - {:p1_stun, github: "processone/stun"}, - {:ehyperloglog, github: "vaxelfel/eHyperLogLog"}, - {:p1_mysql, github: "processone/mysql"}, - {:p1_pgsql, github: "processone/pgsql"}, - {:eredis, github: "wooga/eredis"} + {:p1_xml, git: "https://github.com/processone/xml"}, + {:p1_logger, git: "https://github.com/processone/p1_logger"}, + {:p1_yaml, git: "https://github.com/processone/p1_yaml"}, + {:p1_tls, git: "https://github.com/processone/tls"}, + {:p1_stringprep, git: "https://github.com/processone/stringprep"}, + {:p1_zlib, git: "https://github.com/processone/zlib"}, + {:p1_cache_tab, git: "https://github.com/processone/cache_tab"}, + {:p1_utils, git: "https://github.com/processone/p1_utils"}, + {:p1_iconv, git: "https://github.com/processone/eiconv"}, + {:esip, git: "https://github.com/processone/p1_sip"}, + {:p1_stun, git: "https://github.com/processone/stun"}, + {:ehyperloglog, git: "https://github.com/vaxelfel/eHyperLogLog"}, + {:p1_mysql, git: "https://github.com/processone/mysql"}, + {:p1_pgsql, git: "https://github.com/processone/pgsql"}, + {:eredis, git: "https://github.com/wooga/eredis"} ] end end From 0474804d4baa6449d498e5403d1ac450245bcd55 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 29 Jun 2015 23:32:00 +0200 Subject: [PATCH 136/695] Version number must be SemVersion in mix Semantic version expects versioning with 3 components --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index f4bd4ccf7ed..ea45f871566 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.06", + version: "15.06.0", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", From 0e7d2b73be335353e9938668a699b3dbb7011c56 Mon Sep 17 00:00:00 2001 From: Johan Oudinet Date: Tue, 30 Jun 2015 10:53:45 +0200 Subject: [PATCH 137/695] configure.ac: add AC_CONFIG_MACRO_DIR Otherwise, autoconf fails to find extra macros defined in the m4 directory. --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index a3e26384bf2..0a60de08821 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,8 @@ AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` REQUIRE_ERLANG_MIN="5.9.1 (Erlang/OTP R15B01)" REQUIRE_ERLANG_MAX="9.0.0 (No Max)" +AC_CONFIG_MACRO_DIR([m4]) + # Checks for programs. AC_PROG_MAKE_SET AC_PROG_INSTALL From 4045c848c4732add9bd1ef716719523511cdb8e3 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 2 Jul 2015 00:36:16 +0200 Subject: [PATCH 138/695] Send notifications on MUC configuration changes Notify clients when the room configuration changes, as mandated by XEP-0045, #10.2.1. Closes #623. --- src/mod_muc_room.erl | 34 ++++++++++++++++++++++++++++++++++ test/ejabberd_SUITE.erl | 9 +++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index ff2ab565305..7b4cfbf6daf 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -3732,6 +3732,7 @@ set_xoption([_ | _Opts], _Config) -> {error, ?ERR_BAD_REQUEST}. change_config(Config, StateData) -> + send_config_change_info(Config, StateData), NSD = StateData#state{config = Config}, case {(StateData#state.config)#config.persistent, Config#config.persistent} @@ -3752,6 +3753,39 @@ change_config(Config, StateData) -> _ -> {result, [], NSD} end. +send_config_change_info(Config, #state{config = Config}) -> ok; +send_config_change_info(New, #state{config = Old} = StateData) -> + Codes = case {Old#config.logging, New#config.logging} of + {false, true} -> [<<"170">>]; + {true, false} -> [<<"171">>]; + _ -> [] + end + ++ + case {Old#config.anonymous, New#config.anonymous} of + {true, false} -> [<<"172">>]; + {false, true} -> [<<"173">>]; + _ -> [] + end + ++ + case Old#config{anonymous = New#config.anonymous, + logging = New#config.logging} of + New -> []; + _ -> [<<"104">>] + end, + StatusEls = [#xmlel{name = <<"status">>, + attrs = [{<<"code">>, Code}], + children = []} || Code <- Codes], + Message = #xmlel{name = <<"message">>, + attrs = [{<<"type">>, <<"groupchat">>}, + {<<"id">>, randoms:get_string()}], + children = [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_MUC_USER}], + children = StatusEls}]}, + send_multiple(StateData#state.jid, + StateData#state.server_host, + StateData#state.users, + Message). + remove_nonmembers(StateData) -> lists:foldl(fun ({_LJID, #user{jid = JID}}, SD) -> Affiliation = get_affiliation(JID, SD), diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 4d1a1fc7b43..dc528d79a65 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1122,10 +1122,11 @@ muc_master(Config) -> end end, RoomCfg#xdata.fields), NewRoomCfg = #xdata{type = submit, fields = NewFields}, - %% BUG: We should not receive any sub_els! - #iq{type = result, sub_els = [_|_]} = - send_recv(Config, #iq{type = set, to = Room, - sub_els = [#muc_owner{config = NewRoomCfg}]}), + ID = send(Config, #iq{type = set, to = Room, + sub_els = [#muc_owner{config = NewRoomCfg}]}), + ?recv2(#iq{type = result, id = ID}, + #message{from = Room, type = groupchat, + sub_els = [#muc_user{status_codes = [104]}]}), %% Set subject send(Config, #message{to = Room, type = groupchat, body = [#text{data = Subject}]}), From 95138864f4c33dc700600f823feca1cb3605e6fd Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 3 Jul 2015 01:21:22 +0200 Subject: [PATCH 139/695] Let Travis grab MySQL 5.6 from repo.mysql.com We need MySQL 5.6 or newer in order to get support for InnoDB FULLTEXT Indexes. Closes #624. --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index ca482678faa..9424c811156 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,18 @@ services: - riak before_install: + # + # We need MySQL 5.6 or newer in order to get support for FULLTEXT indexes + # with InnoDB. As soon as Travis ships that version, the following lines + # (except for the "apt-get update" call) can go away. + # + # See: https://github.com/travis-ci/travis-ci/issues/1986 + # + - sudo sed -i -e s/table_cache/table_open_cache/ -e /log_slow_queries/d /etc/mysql/my.cnf + - sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 5072E1F5 + - sudo add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.6' - sudo apt-get -qq update + - sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6 install: - sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev From a25051fead86574c27a024eb048eadf45186599d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 26 Jun 2015 21:33:32 +0200 Subject: [PATCH 140/695] New hook: muc_filter_packet Add a hook that allows for modifying or dropping MUC room messages. Closes #491. --- src/mod_muc_room.erl | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 7b4cfbf6daf..df06bce4f82 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -947,20 +947,32 @@ process_groupchat_message(From, end, case IsAllowed of true -> - send_multiple( - jlib:jid_replace_resource(StateData#state.jid, FromNick), - StateData#state.server_host, - StateData#state.users, - Packet), - NewStateData2 = case has_body_or_subject(Packet) of - true -> - add_message_to_history(FromNick, From, - Packet, - NewStateData1); - false -> - NewStateData1 - end, - {next_state, normal_state, NewStateData2}; + case + ejabberd_hooks:run_fold(muc_filter_packet, + StateData#state.server_host, + Packet, + [StateData, + StateData#state.jid, + From, FromNick]) + of + drop -> + {next_state, normal_state, StateData}; + NewPacket -> + send_multiple(jlib:jid_replace_resource(StateData#state.jid, + FromNick), + StateData#state.server_host, + StateData#state.users, + Packet), + NewStateData2 = case has_body_or_subject(Packet) of + true -> + add_message_to_history(FromNick, From, + Packet, + NewStateData1); + false -> + NewStateData1 + end, + {next_state, normal_state, NewStateData2} + end; _ -> Err = case (StateData#state.config)#config.allow_change_subj From 5856f6d06a24962b23ddb3ba8759d804df57c4df Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 1 Jul 2015 21:15:05 +0200 Subject: [PATCH 141/695] XEP-0198: Increase default "max_ack_queue" value During login, clients might receive a relatively large number of stanzas in one go. For some users, the default value of the "max_ack_queue" option turned out to be too small in that situation. --- src/ejabberd_c2s.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 3869bd54e50..2494fb22822 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -308,7 +308,7 @@ init([{SockMod, Socket}, Opts]) -> MaxAckQueue = case proplists:get_value(max_ack_queue, Opts) of Limit when is_integer(Limit), Limit > 0 -> Limit; infinity -> infinity; - _ -> 500 + _ -> 1000 end, ResumeTimeout = case proplists:get_value(resume_timeout, Opts) of Timeout when is_integer(Timeout), Timeout >= 0 -> Timeout; From b7d7dc5201868be6631f8d11c64b0b544dd7172a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 1 Jul 2015 21:37:06 +0200 Subject: [PATCH 142/695] XEP-0198: Increase timeout during resumption Give gen_fsm:sync_send_all_state_event/3 a little more time to transfer the (possibly somewhat large) c2s #state during session resumption. --- src/ejabberd_c2s.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 2494fb22822..f982f911584 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -3010,7 +3010,7 @@ inherit_session_state(#state{user = U, server = S} = StateData, ResumeID) -> end. resume_session({Time, PID}) -> - (?GEN_FSM):sync_send_all_state_event(PID, {resume_session, Time}, 3000). + (?GEN_FSM):sync_send_all_state_event(PID, {resume_session, Time}, 5000). make_resume_id(StateData) -> {Time, _} = StateData#state.sid, From b0453ea2ce8bf5078c345da4b7d8870d025976c2 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 3 Jul 2015 13:18:35 +0300 Subject: [PATCH 143/695] Remove ehyperloglog dependency --- rebar.config.script | 1 - 1 file changed, 1 deletion(-) diff --git a/rebar.config.script b/rebar.config.script index b4dfaa3ed93..a38d85898fb 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -61,7 +61,6 @@ Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, {esip, ".*", {git, "https://github.com/processone/p1_sip"}}, {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, - {ehyperloglog, ".*", {git, "https://github.com/vaxelfel/eHyperLogLog.git"}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}], ConfigureCmd = fun(Pkg, Flags) -> From 0770252e9bb773a041dc3853b92c6026bdcd46be Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sun, 5 Jul 2015 13:33:34 +0200 Subject: [PATCH 144/695] Fix dialyzer warning The function is call with binary format from ejabberd_c2s. --- src/ejabberd_config.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 43e4154d5a5..81a87a648d8 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -1152,7 +1152,8 @@ opt_type(language) -> opt_type(_) -> [hosts, language]. --spec may_hide_data(string()) -> string(). +-spec may_hide_data(string()) -> string(); + (binary()) -> binary(). may_hide_data(Data) -> case ejabberd_config:get_option( From edb18deb8fdc10bf440ed94ee0459ded9358e75d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 6 Jul 2015 23:45:25 +0200 Subject: [PATCH 145/695] mod_pubsub: Explain caps_update usage in a comment The reason to use the caps_update hook for sending last items to remote contacts is probably not obvious. --- src/mod_pubsub.erl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index f572c33d175..ee6407793ed 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -685,6 +685,15 @@ disco_items(Host, Node, From) -> caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) when Host =/= S -> + %% When a remote contact goes online while the local user is offline, the + %% remote contact won't receive last items from the local user even if + %% ignore_pep_from_offline is set to false. To work around this issue a bit, + %% we'll also send the last items to remote contacts when the local user + %% connects. That's the reason to use the caps_update hook instead of the + %% presence_probe_hook for remote contacts: The latter is only called when a + %% contact becomes available; the former also is also executed when the + %% local user goes online (because that triggers the contact to send a + %% presence packet with CAPS). presence(Host, {presence, U, S, [R], JID}); caps_update(_From, _To, _Feature) -> ok. From 0f964142799cd987b612dc2134c7a11573ab80b7 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 7 Jul 2015 00:24:06 +0200 Subject: [PATCH 146/695] Trigger PEP notifications on CAPS updates Let mod_pubsub send last items whenever a contact updates the entity capabilities. This was already done for remote contacts and is now also done for local contacts. --- src/mod_caps.erl | 39 ++++++++++++++++++--------------------- src/mod_pubsub.erl | 23 +++++++++++++++-------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 4d166ce70ed..6d647908cfe 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -243,27 +243,24 @@ c2s_presence_in(C2SState, error -> gb_trees:empty() end, Caps = read_caps(Els), - {CapsUpdated, NewRs} = case Caps of - nothing when Insert == true -> {false, Rs}; - _ when Insert == true -> - case gb_trees:lookup(LFrom, Rs) of - {value, Caps} -> {false, Rs}; - none -> - {true, - gb_trees:insert(LFrom, Caps, - Rs)}; - _ -> - {true, - gb_trees:update(LFrom, Caps, Rs)} - end; - _ -> {false, gb_trees:delete_any(LFrom, Rs)} - end, - if CapsUpdated -> - ejabberd_hooks:run(caps_update, To#jid.lserver, - [From, To, - get_features(To#jid.lserver, Caps)]); - true -> ok - end, + NewRs = case Caps of + nothing when Insert == true -> Rs; + _ when Insert == true -> + case gb_trees:lookup(LFrom, Rs) of + {value, Caps} -> Rs; + none -> + ejabberd_hooks:run(caps_add, To#jid.lserver, + [From, To, + get_features(To#jid.lserver, Caps)]), + gb_trees:insert(LFrom, Caps, Rs); + _ -> + ejabberd_hooks:run(caps_update, To#jid.lserver, + [From, To, + get_features(To#jid.lserver, Caps)]), + gb_trees:update(LFrom, Caps, Rs) + end; + _ -> gb_trees:delete_any(LFrom, Rs) + end, ejabberd_c2s:set_aux_field(caps_resources, NewRs, C2SState); true -> C2SState diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index ee6407793ed..218445cfbb5 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -62,7 +62,7 @@ -define(PEPNODE, <<"pep">>). %% exports for hooks --export([presence_probe/3, caps_update/3, +-export([presence_probe/3, caps_add/3, caps_update/3, in_subscription/6, out_subscription/4, on_user_offline/3, remove_user/2, disco_local_identity/5, disco_local_features/5, @@ -293,6 +293,8 @@ init([ServerHost, Opts]) -> ?MODULE, remove_user, 50), case lists:member(?PEPNODE, Plugins) of true -> + ejabberd_hooks:add(caps_add, ServerHost, + ?MODULE, caps_add, 80), ejabberd_hooks:add(caps_update, ServerHost, ?MODULE, caps_update, 80), ejabberd_hooks:add(disco_sm_identity, ServerHost, @@ -683,21 +685,24 @@ disco_items(Host, Node, From) -> %% presence hooks handling functions %% -caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) +caps_add(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) when Host =/= S -> %% When a remote contact goes online while the local user is offline, the %% remote contact won't receive last items from the local user even if %% ignore_pep_from_offline is set to false. To work around this issue a bit, %% we'll also send the last items to remote contacts when the local user - %% connects. That's the reason to use the caps_update hook instead of the + %% connects. That's the reason to use the caps_add hook instead of the %% presence_probe_hook for remote contacts: The latter is only called when a - %% contact becomes available; the former also is also executed when the - %% local user goes online (because that triggers the contact to send a - %% presence packet with CAPS). + %% contact becomes available; the former is also executed when the local + %% user goes online (because that triggers the contact to send a presence + %% packet with CAPS). presence(Host, {presence, U, S, [R], JID}); -caps_update(_From, _To, _Feature) -> +caps_add(_From, _To, _Feature) -> ok. +caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) -> + presence(Host, {presence, U, S, [R], JID}). + presence_probe(#jid{luser = U, lserver = S, lresource = R} = JID, JID, Pid) -> presence(S, {presence, JID, Pid}), presence(S, {presence, U, S, [R], JID}); @@ -709,7 +714,7 @@ presence_probe(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = S} = presence(S, {presence, U, S, [R], JID}); presence_probe(_Host, _JID, _Pid) -> %% ignore presence_probe from remote contacts, - %% those are handled via caps_update + %% those are handled via caps_add ok. presence(ServerHost, Presence) -> @@ -881,6 +886,8 @@ terminate(_Reason, ejabberd_router:unregister_route(Host), case lists:member(?PEPNODE, Plugins) of true -> + ejabberd_hooks:delete(caps_add, ServerHost, + ?MODULE, caps_add, 80), ejabberd_hooks:delete(caps_update, ServerHost, ?MODULE, caps_update, 80), ejabberd_hooks:delete(disco_sm_identity, ServerHost, From 259837505116e42e103f726074fed139e032bcaa Mon Sep 17 00:00:00 2001 From: Jerome Sautret Date: Mon, 6 Jul 2015 15:39:23 +0200 Subject: [PATCH 147/695] Changed mam iq get to set as specified by XEP-0313 v0.3 --- src/mod_mam.erl | 99 ++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 43 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index edbc4f91ae3..6739feb08e8 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -34,7 +34,8 @@ -export([start/2, stop/1]). -export([user_send_packet/4, user_receive_packet/5, - process_iq/3, remove_user/2, mod_opt_type/1]). + process_iq_v0_2/3, process_iq_v0_3/3, remove_user/2, + mod_opt_type/1]). -include_lib("stdlib/include/ms_transform.hrl"). -include("jlib.hrl"). @@ -64,13 +65,13 @@ start(Host, Opts) -> init_db(DBType, Host), init_cache(DBType, Opts), gen_iq_handler:add_iq_handler(ejabberd_local, Host, - ?NS_MAM_TMP, ?MODULE, process_iq, IQDisc), + ?NS_MAM_TMP, ?MODULE, process_iq_v0_2, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, - ?NS_MAM_TMP, ?MODULE, process_iq, IQDisc), + ?NS_MAM_TMP, ?MODULE, process_iq_v0_2, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_local, Host, - ?NS_MAM_0, ?MODULE, process_iq, IQDisc), + ?NS_MAM_0, ?MODULE, process_iq_v0_3, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, - ?NS_MAM_0, ?MODULE, process_iq, IQDisc), + ?NS_MAM_0, ?MODULE, process_iq_v0_3, IQDisc), ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, user_receive_packet, 500), ejabberd_hooks:add(user_send_packet, Host, ?MODULE, @@ -197,13 +198,11 @@ user_send_packet(Pkt, C2SState, JID, Peer) -> Pkt end. -process_iq(#jid{lserver = LServer} = From, +% Query archive v0.2 +process_iq_v0_2(#jid{lserver = LServer} = From, #jid{lserver = LServer} = To, #iq{type = get, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> - NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), - Fs = case NS of - ?NS_MAM_TMP -> - lists:flatmap( + Fs = lists:flatmap( fun(#xmlel{name = <<"start">>} = El) -> [{<<"start">>, [xml:get_tag_cdata(El)]}]; (#xmlel{name = <<"end">>} = El) -> @@ -218,9 +217,16 @@ process_iq(#jid{lserver = LServer} = From, [{<<"set">>, SubEl}]; (_) -> [] - end, SubEl#xmlel.children); - ?NS_MAM_0 -> - case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), + end, SubEl#xmlel.children), + process_iq(From, To, IQ, SubEl, Fs); +process_iq_v0_2(From, To, IQ) -> + process_iq(From, To, IQ). + +% Query archive v0.3 +process_iq_v0_3(#jid{lserver = LServer} = From, + #jid{lserver = LServer} = To, + #iq{type = set, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> + Fs = case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of {#xmlel{} = XData, false} -> jlib:parse_xdata_submit(XData); @@ -230,34 +236,16 @@ process_iq(#jid{lserver = LServer} = From, [{<<"set">>, SubEl}]; {false, false} -> [] - end end, - case catch lists:foldl( - fun({<<"start">>, [Data|_]}, {_, End, With, RSM}) -> - {{_, _, _} = jlib:datetime_string_to_timestamp(Data), - End, With, RSM}; - ({<<"end">>, [Data|_]}, {Start, _, With, RSM}) -> - {Start, - {_, _, _} = jlib:datetime_string_to_timestamp(Data), - With, RSM}; - ({<<"with">>, [Data|_]}, {Start, End, _, RSM}) -> - {Start, End, jlib:jid_tolower(jlib:string_to_jid(Data)), RSM}; - ({<<"withroom">>, [Data|_]}, {Start, End, _, RSM}) -> - {Start, End, - {room, jlib:jid_tolower(jlib:string_to_jid(Data))}, - RSM}; - ({<<"withtext">>, [Data|_]}, {Start, End, _, RSM}) -> - {Start, End, {text, Data}, RSM}; - ({<<"set">>, El}, {Start, End, With, _}) -> - {Start, End, With, jlib:rsm_decode(El)}; - (_, Acc) -> - Acc - end, {none, [], none, none}, Fs) of - {'EXIT', _} -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; - {Start, End, With, RSM} -> - select_and_send(From, To, Start, End, With, RSM, IQ) - end; + process_iq(From, To, IQ, SubEl, Fs); +process_iq_v0_3(From, To, IQ) -> + process_iq(From, To, IQ). + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== + +% Preference setting (both v0.2 & v0.3) process_iq(#jid{luser = LUser, lserver = LServer}, #jid{lserver = LServer}, #iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> @@ -289,9 +277,34 @@ process_iq(#jid{luser = LUser, lserver = LServer}, process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. -%%%=================================================================== -%%% Internal functions -%%%=================================================================== +process_iq(From, To, IQ, SubEl, Fs) -> + case catch lists:foldl( + fun({<<"start">>, [Data|_]}, {_, End, With, RSM}) -> + {{_, _, _} = jlib:datetime_string_to_timestamp(Data), + End, With, RSM}; + ({<<"end">>, [Data|_]}, {Start, _, With, RSM}) -> + {Start, + {_, _, _} = jlib:datetime_string_to_timestamp(Data), + With, RSM}; + ({<<"with">>, [Data|_]}, {Start, End, _, RSM}) -> + {Start, End, jlib:jid_tolower(jlib:string_to_jid(Data)), RSM}; + ({<<"withroom">>, [Data|_]}, {Start, End, _, RSM}) -> + {Start, End, + {room, jlib:jid_tolower(jlib:string_to_jid(Data))}, + RSM}; + ({<<"withtext">>, [Data|_]}, {Start, End, _, RSM}) -> + {Start, End, {text, Data}, RSM}; + ({<<"set">>, El}, {Start, End, With, _}) -> + {Start, End, With, jlib:rsm_decode(El)}; + (_, Acc) -> + Acc + end, {none, [], none, none}, Fs) of + {'EXIT', _} -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; + {Start, End, With, RSM} -> + select_and_send(From, To, Start, End, With, RSM, IQ) + end. + should_archive(#xmlel{name = <<"message">>} = Pkt) -> case {xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs), xml:get_subtag_cdata(Pkt, <<"body">>)} of From 6604b9efbb9fda0fd847c907697e03ae00b424c8 Mon Sep 17 00:00:00 2001 From: Jerome Sautret Date: Tue, 7 Jul 2015 18:42:50 +0200 Subject: [PATCH 148/695] Fix MAM tests (EJABS-2480). --- test/ejabberd_SUITE.erl | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index dc528d79a65..470055654d3 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1663,7 +1663,11 @@ mam_query_all(Config, NS) -> QID = randoms:get_string(), MyJID = my_jid(Config), Peer = ?config(slave, Config), - I = send(Config, #iq{type = get, sub_els = [#mam_query{xmlns = NS, id = QID}]}), + Type = case NS of + ?NS_MAM_TMP -> get; + _ -> set + end, + I = send(Config, #iq{type = Type, sub_els = [#mam_query{xmlns = NS, id = QID}]}), maybe_recv_iq_result(NS, I), Iter = if NS == ?NS_MAM_TMP -> lists:seq(1, 5); true -> lists:seq(1, 5) ++ lists:seq(1, 5) @@ -1692,15 +1696,15 @@ mam_query_all(Config, NS) -> mam_query_with(Config, JID, NS) -> MyJID = my_jid(Config), Peer = ?config(slave, Config), - Query = if NS == ?NS_MAM_TMP -> - #mam_query{xmlns = NS, with = JID}; + {Query, Type} = if NS == ?NS_MAM_TMP -> + {#mam_query{xmlns = NS, with = JID}, get}; true -> Fs = [#xdata_field{var = <<"jid">>, values = [jlib:jid_to_string(JID)]}], - #mam_query{xmlns = NS, - xdata = #xdata{type = submit, fields = Fs}} + {#mam_query{xmlns = NS, + xdata = #xdata{type = submit, fields = Fs}}, set} end, - I = send(Config, #iq{type = get, sub_els = [Query]}), + I = send(Config, #iq{type = Type, sub_els = [Query]}), Iter = if NS == ?NS_MAM_TMP -> lists:seq(1, 5); true -> lists:seq(1, 5) ++ lists:seq(1, 5) end, @@ -1733,9 +1737,13 @@ maybe_recv_iq_result(_, _) -> mam_query_rsm(Config, NS) -> MyJID = my_jid(Config), Peer = ?config(slave, Config), + Type = case NS of + ?NS_MAM_TMP -> get; + _ -> set + end, %% Get the first 3 items out of 5 I1 = send(Config, - #iq{type = get, + #iq{type = Type, sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 3}}]}), maybe_recv_iq_result(NS, I1), lists:foreach( @@ -1764,7 +1772,7 @@ mam_query_rsm(Config, NS) -> %% Get the next items starting from the `Last`. %% Limit the response to 2 items. I2 = send(Config, - #iq{type = get, + #iq{type = Type, sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 2, 'after' = Last}}]}), @@ -1800,7 +1808,7 @@ mam_query_rsm(Config, NS) -> end, %% Paging back. Should receive 2 elements: 2, 3. I3 = send(Config, - #iq{type = get, + #iq{type = Type, sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 2, before = First}}]}), @@ -1829,7 +1837,7 @@ mam_query_rsm(Config, NS) -> end, %% Getting the item count. Should be 5 (or 10). I4 = send(Config, - #iq{type = get, + #iq{type = Type, sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{max = 0}}]}), maybe_recv_iq_result(NS, I4), From a16834083858b76da98b9cbfe39c5df7de9fac1a Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 8 Jul 2015 15:35:26 +0300 Subject: [PATCH 149/695] During halt only shutdown MUC rooms on local node --- src/mod_muc.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 6226ca3b220..e798790c5d1 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -115,7 +115,8 @@ shutdown_rooms(Host) -> Rooms = mnesia:dirty_select(muc_online_room, [{#muc_online_room{name_host = '$1', pid = '$2'}, - [{'==', {element, 2, '$1'}, MyHost}], + [{'==', {element, 2, '$1'}, MyHost}, + {'==', {node, '$2'}, node()}], ['$2']}]), [Pid ! shutdown || Pid <- Rooms], Rooms. From 1db65e3614dc2f1c12d549a4f882496c315bb613 Mon Sep 17 00:00:00 2001 From: Jerome Sautret Date: Tue, 7 Jul 2015 13:23:30 +0200 Subject: [PATCH 150/695] Fix mod_mam compatibility with RSM (only with odbc backend). --- src/mod_mam.erl | 94 ++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 6739feb08e8..bd1a5a7a9d3 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -550,6 +550,12 @@ select(#jid{luser = LUser, lserver = LServer} = JidRequestor, Start, End, With, RSM, {odbc, Host}) -> {Query, CountQuery} = make_sql_query(LUser, LServer, Start, End, With, RSM), + % XXX TODO from XEP-0313: + % To conserve resources, a server MAY place a reasonable limit on + % how many stanzas may be pushed to a client in one request. If a + % query returns a number of stanzas greater than this limit and + % the client did not specify a limit using RSM then the server + % should return a policy-violation error to the client. case {ejabberd_odbc:sql_query(Host, Query), ejabberd_odbc:sql_query(Host, CountQuery)} of {{selected, _, Res}, {selected, _, [[Count]]}} -> @@ -718,7 +724,7 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> RSM#rsm_in.direction, RSM#rsm_in.id}; none -> - {none, none, none} + {none, none, <<>>} end, LimitClause = if is_integer(Max), Max >= 0 -> [<<" limit ">>, jlib:integer_to_binary(Max)]; @@ -726,37 +732,35 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> [] end, WithClause = case With of - {text, <<>>} -> - []; - {text, Txt} -> - [<<" and match (txt) against ('">>, - ejabberd_odbc:escape(Txt), <<"')">>]; - {_, _, <<>>} -> - [<<" and bare_peer='">>, - ejabberd_odbc:escape(jlib:jid_to_string(With)), - <<"'">>]; - {_, _, _} -> - [<<" and peer='">>, - ejabberd_odbc:escape(jlib:jid_to_string(With)), - <<"'">>]; - none -> - [] - end, - DirectionClause = case catch jlib:binary_to_integer(ID) of - I when is_integer(I), I >= 0 -> - case Direction of - before -> - [<<" and timestamp < ">>, ID, - <<" order by timestamp desc">>]; - aft -> - [<<" and timestamp > ">>, ID, - <<" order by timestamp asc">>]; - _ -> - [] - end; - _ -> - [] - end, + {text, <<>>} -> + []; + {text, Txt} -> + [<<" and match (txt) against ('">>, + ejabberd_odbc:escape(Txt), <<"')">>]; + {_, _, <<>>} -> + [<<" and bare_peer='">>, + ejabberd_odbc:escape(jlib:jid_to_string(With)), + <<"'">>]; + {_, _, _} -> + [<<" and peer='">>, + ejabberd_odbc:escape(jlib:jid_to_string(With)), + <<"'">>]; + none -> + [] + end, + PageClause = case catch jlib:binary_to_integer(ID) of + I when is_integer(I), I >= 0 -> + case Direction of + before -> + [<<" AND timestamp < ">>, ID]; + aft -> + [<<" AND timestamp > ">>, ID]; + _ -> + [] + end; + _ -> + [] + end, StartClause = case Start of {_, _, _} -> [<<" and timestamp >= ">>, @@ -772,11 +776,27 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> [] end, SUser = ejabberd_odbc:escape(LUser), - {[<<"select timestamp, xml, peer from archive where username='">>, - SUser, <<"'">>] ++ WithClause ++ StartClause ++ EndClause ++ - DirectionClause ++ LimitClause ++ [<<";">>], - [<<"select count(*) from archive where username='">>, - SUser, <<"'">>] ++ WithClause ++ StartClause ++ EndClause ++ [<<";">>]}. + + Query = [<<"SELECT timestamp, xml, peer" + " FROM archive WHERE username='">>, + SUser, <<"'">>, WithClause, StartClause, EndClause, + PageClause], + + QueryPage = + case Direction of + before -> + % ID can be empty because of + % XEP-0059: Result Set Management + % 2.5 Requesting the Last Page in a Result Set + [<<"(">>, Query, <<" ORDER BY timestamp DESC ">>, + LimitClause, <<") ORDER BY timestamp ASC;">>]; + _ -> + [Query, <<" ORDER BY timestamp ASC ">>, + LimitClause, <<";">>] + end, + {QueryPage, + [<<"SELECT COUNT(*) FROM archive WHERE username='">>, + SUser, <<"'">>, WithClause, StartClause, EndClause, <<";">>]}. now_to_usec({MSec, Sec, USec}) -> (MSec*1000000 + Sec)*1000000 + USec. From 0dfc8ade6837f8267e1f3150db629509f5c066fe Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 9 Jul 2015 12:00:08 +0300 Subject: [PATCH 151/695] Fix tests related to MAM --- src/mod_mam.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index bd1a5a7a9d3..cd869c9d875 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -788,8 +788,9 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> % ID can be empty because of % XEP-0059: Result Set Management % 2.5 Requesting the Last Page in a Result Set - [<<"(">>, Query, <<" ORDER BY timestamp DESC ">>, - LimitClause, <<") ORDER BY timestamp ASC;">>]; + [<<"SELECT timestamp, xml, peer FROM (">>, Query, + <<" ORDER BY timestamp DESC ">>, + LimitClause, <<") AS t ORDER BY timestamp ASC;">>]; _ -> [Query, <<" ORDER BY timestamp ASC ">>, LimitClause, <<";">>] From 8e27decdfd9f91bc9ae2c01bc4df2ca7254d8242 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 9 Jul 2015 13:01:37 +0300 Subject: [PATCH 152/695] Fix mod_mam compatibility with RSM for other backends --- src/mod_mam.erl | 32 +++++++++++++++++--------------- test/ejabberd_SUITE.erl | 29 +++++++++++++++++++++++++++++ tools/xmpp_codec.erl | 4 ++-- tools/xmpp_codec.hrl | 2 +- tools/xmpp_codec.spec | 1 + 5 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index cd869c9d875..4e58f9ffb12 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -663,21 +663,23 @@ filter_by_rsm(_Msgs, #rsm_in{max = Max}) when Max =< 0 -> []; filter_by_rsm(Msgs, #rsm_in{max = Max, direction = Direction, id = ID}) -> NewMsgs = case Direction of - aft -> - lists:filter( - fun(#archive_msg{id = I}) -> - I > ID - end, Msgs); - before -> - lists:foldl( - fun(#archive_msg{id = I} = Msg, Acc) when I < ID -> - [Msg|Acc]; - (_, Acc) -> - Acc - end, [], Msgs); - _ -> - Msgs - end, + aft when ID /= <<"">> -> + lists:filter( + fun(#archive_msg{id = I}) -> + I > ID + end, Msgs); + before when ID /= <<"">> -> + lists:foldl( + fun(#archive_msg{id = I} = Msg, Acc) when I < ID -> + [Msg|Acc]; + (_, Acc) -> + Acc + end, [], Msgs); + before when ID == <<"">> -> + lists:reverse(Msgs); + _ -> + Msgs + end, filter_by_max(NewMsgs, Max). filter_by_max(Msgs, undefined) -> diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 470055654d3..8cd21d5e9d2 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1854,6 +1854,35 @@ mam_query_rsm(Config, NS) -> rsm = #rsm_set{count = 10, first = undefined, last = undefined}}]}) + end, + %% Should receive 2 last messages + I5 = send(Config, + #iq{type = Type, + sub_els = [#mam_query{xmlns = NS, + rsm = #rsm_set{max = 2, + before = none}}]}), + maybe_recv_iq_result(NS, I5), + lists:foreach( + fun(N) -> + Text = #text{data = jlib:integer_to_binary(N)}, + ?recv1(#message{to = MyJID, + sub_els = + [#mam_result{ + xmlns = NS, + sub_els = + [#forwarded{ + delay = #delay{}, + sub_els = + [#message{ + from = MyJID, to = Peer, + body = [Text]}]}]}]}) + end, lists:seq(4, 5)), + if NS == ?NS_MAM_TMP -> + ?recv1(#iq{type = result, id = I5, + sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{count = 5}}]}); + true -> + ?recv1(#message{ + sub_els = [#mam_fin{rsm = #rsm_set{count = 10}}]}) end. client_state_master(Config) -> diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 0dbc6280850..08a2e84cae7 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -4746,10 +4746,10 @@ encode_rsm_before(Cdata, _xmlns_attrs) -> _attrs = _xmlns_attrs, {xmlel, <<"before">>, _attrs, _els}. -decode_rsm_before_cdata(__TopXMLNS, <<>>) -> undefined; +decode_rsm_before_cdata(__TopXMLNS, <<>>) -> none; decode_rsm_before_cdata(__TopXMLNS, _val) -> _val. -encode_rsm_before_cdata(undefined, _acc) -> _acc; +encode_rsm_before_cdata(none, _acc) -> _acc; encode_rsm_before_cdata(_val, _acc) -> [{xmlcdata, _val} | _acc]. diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index 567946fe2e6..fa8e5e74d1f 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -280,7 +280,7 @@ units = [] :: [binary()]}). -record(rsm_set, {'after' :: binary(), - before :: binary(), + before :: 'none' | binary(), count :: non_neg_integer(), first :: #rsm_first{}, index :: non_neg_integer(), diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index dfa516ef5df..326d1de3604 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2071,6 +2071,7 @@ -xml(rsm_before, #elem{name = <<"before">>, xmlns = <<"http://jabber.org/protocol/rsm">>, + cdata = #cdata{default = none}, result = '$cdata'}). -xml(rsm_last, From a53191fed5a1cda77b082cefd6e2fbbec223f91e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 10 Jul 2015 13:02:42 +0300 Subject: [PATCH 153/695] Add "complete" attribute to MAM final response (EJABS-2484) --- src/mod_mam.erl | 91 +++++++++++++++++++++++++---------------- test/ejabberd_SUITE.erl | 19 +++++---- tools/xmpp_codec.erl | 81 +++++++++++++++++++++++++++++------- tools/xmpp_codec.hrl | 4 +- tools/xmpp_codec.spec | 10 ++++- 5 files changed, 144 insertions(+), 61 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 4e58f9ffb12..c3c8a2b927a 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -518,10 +518,10 @@ select_and_send(#jid{lserver = LServer} = From, DBType). select_and_send(From, To, Start, End, With, RSM, IQ, DBType) -> - {Msgs, Count} = select_and_start(From, To, Start, End, With, - RSM, DBType), + {Msgs, IsComplete, Count} = select_and_start(From, To, Start, End, With, + RSM, DBType), SortedMsgs = lists:keysort(2, Msgs), - send(From, To, SortedMsgs, RSM, Count, IQ). + send(From, To, SortedMsgs, RSM, Count, IsComplete, IQ). select_and_start(From, _To, StartUser, End, With, RSM, DB) -> {JidRequestor, Start, With2} = case With of @@ -538,17 +538,17 @@ select(#jid{luser = LUser, lserver = LServer} = JidRequestor, Start, End, With, RSM, mnesia) -> MS = make_matchspec(LUser, LServer, Start, End, With), Msgs = mnesia:dirty_select(archive_msg, MS), - FilteredMsgs = filter_by_rsm(Msgs, RSM), + {FilteredMsgs, IsComplete} = filter_by_rsm(Msgs, RSM), Count = length(Msgs), {lists:map( fun(Msg) -> {Msg#archive_msg.id, jlib:binary_to_integer(Msg#archive_msg.id), msg_to_el(Msg, JidRequestor)} - end, FilteredMsgs), Count}; + end, FilteredMsgs), IsComplete, Count}; select(#jid{luser = LUser, lserver = LServer} = JidRequestor, Start, End, With, RSM, {odbc, Host}) -> - {Query, CountQuery} = make_sql_query(LUser, LServer, + {Query, CountQuery} = make_sql_query(LUser, LServer, Start, End, With, RSM), % XXX TODO from XEP-0313: % To conserve resources, a server MAY place a reasonable limit on @@ -559,6 +559,20 @@ select(#jid{luser = LUser, lserver = LServer} = JidRequestor, case {ejabberd_odbc:sql_query(Host, Query), ejabberd_odbc:sql_query(Host, CountQuery)} of {{selected, _, Res}, {selected, _, [[Count]]}} -> + {Max, Direction} = case RSM of + #rsm_in{max = M, direction = D} -> {M, D}; + _ -> {undefined, undefined} + end, + {Res1, IsComplete} = + if Max >= 0 andalso Max /= undefined andalso length(Res) > Max -> + if Direction == before -> + {lists:nthtail(1, Res), false}; + true -> + {lists:sublist(Res, Max), false} + end; + true -> + {Res, true} + end, {lists:map( fun([TS, XML, PeerBin]) -> #xmlel{} = El = xml_stream:parse_element(XML), @@ -569,9 +583,9 @@ select(#jid{luser = LUser, lserver = LServer} = JidRequestor, packet = El, peer = PeerJid}, JidRequestor)} - end, Res), jlib:binary_to_integer(Count)}; - _ -> - {[], 0} + end, Res1), IsComplete, jlib:binary_to_integer(Count)}; + _ -> + {[], false, 0} end. msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, peer = Peer}, @@ -599,14 +613,19 @@ maybe_update_from_to(Pkt, JidRequestor, Peer) -> _ -> Pkt end. -send(From, To, Msgs, RSM, Count, #iq{sub_el = SubEl} = IQ) -> +send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> QID = xml:get_tag_attr_s(<<"queryid">>, SubEl), NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), QIDAttr = if QID /= <<>> -> - [{<<"queryid">>, QID}]; - true -> - [] - end, + [{<<"queryid">>, QID}]; + true -> + [] + end, + CompleteAttr = if NS == ?NS_MAM_TMP -> + []; + NS == ?NS_MAM_0 -> + [{<<"complete">>, jlib:atom_to_binary(IsComplete)}] + end, Els = lists:map( fun({ID, _IDInt, El}) -> #xmlel{name = <<"message">>, @@ -615,7 +634,7 @@ send(From, To, Msgs, RSM, Count, #iq{sub_el = SubEl} = IQ) -> {<<"id">>, ID}|QIDAttr], children = [El]}]} end, Msgs), - RSMOut = make_rsm_out(Msgs, RSM, Count, QIDAttr, NS), + RSMOut = make_rsm_out(Msgs, RSM, Count, QIDAttr ++ CompleteAttr, NS), case NS of ?NS_MAM_TMP -> lists:foreach( @@ -637,30 +656,30 @@ send(From, To, Msgs, RSM, Count, #iq{sub_el = SubEl} = IQ) -> end. -make_rsm_out(_Msgs, none, _Count, _QIDAttr, ?NS_MAM_TMP) -> +make_rsm_out(_Msgs, none, _Count, _Attrs, ?NS_MAM_TMP) -> []; -make_rsm_out(_Msgs, none, _Count, QIDAttr, ?NS_MAM_0) -> - [#xmlel{name = <<"fin">>, attrs = [{<<"xmlns">>, ?NS_MAM_0}|QIDAttr]}]; -make_rsm_out([], #rsm_in{}, Count, QIDAttr, NS) -> +make_rsm_out(_Msgs, none, _Count, Attrs, ?NS_MAM_0) -> + [#xmlel{name = <<"fin">>, attrs = [{<<"xmlns">>, ?NS_MAM_0}|Attrs]}]; +make_rsm_out([], #rsm_in{}, Count, Attrs, NS) -> Tag = if NS == ?NS_MAM_TMP -> <<"query">>; true -> <<"fin">> end, - [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|QIDAttr], - children = jlib:rsm_encode(#rsm_out{count = Count})}]; -make_rsm_out([{FirstID, _, _}|_] = Msgs, #rsm_in{}, Count, QIDAttr, NS) -> + [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|Attrs], + children = jlib:rsm_encode(#rsm_out{count = Count})}]; +make_rsm_out([{FirstID, _, _}|_] = Msgs, #rsm_in{}, Count, Attrs, NS) -> {LastID, _, _} = lists:last(Msgs), Tag = if NS == ?NS_MAM_TMP -> <<"query">>; true -> <<"fin">> end, - [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|QIDAttr], - children = jlib:rsm_encode( - #rsm_out{first = FirstID, count = Count, - last = LastID})}]. + [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|Attrs], + children = jlib:rsm_encode( + #rsm_out{first = FirstID, count = Count, + last = LastID})}]. filter_by_rsm(Msgs, none) -> - Msgs; -filter_by_rsm(_Msgs, #rsm_in{max = Max}) when Max =< 0 -> - []; + {Msgs, true}; +filter_by_rsm(_Msgs, #rsm_in{max = Max}) when Max < 0 -> + {[], true}; filter_by_rsm(Msgs, #rsm_in{max = Max, direction = Direction, id = ID}) -> NewMsgs = case Direction of aft when ID /= <<"">> -> @@ -683,11 +702,11 @@ filter_by_rsm(Msgs, #rsm_in{max = Max, direction = Direction, id = ID}) -> filter_by_max(NewMsgs, Max). filter_by_max(Msgs, undefined) -> - Msgs; + {Msgs, true}; filter_by_max(Msgs, Len) when is_integer(Len), Len >= 0 -> - lists:sublist(Msgs, Len); + {lists:sublist(Msgs, Len), length(Msgs) =< Len}; filter_by_max(_Msgs, _Junk) -> - []. + {[], true}. make_matchspec(LUser, LServer, Start, End, {_, _, <<>>} = With) -> ets:fun2ms( @@ -729,10 +748,10 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> {none, none, <<>>} end, LimitClause = if is_integer(Max), Max >= 0 -> - [<<" limit ">>, jlib:integer_to_binary(Max)]; - true -> - [] - end, + [<<" limit ">>, jlib:integer_to_binary(Max+1)]; + true -> + [] + end, WithClause = case With of {text, <<>>} -> []; diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 8cd21d5e9d2..075a53fe227 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1690,7 +1690,7 @@ mam_query_all(Config, NS) -> if NS == ?NS_MAM_TMP -> ?recv1(#iq{type = result, id = I, sub_els = []}); true -> - ?recv1(#message{sub_els = [#mam_fin{id = QID}]}) + ?recv1(#message{sub_els = [#mam_fin{complete = true, id = QID}]}) end. mam_query_with(Config, JID, NS) -> @@ -1726,7 +1726,7 @@ mam_query_with(Config, JID, NS) -> if NS == ?NS_MAM_TMP -> ?recv1(#iq{type = result, id = I, sub_els = []}); true -> - ?recv1(#message{sub_els = [#mam_fin{}]}) + ?recv1(#message{sub_els = [#mam_fin{complete = true}]}) end. maybe_recv_iq_result(?NS_MAM_0, I1) -> @@ -1767,6 +1767,7 @@ mam_query_rsm(Config, NS) -> rsm = #rsm_set{last = Last, count = 5}}]}); true -> ?recv1(#message{sub_els = [#mam_fin{ + complete = false, rsm = #rsm_set{last = Last, count = 10}}]}) end, %% Get the next items starting from the `Last`. @@ -1802,15 +1803,16 @@ mam_query_rsm(Config, NS) -> true -> ?recv1(#message{ sub_els = [#mam_fin{ + complete = false, rsm = #rsm_set{ count = 10, first = #rsm_first{data = First}}}]}) end, - %% Paging back. Should receive 2 elements: 2, 3. + %% Paging back. Should receive 3 elements: 1, 2, 3. I3 = send(Config, #iq{type = Type, sub_els = [#mam_query{xmlns = NS, - rsm = #rsm_set{max = 2, + rsm = #rsm_set{max = 3, before = First}}]}), maybe_recv_iq_result(NS, I3), lists:foreach( @@ -1827,13 +1829,14 @@ mam_query_rsm(Config, NS) -> [#message{ from = MyJID, to = Peer, body = [Text]}]}]}]}) - end, lists:seq(2, 3)), + end, lists:seq(1, 3)), if NS == ?NS_MAM_TMP -> ?recv1(#iq{type = result, id = I3, sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{count = 5}}]}); true -> ?recv1(#message{ - sub_els = [#mam_fin{rsm = #rsm_set{count = 10}}]}) + sub_els = [#mam_fin{complete = true, + rsm = #rsm_set{count = 10}}]}) end, %% Getting the item count. Should be 5 (or 10). I4 = send(Config, @@ -1851,6 +1854,7 @@ mam_query_rsm(Config, NS) -> true -> ?recv1(#message{ sub_els = [#mam_fin{ + complete = false, rsm = #rsm_set{count = 10, first = undefined, last = undefined}}]}) @@ -1882,7 +1886,8 @@ mam_query_rsm(Config, NS) -> sub_els = [#mam_query{xmlns = NS, rsm = #rsm_set{count = 5}}]}); true -> ?recv1(#message{ - sub_els = [#mam_fin{rsm = #rsm_set{count = 10}}]}) + sub_els = [#mam_fin{complete = false, + rsm = #rsm_set{count = 10}}]}) end. client_state_master(Config) -> diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 08a2e84cae7..987eb7c4135 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -2082,7 +2082,7 @@ encode({mam_result, _, _, _, _} = Result) -> encode_mam_result(Result, []); encode({mam_prefs, _, _, _, _} = Prefs) -> encode_mam_prefs(Prefs, []); -encode({mam_fin, _, _} = Fin) -> +encode({mam_fin, _, _, _, _} = Fin) -> encode_mam_fin(Fin, [{<<"xmlns">>, <<"urn:xmpp:mam:0">>}]); encode({forwarded, _, _} = Forwarded) -> @@ -2308,7 +2308,7 @@ get_ns({rsm_first, _, _}) -> get_ns({rsm_set, _, _, _, _, _, _, _}) -> <<"http://jabber.org/protocol/rsm">>; get_ns({mam_archived, _, _}) -> <<"urn:xmpp:mam:tmp">>; -get_ns({mam_fin, _, _}) -> <<"urn:xmpp:mam:0">>; +get_ns({mam_fin, _, _, _, _}) -> <<"urn:xmpp:mam:0">>; get_ns({forwarded, _, _}) -> <<"urn:xmpp:forward:0">>; get_ns({carbons_disable}) -> <<"urn:xmpp:carbons:2">>; get_ns({carbons_enable}) -> <<"urn:xmpp:carbons:2">>; @@ -2505,7 +2505,7 @@ pp(mam_query, 7) -> pp(mam_archived, 2) -> [by, id]; pp(mam_result, 4) -> [xmlns, queryid, id, sub_els]; pp(mam_prefs, 4) -> [xmlns, default, always, never]; -pp(mam_fin, 2) -> [id, rsm]; +pp(mam_fin, 4) -> [id, rsm, stable, complete]; pp(forwarded, 2) -> [delay, sub_els]; pp(carbons_disable, 0) -> []; pp(carbons_enable, 0) -> []; @@ -3709,9 +3709,10 @@ decode_mam_fin(__TopXMLNS, __IgnoreEls, {xmlel, <<"fin">>, _attrs, _els}) -> Rsm = decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, undefined), - Id = decode_mam_fin_attrs(__TopXMLNS, _attrs, - undefined), - {mam_fin, Id, Rsm}. + {Id, Stable, Complete} = + decode_mam_fin_attrs(__TopXMLNS, _attrs, undefined, + undefined, undefined), + {mam_fin, Id, Rsm, Stable, Complete}. decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [], Rsm) -> Rsm; @@ -3729,16 +3730,37 @@ decode_mam_fin_els(__TopXMLNS, __IgnoreEls, [_ | _els], decode_mam_fin_els(__TopXMLNS, __IgnoreEls, _els, Rsm). decode_mam_fin_attrs(__TopXMLNS, - [{<<"queryid">>, _val} | _attrs], _Id) -> - decode_mam_fin_attrs(__TopXMLNS, _attrs, _val); -decode_mam_fin_attrs(__TopXMLNS, [_ | _attrs], Id) -> - decode_mam_fin_attrs(__TopXMLNS, _attrs, Id); -decode_mam_fin_attrs(__TopXMLNS, [], Id) -> - decode_mam_fin_attr_queryid(__TopXMLNS, Id). - -encode_mam_fin({mam_fin, Id, Rsm}, _xmlns_attrs) -> + [{<<"queryid">>, _val} | _attrs], _Id, Stable, + Complete) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, _val, Stable, + Complete); +decode_mam_fin_attrs(__TopXMLNS, + [{<<"stable">>, _val} | _attrs], Id, _Stable, + Complete) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, _val, + Complete); +decode_mam_fin_attrs(__TopXMLNS, + [{<<"complete">>, _val} | _attrs], Id, Stable, + _Complete) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Stable, + _val); +decode_mam_fin_attrs(__TopXMLNS, [_ | _attrs], Id, + Stable, Complete) -> + decode_mam_fin_attrs(__TopXMLNS, _attrs, Id, Stable, + Complete); +decode_mam_fin_attrs(__TopXMLNS, [], Id, Stable, + Complete) -> + {decode_mam_fin_attr_queryid(__TopXMLNS, Id), + decode_mam_fin_attr_stable(__TopXMLNS, Stable), + decode_mam_fin_attr_complete(__TopXMLNS, Complete)}. + +encode_mam_fin({mam_fin, Id, Rsm, Stable, Complete}, + _xmlns_attrs) -> _els = lists:reverse('encode_mam_fin_$rsm'(Rsm, [])), - _attrs = encode_mam_fin_attr_queryid(Id, _xmlns_attrs), + _attrs = encode_mam_fin_attr_complete(Complete, + encode_mam_fin_attr_stable(Stable, + encode_mam_fin_attr_queryid(Id, + _xmlns_attrs))), {xmlel, <<"fin">>, _attrs, _els}. 'encode_mam_fin_$rsm'(undefined, _acc) -> _acc; @@ -3755,6 +3777,35 @@ encode_mam_fin_attr_queryid(undefined, _acc) -> _acc; encode_mam_fin_attr_queryid(_val, _acc) -> [{<<"queryid">>, _val} | _acc]. +decode_mam_fin_attr_stable(__TopXMLNS, undefined) -> + undefined; +decode_mam_fin_attr_stable(__TopXMLNS, _val) -> + case catch dec_bool(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"stable">>, <<"fin">>, __TopXMLNS}}); + _res -> _res + end. + +encode_mam_fin_attr_stable(undefined, _acc) -> _acc; +encode_mam_fin_attr_stable(_val, _acc) -> + [{<<"stable">>, enc_bool(_val)} | _acc]. + +decode_mam_fin_attr_complete(__TopXMLNS, undefined) -> + undefined; +decode_mam_fin_attr_complete(__TopXMLNS, _val) -> + case catch dec_bool(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"complete">>, <<"fin">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_mam_fin_attr_complete(undefined, _acc) -> _acc; +encode_mam_fin_attr_complete(_val, _acc) -> + [{<<"complete">>, enc_bool(_val)} | _acc]. + decode_mam_prefs(__TopXMLNS, __IgnoreEls, {xmlel, <<"prefs">>, _attrs, _els}) -> {Never, Always} = decode_mam_prefs_els(__TopXMLNS, diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index fa8e5e74d1f..7996f6a1144 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -288,7 +288,9 @@ max :: non_neg_integer()}). -record(mam_fin, {id :: binary(), - rsm :: #rsm_set{}}). + rsm :: #rsm_set{}, + stable :: any(), + complete :: any()}). -record(vcard_tel, {home = false :: boolean(), work = false :: boolean(), diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 326d1de3604..38508ce6c42 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2210,8 +2210,14 @@ -xml(mam_fin, #elem{name = <<"fin">>, xmlns = <<"urn:xmpp:mam:0">>, - result = {mam_fin, '$id', '$rsm'}, - attrs = [#attr{name = <<"queryid">>, label = '$id'}], + result = {mam_fin, '$id', '$rsm', '$stable', '$complete'}, + attrs = [#attr{name = <<"queryid">>, label = '$id'}, + #attr{name = <<"stable">>, label = '$stable', + dec = {dec_bool, []}, + enc = {enc_bool, []}}, + #attr{name = <<"complete">>, label = '$complete', + dec = {dec_bool, []}, + enc = {enc_bool, []}}], refs = [#ref{name = rsm_set, min = 0, max = 1, label = '$rsm'}]}). -xml(forwarded, From 062d2d696f4b6d8a96a81033815ecc50d07e76d2 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 11 Jul 2015 11:20:38 +0200 Subject: [PATCH 154/695] Update dev section to show erl command-line start command --- README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README b/README index 2f78d1973da..31a76778b7a 100644 --- a/README +++ b/README @@ -159,6 +159,10 @@ In order to assist in the development of ejabberd, and particularly the execution of the test suite, a Vagrant environment is available at https://github.com/processone/ejabberd-vagrant-dev. +To start ejabberd in development mode from the repository directory, you can +type a command like: + + EJABBERD_CONFIG_PATH=ejabberd.yml erl -pa ebin -pa deps/*/ebin -pa test -s ejabberd Links ----- From 9ede414f011a1d7de6e8a34e52d659ba2490442f Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 11:54:35 +0200 Subject: [PATCH 155/695] Support more mod_muc_admin translation strings (#659) --- src/mod_muc_admin.erl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 1804ba7e521..6aa3482dc7b 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -241,8 +241,8 @@ web_menu_host(Acc, _Host, Lang) -> ])). web_page_main(_, #request{path=[<<"muc">>], lang = Lang} = _Request) -> - Res = [?XC(<<"h1">>, <<"Multi-User Chat">>), - ?XC(<<"h3">>, <<"Statistics">>), + Res = [?XCT(<<"h1">>, <<"Multi-User Chat">>), + ?XCT(<<"h3">>, <<"Statistics">>), ?XAE(<<"table">>, [], [?XE(<<"tbody">>, [?TDTD(<<"Total rooms">>, ets:info(muc_online_room, size)), ?TDTD(<<"Permanent rooms">>, mnesia:table_info(muc_room, size)), @@ -301,22 +301,22 @@ make_rooms_page(Host, Lang, {Sort_direction, Sort_column}) -> <<"Persistent">>, <<"Logging">>, <<"Just created">>, - <<"Title">>], + <<"Room title">>], {Titles_TR, _} = lists:mapfoldl( fun(Title, Num_column) -> NCS = jlib:integer_to_binary(Num_column), TD = ?XE(<<"td">>, [?CT(Title), ?C(<<" ">>), - ?ACT(<<"?sort=", NCS/binary>>, <<"<">>), + ?AC(<<"?sort=", NCS/binary>>, <<"<">>), ?C(<<" ">>), - ?ACT(<<"?sort=-", NCS/binary>>, <<">">>)]), + ?AC(<<"?sort=-", NCS/binary>>, <<">">>)]), {TD, Num_column+1} end, 1, Titles), - [?XC(<<"h1">>, <<"Multi-User Chat">>), - ?XC(<<"h2">>, <<"Rooms">>), + [?XCT(<<"h1">>, <<"Multi-User Chat">>), + ?XCT(<<"h2">>, <<"Chatrooms">>), ?XE(<<"table">>, [?XE(<<"thead">>, [?XE(<<"tr">>, Titles_TR)] From c012d7555b1c3830e9db45dfdc266ead6d4ede25 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 13:09:58 +0200 Subject: [PATCH 156/695] Add links in WebAdmin to ejabberd and ProcessOne (#661) --- src/ejabberd_web_admin.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index da166581c40..4a1ccbb831d 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -340,8 +340,11 @@ make_xhtml(Els, Host, Node, Lang, JID) -> [{xmlcdata, <<"">>}])]), ?XAE(<<"div">>, [{<<"id">>, <<"copyrightouter">>}], [?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}], - [?XC(<<"p">>, - <<"ejabberd (c) 2002-2015 ProcessOne">>)])])])]}}. + [?XE(<<"p">>, + [?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>), + ?C(<<" (c) 2002-2015 ">>), + ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne">>)] + )])])])]}}. get_base_path(global, cluster) -> <<"/admin/">>; get_base_path(Host, cluster) -> From f4376671ac50ff8ce1c8711425e530a7ec93fb00 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 18:51:17 +0200 Subject: [PATCH 157/695] Set LTR direction to Raw links (#650) --- src/ejabberd_web_admin.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 4a1ccbb831d..1838922bc8e 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -706,7 +706,7 @@ process_admin(Host, nothing -> [] end ++ - [?XE(<<"p">>, [?ACT(<<"../acls-raw/">>, <<"Raw">>)])] ++ + [?XAE(<<"p">>, direction(ltr), [?ACT(<<"../acls-raw/">>, <<"Raw">>)])] ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [acls_to_xhtml(ACLs), ?BR, @@ -805,7 +805,7 @@ process_admin(Host, nothing -> [] end ++ - [?XE(<<"p">>, [?ACT(<<"../access-raw/">>, <<"Raw">>)])] + [?XAE(<<"p">>, direction(ltr), [?ACT(<<"../access-raw/">>, <<"Raw">>)])] ++ [?XAE(<<"form">>, [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], From 65551afcbab38b07a7f7302048f00984334dae77 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 19:01:32 +0200 Subject: [PATCH 158/695] Support RTL page direction in WebAdmin for Hebrew (#650) --- src/ejabberd_web_admin.erl | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 1838922bc8e..1b58af6696f 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -296,7 +296,7 @@ make_xhtml(Els, Host, Node, Lang, JID) -> #xmlel{name = <<"html">>, attrs = [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}, - {<<"xml:lang">>, Lang}, {<<"lang">>, Lang}], + {<<"xml:lang">>, Lang}, {<<"lang">>, Lang}]++direction(Lang), children = [#xmlel{name = <<"head">>, attrs = [], children = @@ -346,6 +346,10 @@ make_xhtml(Els, Host, Node, Lang, JID) -> ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne">>)] )])])])]}}. +direction(ltr) -> [{<<"dir">>, <<"ltr">>}]; +direction(<<"he">>) -> [{<<"dir">>, <<"rtl">>}]; +direction(_) -> []. + get_base_path(global, cluster) -> <<"/admin/">>; get_base_path(Host, cluster) -> <<"/admin/server/", Host/binary, "/">>; @@ -513,7 +517,7 @@ css(Host) -> "0px;\n}\n\nh3 {\n color: #000044;\n " " font-family: Verdana, Arial, Helvetica, " "sans-serif; \n font-size: 10pt;\n " - "font-weight: bold;\n text-align: left;\n " + "font-weight: bold;\n " " padding-top: 20px;\n padding-bottom: " "2px;\n margin-top: 0px;\n margin-bottom: " "0px;\n}\n\n#content a:link {\n color: " @@ -671,7 +675,7 @@ process_admin(Host, end ++ [?XAE(<<"form">>, - [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], + [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [?TEXTAREA(<<"acls">>, (iolist_to_binary(integer_to_list(lists:max([16, NumLines])))), @@ -708,7 +712,7 @@ process_admin(Host, ++ [?XAE(<<"p">>, direction(ltr), [?ACT(<<"../acls-raw/">>, <<"Raw">>)])] ++ [?XAE(<<"form">>, - [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], + [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [acls_to_xhtml(ACLs), ?BR, ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>), @@ -773,7 +777,7 @@ process_admin(Host, end ++ [?XAE(<<"form">>, - [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], + [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [?TEXTAREA(<<"access">>, (iolist_to_binary(integer_to_list(lists:max([16, NumLines])))), @@ -808,7 +812,7 @@ process_admin(Host, [?XAE(<<"p">>, direction(ltr), [?ACT(<<"../access-raw/">>, <<"Raw">>)])] ++ [?XAE(<<"form">>, - [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], + [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}]++direction(ltr), [access_rules_to_xhtml(AccessRules, Lang), ?BR, ?INPUTT(<<"submit">>, <<"delete">>, <<"Delete Selected">>)])], @@ -2384,7 +2388,7 @@ node_ports_to_xhtml(Ports, Lang) -> [?INPUTS(<<"text">>, <<"module", SSPort/binary>>, SModule, <<"15">>)]), - ?XE(<<"td">>, + ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"opts", SSPort/binary>>, (iolist_to_binary(integer_to_list(NumLines))), <<"35">>, SOptsClean)]), @@ -2410,7 +2414,7 @@ node_ports_to_xhtml(Ports, Lang) -> ?XE(<<"td">>, [?INPUTS(<<"text">>, <<"modulenew">>, <<"">>, <<"15">>)]), - ?XE(<<"td">>, + ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"optsnew">>, <<"2">>, <<"35">>, <<"[]">>)]), ?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}], @@ -2527,7 +2531,7 @@ node_modules_to_xhtml(Modules, Lang) -> 40), ?XE(<<"tr">>, [?XC(<<"td">>, SModule), - ?XE(<<"td">>, + ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"opts", SModule/binary>>, (iolist_to_binary(integer_to_list(NumLines))), <<"40">>, SOpts)]), @@ -2546,7 +2550,7 @@ node_modules_to_xhtml(Modules, Lang) -> [?XE(<<"tr">>, [?XE(<<"td">>, [?INPUT(<<"text">>, <<"modulenew">>, <<"">>)]), - ?XE(<<"td">>, + ?XAE(<<"td">>, direction(ltr), [?TEXTAREA(<<"optsnew">>, <<"2">>, <<"40">>, <<"[]">>)]), ?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}], From 3eb0b161b2ab9b3cf16014d6c3f7dec8e782d423 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 20:40:13 +0200 Subject: [PATCH 159/695] Update links to Guide in WebAdmin --- src/ejabberd_web_admin.erl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 1b58af6696f..7f2bd81e442 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -597,7 +597,7 @@ logo_fill() -> process_admin(global, #request{path = [], auth = {_, _, AJID}, lang = Lang}) -> - make_xhtml((?H1GL((?T(<<"Administration">>)), <<"toc">>, + make_xhtml((?H1GL((?T(<<"Administration">>)), <<"">>, <<"Contents">>)) ++ [?XE(<<"ul">>, @@ -666,7 +666,7 @@ process_admin(Host, [{{acl, '$1', '$2'}}]}])), {NumLines, ACLsP} = term_to_paragraph(ACLs, 80), make_xhtml((?H1GL((?T(<<"Access Control Lists">>)), - <<"ACLDefinition">>, <<"ACL Definition">>)) + <<"acl-definition">>, <<"ACL Definition">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -702,7 +702,7 @@ process_admin(Host, [{{acl, {'$1', Host}, '$2'}, [], [{{acl, '$1', '$2'}}]}])), make_xhtml((?H1GL((?T(<<"Access Control Lists">>)), - <<"ACLDefinition">>, <<"ACL Definition">>)) + <<"acl-definition">>, <<"ACL Definition">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -768,7 +768,7 @@ process_admin(Host, [{{access, '$1', '$2'}}]}]), {NumLines, AccessP} = term_to_paragraph(lists:keysort(2,Access), 80), make_xhtml((?H1GL((?T(<<"Access Rules">>)), - <<"AccessRights">>, <<"Access Rights">>)) + <<"access-rights">>, <<"Access Rights">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -801,7 +801,7 @@ process_admin(Host, [{{access, {'$1', Host}, '$2'}, [], [{{access, '$1', '$2'}}]}]), make_xhtml((?H1GL((?T(<<"Access Rules">>)), - <<"AccessRights">>, <<"Access Rights">>)) + <<"access-rights">>, <<"Access Rights">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -860,7 +860,7 @@ process_admin(global, lang = Lang}) -> Res = list_vhosts(Lang, AJID), make_xhtml((?H1GL((?T(<<"Virtual Hosts">>)), - <<"virtualhost">>, <<"Virtual Hosting">>)) + <<"virtual-hosting">>, <<"Virtual Hosting">>)) ++ Res, global, Lang, AJID); process_admin(Host, @@ -1879,9 +1879,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) -> [?XRES(<<(?T(<<"Error">>))/binary, ": ", (list_to_binary(io_lib:format("~p", [Error])))/binary>>)] end, - (?H1GL(list_to_binary(io_lib:format(?T(<<"Backup of ~p">>), [Node])), - <<"list-eja-commands">>, - <<"List of ejabberd Commands">>)) + [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Backup of ~p">>), [Node])))] ++ ResS ++ [?XCT(<<"p">>, @@ -2043,7 +2041,7 @@ get_node(global, Node, [<<"ports">>], Query, Lang) -> []])), H1String = <<(?T(<<"Listened Ports at ">>))/binary, (iolist_to_binary(atom_to_list(Node)))/binary>>, - (?H1GL(H1String, <<"listened">>, <<"Listening Ports">>)) + (?H1GL(H1String, <<"listening-ports">>, <<"Listening Ports">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -2071,7 +2069,7 @@ get_node(Host, Node, [<<"modules">>], Query, Lang) NewModules = lists:sort(rpc:call(Node, gen_mod, loaded_modules_with_opts, [Host])), H1String = list_to_binary(io_lib:format(?T(<<"Modules at ~p">>), [Node])), - (?H1GL(H1String, <<"modoverview">>, + (?H1GL(H1String, <<"modules-overview">>, <<"Modules Overview">>)) ++ case Res of From c53d764119dc90f4e643c334e6603b3e452d1757 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 20:45:55 +0200 Subject: [PATCH 160/695] If local guide.html file not found, redirect to the online guide --- src/ejabberd_web_admin.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 7f2bd81e442..4ff80ecedc1 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -167,15 +167,15 @@ process([<<"doc">>, LocalFile], _Request) -> ?DEBUG("Delivering content.", []), {200, [{<<"Server">>, <<"ejabberd">>}], FileContents}; {error, Error} -> - ?DEBUG("Delivering error: ~p", [Error]), Help = <<" ", FileName/binary, " - Try to specify the path to ejabberd " "documentation with the environment variable " "EJABBERD_DOC_PATH. Check the ejabberd " "Guide for more information.">>, + ?INFO_MSG("Problem '~p' accessing the local Guide file ~s", [Error, Help]), case Error of eacces -> {403, [], <<"Forbidden", Help/binary>>}; - enoent -> {404, [], <<"Not found", Help/binary>>}; + enoent -> {307, [{<<"Location">>, <<"http://docs.ejabberd.im/admin/guide/configuration/">>}], <<"Not found", Help/binary>>}; _Else -> {404, [], <<(iolist_to_binary(atom_to_list(Error)))/binary, Help/binary>>} end From 7395cc910e4cca4ca8adf6109b220d61f50bb4d9 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 15 Jul 2015 21:36:36 +0200 Subject: [PATCH 161/695] Set direction of resource and connection (#650) --- src/ejabberd_web_admin.erl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 4ff80ecedc1..3347f3e6eb8 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1559,16 +1559,18 @@ user_info(User, Server, Query, Lang) -> http_bind -> <<"http-bind">> end, - <<" (", ConnS/binary, + <> + (jlib:atom_to_binary(Node))/binary>> end, - ?LI([?C((<>))]) + case direction(Lang) of + [{_, <<"rtl">>}] -> ?LI([?C((<>))]); + _ -> ?LI([?C((<>))]) + end end, lists:sort(Resources))))] end, From 44cc99d616bfc18bfdb06ea0b10f1c8ff351db64 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 16 Jul 2015 13:30:14 +0300 Subject: [PATCH 162/695] Get rid of 'db_type' for mod_blocking in test suite --- test/ejabberd_SUITE_data/ejabberd.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index b1c95ffdf4c..111d72f7975 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -12,8 +12,7 @@ host_config: mod_announce: db_type: odbc access: local - mod_blocking: - db_type: odbc + mod_blocking: [] mod_caps: db_type: odbc mod_last: @@ -65,8 +64,7 @@ Welcome to this XMPP server." mod_announce: db_type: odbc access: local - mod_blocking: - db_type: odbc + mod_blocking: [] mod_caps: db_type: odbc mod_last: @@ -124,8 +122,7 @@ Welcome to this XMPP server." mod_announce: db_type: odbc access: local - mod_blocking: - db_type: odbc + mod_blocking: [] mod_caps: db_type: odbc mod_last: @@ -176,8 +173,7 @@ Welcome to this XMPP server." mod_announce: db_type: internal access: local - mod_blocking: - db_type: internal + mod_blocking: [] mod_caps: db_type: internal mod_last: @@ -232,8 +228,7 @@ Welcome to this XMPP server." mod_announce: db_type: riak access: local - mod_blocking: - db_type: riak + mod_blocking: [] mod_caps: db_type: riak mod_last: From 7f4c74dec94f54c67c6392670f918ed672faf22e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 17 Jul 2015 14:27:31 +0300 Subject: [PATCH 163/695] Print content types more gracefully --- src/mod_http_fileserver.erl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 68ebf8835b2..8b4d7337ec7 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -167,10 +167,17 @@ initialize(Host, Opts) -> ?DEFAULT_CONTENT_TYPE), ContentTypes = build_list_content_types( gen_mod:get_opt(content_types, Opts, - fun(L) when is_list(L) -> L end, - []), + fun(L) when is_list(L) -> + lists:map( + fun({K, V}) -> + {iolist_to_binary(K), + iolist_to_binary(V)} + end, L) + end, []), ?DEFAULT_CONTENT_TYPES), - ?INFO_MSG("initialize: ~n ~p", [ContentTypes]),%+++ + ?INFO_MSG("known content types: ~s", + [str:join([[$*, K, " -> ", V] || {K, V} <- ContentTypes], + <<", ">>)]), {DocRoot, AccessLog, AccessLogFD, DirectoryIndices, CustomHeaders, DefaultContentType, ContentTypes}. From 9c36a9df784313715d7a7b8fc1e13793b2451406 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Jul 2015 08:03:27 +0200 Subject: [PATCH 164/695] Do not init nodes from mod_pubsub (#609) Let each plugin do its own initialisation in init_plugins init_nodes was an old function to be removed. --- src/mod_pubsub.erl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index f572c33d175..e17b61c568d 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -312,7 +312,6 @@ init([ServerHost, Opts]) -> pubsub_migrate:update_node_database(Host, ServerHost), pubsub_migrate:update_state_database(Host, ServerHost), pubsub_migrate:update_lastitem_database(Host, ServerHost), - init_nodes(Host, ServerHost, NodeTree, Plugins), {_, State} = init_send_loop(ServerHost), {ok, State}. @@ -386,14 +385,6 @@ terminate_plugins(Host, ServerHost, Plugins, TreePlugin) -> TreePlugin:terminate(Host, ServerHost), ok. -init_nodes(Host, ServerHost, _NodeTree, Plugins) -> - case lists:member(<<"hometree">>, Plugins) of - true -> - create_node(Host, ServerHost, <<"/home">>, service_jid(Host), <<"hometree">>), - create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, service_jid(Host), <<"hometree">>); - false -> ok - end. - send_loop(State) -> receive {presence, JID, Pid} -> From 311fedaa125ede17349ade740c3cb9ff33ac4109 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Jul 2015 10:37:26 +0200 Subject: [PATCH 165/695] Let flat be default plugin (#609) --- src/node_buddy.erl | 58 +- src/node_club.erl | 58 +- src/node_dispatch.erl | 4 +- src/node_flat.erl | 769 ++++++++++++++++++++++-- src/node_flat_odbc.erl | 989 +++++++++++++++++++++++++++++-- src/node_hometree.erl | 811 +++----------------------- src/node_hometree_odbc.erl | 1122 ++---------------------------------- src/node_mb.erl | 1 - src/node_pep.erl | 52 +- src/node_pep_odbc.erl | 80 +-- src/node_private.erl | 58 +- src/node_public.erl | 58 +- 12 files changed, 1941 insertions(+), 2119 deletions(-) diff --git a/src/node_buddy.erl b/src/node_buddy.erl index a6ff0d4525b..410fd053408 100644 --- a/src/node_buddy.erl +++ b/src/node_buddy.erl @@ -45,10 +45,10 @@ path_to_node/1]). init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts). + node_flat:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost). + node_flat:terminate(Host, ServerHost). options() -> [{deliver_payloads, true}, @@ -86,89 +86,89 @@ features() -> <<"subscription-notifications">>]. create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - node_hometree:create_node(Nidx, Owner). + node_flat:create_node(Nidx, Owner). delete_node(Removed) -> - node_hometree:delete_node(Removed). + node_flat:delete_node(Removed). subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - node_hometree:purge_node(Nidx, Owner). + node_flat:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> - node_hometree:get_entity_affiliations(Host, Owner). + node_flat:get_entity_affiliations(Host, Owner). get_node_affiliations(Nidx) -> - node_hometree:get_node_affiliations(Nidx). + node_flat:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - node_hometree:get_affiliation(Nidx, Owner). + node_flat:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree:set_affiliation(Nidx, Owner, Affiliation). + node_flat:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> - node_hometree:get_entity_subscriptions(Host, Owner). + node_flat:get_entity_subscriptions(Host, Owner). get_node_subscriptions(Nidx) -> - node_hometree:get_node_subscriptions(Nidx). + node_flat:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - node_hometree:get_subscriptions(Nidx, Owner). + node_flat:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). + node_flat:get_pending_nodes(Host, Owner). get_states(Nidx) -> - node_hometree:get_states(Nidx). + node_flat:get_states(Nidx). get_state(Nidx, JID) -> - node_hometree:get_state(Nidx, JID). + node_flat:get_state(Nidx, JID). set_state(State) -> - node_hometree:set_state(State). + node_flat:set_state(State). get_items(Nidx, From, RSM) -> - node_hometree:get_items(Nidx, From, RSM). + node_flat:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree:get_items(Nidx, JID, AccessModel, + node_flat:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> - node_hometree:get_item(Nidx, ItemId). + node_flat:get_item(Nidx, ItemId). get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + node_flat:get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> - node_hometree:set_item(Item). + node_flat:set_item(Item). get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). + node_flat:get_item_name(Host, Node, Id). node_to_path(Node) -> node_flat:node_to_path(Node). diff --git a/src/node_club.erl b/src/node_club.erl index 6917312f2d4..cf433b695a1 100644 --- a/src/node_club.erl +++ b/src/node_club.erl @@ -45,10 +45,10 @@ path_to_node/1]). init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts). + node_flat:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost). + node_flat:terminate(Host, ServerHost). options() -> [{deliver_payloads, true}, @@ -85,89 +85,89 @@ features() -> <<"subscription-notifications">>]. create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - node_hometree:create_node(Nidx, Owner). + node_flat:create_node(Nidx, Owner). delete_node(Removed) -> - node_hometree:delete_node(Removed). + node_flat:delete_node(Removed). subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - node_hometree:purge_node(Nidx, Owner). + node_flat:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> - node_hometree:get_entity_affiliations(Host, Owner). + node_flat:get_entity_affiliations(Host, Owner). get_node_affiliations(Nidx) -> - node_hometree:get_node_affiliations(Nidx). + node_flat:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - node_hometree:get_affiliation(Nidx, Owner). + node_flat:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree:set_affiliation(Nidx, Owner, Affiliation). + node_flat:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> - node_hometree:get_entity_subscriptions(Host, Owner). + node_flat:get_entity_subscriptions(Host, Owner). get_node_subscriptions(Nidx) -> - node_hometree:get_node_subscriptions(Nidx). + node_flat:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - node_hometree:get_subscriptions(Nidx, Owner). + node_flat:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). + node_flat:get_pending_nodes(Host, Owner). get_states(Nidx) -> - node_hometree:get_states(Nidx). + node_flat:get_states(Nidx). get_state(Nidx, JID) -> - node_hometree:get_state(Nidx, JID). + node_flat:get_state(Nidx, JID). set_state(State) -> - node_hometree:set_state(State). + node_flat:set_state(State). get_items(Nidx, From, RSM) -> - node_hometree:get_items(Nidx, From, RSM). + node_flat:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree:get_items(Nidx, JID, AccessModel, + node_flat:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> - node_hometree:get_item(Nidx, ItemId). + node_flat:get_item(Nidx, ItemId). get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + node_flat:get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> - node_hometree:set_item(Item). + node_flat:set_item(Item). get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). + node_flat:get_item_name(Host, Node, Id). node_to_path(Node) -> node_flat:node_to_path(Node). diff --git a/src/node_dispatch.erl b/src/node_dispatch.erl index 7a12318400a..258405cb056 100644 --- a/src/node_dispatch.erl +++ b/src/node_dispatch.erl @@ -179,7 +179,7 @@ get_item_name(Host, Node, Id) -> node_hometree:get_item_name(Host, Node, Id). node_to_path(Node) -> - node_flat:node_to_path(Node). + node_hometree:node_to_path(Node). path_to_node(Path) -> - node_flat:path_to_node(Path). + node_hometree:path_to_node(Path). diff --git a/src/node_flat.erl b/src/node_flat.erl index e261543801c..736bbdfe188 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -24,6 +24,12 @@ %%% @end %%% ==================================================================== +%%% @doc The module {@module} is the default PubSub plugin. +%%%

    It is used as a default for all unknown PubSub node type. It can serve +%%% as a developer basis and reference to build its own custom pubsub node +%%% types.

    +%%%

    PubSub plugin nodes are using the {@link gen_node} behaviour.

    + -module(node_flat). -behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). @@ -40,9 +46,10 @@ get_entity_subscriptions/2, get_node_subscriptions/1, get_subscriptions/2, set_subscriptions/4, get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/7, get_items/3, get_item/7, + set_state/1, get_items/6, get_items/2, + get_items/7, get_items/3, get_item/7, get_item/2, set_item/1, get_item_name/3, node_to_path/1, - path_to_node/1]). + path_to_node/1, can_fetch_item/2, is_subscribed/1]). init(_Host, _ServerHost, _Opts) -> pubsub_subscription:init(), @@ -60,18 +67,55 @@ init(_Host, _ServerHost, _Opts) -> end, ok. -terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost). +terminate(_Host, _ServerHost) -> + ok. options() -> - node_hometree:options(). + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, open}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, on_sub_and_presence}, + {deliver_notifications, true}, + {presence_based_delivery, false}]. features() -> - node_hometree:features(). - -%% use same code as node_hometree, but do not limite node to -%% the home/localhost/user/... hierarchy -%% any node is allowed + [<<"create-nodes">>, + <<"auto-create">>, + <<"access-authorize">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"get-pending">>, + <<"instant-nodes">>, + <<"manage-subscriptions">>, + <<"modify-affiliations">>, + <<"multi-subscribe">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"publish-only-affiliation">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>, + <<"subscription-options">>]. + +%% @doc Checks if the current user has the permission to create the requested node +%%

    In flat node, any unused node name is allowed. The access parameter is also +%% checked. This parameter depends on the value of the +%% access_createnode ACL value in ejabberd config file.

    create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> LOwner = jlib:jid_tolower(Owner), Allowed = case LOwner of @@ -83,88 +127,684 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> {result, Allowed}. create_node(Nidx, Owner) -> - node_hometree:create_node(Nidx, Owner). - -delete_node(Removed) -> - node_hometree:delete_node(Removed). - + OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + set_state(#pubsub_state{stateid = {OwnerKey, Nidx}, + affiliation = owner}), + {result, {default, broadcast}}. + +delete_node(Nodes) -> + Tr = fun (#pubsub_state{stateid = {J, _}, subscriptions = Ss}) -> + lists:map(fun (S) -> {J, S} end, Ss) + end, + Reply = lists:map(fun (#pubsub_node{id = Nidx} = PubsubNode) -> + {result, States} = get_states(Nidx), + lists:foreach(fun (#pubsub_state{stateid = {LJID, _}, items = Items}) -> + del_items(Nidx, Items), + del_state(Nidx, LJID) + end, States), + {PubsubNode, lists:flatmap(Tr, States)} + end, Nodes), + {result, {default, broadcast, Reply}}. + +%% @doc

    Accepts or rejects subcription requests on a PubSub node.

    +%%

    The mechanism works as follow: +%%

      +%%
    • The main PubSub module prepares the subscription and passes the +%% result of the preparation as a record.
    • +%%
    • This function gets the prepared record and several other parameters and +%% can decide to:
        +%%
      • reject the subscription;
      • +%%
      • allow it as is, letting the main module perform the database +%% persistance;
      • +%%
      • allow it, modifying the record. The main module will store the +%% modified record;
      • +%%
      • allow it, but perform the needed persistance operations.
      +%%

    +%%

    The selected behaviour depends on the return parameter: +%%

      +%%
    • {error, Reason}: an IQ error result will be returned. No +%% subscription will actually be performed.
    • +%%
    • true: Subscribe operation is allowed, based on the +%% unmodified record passed in parameter SubscribeResult. If this +%% parameter contains an error, no subscription will be performed.
    • +%%
    • {true, PubsubState}: Subscribe operation is allowed, but +%% the {@link mod_pubsub:pubsubState()} record returned replaces the value +%% passed in parameter SubscribeResult.
    • +%%
    • {true, done}: Subscribe operation is allowed, but the +%% {@link mod_pubsub:pubsubState()} will be considered as already stored and +%% no further persistance operation will be performed. This case is used, +%% when the plugin module is doing the persistance by itself or when it want +%% to completly disable persistance.
    +%%

    +%%

    In the default plugin module, the record is unchanged.

    subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(Nidx, Sender, Subscriber, - AccessModel, SendLast, PresenceSubscription, - RosterGroup, Options). + SubKey = jlib:jid_tolower(Subscriber), + GenKey = jlib:jid_remove_resource(SubKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + GenState = get_state(Nidx, GenKey), + SubState = case SubKey of + GenKey -> GenState; + _ -> get_state(Nidx, SubKey) + end, + Affiliation = GenState#pubsub_state.affiliation, + Subscriptions = SubState#pubsub_state.subscriptions, + Whitelisted = lists:member(Affiliation, [member, publisher, owner]), + PendingSubscription = lists:any(fun + ({pending, _}) -> true; + (_) -> false + end, + Subscriptions), + Owner = Affiliation == owner, + if not Authorized -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; + (Affiliation == outcast) or (Affiliation == publish_only) -> + {error, ?ERR_FORBIDDEN}; + PendingSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; + (AccessModel == presence) and (not PresenceSubscription) and (not Owner) -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and (not RosterGroup) and (not Owner) -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and (not Whitelisted) and (not Owner) -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + %%ForbiddenAnonymous -> + %% % Requesting entity is anonymous + %% {error, ?ERR_FORBIDDEN}; + true -> + SubId = pubsub_subscription:add_subscription(Subscriber, Nidx, Options), + NewSub = case AccessModel of + authorize -> pending; + _ -> subscribed + end, + set_state(SubState#pubsub_state{subscriptions = + [{NewSub, SubId} | Subscriptions]}), + case {NewSub, SendLast} of + {subscribed, never} -> + {result, {default, subscribed, SubId}}; + {subscribed, _} -> + {result, {default, subscribed, SubId, send_last}}; + {_, _} -> + {result, {default, pending, SubId}} + end + end. +%% @doc

    Unsubscribe the Subscriber from the Node.

    unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + SubKey = jlib:jid_tolower(Subscriber), + GenKey = jlib:jid_remove_resource(SubKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + GenState = get_state(Nidx, GenKey), + SubState = case SubKey of + GenKey -> GenState; + _ -> get_state(Nidx, SubKey) + end, + Subscriptions = lists:filter(fun + ({_Sub, _SubId}) -> true; + (_SubId) -> false + end, + SubState#pubsub_state.subscriptions), + SubIdExists = case SubId of + <<>> -> false; + Binary when is_binary(Binary) -> true; + _ -> false + end, + if + %% Requesting entity is prohibited from unsubscribing entity + not Authorized -> + {error, ?ERR_FORBIDDEN}; + %% Entity did not specify SubId + %%SubId == "", ?? -> + %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %% Invalid subscription identifier + %%InvalidSubId -> + %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + %% Requesting entity is not a subscriber + Subscriptions == [] -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; + %% Subid supplied, so use that. + SubIdExists -> + Sub = first_in_list(fun + ({_, S}) when S == SubId -> true; + (_) -> false + end, + SubState#pubsub_state.subscriptions), + case Sub of + {value, S} -> + delete_subscriptions(SubKey, Nidx, [S], SubState), + {result, default}; + false -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} + end; + %% Asking to remove all subscriptions to the given node + SubId == all -> + delete_subscriptions(SubKey, Nidx, Subscriptions, SubState), + {result, default}; + %% No subid supplied, but there's only one matching subscription + length(Subscriptions) == 1 -> + delete_subscriptions(SubKey, Nidx, Subscriptions, SubState), + {result, default}; + %% No subid and more than one possible subscription match. + true -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} + end. -publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). +delete_subscriptions(SubKey, Nidx, Subscriptions, SubState) -> + NewSubs = lists:foldl(fun ({Subscription, SubId}, Acc) -> + pubsub_subscription:delete_subscription(SubKey, Nidx, SubId), + Acc -- [{Subscription, SubId}] + end, SubState#pubsub_state.subscriptions, Subscriptions), + case {SubState#pubsub_state.affiliation, NewSubs} of + {none, []} -> del_state(Nidx, SubKey); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) + end. -remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). +%% @doc

    Publishes the item passed as parameter.

    +%%

    The mechanism works as follow: +%%

      +%%
    • The main PubSub module prepares the item to publish and passes the +%% result of the preparation as a {@link mod_pubsub:pubsubItem()} record.
    • +%%
    • This function gets the prepared record and several other parameters and can decide to:
        +%%
      • reject the publication;
      • +%%
      • allow the publication as is, letting the main module perform the database persistance;
      • +%%
      • allow the publication, modifying the record. The main module will store the modified record;
      • +%%
      • allow it, but perform the needed persistance operations.
      +%%

    +%%

    The selected behaviour depends on the return parameter: +%%

      +%%
    • {error, Reason}: an iq error result will be return. No +%% publication is actually performed.
    • +%%
    • true: Publication operation is allowed, based on the +%% unmodified record passed in parameter Item. If the Item +%% parameter contains an error, no subscription will actually be +%% performed.
    • +%%
    • {true, Item}: Publication operation is allowed, but the +%% {@link mod_pubsub:pubsubItem()} record returned replaces the value passed +%% in parameter Item. The persistance will be performed by the main +%% module.
    • +%%
    • {true, done}: Publication operation is allowed, but the +%% {@link mod_pubsub:pubsubItem()} will be considered as already stored and +%% no further persistance operation will be performed. This case is used, +%% when the plugin module is doing the persistance by itself or when it want +%% to completly disable persistance.
    +%%

    +%%

    In the default plugin module, the record is unchanged.

    +publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> + SubKey = jlib:jid_tolower(Publisher), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + SubState = case SubKey of + GenKey -> GenState; + _ -> get_state(Nidx, SubKey) + end, + Affiliation = GenState#pubsub_state.affiliation, + Subscribed = case PublishModel of + subscribers -> is_subscribed(GenState#pubsub_state.subscriptions) orelse + is_subscribed(SubState#pubsub_state.subscriptions); + _ -> undefined + end, + if not ((PublishModel == open) or + (PublishModel == publishers) and + ((Affiliation == owner) + or (Affiliation == publisher) + or (Affiliation == publish_only)) + or (Subscribed == true)) -> + {error, ?ERR_FORBIDDEN}; + true -> + if MaxItems > 0 -> + Now = now(), + PubId = {Now, SubKey}, + Item = case get_item(Nidx, ItemId) of + {result, OldItem} -> + OldItem#pubsub_item{modification = PubId, + payload = Payload}; + _ -> + #pubsub_item{itemid = {ItemId, Nidx}, + creation = {Now, GenKey}, + modification = PubId, + payload = Payload} + end, + Items = [ItemId | GenState#pubsub_state.items -- [ItemId]], + {result, {NI, OI}} = remove_extra_items(Nidx, MaxItems, Items), + set_item(Item), + set_state(GenState#pubsub_state{items = NI}), + {result, {default, broadcast, OI}}; + true -> + {result, {default, broadcast, []}} + end + end. +%% @doc

    This function is used to remove extra items, most notably when the +%% maximum number of items has been reached.

    +%%

    This function is used internally by the core PubSub module, as no +%% permission check is performed.

    +%%

    In the default plugin module, the oldest items are removed, but other +%% rules can be used.

    +%%

    If another PubSub plugin wants to delegate the item removal (and if the +%% plugin is using the default pubsub storage), it can implements this function like this: +%% ```remove_extra_items(Nidx, MaxItems, ItemIds) -> +%% node_default:remove_extra_items(Nidx, MaxItems, ItemIds).'''

    +remove_extra_items(_Nidx, unlimited, ItemIds) -> + {result, {ItemIds, []}}; +remove_extra_items(Nidx, MaxItems, ItemIds) -> + NewItems = lists:sublist(ItemIds, MaxItems), + OldItems = lists:nthtail(length(NewItems), ItemIds), + del_items(Nidx, OldItems), + {result, {NewItems, OldItems}}. + +%% @doc

    Triggers item deletion.

    +%%

    Default plugin: The user performing the deletion must be the node owner +%% or a publisher, or PublishModel being open.

    delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + SubKey = jlib:jid_tolower(Publisher), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + #pubsub_state{affiliation = Affiliation, items = Items} = GenState, + Allowed = Affiliation == publisher orelse + Affiliation == owner orelse + PublishModel == open orelse + case get_item(Nidx, ItemId) of + {result, #pubsub_item{creation = {_, GenKey}}} -> true; + _ -> false + end, + if not Allowed -> + {error, ?ERR_FORBIDDEN}; + true -> + case lists:member(ItemId, Items) of + true -> + del_item(Nidx, ItemId), + set_state(GenState#pubsub_state{items = lists:delete(ItemId, Items)}), + {result, {default, broadcast}}; + false -> + case Affiliation of + owner -> + {result, States} = get_states(Nidx), + lists:foldl(fun + (#pubsub_state{items = PI} = S, Res) -> + case lists:member(ItemId, PI) of + true -> + Nitems = lists:delete(ItemId, PI), + del_item(Nidx, ItemId), + set_state(S#pubsub_state{items = Nitems}), + {result, {default, broadcast}}; + false -> + Res + end; + (_, Res) -> + Res + end, + {error, ?ERR_ITEM_NOT_FOUND}, States); + _ -> + {error, ?ERR_ITEM_NOT_FOUND} + end + end + end. purge_node(Nidx, Owner) -> - node_hometree:purge_node(Nidx, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + case GenState of + #pubsub_state{affiliation = owner} -> + {result, States} = get_states(Nidx), + lists:foreach(fun + (#pubsub_state{items = []}) -> + ok; + (#pubsub_state{items = Items} = S) -> + del_items(Nidx, Items), + set_state(S#pubsub_state{items = []}) + end, + States), + {result, {default, broadcast}}; + _ -> + {error, ?ERR_FORBIDDEN} + end. +%% @doc

    Return the current affiliations for the given user

    +%%

    The default module reads affiliations in the main Mnesia +%% pubsub_state table. If a plugin stores its data in the same +%% table, it should return an empty list, as the affiliation will be read by +%% the default PubSub module. Otherwise, it should return its own affiliation, +%% that will be added to the affiliation stored in the main +%% pubsub_state table.

    get_entity_affiliations(Host, Owner) -> - node_hometree:get_entity_affiliations(Host, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), + NodeTree = mod_pubsub:tree(Host), + Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {Host, _}} = Node -> [{Node, A} | Acc]; + _ -> Acc + end + end, + [], States), + {result, Reply}. get_node_affiliations(Nidx) -> - node_hometree:get_node_affiliations(Nidx). + {result, States} = get_states(Nidx), + Tr = fun (#pubsub_state{stateid = {J, _}, affiliation = A}) -> {J, A} end, + {result, lists:map(Tr, States)}. get_affiliation(Nidx, Owner) -> - node_hometree:get_affiliation(Nidx, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + #pubsub_state{affiliation = Affiliation} = get_state(Nidx, GenKey), + {result, Affiliation}. set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree:set_affiliation(Nidx, Owner, Affiliation). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + case {Affiliation, GenState#pubsub_state.subscriptions} of + {none, []} -> del_state(Nidx, GenKey); + _ -> set_state(GenState#pubsub_state{affiliation = Affiliation}) + end. +%% @doc

    Return the current subscriptions for the given user

    +%%

    The default module reads subscriptions in the main Mnesia +%% pubsub_state table. If a plugin stores its data in the same +%% table, it should return an empty list, as the affiliation will be read by +%% the default PubSub module. Otherwise, it should return its own affiliation, +%% that will be added to the affiliation stored in the main +%% pubsub_state table.

    get_entity_subscriptions(Host, Owner) -> - node_hometree:get_entity_subscriptions(Host, Owner). + {U, D, _} = SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + States = case SubKey of + GenKey -> + mnesia:match_object(#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); + _ -> + mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) + ++ + mnesia:match_object(#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) + end, + NodeTree = mod_pubsub:tree(Host), + Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {Host, _}} = Node -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, J} | Acc2] + end, + Acc, Ss); + _ -> + Acc + end + end, + [], States), + {result, Reply}. get_node_subscriptions(Nidx) -> - node_hometree:get_node_subscriptions(Nidx). + {result, States} = get_states(Nidx), + Tr = fun (#pubsub_state{stateid = {J, _}, subscriptions = Subscriptions}) -> + case Subscriptions of + [_ | _] -> + lists:foldl(fun ({S, SubId}, Acc) -> + [{J, S, SubId} | Acc] + end, + [], Subscriptions); + [] -> + []; + _ -> + [{J, none}] + end + end, + {result, lists:flatmap(Tr, States)}. get_subscriptions(Nidx, Owner) -> - node_hometree:get_subscriptions(Nidx, Owner). + SubKey = jlib:jid_tolower(Owner), + SubState = get_state(Nidx, SubKey), + {result, SubState#pubsub_state.subscriptions}. set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + SubKey = jlib:jid_tolower(Owner), + SubState = get_state(Nidx, SubKey), + case {SubId, SubState#pubsub_state.subscriptions} of + {_, []} -> + case Subscription of + none -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; + _ -> + new_subscription(Nidx, Owner, Subscription, SubState) + end; + {<<>>, [{_, SID}]} -> + case Subscription of + none -> unsub_with_subid(Nidx, SID, SubState); + _ -> replace_subscription({Subscription, SID}, SubState) + end; + {<<>>, [_ | _]} -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; + _ -> + case Subscription of + none -> unsub_with_subid(Nidx, SubId, SubState); + _ -> replace_subscription({Subscription, SubId}, SubState) + end + end. +replace_subscription(NewSub, SubState) -> + NewSubs = replace_subscription(NewSub, SubState#pubsub_state.subscriptions, []), + set_state(SubState#pubsub_state{subscriptions = NewSubs}). + +replace_subscription(_, [], Acc) -> Acc; +replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> + replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). + +new_subscription(Nidx, Owner, Sub, SubState) -> + SubId = pubsub_subscription:add_subscription(Owner, Nidx, []), + Subs = SubState#pubsub_state.subscriptions, + set_state(SubState#pubsub_state{subscriptions = [{Sub, SubId} | Subs]}), + {Sub, SubId}. + +unsub_with_subid(Nidx, SubId, #pubsub_state{stateid = {Entity, _}} = SubState) -> + pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, Nidx, SubId), + NewSubs = [{S, Sid} + || {S, Sid} <- SubState#pubsub_state.subscriptions, + SubId =/= Sid], + case {NewSubs, SubState#pubsub_state.affiliation} of + {[], none} -> del_state(Nidx, Entity); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) + end. + +%% @doc

    Returns a list of Owner's nodes on Host with pending +%% subscriptions.

    get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). + GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, + affiliation = owner, + _ = '_'}), + NodeIdxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], + NodeTree = mod_pubsub:tree(Host), + Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, Nidx}} = S, Acc) -> + case lists:member(Nidx, NodeIdxs) of + true -> + case get_nodes_helper(NodeTree, S) of + {value, Node} -> [Node | Acc]; + false -> Acc + end; + false -> + Acc + end + end, + [], pubsub_state), + {result, Reply}. + +get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> + HasPending = fun + ({pending, _}) -> true; + (pending) -> true; + (_) -> false + end, + case lists:any(HasPending, Subs) of + true -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {_, Node}} -> {value, Node}; + _ -> false + end; + false -> + false + end. +%% @doc Returns the list of stored states for a given node. +%%

    For the default PubSub module, states are stored in Mnesia database.

    +%%

    We can consider that the pubsub_state table have been created by the main +%% mod_pubsub module.

    +%%

    PubSub plugins can store the states where they wants (for example in a +%% relational database).

    +%%

    If a PubSub plugin wants to delegate the states storage to the default node, +%% they can implement this function like this: +%% ```get_states(Nidx) -> +%% node_default:get_states(Nidx).'''

    get_states(Nidx) -> - node_hometree:get_states(Nidx). + States = case catch mnesia:match_object( + #pubsub_state{stateid = {'_', Nidx}, _ = '_'}) of + List when is_list(List) -> List; + _ -> [] + end, + {result, States}. + +%% @doc

    Returns a state (one state list), given its reference.

    +get_state(Nidx, Key) -> + StateId = {Key, Nidx}, + case catch mnesia:read({pubsub_state, StateId}) of + [State] when is_record(State, pubsub_state) -> State; + _ -> #pubsub_state{stateid = StateId} + end. -get_state(Nidx, JID) -> - node_hometree:get_state(Nidx, JID). +%% @doc

    Write a state into database.

    +set_state(State) when is_record(State, pubsub_state) -> + mnesia:write(State). +%set_state(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. + +%% @doc

    Delete a state from database.

    +del_state(Nidx, Key) -> + mnesia:delete({pubsub_state, {Key, Nidx}}). + +%% @doc Returns the list of stored items for a given node. +%%

    For the default PubSub module, items are stored in Mnesia database.

    +%%

    We can consider that the pubsub_item table have been created by the main +%% mod_pubsub module.

    +%%

    PubSub plugins can store the items where they wants (for example in a +%% relational database), or they can even decide not to persist any items.

    +%%

    If a PubSub plugin wants to delegate the item storage to the default node, +%% they can implement this function like this: +%% ```get_items(Nidx, From) -> +%% node_default:get_items(Nidx, From).'''

    +get_items(Nidx, From) -> + get_items(Nidx, From, none). +get_items(Nidx, _From, _RSM) -> + Items = mnesia:match_object(#pubsub_item{itemid = {'_', Nidx}, _ = '_'}), + {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), none}}. + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RSM) -> + SubKey = jlib:jid_tolower(JID), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + SubState = get_state(Nidx, SubKey), + Affiliation = GenState#pubsub_state.affiliation, + BareSubscriptions = GenState#pubsub_state.subscriptions, + FullSubscriptions = SubState#pubsub_state.subscriptions, + Whitelisted = can_fetch_item(Affiliation, BareSubscriptions) orelse + can_fetch_item(Affiliation, FullSubscriptions), + if %%SubId == "", ?? -> + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + (Affiliation == outcast) or (Affiliation == publish_only) -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_items(Nidx, JID) + end. -set_state(State) -> - node_hometree:set_state(State). +%% @doc

    Returns an item (one item list), given its reference.

    -get_items(Nidx, From, RSM) -> - node_hometree:get_items(Nidx, From, RSM). +get_item(Nidx, ItemId) -> + case mnesia:read({pubsub_item, {ItemId, Nidx}}) of + [Item] when is_record(Item, pubsub_item) -> {result, Item}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} + end. -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree:get_items(Nidx, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, RSM). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> + SubKey = jlib:jid_tolower(JID), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + Affiliation = GenState#pubsub_state.affiliation, + Subscriptions = GenState#pubsub_state.subscriptions, + Whitelisted = can_fetch_item(Affiliation, Subscriptions), + if %%SubId == "", ?? -> + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + (Affiliation == outcast) or (Affiliation == publish_only) -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_item(Nidx, ItemId) + end. -get_item(Nidx, ItemId) -> - node_hometree:get_item(Nidx, ItemId). +%% @doc

    Write an item into database.

    +set_item(Item) when is_record(Item, pubsub_item) -> + mnesia:write(Item). +%set_item(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. -get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(Nidx, ItemId, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId). +%% @doc

    Delete an item from database.

    +del_item(Nidx, ItemId) -> + mnesia:delete({pubsub_item, {ItemId, Nidx}}). -set_item(Item) -> - node_hometree:set_item(Item). +del_items(Nidx, ItemIds) -> + lists:foreach(fun (ItemId) -> del_item(Nidx, ItemId) + end, + ItemIds). -get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). +get_item_name(_Host, _Node, Id) -> + Id. +%% @doc

    Return the path of the node. In flat it's just node id.

    node_to_path(Node) -> [(Node)]. @@ -178,3 +818,26 @@ path_to_node(Path) -> % default case (used by PEP for example) _ -> iolist_to_binary(Path) end. + +can_fetch_item(owner, _) -> true; +can_fetch_item(member, _) -> true; +can_fetch_item(publisher, _) -> true; +can_fetch_item(publish_only, _) -> false; +can_fetch_item(outcast, _) -> false; +can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). +%can_fetch_item(_Affiliation, _Subscription) -> false. + +is_subscribed(Subscriptions) -> + lists:any(fun + ({subscribed, _SubId}) -> true; + (_) -> false + end, + Subscriptions). + +first_in_list(_Pred, []) -> + false; +first_in_list(Pred, [H | T]) -> + case Pred(H) of + true -> {value, H}; + _ -> first_in_list(Pred, T) + end. diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 9ac2643f8c1..c3f9c7e2694 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -24,6 +24,12 @@ %%% @end %%% ==================================================================== +%%% @doc The module {@module} is the default PubSub plugin. +%%%

    It is used as a default for all unknown PubSub node type. It can serve +%%% as a developer basis and reference to build its own custom pubsub node +%%% types.

    +%%%

    PubSub plugin nodes are using the {@link gen_node} behaviour.

    + -module(node_flat_odbc). -behaviour(gen_pubsub_node). -author('christophe.romain@process-one.net'). @@ -40,16 +46,23 @@ get_entity_subscriptions/2, get_node_subscriptions/1, get_subscriptions/2, set_subscriptions/4, get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/7, get_items/3, get_item/7, + set_state/1, get_items/6, get_items/2, + get_items/7, get_items/3, get_item/7, get_item/2, set_item/1, get_item_name/3, node_to_path/1, path_to_node/1, get_entity_subscriptions_for_send_last/2, get_last_items/3]). -init(Host, ServerHost, Opts) -> - node_hometree_odbc:init(Host, ServerHost, Opts). +-export([decode_jid/1, encode_jid/1, + decode_affiliation/1, decode_subscriptions/1, + encode_affiliation/1, encode_subscriptions/1, + encode_host/1]). + +init(_Host, _ServerHost, _Opts) -> + pubsub_subscription_odbc:init(), + ok. -terminate(Host, ServerHost) -> - node_hometree_odbc:terminate(Host, ServerHost). +terminate(_Host, _ServerHost) -> + ok. options() -> [{odbc, true}, {rsm, true} | node_flat:options()]. @@ -57,110 +70,976 @@ options() -> features() -> [<<"rsm">> | node_flat:features()]. -%% use same code as node_hometree_odbc, but do not limite node to -%% the home/localhost/user/... hierarchy -%% any node is allowed create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - node_hometree_odbc:create_node(Nidx, Owner). + {_U, _S, _R} = OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + State = #pubsub_state{stateid = {OwnerKey, Nidx}, affiliation = owner}, + catch ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values(">>, state_to_raw(Nidx, State), <<");">>]), + {result, {default, broadcast}}. -delete_node(Removed) -> - node_hometree_odbc:delete_node(Removed). +delete_node(Nodes) -> + Reply = lists:map(fun (#pubsub_node{id = Nidx} = PubsubNode) -> + Subscriptions = case catch + ejabberd_odbc:sql_query_t([<<"select jid, subscriptions " + "from pubsub_state where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> + [{decode_jid(SJID), decode_subscriptions(Subs)} || [SJID, Subs] <- RItems]; + _ -> + [] + end, + {PubsubNode, Subscriptions} + end, Nodes), + {result, {default, broadcast, Reply}}. subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, - PresenceSubscription, RosterGroup, Options). + SubKey = jlib:jid_tolower(Subscriber), + GenKey = jlib:jid_remove_resource(SubKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Whitelisted = lists:member(Affiliation, [member, publisher, owner]), + PendingSubscription = lists:any(fun + ({pending, _}) -> true; + (_) -> false + end, + Subscriptions), + Owner = Affiliation == owner, + if not Authorized -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; + (Affiliation == outcast) or (Affiliation == publish_only) -> + {error, ?ERR_FORBIDDEN}; + PendingSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; + (AccessModel == presence) and (not PresenceSubscription) and (not Owner) -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and (not RosterGroup) and (not Owner) -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and (not Whitelisted) and (not Owner) -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + %%ForbiddenAnonymous -> + %% % Requesting entity is anonymous + %% {error, ?ERR_FORBIDDEN}; + true -> + {result, SubId} = pubsub_subscription_odbc:subscribe_node(Subscriber, Nidx, Options), + NewSub = case AccessModel of + authorize -> pending; + _ -> subscribed + end, + update_subscription(Nidx, SubKey, [{NewSub, SubId} | Subscriptions]), + case {NewSub, SendLast} of + {subscribed, never} -> {result, {default, subscribed, SubId}}; + {subscribed, _} -> {result, {default, subscribed, SubId, send_last}}; + {_, _} -> {result, {default, pending, SubId}} + end + end. unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - node_hometree_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + SubKey = jlib:jid_tolower(Subscriber), + GenKey = jlib:jid_remove_resource(SubKey), + Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, SubKey), + SubIdExists = case SubId of + <<>> -> false; + Binary when is_binary(Binary) -> true; + _ -> false + end, + if + %% Requesting entity is prohibited from unsubscribing entity + not Authorized -> + {error, ?ERR_FORBIDDEN}; + %% Entity did not specify SubId + %%SubId == "", ?? -> + %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %% Invalid subscription identifier + %%InvalidSubId -> + %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + %% Requesting entity is not a subscriber + Subscriptions == [] -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; + %% Subid supplied, so use that. + SubIdExists -> + Sub = first_in_list(fun + ({_, S}) when S == SubId -> true; + (_) -> false + end, + Subscriptions), + case Sub of + {value, S} -> + delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions), + {result, default}; + false -> + {error, + ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} + end; + %% Asking to remove all subscriptions to the given node + SubId == all -> + [delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions) + || S <- Subscriptions], + {result, default}; + %% No subid supplied, but there's only one matching subscription + length(Subscriptions) == 1 -> + delete_subscription(SubKey, Nidx, hd(Subscriptions), Affiliation, Subscriptions), + {result, default}; + %% No subid and more than one possible subscription match. + true -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} + end. -publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). +delete_subscription(SubKey, Nidx, {Subscription, SubId}, Affiliation, Subscriptions) -> + NewSubs = Subscriptions -- [{Subscription, SubId}], + pubsub_subscription_odbc:unsubscribe_node(SubKey, Nidx, SubId), + case {Affiliation, NewSubs} of + {none, []} -> del_state(Nidx, SubKey); + _ -> update_subscription(Nidx, SubKey, NewSubs) + end. + +publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> + SubKey = jlib:jid_tolower(Publisher), + GenKey = jlib:jid_remove_resource(SubKey), + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Subscribed = case PublishModel of + subscribers -> node_flat:is_subscribed(Subscriptions); + _ -> undefined + end, + if not ((PublishModel == open) or + (PublishModel == publishers) and + ((Affiliation == owner) + or (Affiliation == publisher) + or (Affiliation == publish_only)) + or (Subscribed == true)) -> + {error, ?ERR_FORBIDDEN}; + true -> + if MaxItems > 0 -> + PubId = {now(), SubKey}, + set_item(#pubsub_item{itemid = {ItemId, Nidx}, + creation = {now(), GenKey}, + modification = PubId, + payload = Payload}), + Items = [ItemId | itemids(Nidx, GenKey) -- [ItemId]], + {result, {_, OI}} = remove_extra_items(Nidx, MaxItems, Items), + {result, {default, broadcast, OI}}; + true -> + {result, {default, broadcast, []}} + end + end. +remove_extra_items(_Nidx, unlimited, ItemIds) -> + {result, {ItemIds, []}}; remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). + NewItems = lists:sublist(ItemIds, MaxItems), + OldItems = lists:nthtail(length(NewItems), ItemIds), + del_items(Nidx, OldItems), + {result, {NewItems, OldItems}}. delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). + SubKey = jlib:jid_tolower(Publisher), + GenKey = jlib:jid_remove_resource(SubKey), + {result, Affiliation} = get_affiliation(Nidx, GenKey), + Allowed = Affiliation == publisher orelse + Affiliation == owner orelse + PublishModel == open orelse + case get_item(Nidx, ItemId) of + {result, #pubsub_item{creation = {_, GenKey}}} -> true; + _ -> false + end, + if not Allowed -> + {error, ?ERR_FORBIDDEN}; + true -> + case del_item(Nidx, ItemId) of + {updated, 1} -> {result, {default, broadcast}}; + _ -> {error, ?ERR_ITEM_NOT_FOUND} + end + end. purge_node(Nidx, Owner) -> - node_hometree_odbc:purge_node(Nidx, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + GenState = get_state(Nidx, GenKey), + case GenState of + #pubsub_state{affiliation = owner} -> + {result, States} = get_states(Nidx), + lists:foreach(fun + (#pubsub_state{items = []}) -> ok; + (#pubsub_state{items = Items}) -> del_items(Nidx, Items) + end, + States), + {result, {default, broadcast}}; + _ -> + {error, ?ERR_FORBIDDEN} + end. get_entity_affiliations(Host, Owner) -> - node_hometree_odbc:get_entity_affiliations(Host, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + H = encode_host(Host), + J = encode_jid(GenKey), + Reply = case catch + ejabberd_odbc:sql_query_t([<<"select node, type, i.nodeid, affiliation " + "from pubsub_state i, pubsub_node n where " + "i.nodeid = n.nodeid and jid='">>, J, <<"' and host='">>, H, <<"';">>]) + of + {selected, [<<"node">>, <<"type">>, <<"nodeid">>, <<"affiliation">>], RItems} -> + [{nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), decode_affiliation(A)} + || [N, T, I, A] <- RItems]; + _ -> + [] + end, + {result, Reply}. get_node_affiliations(Nidx) -> - node_hometree_odbc:get_node_affiliations(Nidx). + Reply = case catch + ejabberd_odbc:sql_query_t([<<"select jid, affiliation from pubsub_state " + "where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"jid">>, <<"affiliation">>], RItems} -> + [{decode_jid(J), decode_affiliation(A)} || [J, A] <- RItems]; + _ -> + [] + end, + {result, Reply}. get_affiliation(Nidx, Owner) -> - node_hometree_odbc:get_affiliation(Nidx, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + J = encode_jid(GenKey), + Reply = case catch + ejabberd_odbc:sql_query_t([<<"select affiliation from pubsub_state " + "where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {selected, [<<"affiliation">>], [[A]]} -> + decode_affiliation(A); + _ -> + none + end, + {result, Reply}. set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree_odbc:set_affiliation(Nidx, Owner, Affiliation). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + {_, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey), + case {Affiliation, Subscriptions} of + {none, []} -> del_state(Nidx, GenKey); + _ -> update_affiliation(Nidx, GenKey, Affiliation) + end. get_entity_subscriptions(Host, Owner) -> - node_hometree_odbc:get_entity_subscriptions(Host, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + H = encode_host(Host), + SJ = encode_jid(SubKey), + GJ = encode_jid(GenKey), + Query = case SubKey of + GenKey -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n " + "where i.nodeid = n.nodeid and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>]; + _ -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n " + "where i.nodeid = n.nodeid and jid in ('">>, SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] + end, + Reply = case catch ejabberd_odbc:sql_query_t(Query) of + {selected, + [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> + lists:foldl(fun ([N, T, I, J, S], Acc) -> + Node = nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Node, none, Jid} | Acc]; + Subs -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, Jid} | Acc2] + end, + Acc, Subs) + end + end, + [], RItems); + _ -> + [] + end, + {result, Reply}. +-spec(get_entity_subscriptions_for_send_last/2 :: + ( + Host :: mod_pubsub:hostPubsub(), + Owner :: jid()) + -> {result, + [{mod_pubsub:pubsubNode(), + mod_pubsub:subscription(), + mod_pubsub:subId(), + ljid()}] + } + ). get_entity_subscriptions_for_send_last(Host, Owner) -> - node_hometree_odbc:get_entity_subscriptions_for_send_last(Host, Owner). + SubKey = jlib:jid_tolower(Owner), + GenKey = jlib:jid_remove_resource(SubKey), + H = encode_host(Host), + SJ = encode_jid(SubKey), + GJ = encode_jid(GenKey), + Query = case SubKey of + GenKey -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n, pubsub_node_option o " + "where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' " + "and val='on_sub_and_presence' and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>]; + _ -> + [<<"select node, type, i.nodeid, jid, subscriptions " + "from pubsub_state i, pubsub_node n, pubsub_node_option o " + "where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' " + "and val='on_sub_and_presence' and jid in ('">>, SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] + end, + Reply = case catch ejabberd_odbc:sql_query_t(Query) of + {selected, + [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> + lists:foldl(fun ([N, T, I, J, S], Acc) -> + Node = nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Node, none, Jid} | Acc]; + Subs -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Node, Sub, SubId, Jid}| Acc2] + end, + Acc, Subs) + end + end, + [], RItems); + _ -> + [] + end, + {result, Reply}. get_node_subscriptions(Nidx) -> - node_hometree_odbc:get_node_subscriptions(Nidx). + Reply = case catch + ejabberd_odbc:sql_query_t([<<"select jid, subscriptions from pubsub_state " + "where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> + lists:foldl(fun ([J, S], Acc) -> + Jid = decode_jid(J), + case decode_subscriptions(S) of + [] -> + [{Jid, none} | Acc]; + Subs -> + lists:foldl(fun ({Sub, SubId}, Acc2) -> + [{Jid, Sub, SubId} | Acc2] + end, + Acc, Subs) + end + end, + [], RItems); + _ -> + [] + end, + {result, Reply}. get_subscriptions(Nidx, Owner) -> - node_hometree_odbc:get_subscriptions(Nidx, Owner). + SubKey = jlib:jid_tolower(Owner), + J = encode_jid(SubKey), + Reply = case catch + ejabberd_odbc:sql_query_t([<<"select subscriptions from pubsub_state where " + "nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {selected, [<<"subscriptions">>], [[S]]} -> + decode_subscriptions(S); + _ -> + [] + end, + {result, Reply}. set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). + SubKey = jlib:jid_tolower(Owner), + SubState = get_state_without_itemids(Nidx, SubKey), + case {SubId, SubState#pubsub_state.subscriptions} of + {_, []} -> + case Subscription of + none -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; + _ -> + new_subscription(Nidx, Owner, Subscription, SubState) + end; + {<<>>, [{_, SID}]} -> + case Subscription of + none -> unsub_with_subid(Nidx, SID, SubState); + _ -> replace_subscription({Subscription, SID}, SubState) + end; + {<<>>, [_ | _]} -> + {error, + ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; + _ -> + case Subscription of + none -> unsub_with_subid(Nidx, SubId, SubState); + _ -> replace_subscription({Subscription, SubId}, SubState) + end + end. + +replace_subscription(NewSub, SubState) -> + NewSubs = replace_subscription(NewSub, SubState#pubsub_state.subscriptions, []), + set_state(SubState#pubsub_state{subscriptions = NewSubs}). + +replace_subscription(_, [], Acc) -> Acc; +replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> + replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). + +new_subscription(Nidx, Owner, Subscription, SubState) -> + {result, SubId} = pubsub_subscription_odbc:subscribe_node(Owner, Nidx, []), + Subscriptions = [{Subscription, SubId} | SubState#pubsub_state.subscriptions], + set_state(SubState#pubsub_state{subscriptions = Subscriptions}), + {Subscription, SubId}. + +unsub_with_subid(Nidx, SubId, SubState) -> + pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, Nidx, SubId), + NewSubs = [{S, Sid} + || {S, Sid} <- SubState#pubsub_state.subscriptions, + SubId =/= Sid], + case {NewSubs, SubState#pubsub_state.affiliation} of + {[], none} -> del_state(Nidx, element(1, SubState#pubsub_state.stateid)); + _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) + end. get_pending_nodes(Host, Owner) -> - node_hometree_odbc:get_pending_nodes(Host, Owner). + GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), + States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, + affiliation = owner, _ = '_'}), + Nidxxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], + NodeTree = mod_pubsub:tree(Host), + Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, Nidx}} = S, Acc) -> + case lists:member(Nidx, Nidxxs) of + true -> + case get_nodes_helper(NodeTree, S) of + {value, Node} -> [Node | Acc]; + false -> Acc + end; + false -> + Acc + end + end, + [], pubsub_state), + {result, Reply}. + +get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> + HasPending = fun + ({pending, _}) -> true; + (pending) -> true; + (_) -> false + end, + case lists:any(HasPending, Subs) of + true -> + case NodeTree:get_node(N) of + #pubsub_node{nodeid = {_, Node}} -> {value, Node}; + _ -> false + end; + false -> + false + end. get_states(Nidx) -> - node_hometree_odbc:get_states(Nidx). + case catch + ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " + "from pubsub_state where nodeid='">>, Nidx, <<"';">>]) + of + {selected, + [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], RItems} -> + {result, + lists:map(fun ([SJID, Aff, Subs]) -> + #pubsub_state{stateid = {decode_jid(SJID), Nidx}, + items = itemids(Nidx, SJID), + affiliation = decode_affiliation(Aff), + subscriptions = decode_subscriptions(Subs)} + end, + RItems)}; + _ -> + {result, []} + end. get_state(Nidx, JID) -> - node_hometree_odbc:get_state(Nidx, JID). + State = get_state_without_itemids(Nidx, JID), + {SJID, _} = State#pubsub_state.stateid, + State#pubsub_state{items = itemids(Nidx, SJID)}. + +-spec(get_state_without_itemids/2 :: + (Nidx :: mod_pubsub:nodeIdx(), + Key :: ljid()) -> + mod_pubsub:pubsubState() + ). +get_state_without_itemids(Nidx, JID) -> + J = encode_jid(JID), + case catch + ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " + "from pubsub_state where jid='">>, J, <<"' and nodeid='">>, Nidx, <<"';">>]) + of + {selected, + [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], [[SJID, Aff, Subs]]} -> + #pubsub_state{stateid = {decode_jid(SJID), Nidx}, + affiliation = decode_affiliation(Aff), + subscriptions = decode_subscriptions(Subs)}; + _ -> + #pubsub_state{stateid = {JID, Nidx}} + end. set_state(State) -> - node_hometree_odbc:set_state(State). + {_, Nidx} = State#pubsub_state.stateid, + set_state(Nidx, State). + +set_state(Nidx, State) -> + {JID, _} = State#pubsub_state.stateid, + J = encode_jid(JID), + S = encode_subscriptions(State#pubsub_state.subscriptions), + A = encode_affiliation(State#pubsub_state.affiliation), + case catch + ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, S, <<"', affiliation='">>, A, + <<"' where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values('">>, + Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '">>, S, <<"');">>]) + end, + ok. + +del_state(Nidx, JID) -> + J = encode_jid(JID), + catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_state where jid='">>, + J, <<"' and nodeid='">>, Nidx, <<"';">>]), + ok. + +get_items(Nidx, _From) -> + case catch + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' order by modification desc;">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; + _ -> + {result, []} + end. + +get_items(Nidx, From, none) -> + MaxItems = case catch + ejabberd_odbc:sql_query_t([<<"select val from pubsub_node_option " + "where nodeid='">>, Nidx, <<"' and name='max_items';">>]) + of + {selected, [<<"val">>], [[Value]]} -> + Tokens = element(2, erl_scan:string(binary_to_list(<>))), + element(2, erl_parse:parse_term(Tokens)); + _ -> + ?MAXITEMS + end, + get_items(Nidx, From, #rsm_in{max = MaxItems}); +get_items(Nidx, _From, + #rsm_in{max = M, direction = Direction, id = I, index = IncIndex}) -> + Max = ejabberd_odbc:escape(jlib:i2l(M)), + {Way, Order} = case Direction of + % aft -> {<<"<">>, <<"desc">>}; + % before when I == <<>> -> {<<"is not">>, <<"asc">>}; + % before -> {<<">">>, <<"asc">>}; + % _ when IncIndex =/= undefined -> + % {<<"<">>, <<"desc">>}; % using index + _ -> + {<<"is not">>, <<"desc">>}% Can be better + end, + [AttrName, Id] = case I of + undefined when IncIndex =/= undefined -> + case catch + ejabberd_odbc:sql_query_t([<<"select modification from pubsub_item pi " + "where exists ( select count(*) as count1 " + "from pubsub_item where nodeid='">>, Nidx, + <<"' and modification > pi.modification having count1 = ">>, + ejabberd_odbc:escape(jlib:i2l(IncIndex)), <<" );">>]) + of + {selected, [_], [[O]]} -> + [<<"modification">>, <<"'", O/binary, "'">>]; + _ -> + [<<"modification">>, <<"null">>] + end; + undefined -> + [<<"modification">>, <<"null">>]; + <<>> -> + [<<"modification">>, <<"null">>]; + I -> + [A, B] = str:tokens(ejabberd_odbc:escape(jlib:i2l(I)), <<"@">>), + [A, <<"'", B/binary, "'">>] + end, + Count = case catch + ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item where nodeid='">>, Nidx, <<"';">>]) + of + {selected, [_], [[C]]} -> C; + _ -> <<"0">> + end, + case catch + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, + AttrName, <<" ">>, Order, <<" limit ">>, jlib:i2l(Max), <<" ;">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + case RItems of + [[_, _, _, F, _]|_] -> + Index = case catch + ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item " + "where nodeid='">>, Nidx, <<"' and ">>, + AttrName, <<" > '">>, F, <<"';">>]) + of + %{selected, [_], [{C}, {In}]} -> [string:strip(C, both, $"), string:strip(In, both, $")]; + {selected, [_], [[In]]} -> In; + _ -> <<"0">> + end, + [_, _, _, L, _] = lists:last(RItems), + RsmOut = #rsm_out{count = Count, index = Index, + first = <<"modification@", F/binary>>, + last = <<"modification@", (jlib:i2l(L))/binary>>}, + {result, {[raw_to_item(Nidx, RItem) || RItem <- RItems], RsmOut}}; + [] -> + {result, {[], #rsm_out{count = Count}}} + end; + _ -> + {result, {[], none}} + end. + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). -get_items(Nidx, From, RSM) -> - node_hometree_odbc:get_items(Nidx, From, RSM). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> + SubKey = jlib:jid_tolower(JID), + GenKey = jlib:jid_remove_resource(SubKey), + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Whitelisted = node_flat:can_fetch_item(Affiliation, Subscriptions), + if %%SubId == "", ?? -> + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + (Affiliation == outcast) or (Affiliation == publish_only) -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_items(Nidx, JID, RSM) + end. -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree_odbc:get_items(Nidx, JID, AccessModel, - PresenceSubscription, RosterGroup, SubId, RSM). +get_last_items(Nidx, _From, Count) -> + case catch + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " + "from pubsub_item where nodeid='">>, Nidx, + <<"' order by modification desc limit ">>, jlib:i2l(Count), <<";">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> + {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; + _ -> + {result, []} + end. get_item(Nidx, ItemId) -> - node_hometree_odbc:get_item(Nidx, ItemId). + I = ejabberd_odbc:escape(ItemId), + case catch + ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " + "modification, payload from pubsub_item " + "where nodeid='">>, Nidx, <<"' and itemid='">>, I, <<"';">>]) + of + {selected, + [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], [RItem]} -> + {result, raw_to_item(Nidx, RItem)}; + _ -> + {error, ?ERR_ITEM_NOT_FOUND} + end. -get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree_odbc:get_item(Nidx, ItemId, JID, - AccessModel, PresenceSubscription, RosterGroup, SubId). +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> + SubKey = jlib:jid_tolower(JID), + GenKey = jlib:jid_remove_resource(SubKey), + {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), + Whitelisted = node_flat:can_fetch_item(Affiliation, Subscriptions), + if %%SubId == "", ?? -> + %% Entity has multiple subscriptions to the node but does not specify a subscription ID + %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; + %%InvalidSubId -> + %% Entity is subscribed but specifies an invalid subscription ID + %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; + (Affiliation == outcast) or (Affiliation == publish_only) -> + {error, ?ERR_FORBIDDEN}; + (AccessModel == presence) and not PresenceSubscription -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; + (AccessModel == roster) and not RosterGroup -> + {error, + ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; + (AccessModel == whitelist) and not Whitelisted -> + {error, + ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; + (AccessModel == authorize) and not Whitelisted -> + {error, ?ERR_FORBIDDEN}; + %%MustPay -> + %% % Payment is required for a subscription + %% {error, ?ERR_PAYMENT_REQUIRED}; + true -> + get_item(Nidx, ItemId) + end. set_item(Item) -> - node_hometree_odbc:set_item(Item). + {ItemId, Nidx} = Item#pubsub_item.itemid, + I = ejabberd_odbc:escape(ItemId), + {C, _} = Item#pubsub_item.creation, + {M, JID} = Item#pubsub_item.modification, + P = encode_jid(JID), + Payload = Item#pubsub_item.payload, + XML = ejabberd_odbc:escape(str:join([xml:element_to_binary(X) || X<-Payload], <<>>)), + S = fun ({T1, T2, T3}) -> + str:join([jlib:i2l(T1, 6), jlib:i2l(T2, 6), jlib:i2l(T3, 6)], <<":">>) + end, + case catch + ejabberd_odbc:sql_query_t([<<"update pubsub_item set publisher='">>, P, + <<"', modification='">>, S(M), + <<"', payload='">>, XML, + <<"' where nodeid='">>, Nidx, <<"' and itemid='">>, I, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_item (nodeid, itemid, " + "publisher, creation, modification, payload) " + "values('">>, Nidx, <<"', '">>, I, <<"', '">>, P, + <<"', '">>, S(C), <<"', '">>, S(M), + <<"', '">>, XML, <<"');">>]) + end, + ok. -get_item_name(Host, Node, Id) -> - node_hometree_odbc:get_item_name(Host, Node, Id). +del_item(Nidx, ItemId) -> + I = ejabberd_odbc:escape(ItemId), + catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid='">>, + I, <<"' and nodeid='">>, Nidx, <<"';">>]). -get_last_items(Nidx, From, Count) -> - node_hometree_odbc:get_last_items(Nidx, From, Count). +del_items(_, []) -> + ok; +del_items(Nidx, [ItemId]) -> + del_item(Nidx, ItemId); +del_items(Nidx, ItemIds) -> + I = str:join([[<<"'">>, ejabberd_odbc:escape(X), <<"'">>] || X <- ItemIds], <<",">>), + catch + ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid in (">>, + I, <<") and nodeid='">>, Nidx, <<"';">>]). + +get_item_name(_Host, _Node, Id) -> + Id. node_to_path(Node) -> - [(Node)]. + node_flat:node_to_path(Node). path_to_node(Path) -> - case Path of - % default slot - [Node] -> iolist_to_binary(Node); - % handle old possible entries, used when migrating database content to new format - [Node | _] when is_binary(Node) -> - iolist_to_binary(str:join([<<"">> | Path], <<"/">>)); - % default case (used by PEP for example) - _ -> iolist_to_binary(Path) + node_flat:path_to_node(Path). + + +first_in_list(_Pred, []) -> + false; +first_in_list(Pred, [H | T]) -> + case Pred(H) of + true -> {value, H}; + _ -> first_in_list(Pred, T) + end. + +itemids(Nidx, {U, S, R}) -> + itemids(Nidx, encode_jid({U, S, R})); +itemids(Nidx, SJID) -> + case catch + ejabberd_odbc:sql_query_t([<<"select itemid from pubsub_item where " + "nodeid='">>, Nidx, <<"' and publisher like '">>, SJID, + <<"%' order by modification desc;">>]) + of + {selected, [<<"itemid">>], RItems} -> + [ItemId || [ItemId] <- RItems]; + _ -> + [] + end. + +select_affiliation_subscriptions(Nidx, JID) -> + J = encode_jid(JID), + case catch + ejabberd_odbc:sql_query_t([<<"select affiliation,subscriptions from " + "pubsub_state where nodeid='">>, + Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {selected, [<<"affiliation">>, <<"subscriptions">>], [[A, S]]} -> + {decode_affiliation(A), decode_subscriptions(S)}; + _ -> + {none, []} + end. + +select_affiliation_subscriptions(Nidx, JID, JID) -> + select_affiliation_subscriptions(Nidx, JID); +select_affiliation_subscriptions(Nidx, GenKey, SubKey) -> + {result, Affiliation} = get_affiliation(Nidx, GenKey), + {result, Subscriptions} = get_subscriptions(Nidx, SubKey), + {Affiliation, Subscriptions}. + +update_affiliation(Nidx, JID, Affiliation) -> + J = encode_jid(JID), + A = encode_affiliation(Affiliation), + case catch + ejabberd_odbc:sql_query_t([<<"update pubsub_state set affiliation='">>, + A, <<"' where nodeid='">>, Nidx, + <<"' and jid='">>, J, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values('">>, Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '');">>]) end. + +update_subscription(Nidx, JID, Subscription) -> + J = encode_jid(JID), + S = encode_subscriptions(Subscription), + case catch + ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, S, + <<"' where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) + of + {updated, 1} -> + ok; + _ -> + catch + ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " + "values('">>, Nidx, <<"', '">>, J, <<"', 'n', '">>, S, <<"');">>]) + end. + +-spec(decode_jid/1 :: + ( SJID :: binary()) + -> ljid() + ). +decode_jid(SJID) -> + jlib:jid_tolower(jlib:string_to_jid(SJID)). + +-spec(decode_affiliation/1 :: + ( Arg :: binary()) + -> atom() + ). +decode_affiliation(<<"o">>) -> owner; +decode_affiliation(<<"p">>) -> publisher; +decode_affiliation(<<"u">>) -> publish_only; +decode_affiliation(<<"m">>) -> member; +decode_affiliation(<<"c">>) -> outcast; +decode_affiliation(_) -> none. + +-spec(decode_subscription/1 :: + ( Arg :: binary()) + -> atom() + ). +decode_subscription(<<"s">>) -> subscribed; +decode_subscription(<<"p">>) -> pending; +decode_subscription(<<"u">>) -> unconfigured; +decode_subscription(_) -> none. + +-spec(decode_subscriptions/1 :: + ( Subscriptions :: binary()) + -> [] | [{atom(), binary()},...] + ). +decode_subscriptions(Subscriptions) -> + lists:foldl(fun (Subscription, Acc) -> + case str:tokens(Subscription, <<":">>) of + [S, SubId] -> [{decode_subscription(S), SubId} | Acc]; + _ -> Acc + end + end, + [], str:tokens(Subscriptions, <<",">>)). + +-spec(encode_jid/1 :: + ( JID :: ljid()) + -> binary() + ). +encode_jid(JID) -> + ejabberd_odbc:escape(jlib:jid_to_string(JID)). + +-spec(encode_host/1 :: + ( Host :: host()) + -> binary() + ). +encode_host({_U, _S, _R} = LJID) -> encode_jid(LJID); +encode_host(Host) -> ejabberd_odbc:escape(Host). + +-spec(encode_affiliation/1 :: + ( Arg :: atom()) + -> binary() + ). +encode_affiliation(owner) -> <<"o">>; +encode_affiliation(publisher) -> <<"p">>; +encode_affiliation(publish_only) -> <<"u">>; +encode_affiliation(member) -> <<"m">>; +encode_affiliation(outcast) -> <<"c">>; +encode_affiliation(_) -> <<"n">>. + +-spec(encode_subscription/1 :: + ( Arg :: atom()) + -> binary() + ). +encode_subscription(subscribed) -> <<"s">>; +encode_subscription(pending) -> <<"p">>; +encode_subscription(unconfigured) -> <<"u">>; +encode_subscription(_) -> <<"n">>. + +-spec(encode_subscriptions/1 :: + ( Subscriptions :: [] | [{atom(), binary()},...]) + -> binary() + ). +encode_subscriptions(Subscriptions) -> + str:join([<<(encode_subscription(S))/binary, ":", SubId/binary>> + || {S, SubId} <- Subscriptions], <<",">>). + +%%% record getter/setter + +state_to_raw(Nidx, State) -> + {JID, _} = State#pubsub_state.stateid, + J = encode_jid(JID), + A = encode_affiliation(State#pubsub_state.affiliation), + S = encode_subscriptions(State#pubsub_state.subscriptions), + [<<"'">>, Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '">>, S, <<"'">>]. + +raw_to_item(Nidx, [ItemId, SJID, Creation, Modification, XML]) -> + JID = decode_jid(SJID), + ToTime = fun (Str) -> + [T1, T2, T3] = str:tokens(Str, <<":">>), + {jlib:l2i(T1), jlib:l2i(T2), jlib:l2i(T3)} + end, + Payload = case xml_stream:parse_element(XML) of + {error, _Reason} -> []; + El -> [El] + end, + #pubsub_item{itemid = {ItemId, Nidx}, + creation = {ToTime(Creation), JID}, + modification = {ToTime(Modification), JID}, + payload = Payload}. diff --git a/src/node_hometree.erl b/src/node_hometree.erl index 01eeccdd9c3..e291887f14f 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -24,20 +24,6 @@ %%% @end %%% ==================================================================== -%%% @todo The item table should be handled by the plugin, but plugin that do -%%% not want to manage it should be able to use the default behaviour. -%%% @todo Plugin modules should be able to register to receive presence update -%%% send to pubsub. - -%%% @doc The module {@module} is the default PubSub plugin. -%%%

    It is used as a default for all unknown PubSub node type. It can serve -%%% as a developer basis and reference to build its own custom pubsub node -%%% types.

    -%%%

    PubSub plugin nodes are using the {@link gen_node} behaviour.

    -%%%

    The API isn't stabilized yet. The pubsub plugin -%%% development is still a work in progress. However, the system is already -%%% useable and useful as is. Please, send us comments, feedback and -%%% improvements.

    -module(node_hometree). -behaviour(gen_pubsub_node). @@ -55,81 +41,32 @@ get_entity_subscriptions/2, get_node_subscriptions/1, get_subscriptions/2, set_subscriptions/4, get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, - get_items/7, get_items/3, get_item/7, + set_state/1, get_items/7, get_items/3, get_item/7, get_item/2, set_item/1, get_item_name/3, node_to_path/1, path_to_node/1]). -init(Host, ServerHost, _Opts) -> - pubsub_subscription:init(), - mnesia:create_table(pubsub_state, - [{disc_copies, [node()]}, - {type, ordered_set}, - {attributes, record_info(fields, pubsub_state)}]), - mnesia:create_table(pubsub_item, - [{disc_only_copies, [node()]}, - {attributes, record_info(fields, pubsub_item)}]), - ItemsFields = record_info(fields, pubsub_item), - case mnesia:table_info(pubsub_item, attributes) of - ItemsFields -> ok; - _ -> mnesia:transform_table(pubsub_item, ignore, ItemsFields) - end, +init(Host, ServerHost, Opts) -> + node_flat:init(Host, ServerHost, Opts), Owner = mod_pubsub:service_jid(Host), mod_pubsub:create_node(Host, ServerHost, <<"/home">>, Owner, <<"hometree">>), mod_pubsub:create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, Owner, <<"hometree">>), ok. -terminate(_Host, _ServerHost) -> - ok. +terminate(Host, ServerHost) -> + node_flat:terminate(Host, ServerHost). options() -> - [{deliver_payloads, true}, - {notify_config, false}, - {notify_delete, false}, - {notify_retract, true}, - {purge_offline, false}, - {persist_items, true}, - {max_items, ?MAXITEMS}, - {subscribe, true}, - {access_model, open}, - {roster_groups_allowed, []}, - {publish_model, publishers}, - {notification_type, headline}, - {max_payload_size, ?MAX_PAYLOAD_SIZE}, - {send_last_published_item, on_sub_and_presence}, - {deliver_notifications, true}, - {presence_based_delivery, false}]. + node_flat:options(). features() -> - [<<"create-nodes">>, - <<"auto-create">>, - <<"access-authorize">>, - <<"delete-nodes">>, - <<"delete-items">>, - <<"get-pending">>, - <<"instant-nodes">>, - <<"manage-subscriptions">>, - <<"modify-affiliations">>, - <<"multi-subscribe">>, - <<"outcast-affiliation">>, - <<"persistent-items">>, - <<"publish">>, - <<"publish-only-affiliation">>, - <<"purge-nodes">>, - <<"retract-items">>, - <<"retrieve-affiliations">>, - <<"retrieve-items">>, - <<"retrieve-subscriptions">>, - <<"subscribe">>, - <<"subscription-notifications">>, - <<"subscription-options">>]. + node_flat:features(). %% @doc Checks if the current user has the permission to create the requested node -%%

    In {@link node_default}, the permission is decided by the place in the +%%

    In hometree node, the permission is decided by the place in the %% hierarchy where the user is creating the node. The access parameter is also -%% checked in the default module. This parameter depends on the value of the +%% checked. This parameter depends on the value of the %% access_createnode ACL value in ejabberd config file.

    -%%

    This function also check that node can be created a a children of its +%%

    This function also check that node can be created as a children of its %% parent node

    create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> LOwner = jlib:jid_tolower(Owner), @@ -150,710 +87,92 @@ create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> {result, Allowed}. create_node(Nidx, Owner) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - set_state(#pubsub_state{stateid = {OwnerKey, Nidx}, - affiliation = owner}), - {result, {default, broadcast}}. + node_flat:create_node(Nidx, Owner). delete_node(Nodes) -> - Tr = fun (#pubsub_state{stateid = {J, _}, subscriptions = Ss}) -> - lists:map(fun (S) -> {J, S} end, Ss) - end, - Reply = lists:map(fun (#pubsub_node{id = Nidx} = PubsubNode) -> - {result, States} = get_states(Nidx), - lists:foreach(fun (#pubsub_state{stateid = {LJID, _}, items = Items}) -> - del_items(Nidx, Items), - del_state(Nidx, LJID) - end, States), - {PubsubNode, lists:flatmap(Tr, States)} - end, Nodes), - {result, {default, broadcast, Reply}}. - -%% @doc

    Accepts or rejects subcription requests on a PubSub node.

    -%%

    The mechanism works as follow: -%%

      -%%
    • The main PubSub module prepares the subscription and passes the -%% result of the preparation as a record.
    • -%%
    • This function gets the prepared record and several other parameters and -%% can decide to:
        -%%
      • reject the subscription;
      • -%%
      • allow it as is, letting the main module perform the database -%% persistance;
      • -%%
      • allow it, modifying the record. The main module will store the -%% modified record;
      • -%%
      • allow it, but perform the needed persistance operations.
      -%%

    -%%

    The selected behaviour depends on the return parameter: -%%

      -%%
    • {error, Reason}: an IQ error result will be returned. No -%% subscription will actually be performed.
    • -%%
    • true: Subscribe operation is allowed, based on the -%% unmodified record passed in parameter SubscribeResult. If this -%% parameter contains an error, no subscription will be performed.
    • -%%
    • {true, PubsubState}: Subscribe operation is allowed, but -%% the {@link mod_pubsub:pubsubState()} record returned replaces the value -%% passed in parameter SubscribeResult.
    • -%%
    • {true, done}: Subscribe operation is allowed, but the -%% {@link mod_pubsub:pubsubState()} will be considered as already stored and -%% no further persistance operation will be performed. This case is used, -%% when the plugin module is doing the persistance by itself or when it want -%% to completly disable persistance.
    -%%

    -%%

    In the default plugin module, the record is unchanged.

    + node_flat:delete_node(Nodes). + subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, - GenState = get_state(Nidx, GenKey), - SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(Nidx, SubKey) - end, - Affiliation = GenState#pubsub_state.affiliation, - Subscriptions = SubState#pubsub_state.subscriptions, - Whitelisted = lists:member(Affiliation, [member, publisher, owner]), - PendingSubscription = lists:any(fun - ({pending, _}) -> true; - (_) -> false - end, - Subscriptions), - Owner = Affiliation == owner, - if not Authorized -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; - (Affiliation == outcast) or (Affiliation == publish_only) -> - {error, ?ERR_FORBIDDEN}; - PendingSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; - (AccessModel == presence) and (not PresenceSubscription) and (not Owner) -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and (not RosterGroup) and (not Owner) -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and (not Whitelisted) and (not Owner) -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - %%ForbiddenAnonymous -> - %% % Requesting entity is anonymous - %% {error, ?ERR_FORBIDDEN}; - true -> - SubId = pubsub_subscription:add_subscription(Subscriber, Nidx, Options), - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed - end, - set_state(SubState#pubsub_state{subscriptions = - [{NewSub, SubId} | Subscriptions]}), - case {NewSub, SendLast} of - {subscribed, never} -> - {result, {default, subscribed, SubId}}; - {subscribed, _} -> - {result, {default, subscribed, SubId, send_last}}; - {_, _} -> - {result, {default, pending, SubId}} - end - end. + node_flat:subscribe_node(Nidx, Sender, Subscriber, + AccessModel, SendLast, PresenceSubscription, + RosterGroup, Options). -%% @doc

    Unsubscribe the Subscriber from the Node.

    unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, - GenState = get_state(Nidx, GenKey), - SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(Nidx, SubKey) - end, - Subscriptions = lists:filter(fun - ({_Sub, _SubId}) -> true; - (_SubId) -> false - end, - SubState#pubsub_state.subscriptions), - SubIdExists = case SubId of - <<>> -> false; - Binary when is_binary(Binary) -> true; - _ -> false - end, - if - %% Requesting entity is prohibited from unsubscribing entity - not Authorized -> - {error, ?ERR_FORBIDDEN}; - %% Entity did not specify SubId - %%SubId == "", ?? -> - %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %% Invalid subscription identifier - %%InvalidSubId -> - %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - %% Requesting entity is not a subscriber - Subscriptions == [] -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; - %% Subid supplied, so use that. - SubIdExists -> - Sub = first_in_list(fun - ({_, S}) when S == SubId -> true; - (_) -> false - end, - SubState#pubsub_state.subscriptions), - case Sub of - {value, S} -> - delete_subscriptions(SubKey, Nidx, [S], SubState), - {result, default}; - false -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} - end; - %% Asking to remove all subscriptions to the given node - SubId == all -> - delete_subscriptions(SubKey, Nidx, Subscriptions, SubState), - {result, default}; - %% No subid supplied, but there's only one matching subscription - length(Subscriptions) == 1 -> - delete_subscriptions(SubKey, Nidx, Subscriptions, SubState), - {result, default}; - %% No subid and more than one possible subscription match. - true -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} - end. - -delete_subscriptions(SubKey, Nidx, Subscriptions, SubState) -> - NewSubs = lists:foldl(fun ({Subscription, SubId}, Acc) -> - pubsub_subscription:delete_subscription(SubKey, Nidx, SubId), - Acc -- [{Subscription, SubId}] - end, SubState#pubsub_state.subscriptions, Subscriptions), - case {SubState#pubsub_state.affiliation, NewSubs} of - {none, []} -> del_state(Nidx, SubKey); - _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) - end. - -%% @doc

    Publishes the item passed as parameter.

    -%%

    The mechanism works as follow: -%%

      -%%
    • The main PubSub module prepares the item to publish and passes the -%% result of the preparation as a {@link mod_pubsub:pubsubItem()} record.
    • -%%
    • This function gets the prepared record and several other parameters and can decide to:
        -%%
      • reject the publication;
      • -%%
      • allow the publication as is, letting the main module perform the database persistance;
      • -%%
      • allow the publication, modifying the record. The main module will store the modified record;
      • -%%
      • allow it, but perform the needed persistance operations.
      -%%

    -%%

    The selected behaviour depends on the return parameter: -%%

      -%%
    • {error, Reason}: an iq error result will be return. No -%% publication is actually performed.
    • -%%
    • true: Publication operation is allowed, based on the -%% unmodified record passed in parameter Item. If the Item -%% parameter contains an error, no subscription will actually be -%% performed.
    • -%%
    • {true, Item}: Publication operation is allowed, but the -%% {@link mod_pubsub:pubsubItem()} record returned replaces the value passed -%% in parameter Item. The persistance will be performed by the main -%% module.
    • -%%
    • {true, done}: Publication operation is allowed, but the -%% {@link mod_pubsub:pubsubItem()} will be considered as already stored and -%% no further persistance operation will be performed. This case is used, -%% when the plugin module is doing the persistance by itself or when it want -%% to completly disable persistance.
    -%%

    -%%

    In the default plugin module, the record is unchanged.

    -publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - SubState = case SubKey of - GenKey -> GenState; - _ -> get_state(Nidx, SubKey) - end, - Affiliation = GenState#pubsub_state.affiliation, - Subscribed = case PublishModel of - subscribers -> is_subscribed(GenState#pubsub_state.subscriptions) orelse - is_subscribed(SubState#pubsub_state.subscriptions); - _ -> undefined - end, - if not ((PublishModel == open) or - (PublishModel == publishers) and - ((Affiliation == owner) - or (Affiliation == publisher) - or (Affiliation == publish_only)) - or (Subscribed == true)) -> - {error, ?ERR_FORBIDDEN}; - true -> - if MaxItems > 0 -> - Now = now(), - PubId = {Now, SubKey}, - Item = case get_item(Nidx, ItemId) of - {result, OldItem} -> - OldItem#pubsub_item{modification = PubId, - payload = Payload}; - _ -> - #pubsub_item{itemid = {ItemId, Nidx}, - creation = {Now, GenKey}, - modification = PubId, - payload = Payload} - end, - Items = [ItemId | GenState#pubsub_state.items -- [ItemId]], - {result, {NI, OI}} = remove_extra_items(Nidx, MaxItems, Items), - set_item(Item), - set_state(GenState#pubsub_state{items = NI}), - {result, {default, broadcast, OI}}; - true -> - {result, {default, broadcast, []}} - end - end. - -%% @doc

    This function is used to remove extra items, most notably when the -%% maximum number of items has been reached.

    -%%

    This function is used internally by the core PubSub module, as no -%% permission check is performed.

    -%%

    In the default plugin module, the oldest items are removed, but other -%% rules can be used.

    -%%

    If another PubSub plugin wants to delegate the item removal (and if the -%% plugin is using the default pubsub storage), it can implements this function like this: -%% ```remove_extra_items(Nidx, MaxItems, ItemIds) -> -%% node_default:remove_extra_items(Nidx, MaxItems, ItemIds).'''

    -remove_extra_items(_Nidx, unlimited, ItemIds) -> - {result, {ItemIds, []}}; + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + remove_extra_items(Nidx, MaxItems, ItemIds) -> - NewItems = lists:sublist(ItemIds, MaxItems), - OldItems = lists:nthtail(length(NewItems), ItemIds), - del_items(Nidx, OldItems), - {result, {NewItems, OldItems}}. - -%% @doc

    Triggers item deletion.

    -%%

    Default plugin: The user performing the deletion must be the node owner -%% or a publisher, or PublishModel being open.

    + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). + delete_item(Nidx, Publisher, PublishModel, ItemId) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - #pubsub_state{affiliation = Affiliation, items = Items} = GenState, - Allowed = Affiliation == publisher orelse - Affiliation == owner orelse - PublishModel == open orelse - case get_item(Nidx, ItemId) of - {result, #pubsub_item{creation = {_, GenKey}}} -> true; - _ -> false - end, - if not Allowed -> - {error, ?ERR_FORBIDDEN}; - true -> - case lists:member(ItemId, Items) of - true -> - del_item(Nidx, ItemId), - set_state(GenState#pubsub_state{items = lists:delete(ItemId, Items)}), - {result, {default, broadcast}}; - false -> - case Affiliation of - owner -> - {result, States} = get_states(Nidx), - lists:foldl(fun - (#pubsub_state{items = PI} = S, Res) -> - case lists:member(ItemId, PI) of - true -> - Nitems = lists:delete(ItemId, PI), - del_item(Nidx, ItemId), - set_state(S#pubsub_state{items = Nitems}), - {result, {default, broadcast}}; - false -> - Res - end; - (_, Res) -> - Res - end, - {error, ?ERR_ITEM_NOT_FOUND}, States); - _ -> - {error, ?ERR_ITEM_NOT_FOUND} - end - end - end. + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - case GenState of - #pubsub_state{affiliation = owner} -> - {result, States} = get_states(Nidx), - lists:foreach(fun - (#pubsub_state{items = []}) -> - ok; - (#pubsub_state{items = Items} = S) -> - del_items(Nidx, Items), - set_state(S#pubsub_state{items = []}) - end, - States), - {result, {default, broadcast}}; - _ -> - {error, ?ERR_FORBIDDEN} - end. - -%% @doc

    Return the current affiliations for the given user

    -%%

    The default module reads affiliations in the main Mnesia -%% pubsub_state table. If a plugin stores its data in the same -%% table, it should return an empty list, as the affiliation will be read by -%% the default PubSub module. Otherwise, it should return its own affiliation, -%% that will be added to the affiliation stored in the main -%% pubsub_state table.

    + node_flat:purge_node(Nidx, Owner). + get_entity_affiliations(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), - NodeTree = mod_pubsub:tree(Host), - Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {Host, _}} = Node -> [{Node, A} | Acc]; - _ -> Acc - end - end, - [], States), - {result, Reply}. + node_flat:get_entity_affiliations(Host, Owner). get_node_affiliations(Nidx) -> - {result, States} = get_states(Nidx), - Tr = fun (#pubsub_state{stateid = {J, _}, affiliation = A}) -> {J, A} end, - {result, lists:map(Tr, States)}. + node_flat:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - #pubsub_state{affiliation = Affiliation} = get_state(Nidx, GenKey), - {result, Affiliation}. + node_flat:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - case {Affiliation, GenState#pubsub_state.subscriptions} of - {none, []} -> del_state(Nidx, GenKey); - _ -> set_state(GenState#pubsub_state{affiliation = Affiliation}) - end. - -%% @doc

    Return the current subscriptions for the given user

    -%%

    The default module reads subscriptions in the main Mnesia -%% pubsub_state table. If a plugin stores its data in the same -%% table, it should return an empty list, as the affiliation will be read by -%% the default PubSub module. Otherwise, it should return its own affiliation, -%% that will be added to the affiliation stored in the main -%% pubsub_state table.

    + node_flat:set_affiliation(Nidx, Owner, Affiliation). + get_entity_subscriptions(Host, Owner) -> - {U, D, _} = SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - States = case SubKey of - GenKey -> - mnesia:match_object(#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); - _ -> - mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}) - ++ - mnesia:match_object(#pubsub_state{stateid = {SubKey, '_'}, _ = '_'}) - end, - NodeTree = mod_pubsub:tree(Host), - Reply = lists:foldl(fun (#pubsub_state{stateid = {J, N}, subscriptions = Ss}, Acc) -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {Host, _}} = Node -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, J} | Acc2] - end, - Acc, Ss); - _ -> - Acc - end - end, - [], States), - {result, Reply}. + node_flat:get_entity_subscriptions(Host, Owner). get_node_subscriptions(Nidx) -> - {result, States} = get_states(Nidx), - Tr = fun (#pubsub_state{stateid = {J, _}, subscriptions = Subscriptions}) -> - case Subscriptions of - [_ | _] -> - lists:foldl(fun ({S, SubId}, Acc) -> - [{J, S, SubId} | Acc] - end, - [], Subscriptions); - [] -> - []; - _ -> - [{J, none}] - end - end, - {result, lists:flatmap(Tr, States)}. + node_flat:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - SubState = get_state(Nidx, SubKey), - {result, SubState#pubsub_state.subscriptions}. + node_flat:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - SubKey = jlib:jid_tolower(Owner), - SubState = get_state(Nidx, SubKey), - case {SubId, SubState#pubsub_state.subscriptions} of - {_, []} -> - case Subscription of - none -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; - _ -> - new_subscription(Nidx, Owner, Subscription, SubState) - end; - {<<>>, [{_, SID}]} -> - case Subscription of - none -> unsub_with_subid(Nidx, SID, SubState); - _ -> replace_subscription({Subscription, SID}, SubState) - end; - {<<>>, [_ | _]} -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; - _ -> - case Subscription of - none -> unsub_with_subid(Nidx, SubId, SubState); - _ -> replace_subscription({Subscription, SubId}, SubState) - end - end. - -replace_subscription(NewSub, SubState) -> - NewSubs = replace_subscription(NewSub, SubState#pubsub_state.subscriptions, []), - set_state(SubState#pubsub_state{subscriptions = NewSubs}). - -replace_subscription(_, [], Acc) -> Acc; -replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> - replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). - -new_subscription(Nidx, Owner, Sub, SubState) -> - SubId = pubsub_subscription:add_subscription(Owner, Nidx, []), - Subs = SubState#pubsub_state.subscriptions, - set_state(SubState#pubsub_state{subscriptions = [{Sub, SubId} | Subs]}), - {Sub, SubId}. - -unsub_with_subid(Nidx, SubId, #pubsub_state{stateid = {Entity, _}} = SubState) -> - pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, Nidx, SubId), - NewSubs = [{S, Sid} - || {S, Sid} <- SubState#pubsub_state.subscriptions, - SubId =/= Sid], - case {NewSubs, SubState#pubsub_state.affiliation} of - {[], none} -> del_state(Nidx, Entity); - _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) - end. - -%% @doc

    Returns a list of Owner's nodes on Host with pending -%% subscriptions.

    + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). + get_pending_nodes(Host, Owner) -> - GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, - affiliation = owner, - _ = '_'}), - NodeIdxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], - NodeTree = mod_pubsub:tree(Host), - Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, Nidx}} = S, Acc) -> - case lists:member(Nidx, NodeIdxs) of - true -> - case get_nodes_helper(NodeTree, S) of - {value, Node} -> [Node | Acc]; - false -> Acc - end; - false -> - Acc - end - end, - [], pubsub_state), - {result, Reply}. - -get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> - HasPending = fun - ({pending, _}) -> true; - (pending) -> true; - (_) -> false - end, - case lists:any(HasPending, Subs) of - true -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {_, Node}} -> {value, Node}; - _ -> false - end; - false -> - false - end. - -%% @doc Returns the list of stored states for a given node. -%%

    For the default PubSub module, states are stored in Mnesia database.

    -%%

    We can consider that the pubsub_state table have been created by the main -%% mod_pubsub module.

    -%%

    PubSub plugins can store the states where they wants (for example in a -%% relational database).

    -%%

    If a PubSub plugin wants to delegate the states storage to the default node, -%% they can implement this function like this: -%% ```get_states(Nidx) -> -%% node_default:get_states(Nidx).'''

    + node_flat:get_pending_nodes(Host, Owner). + get_states(Nidx) -> - States = case catch mnesia:match_object( - #pubsub_state{stateid = {'_', Nidx}, _ = '_'}) of - List when is_list(List) -> List; - _ -> [] - end, - {result, States}. - -%% @doc

    Returns a state (one state list), given its reference.

    -get_state(Nidx, Key) -> - StateId = {Key, Nidx}, - case catch mnesia:read({pubsub_state, StateId}) of - [State] when is_record(State, pubsub_state) -> State; - _ -> #pubsub_state{stateid = StateId} - end. - -%% @doc

    Write a state into database.

    -set_state(State) when is_record(State, pubsub_state) -> - mnesia:write(State). -%set_state(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. - -%% @doc

    Delete a state from database.

    -del_state(Nidx, Key) -> - mnesia:delete({pubsub_state, {Key, Nidx}}). - -%% @doc Returns the list of stored items for a given node. -%%

    For the default PubSub module, items are stored in Mnesia database.

    -%%

    We can consider that the pubsub_item table have been created by the main -%% mod_pubsub module.

    -%%

    PubSub plugins can store the items where they wants (for example in a -%% relational database), or they can even decide not to persist any items.

    -%%

    If a PubSub plugin wants to delegate the item storage to the default node, -%% they can implement this function like this: -%% ```get_items(Nidx, From) -> -%% node_default:get_items(Nidx, From).'''

    -get_items(Nidx, From) -> - get_items(Nidx, From, none). -get_items(Nidx, _From, _RSM) -> - Items = mnesia:match_object(#pubsub_item{itemid = {'_', Nidx}, _ = '_'}), - {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), none}}. - -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RSM) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - SubState = get_state(Nidx, SubKey), - Affiliation = GenState#pubsub_state.affiliation, - BareSubscriptions = GenState#pubsub_state.subscriptions, - FullSubscriptions = SubState#pubsub_state.subscriptions, - Whitelisted = can_fetch_item(Affiliation, BareSubscriptions) orelse - can_fetch_item(Affiliation, FullSubscriptions), - if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - (Affiliation == outcast) or (Affiliation == publish_only) -> - {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> - get_items(Nidx, JID) - end. - -%% @doc

    Returns an item (one item list), given its reference.

    + node_flat:get_states(Nidx). + +get_state(Nidx, JID) -> + node_flat:get_state(Nidx, JID). + +set_state(State) -> + node_flat:set_state(State). + +get_items(Nidx, From, RSM) -> + node_flat:get_items(Nidx, From, RSM). + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_flat:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> - case mnesia:read({pubsub_item, {ItemId, Nidx}}) of - [Item] when is_record(Item, pubsub_item) -> {result, Item}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} - end. - -get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - Affiliation = GenState#pubsub_state.affiliation, - Subscriptions = GenState#pubsub_state.subscriptions, - Whitelisted = can_fetch_item(Affiliation, Subscriptions), - if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - (Affiliation == outcast) or (Affiliation == publish_only) -> - {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> - get_item(Nidx, ItemId) - end. - -%% @doc

    Write an item into database.

    -set_item(Item) when is_record(Item, pubsub_item) -> - mnesia:write(Item). -%set_item(_) -> {error, ?ERR_INTERNAL_SERVER_ERROR}. - -%% @doc

    Delete an item from database.

    -del_item(Nidx, ItemId) -> - mnesia:delete({pubsub_item, {ItemId, Nidx}}). - -del_items(Nidx, ItemIds) -> - lists:foreach(fun (ItemId) -> del_item(Nidx, ItemId) - end, - ItemIds). - -get_item_name(_Host, _Node, Id) -> - Id. - -%% @doc

    Return the name of the node if known: Default is to return -%% node id.

    + node_flat:get_item(Nidx, ItemId). + +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). + +set_item(Item) -> + node_flat:set_item(Item). + +get_item_name(Host, Node, Id) -> + node_flat:get_item_name(Host, Node, Id). + +%% @doc

    Return the path of the node.

    node_to_path(Node) -> str:tokens(Node, <<"/">>). path_to_node([]) -> <<>>; path_to_node(Path) -> iolist_to_binary(str:join([<<"">> | Path], <<"/">>)). -can_fetch_item(owner, _) -> true; -can_fetch_item(member, _) -> true; -can_fetch_item(publisher, _) -> true; -can_fetch_item(publish_only, _) -> false; -can_fetch_item(outcast, _) -> false; -can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). -%can_fetch_item(_Affiliation, _Subscription) -> false. - -is_subscribed(Subscriptions) -> - lists:any(fun - ({subscribed, _SubId}) -> true; - (_) -> false - end, - Subscriptions). - -first_in_list(_Pred, []) -> - false; -first_in_list(Pred, [H | T]) -> - case Pred(H) of - true -> {value, H}; - _ -> first_in_list(Pred, T) - end. diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index e99ce7247f8..d5d29cf75cd 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -24,20 +24,6 @@ %%% @end %%% ==================================================================== -%%% @todo The item table should be handled by the plugin, but plugin that do -%%% not want to manage it should be able to use the default behaviour. -%%% @todo Plugin modules should be able to register to receive presence update -%%% send to pubsub. - -%%% @doc The module {@module} is the default PubSub plugin. -%%%

    It is used as a default for all unknown PubSub node type. It can serve -%%% as a developer basis and reference to build its own custom pubsub node -%%% types.

    -%%%

    PubSub plugin nodes are using the {@link gen_node} behaviour.

    -%%%

    The API isn't stabilized yet. The pubsub plugin -%%% development is still a work in progress. However, the system is already -%%% useable and useful as is. Please, send us comments, feedback and -%%% improvements.

    -module(node_hometree_odbc). -behaviour(gen_pubsub_node). @@ -55,26 +41,20 @@ get_entity_subscriptions/2, get_node_subscriptions/1, get_subscriptions/2, set_subscriptions/4, get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/7, get_items/3, - get_items/6, get_items/2, get_item/7, + set_state/1, get_items/7, get_items/3, get_item/7, get_item/2, set_item/1, get_item_name/3, node_to_path/1, path_to_node/1, get_entity_subscriptions_for_send_last/2, get_last_items/3]). --export([decode_jid/1, encode_jid/1, - decode_affiliation/1, decode_subscriptions/1, - encode_affiliation/1, encode_subscriptions/1, - encode_host/1]). - -init(Host, ServerHost, _Opts) -> - pubsub_subscription_odbc:init(), +init(Host, ServerHost, Opts) -> + node_flat_odbc:init(Host, ServerHost, Opts), Owner = mod_pubsub:service_jid(Host), mod_pubsub:create_node(Host, ServerHost, <<"/home">>, Owner, <<"hometree">>), mod_pubsub:create_node(Host, ServerHost, <<"/home/", ServerHost/binary>>, Owner, <<"hometree">>), ok. -terminate(_Host, _ServerHost) -> - ok. +terminate(Host, ServerHost) -> + node_flat_odbc:terminate(Host, ServerHost). options() -> [{odbc, true}, {rsm, true} | node_hometree:options()]. @@ -82,921 +62,96 @@ options() -> features() -> [<<"rsm">> | node_hometree:features()]. -%% @doc Checks if the current user has the permission to create the requested node -%%

    In {@link node_default}, the permission is decided by the place in the -%% hierarchy where the user is creating the node. The access parameter is also -%% checked in the default module. This parameter depends on the value of the -%% access_createnode ACL value in ejabberd config file.

    -%%

    This function also check that node can be created a a children of its -%% parent node

    create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - {_U, _S, _R} = OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - State = #pubsub_state{stateid = {OwnerKey, Nidx}, affiliation = owner}, - catch ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " - "values(">>, state_to_raw(Nidx, State), <<");">>]), - {result, {default, broadcast}}. + node_flat_odbc:create_node(Nidx, Owner). delete_node(Nodes) -> - Reply = lists:map(fun (#pubsub_node{id = Nidx} = Node) -> - Subscriptions = case catch - ejabberd_odbc:sql_query_t([<<"select jid, subscriptions " - "from pubsub_state where nodeid='">>, Nidx, <<"';">>]) - of - {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> - [{decode_jid(SJID), decode_subscriptions(Subs)} || [SJID, Subs] <- RItems]; - _ -> - [] - end, - {Node, Subscriptions} - end, - Nodes), - {result, {default, broadcast, Reply}}. + node_flat_odbc:delete_node(Nodes). -%% @doc

    Accepts or rejects subcription requests on a PubSub node.

    -%%

    The mechanism works as follow: -%%

      -%%
    • The main PubSub module prepares the subscription and passes the -%% result of the preparation as a record.
    • -%%
    • This function gets the prepared record and several other parameters and -%% can decide to:
        -%%
      • reject the subscription;
      • -%%
      • allow it as is, letting the main module perform the database -%% persistance;
      • -%%
      • allow it, modifying the record. The main module will store the -%% modified record;
      • -%%
      • allow it, but perform the needed persistance operations.
      -%%

    -%%

    The selected behaviour depends on the return parameter: -%%

      -%%
    • {error, Reason}: an IQ error result will be returned. No -%% subscription will actually be performed.
    • -%%
    • true: Subscribe operation is allowed, based on the -%% unmodified record passed in parameter SubscribeResult. If this -%% parameter contains an error, no subscription will be performed.
    • -%%
    • {true, PubsubState}: Subscribe operation is allowed, but -%% the {@link mod_pubsub:pubsubState()} record returned replaces the value -%% passed in parameter SubscribeResult.
    • -%%
    • {true, done}: Subscribe operation is allowed, but the -%% {@link mod_pubsub:pubsubState()} will be considered as already stored and -%% no further persistance operation will be performed. This case is used, -%% when the plugin module is doing the persistance by itself or when it want -%% to completly disable persistance.
    -%%

    -%%

    In the default plugin module, the record is unchanged.

    subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, - {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), - Whitelisted = lists:member(Affiliation, [member, publisher, owner]), - PendingSubscription = lists:any(fun - ({pending, _}) -> true; - (_) -> false - end, - Subscriptions), - Owner = Affiliation == owner, - if not Authorized -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"invalid-jid">>)}; - (Affiliation == outcast) or (Affiliation == publish_only) -> - {error, ?ERR_FORBIDDEN}; - PendingSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"pending-subscription">>)}; - (AccessModel == presence) and (not PresenceSubscription) and (not Owner) -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and (not RosterGroup) and (not Owner) -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and (not Whitelisted) and (not Owner) -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - %%ForbiddenAnonymous -> - %% % Requesting entity is anonymous - %% {error, ?ERR_FORBIDDEN}; - true -> - {result, SubId} = pubsub_subscription_odbc:subscribe_node(Subscriber, Nidx, Options), - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed - end, - update_subscription(Nidx, SubKey, [{NewSub, SubId} | Subscriptions]), - case {NewSub, SendLast} of - {subscribed, never} -> {result, {default, subscribed, SubId}}; - {subscribed, _} -> {result, {default, subscribed, SubId, send_last}}; - {_, _} -> {result, {default, pending, SubId}} - end - end. + node_flat_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). -%% @doc

    Unsubscribe the Subscriber from the Node.

    unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, - {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, SubKey), - SubIdExists = case SubId of - <<>> -> false; - Binary when is_binary(Binary) -> true; - _ -> false - end, - if - %% Requesting entity is prohibited from unsubscribing entity - not Authorized -> - {error, ?ERR_FORBIDDEN}; - %% Entity did not specify SubId - %%SubId == "", ?? -> - %% {error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %% Invalid subscription identifier - %%InvalidSubId -> - %% {error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - %% Requesting entity is not a subscriber - Subscriptions == [] -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)}; - %% Subid supplied, so use that. - SubIdExists -> - Sub = first_in_list(fun - ({_, S}) when S == SubId -> true; - (_) -> false - end, - Subscriptions), - case Sub of - {value, S} -> - delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions), - {result, default}; - false -> - {error, - ?ERR_EXTENDED((?ERR_UNEXPECTED_REQUEST_CANCEL), <<"not-subscribed">>)} - end; - %% Asking to remove all subscriptions to the given node - SubId == all -> - [delete_subscription(SubKey, Nidx, S, Affiliation, Subscriptions) - || S <- Subscriptions], - {result, default}; - %% No subid supplied, but there's only one matching subscription - length(Subscriptions) == 1 -> - delete_subscription(SubKey, Nidx, hd(Subscriptions), Affiliation, Subscriptions), - {result, default}; - %% No subid and more than one possible subscription match. - true -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)} - end. + node_flat_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId). -delete_subscription(SubKey, Nidx, {Subscription, SubId}, Affiliation, Subscriptions) -> - NewSubs = Subscriptions -- [{Subscription, SubId}], - pubsub_subscription_odbc:unsubscribe_node(SubKey, Nidx, SubId), - case {Affiliation, NewSubs} of - {none, []} -> del_state(Nidx, SubKey); - _ -> update_subscription(Nidx, SubKey, NewSubs) - end. +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_flat_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). -%% @doc

    Publishes the item passed as parameter.

    -%%

    The mechanism works as follow: -%%

      -%%
    • The main PubSub module prepares the item to publish and passes the -%% result of the preparation as a {@link mod_pubsub:pubsubItem()} record.
    • -%%
    • This function gets the prepared record and several other parameters and can decide to:
        -%%
      • reject the publication;
      • -%%
      • allow the publication as is, letting the main module perform the database persistance;
      • -%%
      • allow the publication, modifying the record. The main module will store the modified record;
      • -%%
      • allow it, but perform the needed persistance operations.
      -%%

    -%%

    The selected behaviour depends on the return parameter: -%%

      -%%
    • {error, Reason}: an iq error result will be return. No -%% publication is actually performed.
    • -%%
    • true: Publication operation is allowed, based on the -%% unmodified record passed in parameter Item. If the Item -%% parameter contains an error, no subscription will actually be -%% performed.
    • -%%
    • {true, Item}: Publication operation is allowed, but the -%% {@link mod_pubsub:pubsubItem()} record returned replaces the value passed -%% in parameter Item. The persistance will be performed by the main -%% module.
    • -%%
    • {true, done}: Publication operation is allowed, but the -%% {@link mod_pubsub:pubsubItem()} will be considered as already stored and -%% no further persistance operation will be performed. This case is used, -%% when the plugin module is doing the persistance by itself or when it want -%% to completly disable persistance.
    -%%

    -%%

    In the default plugin module, the record is unchanged.

    -publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), - {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), - Subscribed = case PublishModel of - subscribers -> is_subscribed(Subscriptions); - _ -> undefined - end, - if not ((PublishModel == open) or - (PublishModel == publishers) and - ((Affiliation == owner) - or (Affiliation == publisher) - or (Affiliation == publish_only)) - or (Subscribed == true)) -> - {error, ?ERR_FORBIDDEN}; - true -> - if MaxItems > 0 -> - PubId = {now(), SubKey}, - set_item(#pubsub_item{itemid = {ItemId, Nidx}, - creation = {now(), GenKey}, - modification = PubId, - payload = Payload}), - Items = [ItemId | itemids(Nidx, GenKey) -- [ItemId]], - {result, {_, OI}} = remove_extra_items(Nidx, MaxItems, Items), - {result, {default, broadcast, OI}}; - true -> - {result, {default, broadcast, []}} - end - end. - -%% @doc

    This function is used to remove extra items, most notably when the -%% maximum number of items has been reached.

    -%%

    This function is used internally by the core PubSub module, as no -%% permission check is performed.

    -%%

    In the default plugin module, the oldest items are removed, but other -%% rules can be used.

    -%%

    If another PubSub plugin wants to delegate the item removal (and if the -%% plugin is using the default pubsub storage), it can implements this function like this: -%% ```remove_extra_items(Nidx, MaxItems, ItemIds) -> -%% node_default:remove_extra_items(Nidx, MaxItems, ItemIds).'''

    -remove_extra_items(_Nidx, unlimited, ItemIds) -> - {result, {ItemIds, []}}; remove_extra_items(Nidx, MaxItems, ItemIds) -> - NewItems = lists:sublist(ItemIds, MaxItems), - OldItems = lists:nthtail(length(NewItems), ItemIds), - del_items(Nidx, OldItems), - {result, {NewItems, OldItems}}. + node_flat_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). -%% @doc

    Triggers item deletion.

    -%%

    Default plugin: The user performing the deletion must be the node owner -%% or a publisher, or PublishModel being open.

    delete_item(Nidx, Publisher, PublishModel, ItemId) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), - {result, Affiliation} = get_affiliation(Nidx, GenKey), - Allowed = Affiliation == publisher orelse - Affiliation == owner orelse - PublishModel == open orelse - case get_item(Nidx, ItemId) of - {result, #pubsub_item{creation = {_, GenKey}}} -> true; - _ -> false - end, - if not Allowed -> - {error, ?ERR_FORBIDDEN}; - true -> - case del_item(Nidx, ItemId) of - {updated, 1} -> {result, {default, broadcast}}; - _ -> {error, ?ERR_ITEM_NOT_FOUND} - end - end. + node_flat_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - GenState = get_state(Nidx, GenKey), - case GenState of - #pubsub_state{affiliation = owner} -> - {result, States} = get_states(Nidx), - lists:foreach(fun - (#pubsub_state{items = []}) -> ok; - (#pubsub_state{items = Items}) -> del_items(Nidx, Items) - end, - States), - {result, {default, broadcast}}; - _ -> - {error, ?ERR_FORBIDDEN} - end. + node_flat_odbc:purge_node(Nidx, Owner). -%% @doc

    Return the current affiliations for the given user

    -%%

    The default module reads affiliations in the main Mnesia -%% pubsub_state table. If a plugin stores its data in the same -%% table, it should return an empty list, as the affiliation will be read by -%% the default PubSub module. Otherwise, it should return its own affiliation, -%% that will be added to the affiliation stored in the main -%% pubsub_state table.

    get_entity_affiliations(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - H = encode_host(Host), - J = encode_jid(GenKey), - Reply = case catch - ejabberd_odbc:sql_query_t([<<"select node, type, i.nodeid, affiliation " - "from pubsub_state i, pubsub_node n where " - "i.nodeid = n.nodeid and jid='">>, J, <<"' and host='">>, H, <<"';">>]) - of - {selected, [<<"node">>, <<"type">>, <<"nodeid">>, <<"affiliation">>], RItems} -> - [{nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), decode_affiliation(A)} - || [N, T, I, A] <- RItems]; - _ -> - [] - end, - {result, Reply}. + node_flat_odbc:get_entity_affiliations(Host, Owner). get_node_affiliations(Nidx) -> - Reply = case catch - ejabberd_odbc:sql_query_t([<<"select jid, affiliation from pubsub_state " - "where nodeid='">>, Nidx, <<"';">>]) - of - {selected, [<<"jid">>, <<"affiliation">>], RItems} -> - [{decode_jid(J), decode_affiliation(A)} || [J, A] <- RItems]; - _ -> - [] - end, - {result, Reply}. + node_flat_odbc:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - J = encode_jid(GenKey), - Reply = case catch - ejabberd_odbc:sql_query_t([<<"select affiliation from pubsub_state " - "where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) - of - {selected, [<<"affiliation">>], [[A]]} -> - decode_affiliation(A); - _ -> - none - end, - {result, Reply}. + node_flat_odbc:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - {_, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey), - case {Affiliation, Subscriptions} of - {none, []} -> del_state(Nidx, GenKey); - _ -> update_affiliation(Nidx, GenKey, Affiliation) - end. + node_flat_odbc:set_affiliation(Nidx, Owner, Affiliation). -%% @doc

    Return the current subscriptions for the given user

    -%%

    The default module reads subscriptions in the main Mnesia -%% pubsub_state table. If a plugin stores its data in the same -%% table, it should return an empty list, as the affiliation will be read by -%% the default PubSub module. Otherwise, it should return its own affiliation, -%% that will be added to the affiliation stored in the main -%% pubsub_state table.

    get_entity_subscriptions(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - H = encode_host(Host), - SJ = encode_jid(SubKey), - GJ = encode_jid(GenKey), - Query = case SubKey of - GenKey -> - [<<"select node, type, i.nodeid, jid, subscriptions " - "from pubsub_state i, pubsub_node n " - "where i.nodeid = n.nodeid and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>]; - _ -> - [<<"select node, type, i.nodeid, jid, subscriptions " - "from pubsub_state i, pubsub_node n " - "where i.nodeid = n.nodeid and jid in ('">>, SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] - end, - Reply = case catch ejabberd_odbc:sql_query_t(Query) of - {selected, - [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> - lists:foldl(fun ([N, T, I, J, S], Acc) -> - Node = nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> - [{Node, none, Jid} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, Jid} | Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> - [] - end, - {result, Reply}. + node_flat_odbc:get_entity_subscriptions(Host, Owner). -%% do the same as get_entity_subscriptions but filter result only to -%% nodes having send_last_published_item=on_sub_and_presence -%% as this call avoid seeking node, it must return node and type as well --spec(get_entity_subscriptions_for_send_last/2 :: - ( - Host :: mod_pubsub:hostPubsub(), - Owner :: jid()) - -> {result, - [{mod_pubsub:pubsubNode(), - mod_pubsub:subscription(), - mod_pubsub:subId(), - ljid()}] - } - ). get_entity_subscriptions_for_send_last(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), - H = encode_host(Host), - SJ = encode_jid(SubKey), - GJ = encode_jid(GenKey), - Query = case SubKey of - GenKey -> - [<<"select node, type, i.nodeid, jid, subscriptions " - "from pubsub_state i, pubsub_node n, pubsub_node_option o " - "where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' " - "and val='on_sub_and_presence' and jid like '">>, GJ, <<"%' and host='">>, H, <<"';">>]; - _ -> - [<<"select node, type, i.nodeid, jid, subscriptions " - "from pubsub_state i, pubsub_node n, pubsub_node_option o " - "where i.nodeid = n.nodeid and n.nodeid = o.nodeid and name='send_last_published_item' " - "and val='on_sub_and_presence' and jid in ('">>, SJ, <<"', '">>, GJ, <<"') and host='">>, H, <<"';">>] - end, - Reply = case catch ejabberd_odbc:sql_query_t(Query) of - {selected, - [<<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> - lists:foldl(fun ([N, T, I, J, S], Acc) -> - Node = nodetree_tree_odbc:raw_to_node(Host, [N, <<"">>, T, I]), - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> - [{Node, none, Jid} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Node, Sub, SubId, Jid}| Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> - [] - end, - {result, Reply}. + node_flat_odbc:get_entity_subscriptions_for_send_last(Host, Owner). get_node_subscriptions(Nidx) -> - Reply = case catch - ejabberd_odbc:sql_query_t([<<"select jid, subscriptions from pubsub_state " - "where nodeid='">>, Nidx, <<"';">>]) - of - {selected, [<<"jid">>, <<"subscriptions">>], RItems} -> - lists:foldl(fun ([J, S], Acc) -> - Jid = decode_jid(J), - case decode_subscriptions(S) of - [] -> - [{Jid, none} | Acc]; - Subs -> - lists:foldl(fun ({Sub, SubId}, Acc2) -> - [{Jid, Sub, SubId} | Acc2] - end, - Acc, Subs) - end - end, - [], RItems); - _ -> - [] - end, - {result, Reply}. + node_flat_odbc:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - J = encode_jid(SubKey), - Reply = case catch - ejabberd_odbc:sql_query_t([<<"select subscriptions from pubsub_state where " - "nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) - of - {selected, [<<"subscriptions">>], [[S]]} -> - decode_subscriptions(S); - _ -> - [] - end, - {result, Reply}. + node_flat_odbc:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - SubKey = jlib:jid_tolower(Owner), - SubState = get_state_without_itemids(Nidx, SubKey), - case {SubId, SubState#pubsub_state.subscriptions} of - {_, []} -> - case Subscription of - none -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"not-subscribed">>)}; - _ -> - new_subscription(Nidx, Owner, Subscription, SubState) - end; - {<<>>, [{_, SID}]} -> - case Subscription of - none -> unsub_with_subid(Nidx, SID, SubState); - _ -> replace_subscription({Subscription, SID}, SubState) - end; - {<<>>, [_ | _]} -> - {error, - ?ERR_EXTENDED((?ERR_BAD_REQUEST), <<"subid-required">>)}; - _ -> - case Subscription of - none -> unsub_with_subid(Nidx, SubId, SubState); - _ -> replace_subscription({Subscription, SubId}, SubState) - end - end. - -replace_subscription(NewSub, SubState) -> - NewSubs = replace_subscription(NewSub, SubState#pubsub_state.subscriptions, []), - set_state(SubState#pubsub_state{subscriptions = NewSubs}). + node_flat_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). -replace_subscription(_, [], Acc) -> Acc; -replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> - replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). - -new_subscription(Nidx, Owner, Subscription, SubState) -> - {result, SubId} = pubsub_subscription_odbc:subscribe_node(Owner, Nidx, []), - Subscriptions = [{Subscription, SubId} | SubState#pubsub_state.subscriptions], - set_state(SubState#pubsub_state{subscriptions = Subscriptions}), - {Subscription, SubId}. - -unsub_with_subid(Nidx, SubId, SubState) -> - pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, Nidx, SubId), - NewSubs = [{S, Sid} - || {S, Sid} <- SubState#pubsub_state.subscriptions, - SubId =/= Sid], - case {NewSubs, SubState#pubsub_state.affiliation} of - {[], none} -> del_state(Nidx, element(1, SubState#pubsub_state.stateid)); - _ -> set_state(SubState#pubsub_state{subscriptions = NewSubs}) - end. - -%% @doc

    Returns a list of Owner's nodes on Host with pending -%% subscriptions.

    get_pending_nodes(Host, Owner) -> - GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), - States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, - affiliation = owner, _ = '_'}), - Nidxxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], - NodeTree = mod_pubsub:tree(Host), - Reply = mnesia:foldl(fun (#pubsub_state{stateid = {_, Nidx}} = S, Acc) -> - case lists:member(Nidx, Nidxxs) of - true -> - case get_nodes_helper(NodeTree, S) of - {value, Node} -> [Node | Acc]; - false -> Acc - end; - false -> - Acc - end - end, - [], pubsub_state), - {result, Reply}. + node_flat_odbc:get_pending_nodes(Host, Owner). -get_nodes_helper(NodeTree, #pubsub_state{stateid = {_, N}, subscriptions = Subs}) -> - HasPending = fun - ({pending, _}) -> true; - (pending) -> true; - (_) -> false - end, - case lists:any(HasPending, Subs) of - true -> - case NodeTree:get_node(N) of - #pubsub_node{nodeid = {_, Node}} -> {value, Node}; - _ -> false - end; - false -> - false - end. - -%% @doc Returns the list of stored states for a given node. -%%

    For the default PubSub module, states are stored in Mnesia database.

    -%%

    We can consider that the pubsub_state table have been created by the main -%% mod_pubsub module.

    -%%

    PubSub plugins can store the states where they wants (for example in a -%% relational database).

    -%%

    If a PubSub plugin wants to delegate the states storage to the default node, -%% they can implement this function like this: -%% ```get_states(Nidx) -> -%% node_default:get_states(Nidx).'''

    get_states(Nidx) -> - case catch - ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " - "from pubsub_state where nodeid='">>, Nidx, <<"';">>]) - of - {selected, - [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], RItems} -> - {result, - lists:map(fun ([SJID, Aff, Subs]) -> - #pubsub_state{stateid = {decode_jid(SJID), Nidx}, - items = itemids(Nidx, SJID), - affiliation = decode_affiliation(Aff), - subscriptions = decode_subscriptions(Subs)} - end, - RItems)}; - _ -> - {result, []} - end. + node_flat_odbc:get_states(Nidx). -%% @doc

    Returns a state (one state list), given its reference.

    get_state(Nidx, JID) -> - State = get_state_without_itemids(Nidx, JID), - {SJID, _} = State#pubsub_state.stateid, - State#pubsub_state{items = itemids(Nidx, SJID)}. - --spec(get_state_without_itemids/2 :: - (Nidx :: mod_pubsub:nodeIdx(), - Key :: ljid()) -> - mod_pubsub:pubsubState() - ). -get_state_without_itemids(Nidx, JID) -> - J = encode_jid(JID), - case catch - ejabberd_odbc:sql_query_t([<<"select jid, affiliation, subscriptions " - "from pubsub_state where jid='">>, J, <<"' and nodeid='">>, Nidx, <<"';">>]) - of - {selected, - [<<"jid">>, <<"affiliation">>, <<"subscriptions">>], [[SJID, Aff, Subs]]} -> - #pubsub_state{stateid = {decode_jid(SJID), Nidx}, - affiliation = decode_affiliation(Aff), - subscriptions = decode_subscriptions(Subs)}; - _ -> - #pubsub_state{stateid = {JID, Nidx}} - end. + node_flat_odbc:get_state(Nidx, JID). -%% @doc

    Write a state into database.

    set_state(State) -> - {_, Nidx} = State#pubsub_state.stateid, - set_state(Nidx, State). + node_flat_odbc:set_state(State). -set_state(Nidx, State) -> - {JID, _} = State#pubsub_state.stateid, - J = encode_jid(JID), - S = encode_subscriptions(State#pubsub_state.subscriptions), - A = encode_affiliation(State#pubsub_state.affiliation), - case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, S, <<"', affiliation='">>, A, - <<"' where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) - of - {updated, 1} -> - ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " - "values('">>, - Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '">>, S, <<"');">>]) - end, - ok. - -%% @doc

    Delete a state from database.

    -del_state(Nidx, JID) -> - J = encode_jid(JID), - catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_state where jid='">>, - J, <<"' and nodeid='">>, Nidx, <<"';">>]), - ok. - -%% @doc Returns the list of stored items for a given node. -%%

    For the default PubSub module, items are stored in Mnesia database.

    -%%

    We can consider that the pubsub_item table have been created by the main -%% mod_pubsub module.

    -%%

    PubSub plugins can store the items where they wants (for example in a -%% relational database), or they can even decide not to persist any items.

    -%%

    If a PubSub plugin wants to delegate the item storage to the default node, -%% they can implement this function like this: -%% ```get_items(Nidx, From) -> -%% node_default:get_items(Nidx, From).'''

    -get_items(Nidx, _From) -> - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " - "from pubsub_item where nodeid='">>, Nidx, - <<"' order by modification desc;">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> - {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; - _ -> - {result, []} - end. - -get_items(Nidx, From, none) -> - MaxItems = case catch - ejabberd_odbc:sql_query_t([<<"select val from pubsub_node_option " - "where nodeid='">>, Nidx, <<"' and name='max_items';">>]) - of - {selected, [<<"val">>], [[Value]]} -> - Tokens = element(2, erl_scan:string(binary_to_list(<>))), - element(2, erl_parse:parse_term(Tokens)); - _ -> - ?MAXITEMS - end, - get_items(Nidx, From, #rsm_in{max = MaxItems}); -get_items(Nidx, _From, - #rsm_in{max = M, direction = Direction, id = I, index = IncIndex}) -> - Max = ejabberd_odbc:escape(jlib:i2l(M)), - {Way, Order} = case Direction of - % aft -> {<<"<">>, <<"desc">>}; - % before when I == <<>> -> {<<"is not">>, <<"asc">>}; - % before -> {<<">">>, <<"asc">>}; - % _ when IncIndex =/= undefined -> - % {<<"<">>, <<"desc">>}; % using index - _ -> - {<<"is not">>, <<"desc">>}% Can be better - end, - [AttrName, Id] = case I of - undefined when IncIndex =/= undefined -> - case catch - ejabberd_odbc:sql_query_t([<<"select modification from pubsub_item pi " - "where exists ( select count(*) as count1 " - "from pubsub_item where nodeid='">>, Nidx, - <<"' and modification > pi.modification having count1 = ">>, - ejabberd_odbc:escape(jlib:i2l(IncIndex)), <<" );">>]) - of - {selected, [_], [[O]]} -> - [<<"modification">>, <<"'", O/binary, "'">>]; - _ -> - [<<"modification">>, <<"null">>] - end; - undefined -> - [<<"modification">>, <<"null">>]; - <<>> -> - [<<"modification">>, <<"null">>]; - I -> - [A, B] = str:tokens(ejabberd_odbc:escape(jlib:i2l(I)), <<"@">>), - [A, <<"'", B/binary, "'">>] - end, - Count = case catch - ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item where nodeid='">>, Nidx, <<"';">>]) - of - {selected, [_], [[C]]} -> C; - _ -> <<"0">> - end, - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " - "from pubsub_item where nodeid='">>, Nidx, - <<"' and ">>, AttrName, <<" ">>, Way, <<" ">>, Id, <<" order by ">>, - AttrName, <<" ">>, Order, <<" limit ">>, jlib:i2l(Max), <<" ;">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> - case RItems of - [[_, _, _, F, _]|_] -> - Index = case catch - ejabberd_odbc:sql_query_t([<<"select count(*) from pubsub_item " - "where nodeid='">>, Nidx, <<"' and ">>, - AttrName, <<" > '">>, F, <<"';">>]) - of - %{selected, [_], [{C}, {In}]} -> [string:strip(C, both, $"), string:strip(In, both, $")]; - {selected, [_], [[In]]} -> In; - _ -> <<"0">> - end, - [_, _, _, L, _] = lists:last(RItems), - RsmOut = #rsm_out{count = Count, index = Index, - first = <<"modification@", F/binary>>, - last = <<"modification@", (jlib:i2l(L))/binary>>}, - {result, {[raw_to_item(Nidx, RItem) || RItem <- RItems], RsmOut}}; - [] -> - {result, {[], #rsm_out{count = Count}}} - end; - _ -> - {result, {[], none}} - end. +get_items(Nidx, From, RSM) -> + node_flat_odbc:get_items(Nidx, From, RSM). -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_flat_odbc:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), - {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), - Whitelisted = can_fetch_item(Affiliation, Subscriptions), - if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - (Affiliation == outcast) or (Affiliation == publish_only) -> - {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> - get_items(Nidx, JID, RSM) - end. - -get_last_items(Nidx, _From, Count) -> - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " - "from pubsub_item where nodeid='">>, Nidx, - <<"' order by modification desc limit ">>, jlib:i2l(Count), <<";">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> - {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; - _ -> - {result, []} - end. - -%% @doc

    Returns an item (one item list), given its reference.

    get_item(Nidx, ItemId) -> - I = ejabberd_odbc:escape(ItemId), - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, " - "modification, payload from pubsub_item " - "where nodeid='">>, Nidx, <<"' and itemid='">>, I, <<"';">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], [RItem]} -> - {result, raw_to_item(Nidx, RItem)}; - _ -> - {error, ?ERR_ITEM_NOT_FOUND} - end. + node_flat_odbc:get_item(Nidx, ItemId). -get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), - {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), - Whitelisted = can_fetch_item(Affiliation, Subscriptions), - if %%SubId == "", ?? -> - %% Entity has multiple subscriptions to the node but does not specify a subscription ID - %{error, ?ERR_EXTENDED(?ERR_BAD_REQUEST, "subid-required")}; - %%InvalidSubId -> - %% Entity is subscribed but specifies an invalid subscription ID - %{error, ?ERR_EXTENDED(?ERR_NOT_ACCEPTABLE, "invalid-subid")}; - (Affiliation == outcast) or (Affiliation == publish_only) -> - {error, ?ERR_FORBIDDEN}; - (AccessModel == presence) and not PresenceSubscription -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"presence-subscription-required">>)}; - (AccessModel == roster) and not RosterGroup -> - {error, - ?ERR_EXTENDED((?ERR_NOT_AUTHORIZED), <<"not-in-roster-group">>)}; - (AccessModel == whitelist) and not Whitelisted -> - {error, - ?ERR_EXTENDED((?ERR_NOT_ALLOWED), <<"closed-node">>)}; - (AccessModel == authorize) and not Whitelisted -> - {error, ?ERR_FORBIDDEN}; - %%MustPay -> - %% % Payment is required for a subscription - %% {error, ?ERR_PAYMENT_REQUIRED}; - true -> - get_item(Nidx, ItemId) - end. +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat_odbc:get_item(Nidx, ItemId, JID, + AccessModel, PresenceSubscription, RosterGroup, SubId). -%% @doc

    Write an item into database.

    set_item(Item) -> - {ItemId, Nidx} = Item#pubsub_item.itemid, - I = ejabberd_odbc:escape(ItemId), - {C, _} = Item#pubsub_item.creation, - {M, JID} = Item#pubsub_item.modification, - P = encode_jid(JID), - Payload = Item#pubsub_item.payload, - XML = ejabberd_odbc:escape(str:join([xml:element_to_binary(X) || X<-Payload], <<>>)), - S = fun ({T1, T2, T3}) -> - str:join([jlib:i2l(T1, 6), jlib:i2l(T2, 6), jlib:i2l(T3, 6)], <<":">>) - end, - case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_item set publisher='">>, P, - <<"', modification='">>, S(M), - <<"', payload='">>, XML, - <<"' where nodeid='">>, Nidx, <<"' and itemid='">>, I, <<"';">>]) - of - {updated, 1} -> - ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_item (nodeid, itemid, " - "publisher, creation, modification, payload) " - "values('">>, Nidx, <<"', '">>, I, <<"', '">>, P, - <<"', '">>, S(C), <<"', '">>, S(M), - <<"', '">>, XML, <<"');">>]) - end, - ok. - -%% @doc

    Delete an item from database.

    -del_item(Nidx, ItemId) -> - I = ejabberd_odbc:escape(ItemId), - catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid='">>, - I, <<"' and nodeid='">>, Nidx, <<"';">>]). + node_flat_odbc:set_item(Item). -del_items(_, []) -> - ok; -del_items(Nidx, [ItemId]) -> - del_item(Nidx, ItemId); -del_items(Nidx, ItemIds) -> - I = str:join([[<<"'">>, ejabberd_odbc:escape(X), <<"'">>] || X <- ItemIds], <<",">>), - catch - ejabberd_odbc:sql_query_t([<<"delete from pubsub_item where itemid in (">>, - I, <<") and nodeid='">>, Nidx, <<"';">>]). +get_item_name(Host, Node, Id) -> + node_flat_odbc:get_item_name(Host, Node, Id). -get_item_name(_Host, _Node, Id) -> - Id. +get_last_items(Nidx, From, Count) -> + node_flat_odbc:get_last_items(Nidx, From, Count). node_to_path(Node) -> node_hometree:node_to_path(Node). @@ -1004,196 +159,3 @@ node_to_path(Node) -> path_to_node(Path) -> node_hometree:path_to_node(Path). -can_fetch_item(owner, _) -> true; -can_fetch_item(member, _) -> true; -can_fetch_item(publisher, _) -> true; -can_fetch_item(publish_only, _) -> false; -can_fetch_item(outcast, _) -> false; -can_fetch_item(none, Subscriptions) -> is_subscribed(Subscriptions). -%can_fetch_item(_Affiliation, _Subscription) -> false. - -is_subscribed(Subscriptions) -> - lists:any(fun - ({subscribed, _SubId}) -> true; - (_) -> false - end, - Subscriptions). - -first_in_list(_Pred, []) -> - false; -first_in_list(Pred, [H | T]) -> - case Pred(H) of - true -> {value, H}; - _ -> first_in_list(Pred, T) - end. - -itemids(Nidx, {U, S, R}) -> - itemids(Nidx, encode_jid({U, S, R})); -itemids(Nidx, SJID) -> - case catch - ejabberd_odbc:sql_query_t([<<"select itemid from pubsub_item where " - "nodeid='">>, Nidx, <<"' and publisher like '">>, SJID, - <<"%' order by modification desc;">>]) - of - {selected, [<<"itemid">>], RItems} -> - [ItemId || [ItemId] <- RItems]; - _ -> - [] - end. - -select_affiliation_subscriptions(Nidx, JID) -> - J = encode_jid(JID), - case catch - ejabberd_odbc:sql_query_t([<<"select affiliation,subscriptions from " - "pubsub_state where nodeid='">>, - Nidx, <<"' and jid='">>, J, <<"';">>]) - of - {selected, [<<"affiliation">>, <<"subscriptions">>], [[A, S]]} -> - {decode_affiliation(A), decode_subscriptions(S)}; - _ -> - {none, []} - end. - -select_affiliation_subscriptions(Nidx, JID, JID) -> - select_affiliation_subscriptions(Nidx, JID); -select_affiliation_subscriptions(Nidx, GenKey, SubKey) -> - {result, Affiliation} = get_affiliation(Nidx, GenKey), - {result, Subscriptions} = get_subscriptions(Nidx, SubKey), - {Affiliation, Subscriptions}. - -update_affiliation(Nidx, JID, Affiliation) -> - J = encode_jid(JID), - A = encode_affiliation(Affiliation), - case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_state set affiliation='">>, - A, <<"' where nodeid='">>, Nidx, - <<"' and jid='">>, J, <<"';">>]) - of - {updated, 1} -> - ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " - "values('">>, Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '');">>]) - end. - -update_subscription(Nidx, JID, Subscription) -> - J = encode_jid(JID), - S = encode_subscriptions(Subscription), - case catch - ejabberd_odbc:sql_query_t([<<"update pubsub_state set subscriptions='">>, S, - <<"' where nodeid='">>, Nidx, <<"' and jid='">>, J, <<"';">>]) - of - {updated, 1} -> - ok; - _ -> - catch - ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " - "values('">>, Nidx, <<"', '">>, J, <<"', 'n', '">>, S, <<"');">>]) - end. - --spec(decode_jid/1 :: - ( SJID :: binary()) - -> ljid() - ). -decode_jid(SJID) -> - jlib:jid_tolower(jlib:string_to_jid(SJID)). - --spec(decode_affiliation/1 :: - ( Arg :: binary()) - -> atom() - ). -decode_affiliation(<<"o">>) -> owner; -decode_affiliation(<<"p">>) -> publisher; -decode_affiliation(<<"u">>) -> publish_only; -decode_affiliation(<<"m">>) -> member; -decode_affiliation(<<"c">>) -> outcast; -decode_affiliation(_) -> none. - --spec(decode_subscription/1 :: - ( Arg :: binary()) - -> atom() - ). -decode_subscription(<<"s">>) -> subscribed; -decode_subscription(<<"p">>) -> pending; -decode_subscription(<<"u">>) -> unconfigured; -decode_subscription(_) -> none. - --spec(decode_subscriptions/1 :: - ( Subscriptions :: binary()) - -> [] | [{atom(), binary()},...] - ). -decode_subscriptions(Subscriptions) -> - lists:foldl(fun (Subscription, Acc) -> - case str:tokens(Subscription, <<":">>) of - [S, SubId] -> [{decode_subscription(S), SubId} | Acc]; - _ -> Acc - end - end, - [], str:tokens(Subscriptions, <<",">>)). - --spec(encode_jid/1 :: - ( JID :: ljid()) - -> binary() - ). -encode_jid(JID) -> - ejabberd_odbc:escape(jlib:jid_to_string(JID)). - --spec(encode_host/1 :: - ( Host :: host()) - -> binary() - ). -encode_host({_U, _S, _R} = LJID) -> encode_jid(LJID); -encode_host(Host) -> ejabberd_odbc:escape(Host). - --spec(encode_affiliation/1 :: - ( Arg :: atom()) - -> binary() - ). -encode_affiliation(owner) -> <<"o">>; -encode_affiliation(publisher) -> <<"p">>; -encode_affiliation(publish_only) -> <<"u">>; -encode_affiliation(member) -> <<"m">>; -encode_affiliation(outcast) -> <<"c">>; -encode_affiliation(_) -> <<"n">>. - --spec(encode_subscription/1 :: - ( Arg :: atom()) - -> binary() - ). -encode_subscription(subscribed) -> <<"s">>; -encode_subscription(pending) -> <<"p">>; -encode_subscription(unconfigured) -> <<"u">>; -encode_subscription(_) -> <<"n">>. - --spec(encode_subscriptions/1 :: - ( Subscriptions :: [] | [{atom(), binary()},...]) - -> binary() - ). -encode_subscriptions(Subscriptions) -> - str:join([<<(encode_subscription(S))/binary, ":", SubId/binary>> - || {S, SubId} <- Subscriptions], <<",">>). - -%%% record getter/setter - -state_to_raw(Nidx, State) -> - {JID, _} = State#pubsub_state.stateid, - J = encode_jid(JID), - A = encode_affiliation(State#pubsub_state.affiliation), - S = encode_subscriptions(State#pubsub_state.subscriptions), - [<<"'">>, Nidx, <<"', '">>, J, <<"', '">>, A, <<"', '">>, S, <<"'">>]. - -raw_to_item(Nidx, [ItemId, SJID, Creation, Modification, XML]) -> - JID = decode_jid(SJID), - ToTime = fun (Str) -> - [T1, T2, T3] = str:tokens(Str, <<":">>), - {jlib:l2i(T1), jlib:l2i(T2), jlib:l2i(T3)} - end, - Payload = case xml_stream:parse_element(XML) of - {error, _Reason} -> []; - El -> [El] - end, - #pubsub_item{itemid = {ItemId, Nidx}, - creation = {ToTime(Creation), JID}, - modification = {ToTime(Modification), JID}, - payload = Payload}. diff --git a/src/node_mb.erl b/src/node_mb.erl index 9dc4bf81f7a..91e49505c92 100644 --- a/src/node_mb.erl +++ b/src/node_mb.erl @@ -37,7 +37,6 @@ %%% ignore_pep_from_offline: false %%% plugins: %%% - "flat" -%%% - "hometree" %%% - "pep" # Requires mod_caps. %%% pep_mapping: %%% "urn:xmpp:microblog:0": "mb" diff --git a/src/node_pep.erl b/src/node_pep.erl index 34a841d3ed1..b219f6449f6 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -49,12 +49,12 @@ path_to_node/1]). init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts), + node_flat:init(Host, ServerHost, Opts), complain_if_modcaps_disabled(ServerHost), ok. terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost), ok. + node_flat:terminate(Host, ServerHost), ok. options() -> [{deliver_payloads, true}, @@ -112,34 +112,34 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> {result, Allowed}. create_node(Nidx, Owner) -> - node_hometree:create_node(Nidx, Owner). + node_flat:create_node(Nidx, Owner). delete_node(Nodes) -> - {result, {_, _, Result}} = node_hometree:delete_node(Nodes), + {result, {_, _, Result}} = node_flat:delete_node(Nodes), {result, {[], Result}}. subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - case node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of + case node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of {error, Error} -> {error, Error}; {result, _} -> {result, []} end. publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - node_hometree:purge_node(Nidx, Owner). + node_flat:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> {_, D, _} = SubKey = jlib:jid_tolower(Owner), @@ -158,13 +158,13 @@ get_entity_affiliations(Host, Owner) -> get_node_affiliations(Nidx) -> - node_hometree:get_node_affiliations(Nidx). + node_flat:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - node_hometree:get_affiliation(Nidx, Owner). + node_flat:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree:set_affiliation(Nidx, Owner, Affiliation). + node_flat:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> {U, D, _} = SubKey = jlib:jid_tolower(Owner), @@ -198,45 +198,45 @@ get_entity_subscriptions(Host, Owner) -> {result, Reply}. get_node_subscriptions(Nidx) -> - node_hometree:get_node_subscriptions(Nidx). + node_flat:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - node_hometree:get_subscriptions(Nidx, Owner). + node_flat:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). + node_flat:get_pending_nodes(Host, Owner). get_states(Nidx) -> - node_hometree:get_states(Nidx). + node_flat:get_states(Nidx). get_state(Nidx, JID) -> - node_hometree:get_state(Nidx, JID). + node_flat:get_state(Nidx, JID). set_state(State) -> - node_hometree:set_state(State). + node_flat:set_state(State). get_items(Nidx, From, RSM) -> - node_hometree:get_items(Nidx, From, RSM). + node_flat:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree:get_items(Nidx, JID, AccessModel, + node_flat:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> - node_hometree:get_item(Nidx, ItemId). + node_flat:get_item(Nidx, ItemId). get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + node_flat:get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> - node_hometree:set_item(Item). + node_flat:set_item(Item). get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). + node_flat:get_item_name(Host, Node, Id). node_to_path(Node) -> node_flat:node_to_path(Node). diff --git a/src/node_pep_odbc.erl b/src/node_pep_odbc.erl index d80e686fbc7..39ea8f0b766 100644 --- a/src/node_pep_odbc.erl +++ b/src/node_pep_odbc.erl @@ -50,12 +50,12 @@ get_entity_subscriptions_for_send_last/2, get_last_items/3]). init(Host, ServerHost, Opts) -> - node_hometree_odbc:init(Host, ServerHost, Opts), + node_flat_odbc:init(Host, ServerHost, Opts), complain_if_modcaps_disabled(ServerHost), ok. terminate(Host, ServerHost) -> - node_hometree_odbc:terminate(Host, ServerHost), ok. + node_flat_odbc:terminate(Host, ServerHost), ok. options() -> [{odbc, true}, {rsm, true} | node_pep:options()]. @@ -67,56 +67,56 @@ create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_pep:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - node_hometree_odbc:create_node(Nidx, Owner), + node_flat_odbc:create_node(Nidx, Owner), {result, {default, broadcast}}. delete_node(Nodes) -> - {result, {_, _, Result}} = node_hometree_odbc:delete_node(Nodes), + {result, {_, _, Result}} = node_flat_odbc:delete_node(Nodes), {result, {[], Result}}. subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + node_flat_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - case node_hometree_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of + case node_flat_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId) of {error, Error} -> {error, Error}; {result, _} -> {result, []} end. publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + node_flat_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). + node_flat_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). + node_flat_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - node_hometree_odbc:purge_node(Nidx, Owner). + node_flat_odbc:purge_node(Nidx, Owner). get_entity_affiliations(_Host, Owner) -> OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), - node_hometree_odbc:get_entity_affiliations(OwnerKey, Owner). + node_flat_odbc:get_entity_affiliations(OwnerKey, Owner). get_node_affiliations(Nidx) -> - node_hometree_odbc:get_node_affiliations(Nidx). + node_flat_odbc:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - node_hometree_odbc:get_affiliation(Nidx, Owner). + node_flat_odbc:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree_odbc:set_affiliation(Nidx, Owner, Affiliation). + node_flat_odbc:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(_Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - Host = node_hometree_odbc:encode_host(element(2, SubKey)), - SJ = node_hometree_odbc:encode_jid(SubKey), - GJ = node_hometree_odbc:encode_jid(GenKey), + Host = node_flat_odbc:encode_host(element(2, SubKey)), + SJ = node_flat_odbc:encode_jid(SubKey), + GJ = node_flat_odbc:encode_jid(GenKey), Query = case SubKey of GenKey -> [<<"select host, node, type, i.nodeid, jid, " @@ -134,11 +134,11 @@ get_entity_subscriptions(_Host, Owner) -> [<<"host">>, <<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> lists:map(fun ([H, N, T, I, J, S]) -> - O = node_hometree_odbc:decode_jid(H), + O = node_flat_odbc:decode_jid(H), Node = nodetree_tree_odbc:raw_to_node(O, [N, <<"">>, T, I]), {Node, - node_hometree_odbc:decode_subscriptions(S), - node_hometree_odbc:decode_jid(J)} + node_flat_odbc:decode_subscriptions(S), + node_flat_odbc:decode_jid(J)} end, RItems); _ -> @@ -149,9 +149,9 @@ get_entity_subscriptions(_Host, Owner) -> get_entity_subscriptions_for_send_last(_Host, Owner) -> SubKey = jlib:jid_tolower(Owner), GenKey = jlib:jid_remove_resource(SubKey), - Host = node_hometree_odbc:encode_host(element(2, SubKey)), - SJ = node_hometree_odbc:encode_jid(SubKey), - GJ = node_hometree_odbc:encode_jid(GenKey), + Host = node_flat_odbc:encode_host(element(2, SubKey)), + SJ = node_flat_odbc:encode_jid(SubKey), + GJ = node_flat_odbc:encode_jid(GenKey), Query = case SubKey of GenKey -> [<<"select host, node, type, i.nodeid, jid, " @@ -173,11 +173,11 @@ get_entity_subscriptions_for_send_last(_Host, Owner) -> [<<"host">>, <<"node">>, <<"type">>, <<"nodeid">>, <<"jid">>, <<"subscriptions">>], RItems} -> lists:map(fun ([H, N, T, I, J, S]) -> - O = node_hometree_odbc:decode_jid(H), + O = node_flat_odbc:decode_jid(H), Node = nodetree_tree_odbc:raw_to_node(O, [N, <<"">>, T, I]), {Node, - node_hometree_odbc:decode_subscriptions(S), - node_hometree_odbc:decode_jid(J)} + node_flat_odbc:decode_subscriptions(S), + node_flat_odbc:decode_jid(J)} end, RItems); _ -> @@ -186,48 +186,48 @@ get_entity_subscriptions_for_send_last(_Host, Owner) -> {result, Reply}. get_node_subscriptions(Nidx) -> - node_hometree_odbc:get_node_subscriptions(Nidx). + node_flat_odbc:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - node_hometree_odbc:get_subscriptions(Nidx, Owner). + node_flat_odbc:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). + node_flat_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> - node_hometree_odbc:get_pending_nodes(Host, Owner). + node_flat_odbc:get_pending_nodes(Host, Owner). get_states(Nidx) -> - node_hometree_odbc:get_states(Nidx). + node_flat_odbc:get_states(Nidx). get_state(Nidx, JID) -> - node_hometree_odbc:get_state(Nidx, JID). + node_flat_odbc:get_state(Nidx, JID). set_state(State) -> - node_hometree_odbc:set_state(State). + node_flat_odbc:set_state(State). get_items(Nidx, From, RSM) -> - node_hometree_odbc:get_items(Nidx, From, RSM). + node_flat_odbc:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree_odbc:get_items(Nidx, JID, AccessModel, + node_flat_odbc:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_last_items(Nidx, JID, Count) -> - node_hometree_odbc:get_last_items(Nidx, JID, Count). + node_flat_odbc:get_last_items(Nidx, JID, Count). get_item(Nidx, ItemId) -> - node_hometree_odbc:get_item(Nidx, ItemId). + node_flat_odbc:get_item(Nidx, ItemId). get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree_odbc:get_item(Nidx, ItemId, JID, AccessModel, + node_flat_odbc:get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> - node_hometree_odbc:set_item(Item). + node_flat_odbc:set_item(Item). get_item_name(Host, Node, Id) -> - node_hometree_odbc:get_item_name(Host, Node, Id). + node_flat_odbc:get_item_name(Host, Node, Id). node_to_path(Node) -> node_flat_odbc:node_to_path(Node). diff --git a/src/node_private.erl b/src/node_private.erl index eab06d56209..d27b5e29d2f 100644 --- a/src/node_private.erl +++ b/src/node_private.erl @@ -45,10 +45,10 @@ path_to_node/1]). init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts). + node_flat:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost). + node_flat:terminate(Host, ServerHost). options() -> [{deliver_payloads, true}, @@ -85,89 +85,89 @@ features() -> <<"subscription-notifications">>]. create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - node_hometree:create_node(Nidx, Owner). + node_flat:create_node(Nidx, Owner). delete_node(Removed) -> - node_hometree:delete_node(Removed). + node_flat:delete_node(Removed). subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - node_hometree:purge_node(Nidx, Owner). + node_flat:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> - node_hometree:get_entity_affiliations(Host, Owner). + node_flat:get_entity_affiliations(Host, Owner). get_node_affiliations(Nidx) -> - node_hometree:get_node_affiliations(Nidx). + node_flat:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - node_hometree:get_affiliation(Nidx, Owner). + node_flat:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree:set_affiliation(Nidx, Owner, Affiliation). + node_flat:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> - node_hometree:get_entity_subscriptions(Host, Owner). + node_flat:get_entity_subscriptions(Host, Owner). get_node_subscriptions(Nidx) -> - node_hometree:get_node_subscriptions(Nidx). + node_flat:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - node_hometree:get_subscriptions(Nidx, Owner). + node_flat:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). + node_flat:get_pending_nodes(Host, Owner). get_states(Nidx) -> - node_hometree:get_states(Nidx). + node_flat:get_states(Nidx). get_state(Nidx, JID) -> - node_hometree:get_state(Nidx, JID). + node_flat:get_state(Nidx, JID). set_state(State) -> - node_hometree:set_state(State). + node_flat:set_state(State). get_items(Nidx, From, RSM) -> - node_hometree:get_items(Nidx, From, RSM). + node_flat:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree:get_items(Nidx, JID, AccessModel, + node_flat:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> - node_hometree:get_item(Nidx, ItemId). + node_flat:get_item(Nidx, ItemId). get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + node_flat:get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> - node_hometree:set_item(Item). + node_flat:set_item(Item). get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). + node_flat:get_item_name(Host, Node, Id). node_to_path(Node) -> node_flat:node_to_path(Node). diff --git a/src/node_public.erl b/src/node_public.erl index efefd67fe45..b3f2092510c 100644 --- a/src/node_public.erl +++ b/src/node_public.erl @@ -45,10 +45,10 @@ path_to_node/1]). init(Host, ServerHost, Opts) -> - node_hometree:init(Host, ServerHost, Opts). + node_flat:init(Host, ServerHost, Opts). terminate(Host, ServerHost) -> - node_hometree:terminate(Host, ServerHost). + node_flat:terminate(Host, ServerHost). options() -> [{deliver_payloads, true}, @@ -85,89 +85,89 @@ features() -> <<"subscription-notifications">>]. create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> - node_hometree:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - node_hometree:create_node(Nidx, Owner). + node_flat:create_node(Nidx, Owner). delete_node(Removed) -> - node_hometree:delete_node(Removed). + node_flat:delete_node(Removed). subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - node_hometree:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options). unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - node_hometree:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> - node_hometree:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). remove_extra_items(Nidx, MaxItems, ItemIds) -> - node_hometree:remove_extra_items(Nidx, MaxItems, ItemIds). + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). delete_item(Nidx, Publisher, PublishModel, ItemId) -> - node_hometree:delete_item(Nidx, Publisher, PublishModel, ItemId). + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). purge_node(Nidx, Owner) -> - node_hometree:purge_node(Nidx, Owner). + node_flat:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> - node_hometree:get_entity_affiliations(Host, Owner). + node_flat:get_entity_affiliations(Host, Owner). get_node_affiliations(Nidx) -> - node_hometree:get_node_affiliations(Nidx). + node_flat:get_node_affiliations(Nidx). get_affiliation(Nidx, Owner) -> - node_hometree:get_affiliation(Nidx, Owner). + node_flat:get_affiliation(Nidx, Owner). set_affiliation(Nidx, Owner, Affiliation) -> - node_hometree:set_affiliation(Nidx, Owner, Affiliation). + node_flat:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> - node_hometree:get_entity_subscriptions(Host, Owner). + node_flat:get_entity_subscriptions(Host, Owner). get_node_subscriptions(Nidx) -> - node_hometree:get_node_subscriptions(Nidx). + node_flat:get_node_subscriptions(Nidx). get_subscriptions(Nidx, Owner) -> - node_hometree:get_subscriptions(Nidx, Owner). + node_flat:get_subscriptions(Nidx, Owner). set_subscriptions(Nidx, Owner, Subscription, SubId) -> - node_hometree:set_subscriptions(Nidx, Owner, Subscription, SubId). + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). get_pending_nodes(Host, Owner) -> - node_hometree:get_pending_nodes(Host, Owner). + node_flat:get_pending_nodes(Host, Owner). get_states(Nidx) -> - node_hometree:get_states(Nidx). + node_flat:get_states(Nidx). get_state(Nidx, JID) -> - node_hometree:get_state(Nidx, JID). + node_flat:get_state(Nidx, JID). set_state(State) -> - node_hometree:set_state(State). + node_flat:set_state(State). get_items(Nidx, From, RSM) -> - node_hometree:get_items(Nidx, From, RSM). + node_flat:get_items(Nidx, From, RSM). get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> - node_hometree:get_items(Nidx, JID, AccessModel, + node_flat:get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM). get_item(Nidx, ItemId) -> - node_hometree:get_item(Nidx, ItemId). + node_flat:get_item(Nidx, ItemId). get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - node_hometree:get_item(Nidx, ItemId, JID, AccessModel, + node_flat:get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId). set_item(Item) -> - node_hometree:set_item(Item). + node_flat:set_item(Item). get_item_name(Host, Node, Id) -> - node_hometree:get_item_name(Host, Node, Id). + node_flat:get_item_name(Host, Node, Id). node_to_path(Node) -> node_flat:node_to_path(Node). From 9aa2d92d9048fb0fd7e1ec9d443aab8be7d33a8f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Jul 2015 10:48:44 +0200 Subject: [PATCH 166/695] Allow include of simple dependencies (EJAB-1737)(#391) Either contributed module include dependencies this way deps/ dep1/ src/ include/ dep1/ src/ include/ Or includes rebar.config or rebar.config.script: In this case, only git is supported (if git command available) and ext_mod checkout code in deps directory. In both case, only basic built procedure is supported. ext_mod does not do more than bare compilation like this: erlc -I include src/*erl --- src/ext_mod.erl | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index bfc448dcfa1..070fdf9d3d4 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -445,9 +445,14 @@ compile_and_install(Module, Spec) -> true -> {ok, Dir} = file:get_cwd(), file:set_cwd(SrcDir), - Result = case compile(Module, Spec, LibDir) of - ok -> install(Module, Spec, LibDir); - Error -> Error + Result = case compile_deps(Module, Spec, LibDir) of + ok -> + case compile(Module, Spec, LibDir) of + ok -> install(Module, Spec, LibDir); + Error -> Error + end; + Error -> + Error end, file:set_cwd(Dir), Result; @@ -459,6 +464,35 @@ compile_and_install(Module, Spec) -> end end. +compile_deps(_Module, _Spec, DestDir) -> + case filelib:is_dir("deps") of + true -> ok; + false -> fetch_rebar_deps() + end, + Ebin = filename:join(DestDir, "ebin"), + filelib:ensure_dir(filename:join(Ebin, ".")), + Result = lists:foldl(fun(Dep, Acc) -> + Inc = filename:join(Dep, "include"), + Src = filename:join(Dep, "src"), + Options = [{outdir, Ebin}, {i, Inc}], + [file:copy(App, Ebin) || App <- filelib:wildcard(Src++"/*.app")], + Acc++[case compile:file(File, Options) of + {ok, _} -> ok; + {ok, _, _} -> ok; + {ok, _, _, _} -> ok; + error -> {error, {compilation_failed, File}}; + Error -> Error + end + || File <- filelib:wildcard(Src++"/*.erl")] + end, [], filelib:wildcard("deps/*")), + case lists:dropwhile( + fun(ok) -> true; + (_) -> false + end, Result) of + [] -> ok; + [Error|_] -> Error + end. + compile(_Module, _Spec, DestDir) -> Ebin = filename:join(DestDir, "ebin"), filelib:ensure_dir(filename:join(Ebin, ".")), @@ -470,6 +504,7 @@ compile(_Module, _Spec, DestDir) -> Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc}, verbose, report_errors, report_warnings] ++ Logger ++ ExtLib, + [file:copy(App, Ebin) || App <- filelib:wildcard("src/*.app")], Result = [case compile:file(File, Options) of {ok, _} -> ok; {ok, _, _} -> ok; @@ -504,6 +539,42 @@ install(Module, Spec, DestDir) -> Error -> Error end. +%% -- minimalist rebar spec parser, only support git + +fetch_rebar_deps() -> + case rebar_deps("rebar.config")++rebar_deps("rebar.config.script") of + [] -> + ok; + Deps -> + filelib:ensure_dir(filename:join("deps", ".")), + lists:foreach(fun({_App, Cmd}) -> + os:cmd("cd deps; "++Cmd++"; cd ..") + end, Deps) + end. +rebar_deps(Script) -> + case file:script(Script) of + {ok, Config} when is_list(Config) -> + [rebar_dep(Dep) || Dep <- proplists:get_value(deps, Config, [])]; + {ok, {deps, Deps}} -> + [rebar_dep(Dep) || Dep <- Deps]; + _ -> + [] + end. +rebar_dep({App, _, {git, Url}}) -> + {App, "git clone "++Url++" "++filename:basename(App)}; +rebar_dep({App, _, {git, Url, {branch, Ref}}}) -> + {App, "git clone -n "++Url++" "++filename:basename(App)++ + "; (cd "++filename:basename(App)++ + "; git checkout -q origin/"++Ref++")"}; +rebar_dep({App, _, {git, Url, {tag, Ref}}}) -> + {App, "git clone -n "++Url++" "++filename:basename(App)++ + "; (cd "++filename:basename(App)++ + "; git checkout -q "++Ref++")"}; +rebar_dep({App, _, {git, Url, Ref}}) -> + {App, "git clone -n "++Url++" "++filename:basename(App)++ + "; (cd "++filename:basename(App)++ + "; git checkout -q "++Ref++")"}. + %% -- YAML spec parser consult(File) -> From 9091fcb1a1d835f9c693656212fe5fe874379fb7 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 22 Jul 2015 11:20:06 +0200 Subject: [PATCH 167/695] Let nodetree call default flat plugin now this fix mistake from previous commit 311fedaa --- src/nodetree_tree_odbc.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nodetree_tree_odbc.erl b/src/nodetree_tree_odbc.erl index 38fb51c2afd..038dc472cdc 100644 --- a/src/nodetree_tree_odbc.erl +++ b/src/nodetree_tree_odbc.erl @@ -66,7 +66,7 @@ set_node(Record) when is_record(Record, pubsub_node) -> [First | _] -> First end, Type = Record#pubsub_node.type, - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), N = ejabberd_odbc:escape(Node), P = ejabberd_odbc:escape(Parent), Nidx = case nodeidx(Host, Node) of @@ -116,7 +116,7 @@ get_node(Host, Node, _From) -> get_node(Host, Node). get_node(Host, Node) -> - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), N = ejabberd_odbc:escape(Node), case catch ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " @@ -151,7 +151,7 @@ get_nodes(Host, _From) -> get_nodes(Host). get_nodes(Host) -> - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), case catch ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " "pubsub_node where host='">>, H, <<"';">>]) @@ -178,7 +178,7 @@ get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). get_subnodes(Host, Node) -> - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), N = ejabberd_odbc:escape(Node), case catch ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " @@ -196,7 +196,7 @@ get_subnodes_tree(Host, Node, _From) -> get_subnodes_tree(Host, Node). get_subnodes_tree(Host, Node) -> - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), N = ejabberd_odbc:escape(Node), case catch ejabberd_odbc:sql_query_t([<<"select node, parent, type, nodeid from " @@ -256,7 +256,7 @@ create_node(Host, Node, Type, Owner, Options, Parents) -> end. delete_node(Host, Node) -> - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), N = ejabberd_odbc:escape(Node), Removed = get_subnodes_tree(Host, Node), catch ejabberd_odbc:sql_query_t([<<"delete from pubsub_node where host='">>, @@ -295,7 +295,7 @@ raw_to_node(Host, [Node, Parent, Type, Nidx]) -> id = Nidx, type = Type, options = Options}. nodeidx(Host, Node) -> - H = node_hometree_odbc:encode_host(Host), + H = node_flat_odbc:encode_host(Host), N = ejabberd_odbc:escape(Node), case catch ejabberd_odbc:sql_query_t([<<"select nodeid from pubsub_node where " @@ -311,5 +311,5 @@ nodeidx(Host, Node) -> end. nodeowners(Nidx) -> - {result, Res} = node_hometree_odbc:get_node_affiliations(Nidx), + {result, Res} = node_flat_odbc:get_node_affiliations(Nidx), [LJID || {LJID, Aff} <- Res, Aff =:= owner]. From 8df134e02577503cf331f7c11c438a9577a93f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 22 Jul 2015 11:54:11 +0200 Subject: [PATCH 168/695] Don't crash web admin when displaying info about websocket using users --- src/ejabberd_c2s.erl | 1 + src/ejabberd_web_admin.erl | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f982f911584..e6f55c48993 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2025,6 +2025,7 @@ get_conn_type(StateData) -> p1_tls -> c2s_compressed_tls end; ejabberd_http_bind -> http_bind; + ejabberd_http_ws -> websocket; _ -> unknown end. diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 3347f3e6eb8..75313de2b60 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1557,7 +1557,11 @@ user_info(User, Server, Query, Lang) -> c2s_compressed_tls -> <<"tls+zlib">>; http_bind -> - <<"http-bind">> + <<"http-bind">>; + websocket -> + <<"websocket">>; + _ -> + <<"unknown">> end, < Date: Thu, 23 Jul 2015 13:16:15 +0200 Subject: [PATCH 169/695] Provide command for ODBC's convert_to_scram --- src/ejabberd_admin.erl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 89421d99622..a0b32304fc8 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -167,6 +167,10 @@ commands() -> desc = "Export all tables as SQL queries to a file", module = ejd2odbc, function = export, args = [{host, string}, {file, string}], result = {res, rescode}}, + #ejabberd_commands{name = convert_to_scram, tags = [odbc], + desc = "Convert the passwords in 'users' ODBC table to SCRAM", + module = ejabberd_auth_odbc, function = convert_to_scram, + args = [{host, binary}], result = {res, rescode}}, #ejabberd_commands{name = convert_to_yaml, tags = [config], desc = "Convert the input file from Erlang to YAML format", From 8fedc945bfc1a470a616e7a503d1672ba1f8e6ef Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 24 Jul 2015 13:44:01 +0200 Subject: [PATCH 170/695] Allow migration of old pubsub items with xmlelement in body (#479) --- src/pubsub_migrate.erl | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/pubsub_migrate.erl b/src/pubsub_migrate.erl index e48efcd494d..dc01b9af66b 100644 --- a/src/pubsub_migrate.erl +++ b/src/pubsub_migrate.erl @@ -29,7 +29,8 @@ -include("pubsub.hrl"). -include("logger.hrl"). --export([update_node_database/2, update_state_database/2, update_lastitem_database/2]). +-export([update_node_database/2, update_state_database/2]). +-export([update_item_database/2, update_lastitem_database/2]). update_item_database_binary() -> F = fun () -> @@ -57,6 +58,27 @@ update_item_database_binary() -> ?INFO_MSG("Pubsub items table has been binarized: ~p", [Result]) end. +update_item_database(_Host, _ServerHost) -> + F = fun() -> + ?INFO_MSG("Migration of old pubsub items...", []), + lists:foreach(fun (Key) -> + [Item] = mnesia:read({pubsub_item, Key}), + Payload = [xmlelement_to_xmlel(El) || El <- Item#pubsub_item.payload], + mnesia:write(Item#pubsub_item{payload=Payload}) + end, + mnesia:all_keys(pubsub_item)) + end, + case mnesia:transaction(F) of + {aborted, Reason} -> + ?ERROR_MSG("Failed to migrate old pubsub items to xmlel: ~p", [Reason]); + {atomic, Result} -> + ?INFO_MSG("Pubsub items has been migrated: ~p", [Result]) + end. + +xmlelement_to_xmlel({xmlelement, A, B, C}) when is_list(C) -> + {xmlel, A, B, [xmlelement_to_xmlel(El) || El <- C]}; +xmlelement_to_xmlel(El) -> + El. update_node_database_binary() -> F = fun () -> From 32fc586c08dc4d80cfb7dda33ae5e6a370cc6f9f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 24 Jul 2015 14:30:31 +0200 Subject: [PATCH 171/695] Allow contribution to include .yml or .yaml config file --- src/ejabberd_config.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 81a87a648d8..18abf40ce9e 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -206,7 +206,7 @@ get_plain_terms_file(File1, Opts) -> BinTerms1 = strings_to_binary(Terms), ModInc = case proplists:get_bool(include_modules_configs, Opts) of true -> - filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.yaml"); + filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.{yml,yaml}"); _ -> [] end, From e211bf713122322562d950439a7d24c00ff82ed5 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 24 Jul 2015 15:09:57 +0200 Subject: [PATCH 172/695] Ensure config snippet is loaded at module installation (EJAB-1741) --- src/ext_mod.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 070fdf9d3d4..002c5dd9161 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -164,6 +164,7 @@ install(Package) when is_binary(Package) -> case compile_and_install(Module, Attrs) of ok -> code:add_patha(module_ebin_dir(Module)), + ejabberd_config:reload_file(), ok; Error -> delete_path(module_lib_dir(Module)), @@ -182,7 +183,8 @@ uninstall(Package) when is_binary(Package) -> code:purge(Module), code:delete(Module), code:del_path(module_ebin_dir(Module)), - delete_path(module_lib_dir(Module)); + delete_path(module_lib_dir(Module)), + ejabberd_config:reload_file(); false -> {error, not_installed} end. From 76104cd117126a2ac8b20b2ddcce4ec6ff12004a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 24 Jul 2015 15:45:29 +0200 Subject: [PATCH 173/695] Fix problem with merging values from multiple config files --- src/ejabberd_config.erl | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 18abf40ce9e..2ea4c36e9e9 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -385,18 +385,19 @@ include_config_files(Terms) -> include_config_file(File, Opts) end, lists:flatten(FileOpts)), - SpecialTerms = dict:from_list([{hosts, none}, {listen, none}, {modules, none}]), + SpecialTerms = dict:from_list([{hosts, []}, {listen, []}, {modules, []}]), + PartDict = dict:store(rest, [], SpecialTerms), Partition = fun(L) -> lists:foldr(fun({Name, Val} = Pair, Dict) -> case dict:find(Name, SpecialTerms) of {ok, _} -> - dict:store(Name, Val, Dict); + dict:append_list(Name, Val, Dict); _ -> - dict:update(rest, fun(L1) -> [Pair|L1] end, Dict) + dict:append(rest, Pair, Dict) end; (Tuple, Dict2) -> - dict:update(rest, fun(L2) -> [Tuple|L2] end, Dict2) - end, dict:from_list([{rest, []}]), L) + dict:append(rest, Tuple, Dict2) + end, PartDict, L) end, Merged = dict:merge(fun(_Name, V1, V2) -> V1 ++ V2 end, From d03d08539ba19d349542ba6d72a3b511af473b41 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 27 Jul 2015 11:23:51 +0200 Subject: [PATCH 174/695] Reuse some strings in WebAdmin's Listening Ports --- src/ejabberd_web_admin.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 75313de2b60..45ad7b6dc54 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -2399,11 +2399,11 @@ node_ports_to_xhtml(Ports, Lang) -> ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"add", SSPort/binary>>, - <<"Update">>)]), + <<"Restart">>)]), ?XE(<<"td">>, [?INPUTT(<<"submit">>, <<"delete", SSPort/binary>>, - <<"Delete">>)])]) + <<"Stop">>)])]) end, Ports) ++ @@ -2423,7 +2423,7 @@ node_ports_to_xhtml(Ports, Lang) -> <<"[]">>)]), ?XAE(<<"td">>, [{<<"colspan">>, <<"2">>}], [?INPUTT(<<"submit">>, <<"addnew">>, - <<"Add New">>)])])]))]). + <<"Start">>)])])]))]). make_netprot_html(NetProt) -> ?XAE(<<"select">>, [{<<"name">>, <<"netprotnew">>}], From 5305b4a82c4b72107b8d75a72799ed49ef09b4cc Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 27 Jul 2015 11:41:38 +0200 Subject: [PATCH 175/695] Updated Hebrew translation (thanks to Isratine Citizen) --- priv/msgs/he.po | 1066 +++++++++++++++++++++++------------------------ 1 file changed, 532 insertions(+), 534 deletions(-) diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 0fc6f8ed65d..5109c1b9a85 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -12,868 +12,847 @@ msgstr "" "X-Language: Hebrew\n" "X-Poedit-Language: Hebrew (עברית)\n" "X-Generator: Poedit 1.5.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Source-Language: en\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:522 ejabberd_c2s.erl:869 msgid "Use of STARTTLS required" msgstr "נדרש שימוש של STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:620 msgid "No resource provided" msgstr "לא סופק משאב" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1395 msgid "Replaced by new connection" msgstr "הוחלף בחיבור חדש" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1399 mod_configure.erl:1854 mod_muc_log.erl:476 +#: mod_muc_log.erl:479 msgid "has been kicked" msgstr "נבעט/ה" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2484 msgid "Too many unacked stanzas" -msgstr "" +msgstr "יותר מדי סטנזות בלי אישורי קבלה" # תמליל # כפי שעינייך רואות -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "הזן את הטקסט אותו הינך רואה" # כדי שלא לחסומן -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" -msgstr "ההודעות שלך לערוץ ~s הינן חסומות. כדי למנוע את חסימתן, בקר בכתובת ~s" +msgstr "ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s" # בקר את עמוד -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "במידה ואינך רואה תמונת CAPTCHA כאן, בקר בעמוד הרשת." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "עמוד רשת CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "‏CAPTCHA הינה בתוקף." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "לא מורשה" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "מנהל רשת ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:600 ejabberd_web_admin.erl:611 msgid "Administration" msgstr "הנהלה" -# כניסה אל בקרת רשימות -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:668 ejabberd_web_admin.erl:704 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "רשימות בקרת גישה" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:672 ejabberd_web_admin.erl:708 +#: ejabberd_web_admin.erl:774 ejabberd_web_admin.erl:807 +#: ejabberd_web_admin.erl:848 ejabberd_web_admin.erl:1324 +#: ejabberd_web_admin.erl:1609 ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1803 ejabberd_web_admin.erl:1883 +#: ejabberd_web_admin.erl:2053 ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2179 mod_offline.erl:795 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" -msgstr "" +msgstr "נשלח" # פגום -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 +#: ejabberd_web_admin.erl:849 ejabberd_web_admin.erl:1325 +#: ejabberd_web_admin.erl:1610 ejabberd_web_admin.erl:1770 +#: ejabberd_web_admin.erl:2054 ejabberd_web_admin.erl:2083 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "פורמט רע" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:684 ejabberd_web_admin.erl:721 +#: ejabberd_web_admin.erl:786 ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:1872 mod_shared_roster.erl:1274 msgid "Submit" -msgstr "שליחה" +msgstr "שלח" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:713 ejabberd_web_admin.erl:812 msgid "Raw" -msgstr "" +msgstr "גולמי" # נבחרים -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:818 mod_offline.erl:817 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "מחק נבחרות" # חוקי -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:770 ejabberd_web_admin.erl:803 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "כללי גישה" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:844 msgid "~s access rule configuration" msgstr "~s תצורת כללי גישה" # וירטואליים -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:862 msgid "Virtual Hosts" msgstr "מארחים מדומים" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:871 ejabberd_web_admin.erl:879 msgid "Users" msgstr "משתמשים" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:886 ejabberd_web_admin.erl:1270 +#: mod_configure.erl:524 msgid "Online Users" msgstr "משתמשים מקוונים" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:902 msgid "Users Last Activity" msgstr "פעילות משתמשים אחרונה" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:906 msgid "Period: " msgstr "משך זמן: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:919 msgid "Last month" msgstr "חודש אחרון" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:920 msgid "Last year" msgstr "שנה אחרונה" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:922 msgid "All activity" msgstr "כל פעילות" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:925 msgid "Show Ordinary Table" msgstr "הצג טבלה רגילה" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:928 msgid "Show Integral Table" msgstr "הצג טבלה אינטגרלית" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:935 ejabberd_web_admin.erl:1780 +#: mod_muc_admin.erl:245 msgid "Statistics" msgstr "סטטיסטיקה" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:945 msgid "Not Found" msgstr "לא נמצא" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:958 msgid "Node not found" -msgstr "ממסר לא נמצא" +msgstr "צומת לא נמצא" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1180 mod_shared_roster.erl:1166 msgid "Add New" msgstr "הוסף חדש" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1268 msgid "Host" msgstr "מארח" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1269 msgid "Registered Users" msgstr "משתמשים רשומים" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1333 ejabberd_web_admin.erl:1388 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "משתמש" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1338 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3353 +#: mod_register.erl:272 msgid "Password" msgstr "סיסמה" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1347 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "הוסף משתמש" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1389 msgid "Offline Messages" msgstr "הודעות לא מקוונות" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1390 ejabberd_web_admin.erl:1620 msgid "Last Activity" msgstr "פעילות אחרונה" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1408 ejabberd_web_admin.erl:1592 +#: mod_configure.erl:1917 msgid "Never" msgstr "אף פעם" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1426 ejabberd_web_admin.erl:1603 +#: mod_configure.erl:1927 msgid "Online" msgstr "מקוון" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1482 ejabberd_web_admin.erl:1501 msgid "Registered Users:" msgstr "משתמשים רשומים:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1485 ejabberd_web_admin.erl:1504 +#: ejabberd_web_admin.erl:2120 msgid "Online Users:" msgstr "משתמשים מקוונים:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1488 msgid "Outgoing s2s Connections:" msgstr "חיבורי s2s יוצאים:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1491 msgid "Outgoing s2s Servers:" msgstr "שרתי s2s יוצאים:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 -#, fuzzy +#: ejabberd_web_admin.erl:1527 ejabberd_web_admin.erl:1727 +#: ejabberd_web_admin.erl:1737 ejabberd_web_admin.erl:2147 mod_roster.erl:1430 msgid "None" -msgstr "ללא" +msgstr "אין" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1584 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "שנה סיסמה" -#: ejabberd_web_admin.erl:1596 -#, fuzzy +#: ejabberd_web_admin.erl:1605 msgid "User ~s" -msgstr "משתמש " +msgstr "משתמש ~s" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1616 msgid "Connected Resources:" msgstr "משאבים מחוברים:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1618 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "סיסמה:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1625 mod_configure.erl:2118 msgid "Remove User" msgstr "הסר משתמש" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1673 msgid "No Data" msgstr "אין מידע" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1746 msgid "Nodes" -msgstr "ממסרים" +msgstr "צמתים" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1747 mod_configure.erl:528 msgid "Running Nodes" -msgstr "ממסרים שמורצים כעת" +msgstr "צמתים מורצים" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1748 mod_configure.erl:529 msgid "Stopped Nodes" -msgstr "ממסרים שנפסקו" +msgstr "צמתים שנפסקו" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 -#, fuzzy +#: ejabberd_web_admin.erl:1766 ejabberd_web_admin.erl:1791 msgid "Node ~p" -msgstr "ממסר" +msgstr "צומת ~p" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1775 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "מסד נתונים" -# גיבוי -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1776 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" -msgstr "גבה" +msgstr "גיבוי" -#: ejabberd_web_admin.erl:1769 -#, fuzzy +#: ejabberd_web_admin.erl:1778 msgid "Listened Ports" msgstr "פורטים מואזנים" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1781 ejabberd_web_admin.erl:2194 msgid "Update" msgstr "עדכן" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1785 ejabberd_web_admin.erl:2402 +#: ejabberd_web_admin.erl:2546 msgid "Restart" msgstr "אתחל" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1787 ejabberd_web_admin.erl:2406 +#: ejabberd_web_admin.erl:2550 msgid "Stop" msgstr "הפסק" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1794 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "מודולים" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1799 msgid "RPC Call Error" msgstr "שגיאת קריאת RPC" -#: ejabberd_web_admin.erl:1841 -#, fuzzy +#: ejabberd_web_admin.erl:1850 msgid "Database Tables at ~p" -msgstr "טבלאות מסד נתונים אצל " +msgstr "טבלאות מסד נתונים אצל ~p" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1860 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "שם" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1861 msgid "Storage Type" msgstr "טיפוס אחסון" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1862 msgid "Elements" msgstr "אלמנטים" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1863 msgid "Memory" msgstr "זיכרון" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1885 ejabberd_web_admin.erl:2056 msgid "Error" msgstr "שגיאה" -#: ejabberd_web_admin.erl:1879 -#, fuzzy +#: ejabberd_web_admin.erl:1888 msgid "Backup of ~p" -msgstr "גיבוי של " +msgstr "גיבוי של ~p" # האינטגרלי לחוד -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1892 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " "separately." msgstr "" -"נא לשים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך " +"אנא שים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך " "עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך " "בנפרד." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1902 msgid "Store binary backup:" msgstr "אחסן גיבוי בינארי:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1909 ejabberd_web_admin.erl:1919 +#: ejabberd_web_admin.erl:1930 ejabberd_web_admin.erl:1939 +#: ejabberd_web_admin.erl:1949 ejabberd_web_admin.erl:1962 +#: ejabberd_web_admin.erl:1974 ejabberd_web_admin.erl:1990 +#: ejabberd_web_admin.erl:2006 ejabberd_web_admin.erl:2017 +#: ejabberd_web_admin.erl:2027 msgid "OK" msgstr "אישור" # ללא דיחוי -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1912 msgid "Restore binary backup immediately:" msgstr "שחזר גיבוי בינארי לאלתר:" # לאחר אתחול בא של -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1922 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "שחזר גיבוי בינארי לאחר האתחול הבא של ejabberd (מצריך פחות זיכרון):" # תמליל ברור -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1932 msgid "Store plain text backup:" msgstr "אחסן גיבוי טקסט גלוי (plain text):" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1942 msgid "Restore plain text backup immediately:" msgstr "שחזר גיבוי טקסט גלוי (plain text) לאלתר:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1952 msgid "Import users data from a PIEFXIS file (XEP-0227):" -msgstr "ייבוא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):" +msgstr "יבא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1965 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" -msgstr "" -"ייצוא מידע של כל המשתמשים אשר מצויים בשרת זה אל קבצי PIEFXIS (‫XEP-0227):" +msgstr "יצא מידע של כל המשתמשים שבתוך בשרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1977 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" -msgstr "ייצוא מידע של כל המשתמשים בתוך מארח אל קבצי PIEFXIS (‫XEP-0227):" +msgstr "יצא מידע של כל המשתמשים שבתוך מארח לתוך קבצי PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1993 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "יצא את כל טבלאות בתור שאילתות SQL לתוך קובץ:" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2009 msgid "Import user data from jabberd14 spool file:" -msgstr "ייבוא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:" +msgstr "יבא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2020 msgid "Import users data from jabberd14 spool directory:" -msgstr "ייבוא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:" +msgstr "יבא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:" -#: ejabberd_web_admin.erl:2041 -#, fuzzy +#: ejabberd_web_admin.erl:2048 msgid "Listened Ports at " msgstr "פורטים מואזנים אצל " -#: ejabberd_web_admin.erl:2070 -#, fuzzy +#: ejabberd_web_admin.erl:2077 msgid "Modules at ~p" -msgstr "מודולים אצל " +msgstr "מודולים אצל ~p" -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2108 msgid "Statistics of ~p" -msgstr "סטטיסטיקות עבור ~p" +msgstr "סטטיסטיקות של ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2112 msgid "Uptime:" msgstr "זמן פעילות:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2116 msgid "CPU Time:" msgstr "זמן מחשב (CPU):" # זיכרון דברים (דיני חוזים) -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2124 msgid "Transactions Committed:" -msgstr "טרנזקציות בוצעו:" +msgstr "טרנזקציות שבוצעו:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2128 msgid "Transactions Aborted:" -msgstr "טרנזקציות בוטלו:" +msgstr "טרנזקציות שבוטלו:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2132 msgid "Transactions Restarted:" -msgstr "טרנזקציות הותחלו מחדש:" +msgstr "טרנזקציות שהותחלו מחדש:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2136 msgid "Transactions Logged:" -msgstr "טרנזקציות נרשמו:" +msgstr "טרנזקציות שנרשמו:" -#: ejabberd_web_admin.erl:2169 -#, fuzzy +#: ejabberd_web_admin.erl:2176 msgid "Update ~p" -msgstr "עדכן" +msgstr "עדכון ~p" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2187 msgid "Update plan" -msgstr "" +msgstr "תכנית עדכון" # adjusted -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2188 msgid "Modified modules" msgstr "מודולים שהותאמו" -# תסריט עדכון -#: ejabberd_web_admin.erl:2182 -#, fuzzy +#: ejabberd_web_admin.erl:2189 msgid "Update script" -msgstr "עדכן תסריט" +msgstr "תסריט עדכון" -#: ejabberd_web_admin.erl:2183 -#, fuzzy +#: ejabberd_web_admin.erl:2190 msgid "Low level update script" msgstr "תסריט עדכון Low level" -#: ejabberd_web_admin.erl:2184 -#, fuzzy +#: ejabberd_web_admin.erl:2191 msgid "Script check" -msgstr "תסריט בדיקה" +msgstr "בדיקת תסריט" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2371 msgid "IP" msgstr "‫IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2371 msgid "Port" msgstr "פורט" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2372 msgid "Protocol" msgstr "פרוטוקול" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2373 ejabberd_web_admin.erl:2528 msgid "Module" msgstr "מודול" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2374 ejabberd_web_admin.erl:2529 msgid "Options" msgstr "אפשרויות" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "מחק" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2426 ejabberd_web_admin.erl:2562 msgid "Start" msgstr "התחל" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "פקודות" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "פינג" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "פונג" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" -msgstr "באמת למחוק את הודעת היום?" +msgstr "באמת למחוק את בשורת היום?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "נושא" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "גוף הודעה" -#: mod_announce.erl:636 -#, fuzzy +#: mod_announce.erl:627 msgid "No body provided for announce message" -msgstr "לא סופק גוף עבור announce message" +msgstr "לא סופק גוף עבור הודעת בשורה" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" -msgstr "מודעות" +msgstr "בשורות" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" -msgstr "שלח מודעות אל כל המשתמשים" +msgstr "שלח בשורה לכל המשתמשים" # אצל כל -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" -msgstr "שלח מודעות אל כל המשתמשים בכל המארחים" +msgstr "שלח בשורה לכל המשתמשים בכל המארחים" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" -msgstr "שלח מודעות אל כל המשתמשים המקוונים" +msgstr "שלח בשורה לכל המשתמשים המקוונים" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" -msgstr "שלח מודעות אל כל המשתמשים המקוונים בכל המארחים" +msgstr "שלח בשורה לכל המשתמשים המקוונים בכל המארחים" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" -msgstr "קבע הודעת היום ושלח אל משתמשים מקוונים" +msgstr "קבע את בשורת היום ושלח למשתמשים מקוונים" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" -msgstr "קבע הודעת היום בכל המארחים ושלח אל משתמשים מקוונים" +msgstr "קבע את בשורת היום בכל המארחים ושלח למשתמשים מקוונים" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" -msgstr "עדכן הודעת היום (אל תשלח)" +msgstr "עדכן את בשורת היום (אל תשלח)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" -msgstr "עדכן הודעת היום בכל המארחים (אל תשלח)" +msgstr "עדכן את בשורת היום בכל המארחים (אל תשלח)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" -msgstr "מחק הודעת היום" +msgstr "מחק את בשורת היום" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" -msgstr "מחק הודעת היום בכל המארחים" +msgstr "מחק את בשורת היום בכל המארחים" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "תצורה" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "התחל מודולים" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "הפסק מודולים" # שחזור -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "שחזר" # הטל אל קובץ תמליל -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" -msgstr "השלך אל קובץ טקסט" +msgstr "השלך לקובץ טקסט" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "ייבוא קובץ" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "ייבוא מדור" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "אתחל שירות" # שירות כיבוי -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "כבה שירות" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "מחק משתמש" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "סיים סשן משתמש" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "השג סיסמת משתמש" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "שנה סיסמת משתמש" # התחברות -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "השג זמן כניסה אחרון של משתמש" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "השג סטטיסטיקת משתמש" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "השג מספר של משתמשים רשומים" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "השג מספר של משתמשים מקוונים" # הנהלת -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ניהול משתמשים" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "כל המשתמשים" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "חיבורי s2s יוצאים" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "ניהול גיבוי" -# help is needed with spool -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" -msgstr "ייבוא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14" +msgstr "יבא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "אל ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "מאת ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "תצורת טבלאות מסד נתונים אצל " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "בחר טיפוס אחסון של טבלאות" # Typo: Disk (unsure) -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "העתק של תקליטור בלבד" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "העתק RAM וגם תקליטור" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "העתק RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" -msgstr "עותק מרוחק" +msgstr "העתק מרוחק" -# at (time)? -# בשעה -#: mod_configure.erl:1046 -#, fuzzy +# at (time)? בשעה +#: mod_configure.erl:1045 msgid "Stop Modules at " -msgstr "הפסק מודולים at " +msgstr "הפסק מודולים אצל " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "בחר מודולים להפסקה" -#: mod_configure.erl:1073 -#, fuzzy +# at (time)? בשעה +#: mod_configure.erl:1072 msgid "Start Modules at " -msgstr "התחל מודולים at " +msgstr "התחל מודולים אצל " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "הזן רשימה של {מודול, [אפשרויות]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "רשימה של מודולים להפעלה" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " -msgstr "גבה אל קובץ אצל " +msgstr "גבה לקובץ אצל " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" -msgstr "הזן נתיב אל קובץ גיבוי" +msgstr "הזן נתיב לקובץ גיבוי" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" -msgstr "נתיב אל קובץ" +msgstr "נתיב לקובץ" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "שחזר גיבוי מתוך קובץ אצל " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " -msgstr "השלך גיבוי אל קובץ טקסט אצל " +msgstr "השלך גיבוי לקובץ טקסט אצל " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" -msgstr "הזן נתיב אל קובץ טקסט" +msgstr "הזן נתיב לקובץ טקסט" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "ייבוא משתמש מתוך קובץ אצל " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" -msgstr "הזן נתיב אל קובץ סליל (spool file) של jabberd14" +msgstr "הזן נתיב לקובץ סליל (spool file) של jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "ייבוא משתמשים מתוך מדור אצל " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" -msgstr "הזן נתיב אל מדור סליל (spool dir) של jabberd14" +msgstr "הזן נתיב למדור סליל (spool dir) של jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" -msgstr "נתיב אל מדור" +msgstr "נתיב למדור" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "זמן שיהוי" -# כניסה אל תצורת בקרת רשימה -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "תצורת רשימת בקרת גישה" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "רשימות בקרת גישה" -# כניסה אל תצורה -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "תצורת גישה" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "כללי גישה" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "מזהה Jabber" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "אימות סיסמה" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "מספר של משתמשים רשומים" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "מספר של משתמשים מקוונים" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "כניסה אחרונה" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "גודל רשימה" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "כתובות IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "משאבים" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "ניהול של " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "פעולה על משתמש" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "ערוך מאפיינים" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה " +"בשעה ~s UTC" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "כתובת IP זו רשומה ברשימה שחורה בתוך ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -896,8 +875,8 @@ msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -"הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לשם התחברות אל " -"שרתים של IRC" +"הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לצורך התחברות לשרתי " +"IRC" #: mod_irc.erl:659 msgid "IRC Username" @@ -929,7 +908,7 @@ msgstr "פרמטרים של חיבור" #: mod_irc.erl:874 msgid "Join IRC channel" -msgstr "הצטרף אל ערוץ IRC" +msgstr "הצטרף לערוץ IRC" # לא לשים סימן # ראשון # לא לשים את סימן # הראשון @@ -943,11 +922,11 @@ msgstr "שרת IRC" #: mod_irc.erl:938 mod_irc.erl:946 msgid "Join the IRC channel here." -msgstr "הצטרף אל ערוץ IRC כאן." +msgstr "הצטרף לערוץ IRC כאן." #: mod_irc.erl:955 msgid "Join the IRC channel in this Jabber ID: ~s" -msgstr "הצטרף אל ערוץ IRC במזהה Jabber זה: ~s" +msgstr "הצטרף לערוץ IRC במזהה Jabber זה: ~s" #: mod_irc.erl:1034 msgid "IRC settings" @@ -960,8 +939,8 @@ msgid "" "Press 'Next' to get more fields to fill in. Press 'Complete' to save " "settings." msgstr "" -"הזן שם משתמש וקידודים בהם ברצונך להשתמש לשם התחברות אל שרתים של IRC. לחץ " -"'הבא' כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות." +"הזן שם משתמש וקידודים בהם ברצונך להשתמש לצורך התחברות לשרתי IRC. לחץ 'הבא' " +"כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות." #: mod_irc.erl:1048 msgid "IRC username" @@ -983,504 +962,524 @@ msgstr "קידוד עבור שרת ~b" msgid "Server ~b" msgstr "שרת ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:776 mod_muc_admin.erl:319 msgid "Chatrooms" msgstr "חדרי שיחה" # to register nickname -#: mod_muc.erl:914 +#: mod_muc.erl:969 msgid "You need a client that supports x:data to register the nickname" msgstr "עליך להשתמש בלקוח אשר תומך x:data בכדי לרשום את שם הכינוי" -#: mod_muc.erl:924 +#: mod_muc.erl:979 msgid "Nickname Registration at " msgstr "רישום שם כינוי אצל " # אותו ברצונך לרשום -#: mod_muc.erl:930 +#: mod_muc.erl:985 msgid "Enter nickname you want to register" msgstr "הזן שם כינוי אשר ברצונך לרושמו" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:986 mod_muc_room.erl:4228 mod_roster.erl:1436 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "שם כינוי" -#: mod_muc.erl:1094 +#: mod_muc.erl:1149 msgid "ejabberd MUC module" msgstr "מודול MUC של ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:229 mod_muc_admin.erl:232 mod_muc_admin.erl:244 +#: mod_muc_admin.erl:318 +msgid "Multi-User Chat" +msgstr "שיחה מרובת משתמשים" + +#: mod_muc_admin.erl:247 +msgid "Total rooms" +msgstr "חדרים סה״כ" + +#: mod_muc_admin.erl:248 +msgid "Permanent rooms" +msgstr "חדרים קבועים" + +#: mod_muc_admin.erl:249 +msgid "Registered nicknames" +msgstr "שמות כינוי רשומים" + +#: mod_muc_admin.erl:252 +msgid "List of rooms" +msgstr "רשימה של חדרים" + +#: mod_muc_log.erl:447 mod_muc_log.erl:456 msgid "Chatroom configuration modified" msgstr "תצורת חדר שיחה שונתה" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:459 msgid "joins the room" msgstr "נכנס/ת אל החדר" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:462 mod_muc_log.erl:465 msgid "leaves the room" -msgstr "עוזב/ת אל החדר" +msgstr "עוזב/ת את החדר" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:469 mod_muc_log.erl:472 msgid "has been banned" msgstr "נאסר/ה" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:484 msgid "has been kicked because of an affiliation change" msgstr "נבעט/ה משום שינוי סינוף" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:489 msgid "has been kicked because the room has been changed to members-only" msgstr "נבעט/ה משום שהחדר שונה אל חברים-בלבד" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:494 msgid "has been kicked because of a system shutdown" msgstr "נבעט/ה משום כיבוי מערכת" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:499 msgid "is now known as" msgstr "ידועה כעת בכינוי" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:502 mod_muc_log.erl:841 msgid " has set the subject to: " msgstr " הגדיר/ה את הנושא אל: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:542 msgid "Chatroom is created" -msgstr "חדר שיחה נוצר" +msgstr "חדר שיחה הינו נוצר" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:544 msgid "Chatroom is destroyed" -msgstr "חדר שיחה הרוס" +msgstr "חדר שיחה הינו הרוס" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:546 msgid "Chatroom is started" -msgstr "חדר שיחה מותחל" +msgstr "חדר שיחה הינו מותחל" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:548 msgid "Chatroom is stopped" -msgstr "חדר שיחה הופסק" +msgstr "חדר שיחה הינו מופסק" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:552 msgid "Monday" msgstr "יום שני" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:553 msgid "Tuesday" msgstr "יום שלישי" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:554 msgid "Wednesday" msgstr "יום רביעי" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:555 msgid "Thursday" msgstr "יום חמישי" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:556 msgid "Friday" msgstr "יום שישי" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:557 msgid "Saturday" msgstr "יום שבת" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:558 msgid "Sunday" msgstr "יום ראשון" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:562 msgid "January" msgstr "ינואר" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:563 msgid "February" msgstr "פברואר" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:564 msgid "March" msgstr "מרץ" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:565 msgid "April" msgstr "אפריל" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:566 msgid "May" msgstr "מאי" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:567 msgid "June" msgstr "יוני" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:568 msgid "July" msgstr "יולי" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:569 msgid "August" msgstr "אוגוסט" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:570 msgid "September" msgstr "ספטמבר" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:571 msgid "October" msgstr "אוקטובר" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:572 msgid "November" msgstr "נובמבר" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:573 msgid "December" msgstr "דצמבר" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:961 msgid "Room Configuration" msgstr "תצורת חדר" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:981 msgid "Room Occupants" msgstr "נוכחי חדר" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:982 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:987 msgid "Only moderators are allowed to change the subject in this room" msgstr "רק אחראים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "חדר זה אינו אנונימי" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2728 msgid "Jabber ID ~s is invalid" msgstr "מזהה Jabber ‏~s הינו שגוי" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2742 msgid "Nickname ~s does not exist in the room" msgstr "שם כינוי ~s לא קיים בחדר" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2765 mod_muc_room.erl:3145 msgid "Invalid affiliation: ~s" msgstr "סינוף שגוי: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2816 msgid "Invalid role: ~s" msgstr "תפקיד שגוי: ~s" # תצורה של חדר -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3318 msgid "Configuration of room ~s" msgstr "תצורת חדר ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3329 msgid "Room title" msgstr "כותרת חדר" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3331 mod_muc_room.erl:4065 msgid "Room description" msgstr "תיאור חדר" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3339 msgid "Make room persistent" msgstr "הפוך חדר אל קבוע" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3345 msgid "Make room public searchable" msgstr "הפוך חדר אל בר חיפוש פומבי" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3348 msgid "Make participants list public" msgstr "הפוך רשימת משתתפים אל פומבית" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3350 msgid "Make room password protected" msgstr "הפוך חדר אל מוגן במילת מעבר" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3364 msgid "Maximum Number of Occupants" msgstr "מספר מרבי של נוכחים" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3376 msgid "No limit" msgstr "ללא הגבלה" # הצג כתובות JID ממשיות ל -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "Present real Jabber IDs to" msgstr "הצג כתובות JID ממשיות" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3420 mod_muc_room.erl:3483 msgid "moderators only" msgstr "לאחראים בלבד" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3430 mod_muc_room.erl:3493 msgid "anyone" msgstr "לכל אחד" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Make room members-only" msgstr "הפוך חדר אל חברים-בלבד" # חדר מבוקר חדר תחת ביקורת -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3439 msgid "Make room moderated" msgstr "הפוך חדר אל מבוקר" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3442 msgid "Default users as participants" msgstr "משתמשים משתמטים כמשתתפים" # התרה -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3445 msgid "Allow users to change the subject" msgstr "התר למשתמשים לשנות את הנושא" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3448 msgid "Allow users to send private messages" msgstr "התר למשתמשים לשלוח הודעות פרטיות" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3456 msgid "Allow visitors to send private messages to" msgstr "התר למבקרים לשלוח הודעות פרטיות אל" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3474 msgid "nobody" msgstr "אף אחד" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3499 msgid "Allow users to query other users" msgstr "התר למשתמשים לתשאל משתמשים אחרים" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3502 msgid "Allow users to send invites" msgstr "התר למשתמשים לשלוח הזמנות" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3505 msgid "Allow visitors to send status text in presence updates" msgstr "התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3509 msgid "Allow visitors to change nickname" msgstr "התר למבקרים לשנות שם כינוי" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3512 msgid "Allow visitors to send voice requests" msgstr "התר למבקרים לשלוח בקשות ביטוי" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3515 msgid "Minimum interval between voice requests (in seconds)" msgstr "תדירות מינימלית בין בקשות ביטוי (בשניות)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3522 msgid "Make room CAPTCHA protected" msgstr "הפוך חדר אל מוגן CAPTCHA" # זהויות -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3528 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "הוצא כתובות של Jabber מתוך אתגר CAPTCHA" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3537 msgid "Enable logging" msgstr "אפשור רישום פעילות" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3547 msgid "You need an x:data capable client to configure room" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר חדר" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4067 msgid "Number of occupants" msgstr "מספר של נוכחים" -# private what? (fe/male) -#: mod_muc_room.erl:4097 -#, fuzzy +#: mod_muc_room.erl:4137 msgid "private, " msgstr "פרטי, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4201 msgid "Voice request" msgstr "בקשת ביטוי" # אשר או דחה -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4206 msgid "Either approve or decline the voice request." msgstr "או שתאשר או שתדחה את בקשת הביטוי." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4226 msgid "User JID" msgstr "‏JID משתמש" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4230 msgid "Grant voice to this person?" msgstr "להעניק ביטוי לאישיות זו?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4373 msgid "~s invites you to the room ~s" -msgstr "‫~s מזמינך אל החדר ~s" +msgstr "‫~s מזמינך לחדר ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4385 msgid "the password is" msgstr "הסיסמה היא" -#: mod_offline.erl:773 +#: mod_multicast.erl:259 +msgid "Multicast" +msgstr "שידור מרובב" + +#: mod_multicast.erl:274 +msgid "ejabberd Multicast service" +msgstr "שירות שידור מרובב של ejabberd" + +#: mod_offline.erl:791 msgid "~s's Offline Messages Queue" msgstr "תור הודעות לא מקוונות של ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:804 msgid "Time" msgstr "זמן" -# מאת -#: mod_offline.erl:787 +#: mod_offline.erl:805 msgid "From" -msgstr "מן" +msgstr "מאת" -#: mod_offline.erl:788 +#: mod_offline.erl:806 msgid "To" -msgstr "אל" +msgstr "לכבוד" -#: mod_offline.erl:789 -#, fuzzy +#: mod_offline.erl:807 msgid "Packet" msgstr "חבילת מידע" -#: mod_offline.erl:967 +#: mod_offline.erl:985 msgid "Offline Messages:" msgstr "הודעות לא מקוונות:" -#: mod_offline.erl:971 +#: mod_offline.erl:989 msgid "Remove All Offline Messages" msgstr "הסר את כל ההודעות הלא מקוונות" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "מודול SOCKS5 Bytestreams של ejabberd" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "‫Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "מודול Publish-Subscribe של ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "בקשת מנוי PubSub" # ההרשמה -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "בחר האם לאשר את המנוי של ישות זו." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" -msgstr "מזהה ממסר (NID)" +msgstr "מזהה צומת (NID)" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "כתובת מנוי" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" -msgstr "להתיר לכתובת JID זו להירשם אל ממסר PubSub זה?" +msgstr "להתיר לכתובת JID זו להירשם לצומת PubSub זה?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" -msgstr "מסירת מטען ייעוד (מטע״ד) יחד עם התראות אירוע" +msgstr "מסירת מטעני ייעוד (מטע״ד) יחד עם התראות אירוע" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "מסירת התראות אירוע" # משתמשים רשומים -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" -msgstr "הודע מנויים כאשר תצורת הממסר משתנה" +msgstr "הודע מנויים כאשר תצורת הצומת משתנה" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" -msgstr "הודע מנויים כאשר הממסר נמחק" +msgstr "הודע מנויים כאשר הצומת נמחק" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" -msgstr "הודע מנויים כאשר פריטים מוסרים מתוך הממסר" +msgstr "הודע מנויים כאשר פריטים מוסרים מתוך הצומת" # Typo: store -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "פריטים קבועים לאחסון" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" -msgstr "שם ידידותי עבור הממסר" +msgstr "שם ידידותי עבור הצומת" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "מספר מרבי של פריטים לקיבוע" # בין אם -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "האם להתיר מנויים" # ציין מודל גישה -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "ציין את מודל הגישה" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "קבוצות רשימה מורשות להירשם" # ציין מודל פרסום -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "ציין את מודל הפרסום" # טהר -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "טיהור כל הפריטים כאשר המפרסם הרלוונטי " # ציין טיפוס הודעת אירוע -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "ציין את טיפוס הודעת האירוע" # בבתים בבייטים (bytes) -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" -msgstr "גודל מרבי של מטען הייעוד ביחידות מידה של byte" +msgstr "גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "מתי לשלוח פריט מפורסם אחרון" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" -msgstr "מסור התראות אל משתמשים זמינים בלבד" +msgstr "מסור התראות למשתמשים זמינים בלבד" -# מסונף -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" -msgstr "" +msgstr "האוספים עמם צומת מסונף" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "עליך להשתמש בלקוח אשר תומך x:data וגם CAPTCHA בכדי להירשם" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "בחר שם משתמש וסיסמה להירשם עם שרת זה" @@ -1517,7 +1516,7 @@ msgstr "רישום חשבון Jabber" msgid "Register a Jabber account" msgstr "רשום חשבון Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "בטל רישום חשבון Jabber" @@ -1531,38 +1530,37 @@ msgstr "" "IDentifier) תגובש באופן של: username@server. נא לקרוא בזהירות את ההוראות " "למילוי השדות באופן נכון." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "שם משתמש:" # כמו #: mod_register_web.erl:230 -#, fuzzy msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." -msgstr "This is case insensitive: macbeth הינה זהה כשם MacBeth וגם Macbeth." +msgstr "חלק זה אינו ער לרישיות: macbeth הינה זהה כשם MacBeth וגם Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" msgstr "תווים לא מורשים:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "שרת:" # אל נא לומר -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." -msgstr "אל תגלה את הסיסמה שלך לאף אחד, אפילו לא למנהלים של שרת Jabber" +msgstr "אל תגלה את הסיסמה שלך לאף אחד, אפילו לא למנהלים של שרת Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "ביכולתך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber." # בוטח # trust that your -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1571,7 +1569,7 @@ msgstr "" "זו רק אם אתה סמוך כי המחשב שלך הינו מוגן." # תישכח -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1580,168 +1578,174 @@ msgstr "" "שנן את הסיסמה שלך, או רשום אותה בנייר שמור במקום בטוח. אצל Jabber אין דרך " "אוטומטית לשחזר את הסיסמה שלך במידה וזו תישמט מתוך זיכרונך." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "אימות סיסמה:" # רשום -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "הרשם" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "סיסמה ישנה:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "סיסמה חדשה:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "עמוד זה מתיר לך לבטל רישום של חשבון Jabber בשרת Jabber זה." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "בטל רישום" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" -msgstr "מִנּוּי" +msgstr "הרשמה" -# ממתינות -#: mod_roster.erl:1434 -#, fuzzy +#: mod_roster.erl:1438 msgid "Pending" -msgstr "ממתינים" +msgstr "ממתינות" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "קבוצות" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "הענק תוקף" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "הסר" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "רשימה של " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "הוסף JID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "רשימה" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "קבוצות רשימה משותפות" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "שם:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "תיאור:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "חברים:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "קבוצות מוצגות:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "קבוצה " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 -#, fuzzy +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "שרת ג׳אבּר Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "יום הולדת" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "עיר" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "ארץ" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "דוא״ל" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "שם משפחה" # נא למלא # שקול לתאום # note: matching > wanted -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "" "מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף " -"שדה כדי להתאים אל מחרוזת-משנה)" +"שדה כדי להתאים למחרוזת-משנה)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "שם מלא" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "שם אמצעי" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "שם ארגון" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "יחידת איגוד" # בקרב -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "חיפוש משתמשים אצל " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי לחפש" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "חיפוש משתמש vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "מודול vCard של ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "תוצאות חיפוש עבור " # שקול -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "מלא את שדות אלו כדי לחפש עבור כל משתמש Jabber מבוקש" +#~ msgid "Code Update" +#~ msgstr "עדכון קוד" + +#~ msgid "Delete" +#~ msgstr "מחק" + +#~ msgid "This room is not anonymous" +#~ msgstr "חדר זה אינו אנונימי" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "רשימת הפרטיות הפעילה שלך אסרה את הניתוב של סטנזה זו." @@ -1878,12 +1882,6 @@ msgstr "מלא את שדות אלו כדי לחפש עבור כל משתמש Jab #~ msgid "Rooms" #~ msgstr "חדרים" -#~ msgid "Multicast" -#~ msgstr "שידור מרובב" - -#~ msgid "ejabberd Multicast service" -#~ msgstr "שירות שידור מרובב של ejabberd" - #~ msgid "Notify owners about new subscribers and unsubscribers" #~ msgstr "הודע בעלים אודות מנויים חדשים ומנויים שביטלו מנוי" From 5788609e5c4a3bd6879e144e45648bdab8fcce02 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 27 Jul 2015 11:43:31 +0200 Subject: [PATCH 176/695] Updated Spanish translation --- priv/msgs/es.po | 842 +++++++++++++++++++++++++----------------------- 1 file changed, 435 insertions(+), 407 deletions(-) diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 2e0ca398b19..4a362847e24 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: es\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2015-02-26 17:56+0100\n" +"PO-Revision-Date: 2015-07-24 12:41+0100\n" "Last-Translator: Badlop \n" "Language-Team: \n" "Language: es\n" @@ -14,336 +14,337 @@ msgstr "" "X-Language: Spanish (castellano)\n" "X-Generator: Poedit 1.6.10\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:522 ejabberd_c2s.erl:869 msgid "Use of STARTTLS required" msgstr "Es obligatorio usar STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:620 msgid "No resource provided" msgstr "No se ha proporcionado recurso" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1395 msgid "Replaced by new connection" msgstr "Reemplazado por una nueva conexión" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1399 mod_configure.erl:1854 mod_muc_log.erl:476 +#: mod_muc_log.erl:479 msgid "has been kicked" msgstr "ha sido expulsado" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2484 msgid "Too many unacked stanzas" msgstr "Demasiados mensajes sin haber reconocido recibirlos" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Teclea el texto que ves" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Tus mensajes a ~s están siendo bloqueados. Para desbloquearlos, visita ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Si no ves la imagen CAPTCHA aquí, visita la página web." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Página web de CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es válido." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "No autorizado" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:600 ejabberd_web_admin.erl:611 msgid "Administration" msgstr "Administración" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:668 ejabberd_web_admin.erl:704 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Control de Acceso" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:672 ejabberd_web_admin.erl:708 +#: ejabberd_web_admin.erl:774 ejabberd_web_admin.erl:807 +#: ejabberd_web_admin.erl:848 ejabberd_web_admin.erl:1324 +#: ejabberd_web_admin.erl:1609 ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1803 ejabberd_web_admin.erl:1883 +#: ejabberd_web_admin.erl:2053 ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2179 mod_offline.erl:795 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Enviado" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 +#: ejabberd_web_admin.erl:849 ejabberd_web_admin.erl:1325 +#: ejabberd_web_admin.erl:1610 ejabberd_web_admin.erl:1770 +#: ejabberd_web_admin.erl:2054 ejabberd_web_admin.erl:2083 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Mal formato" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:684 ejabberd_web_admin.erl:721 +#: ejabberd_web_admin.erl:786 ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:1872 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:713 ejabberd_web_admin.erl:812 msgid "Raw" msgstr "Crudo" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:818 mod_offline.erl:817 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Eliminar los seleccionados" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:770 ejabberd_web_admin.erl:803 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Reglas de Acceso" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:844 msgid "~s access rule configuration" msgstr "Configuración de las Regla de Acceso ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:862 msgid "Virtual Hosts" msgstr "Dominios Virtuales" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:871 ejabberd_web_admin.erl:879 msgid "Users" msgstr "Usuarios" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:886 ejabberd_web_admin.erl:1270 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:902 msgid "Users Last Activity" msgstr "Última actividad de los usuarios" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:906 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:919 msgid "Last month" msgstr "Último mes" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:920 msgid "Last year" msgstr "Último año" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:922 msgid "All activity" msgstr "Toda la actividad" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:925 msgid "Show Ordinary Table" msgstr "Mostrar Tabla Ordinaria" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:928 msgid "Show Integral Table" msgstr "Mostrar Tabla Integral" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:935 ejabberd_web_admin.erl:1780 +#: mod_muc_admin.erl:245 msgid "Statistics" msgstr "Estadísticas" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:945 msgid "Not Found" msgstr "No encontrado" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:958 msgid "Node not found" msgstr "Nodo no encontrado" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1180 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Añadir nuevo" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1268 msgid "Host" msgstr "Dominio" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1269 msgid "Registered Users" msgstr "Usuarios registrados" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1333 ejabberd_web_admin.erl:1388 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Usuario" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1338 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3353 +#: mod_register.erl:272 msgid "Password" msgstr "Contraseña" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1347 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Añadir usuario" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1389 msgid "Offline Messages" msgstr "Mensajes diferidos" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1390 ejabberd_web_admin.erl:1620 msgid "Last Activity" msgstr "Última actividad" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1408 ejabberd_web_admin.erl:1592 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1426 ejabberd_web_admin.erl:1603 +#: mod_configure.erl:1927 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1482 ejabberd_web_admin.erl:1501 msgid "Registered Users:" msgstr "Usuarios registrados:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1485 ejabberd_web_admin.erl:1504 +#: ejabberd_web_admin.erl:2120 msgid "Online Users:" msgstr "Usuarios conectados:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1488 msgid "Outgoing s2s Connections:" msgstr "Conexiones S2S salientes:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1491 msgid "Outgoing s2s Servers:" msgstr "Servidores S2S salientes:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1527 ejabberd_web_admin.erl:1727 +#: ejabberd_web_admin.erl:1737 ejabberd_web_admin.erl:2147 mod_roster.erl:1430 msgid "None" msgstr "Ninguno" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1584 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Cambiar contraseña" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1605 msgid "User ~s" msgstr "Usuario ~s" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1616 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1618 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Contraseña:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1625 mod_configure.erl:2118 msgid "Remove User" msgstr "Eliminar usuario" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1673 msgid "No Data" msgstr "Sin datos" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1746 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1747 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1748 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detenidos" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1766 ejabberd_web_admin.erl:1791 msgid "Node ~p" msgstr "Nodo ~p" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1775 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1776 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar copia de seguridad" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1778 msgid "Listened Ports" msgstr "Puertos de escucha" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1781 ejabberd_web_admin.erl:2194 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1785 ejabberd_web_admin.erl:2402 +#: ejabberd_web_admin.erl:2546 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1787 ejabberd_web_admin.erl:2406 +#: ejabberd_web_admin.erl:2550 msgid "Stop" msgstr "Detener" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1794 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1799 msgid "RPC Call Error" msgstr "Error en la llamada RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1850 msgid "Database Tables at ~p" msgstr "Tablas de la base de datos en ~p" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1860 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nombre" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1861 msgid "Storage Type" msgstr "Tipo de almacenamiento" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1862 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1863 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1885 ejabberd_web_admin.erl:2056 msgid "Error" msgstr "Error" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1888 msgid "Backup of ~p" msgstr "Copia de seguridad de ~p" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1892 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -353,483 +354,479 @@ msgstr "" "datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia " "de seguridad de tu base de datos SQL." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1902 msgid "Store binary backup:" msgstr "Guardar copia de seguridad binaria:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1909 ejabberd_web_admin.erl:1919 +#: ejabberd_web_admin.erl:1930 ejabberd_web_admin.erl:1939 +#: ejabberd_web_admin.erl:1949 ejabberd_web_admin.erl:1962 +#: ejabberd_web_admin.erl:1974 ejabberd_web_admin.erl:1990 +#: ejabberd_web_admin.erl:2006 ejabberd_web_admin.erl:2017 +#: ejabberd_web_admin.erl:2027 msgid "OK" msgstr "Aceptar" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1912 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridad binaria:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1922 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar copia de seguridad binaria en el siguiente reinicio de ejabberd " "(requiere menos memoria que si instantánea):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1932 msgid "Store plain text backup:" msgstr "Guardar copia de seguridad en texto plano:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1942 msgid "Restore plain text backup immediately:" msgstr "Restaurar copias de seguridad de texto plano inmediatamente:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1952 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuarios desde un fichero PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1965 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos los usuarios del servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1977 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de los usuarios de un dominio a ficheros PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1993 msgid "Export all tables as SQL queries to a file:" msgstr "Exportar todas las tablas a un fichero SQL:" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2009 msgid "Import user data from jabberd14 spool file:" msgstr "Importar usuario de fichero spool de jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2020 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar usuarios del directorio spool de jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2048 msgid "Listened Ports at " msgstr "Puertos de escucha en " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2077 msgid "Modules at ~p" msgstr "Módulos en ~p" -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2108 msgid "Statistics of ~p" msgstr "Estadísticas de ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2112 msgid "Uptime:" msgstr "Tiempo desde el inicio:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2116 msgid "CPU Time:" msgstr "Tiempo consumido de CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2124 msgid "Transactions Committed:" msgstr "Transacciones finalizadas:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2128 msgid "Transactions Aborted:" msgstr "Transacciones abortadas:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2132 msgid "Transactions Restarted:" msgstr "Transacciones reiniciadas:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2136 msgid "Transactions Logged:" msgstr "Transacciones registradas:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2176 msgid "Update ~p" msgstr "Actualizar ~p" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2187 msgid "Update plan" msgstr "Plan de actualización" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2188 msgid "Modified modules" msgstr "Módulos modificados" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2189 msgid "Update script" msgstr "Script de actualización" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2190 msgid "Low level update script" msgstr "Script de actualización a bajo nivel" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2191 msgid "Script check" msgstr "Comprobación de script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2371 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2371 msgid "Port" msgstr "Puerto" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2372 msgid "Protocol" msgstr "Protocolo" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2373 ejabberd_web_admin.erl:2528 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2374 ejabberd_web_admin.erl:2529 msgid "Options" msgstr "Opciones" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Eliminar" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2426 ejabberd_web_admin.erl:2562 msgid "Start" msgstr "Iniciar" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandos" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "¿Está seguro de quere borrar el mensaje del dia?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Asunto" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Cuerpo del mensaje" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "No se ha proporcionado cuerpo de mensaje para el anuncio" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Anuncios" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anuncio a todos los usuarios" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Enviar anuncio a todos los usuarios en todos los dominios" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Enviar anuncio a todos los usuarios conectados" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Enviar anuncio a todos los usuarios conectados en todos los dominios" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Poner mensaje del dia y enviar a todos los usuarios conectados" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Poner mensaje del día en todos los dominios y enviar a los usuarios " "conectados" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Actualizar mensaje del dia, pero no enviarlo" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Actualizar el mensaje del día en todos los dominos (pero no enviarlo)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Borrar mensaje del dia" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Borrar el mensaje del día en todos los dominios" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configuración" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Detener módulos" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar a fichero de texto" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar fichero" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directorio" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar el servicio" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Detener el servicio" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Borrar usuario" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Cerrar sesión de usuario" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Ver contraseña de usuario" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Cambiar contraseña de usuario" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Ver fecha de la última conexión de usuario" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Ver estadísticas de usuario" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Ver número de usuarios registrados" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Ver número de usuarios conectados" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Administración de usuarios" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Todos los usuarios" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Conexiones S2S salientes" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestión de copia de seguridad" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuarios de ficheros spool de jabberd-1.4" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuración de tablas de la base de datos en " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecciona tipo de almacenamiento de las tablas" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copia en disco solamente" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copia en RAM y disco" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia en RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Detener módulos en " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecciona módulos a detener" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar módulos en " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduce lista de {módulo, [opciones]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista de módulos a iniciar" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Guardar copia de seguridad en fichero en " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Introduce ruta al fichero de copia de seguridad" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Ruta al fichero" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura copia de seguridad desde el fichero en " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exporta copia de seguridad a fichero de texto en " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduce ruta al fichero de texto" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importa usuario desde fichero en " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introduce ruta al fichero jabberd14 spool" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuarios desde el directorio en " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introduce la ruta al directorio de jabberd14 spools" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ruta al directorio" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Retraso temporal" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuración de la Lista de Control de Acceso" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Control de Acceso" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuración de accesos" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Reglas de acceso" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificación de la contraseña" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número de usuarios registrados" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número de usuarios conectados" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Última conexión" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Tamaño de la lista de contactos" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Direcciones IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administración de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Acción en el usuario" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Editar propiedades" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" @@ -837,7 +834,7 @@ msgstr "" "Demasiadas (~p) autenticaciones fallidas de esta dirección IP (~s). La " "dirección será desbloqueada en ~s UTC" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Esta dirección IP está en la lista negra en ~s" @@ -949,486 +946,511 @@ msgstr "Codificación del servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:776 mod_muc_admin.erl:319 msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:914 +#: mod_muc.erl:969 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder registrar el apodo" -#: mod_muc.erl:924 +#: mod_muc.erl:979 msgid "Nickname Registration at " msgstr "Registro del apodo en " -#: mod_muc.erl:930 +#: mod_muc.erl:985 msgid "Enter nickname you want to register" msgstr "Introduce el apodo que quieras registrar" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:986 mod_muc_room.erl:4228 mod_roster.erl:1436 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Apodo" -#: mod_muc.erl:1094 +#: mod_muc.erl:1149 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:229 mod_muc_admin.erl:232 mod_muc_admin.erl:244 +#: mod_muc_admin.erl:318 +msgid "Multi-User Chat" +msgstr "Salas de Charla" + +#: mod_muc_admin.erl:247 +msgid "Total rooms" +msgstr "Salas totales" + +#: mod_muc_admin.erl:248 +msgid "Permanent rooms" +msgstr "Salas permanentes" + +#: mod_muc_admin.erl:249 +msgid "Registered nicknames" +msgstr "Apodos registrados" + +#: mod_muc_admin.erl:252 +msgid "List of rooms" +msgstr "Lista de salas" + +#: mod_muc_log.erl:447 mod_muc_log.erl:456 msgid "Chatroom configuration modified" msgstr "Configuración de la sala modificada" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:459 msgid "joins the room" msgstr "entra en la sala" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:462 mod_muc_log.erl:465 msgid "leaves the room" msgstr "sale de la sala" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:469 mod_muc_log.erl:472 msgid "has been banned" msgstr "ha sido bloqueado" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:484 msgid "has been kicked because of an affiliation change" msgstr "ha sido expulsado por un cambio de su afiliación" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:489 msgid "has been kicked because the room has been changed to members-only" msgstr "ha sido expulsado porque la sala es ahora solo para miembros" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:494 msgid "has been kicked because of a system shutdown" msgstr "ha sido expulsado porque el sistema se va a detener" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:499 msgid "is now known as" msgstr "se cambia el nombre a" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:502 mod_muc_log.erl:841 msgid " has set the subject to: " msgstr " ha puesto el asunto: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:542 msgid "Chatroom is created" msgstr "Se ha creado la sala" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:544 msgid "Chatroom is destroyed" msgstr "Se ha destruido la sala" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:546 msgid "Chatroom is started" msgstr "Se ha iniciado la sala" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:548 msgid "Chatroom is stopped" msgstr "Se ha detenido la sala" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:552 msgid "Monday" msgstr "lunes" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:553 msgid "Tuesday" msgstr "martes" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:554 msgid "Wednesday" msgstr "miércoles" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:555 msgid "Thursday" msgstr "jueves" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:556 msgid "Friday" msgstr "viernes" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:557 msgid "Saturday" msgstr "sábado" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:558 msgid "Sunday" msgstr "domingo" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:562 msgid "January" msgstr "enero" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:563 msgid "February" msgstr "febrero" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:564 msgid "March" msgstr "marzo" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:565 msgid "April" msgstr "abril" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:566 msgid "May" msgstr "mayo" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:567 msgid "June" msgstr "junio" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:568 msgid "July" msgstr "julio" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:569 msgid "August" msgstr "agosto" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:570 msgid "September" msgstr "septiembre" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:571 msgid "October" msgstr "octubre" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:572 msgid "November" msgstr "noviembre" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:573 msgid "December" msgstr "diciembre" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:961 msgid "Room Configuration" msgstr "Configuración de la sala" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:981 msgid "Room Occupants" msgstr "Ocupantes de la sala" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:982 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Solo los moderadores y participantes pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:987 msgid "Only moderators are allowed to change the subject in this room" msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Sala no anónima" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2728 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no es válido" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2742 msgid "Nickname ~s does not exist in the room" msgstr "El apodo ~s no existe en la sala" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2765 mod_muc_room.erl:3145 msgid "Invalid affiliation: ~s" msgstr "Afiliación no válida: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2816 msgid "Invalid role: ~s" msgstr "Rol no válido: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3318 msgid "Configuration of room ~s" msgstr "Configuración para la sala ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3329 msgid "Room title" msgstr "Título de la sala" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3331 mod_muc_room.erl:4065 msgid "Room description" msgstr "Descripción de la sala" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3339 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3345 msgid "Make room public searchable" msgstr "Sala públicamente visible" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3348 msgid "Make participants list public" msgstr "La lista de participantes es pública" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3350 msgid "Make room password protected" msgstr "Proteger la sala con contraseña" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3364 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3376 msgid "No limit" msgstr "Sin límite" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "Present real Jabber IDs to" msgstr "Los Jabber ID reales pueden verlos" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3420 mod_muc_room.erl:3483 msgid "moderators only" msgstr "solo moderadores" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3430 mod_muc_room.erl:3493 msgid "anyone" msgstr "cualquiera" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Make room members-only" msgstr "Sala sólo para miembros" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3439 msgid "Make room moderated" msgstr "Sala moderada" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3442 msgid "Default users as participants" msgstr "Los usuarios son participantes por defecto" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3445 msgid "Allow users to change the subject" msgstr "Permitir a los usuarios cambiar el asunto" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3448 msgid "Allow users to send private messages" msgstr "Permitir a los usuarios enviar mensajes privados" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3456 msgid "Allow visitors to send private messages to" msgstr "Permitir a los visitantes enviar mensajes privados a" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3474 msgid "nobody" msgstr "nadie" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3499 msgid "Allow users to query other users" msgstr "Permitir a los usuarios consultar a otros usuarios" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3502 msgid "Allow users to send invites" msgstr "Permitir a los usuarios enviar invitaciones" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3505 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir a los visitantes enviar texto de estado en las actualizaciones de " "presencia" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3509 msgid "Allow visitors to change nickname" msgstr "Permitir a los visitantes cambiarse el apodo" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3512 msgid "Allow visitors to send voice requests" msgstr "Permitir a los visitantes enviar peticiones de voz" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3515 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalo mínimo entre peticiones de voz (en segundos)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3522 msgid "Make room CAPTCHA protected" msgstr "Proteger la sala con CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3528 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir Jabber IDs de las pruebas de CAPTCHA" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3537 msgid "Enable logging" msgstr "Guardar históricos" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3547 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar la sala" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4067 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4137 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4201 msgid "Voice request" msgstr "Petición de voz" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4206 msgid "Either approve or decline the voice request." msgstr "Aprueba o rechaza la petición de voz." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4226 msgid "User JID" msgstr "Jabber ID del usuario" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4230 msgid "Grant voice to this person?" msgstr "¿Conceder voz a esta persona?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4373 msgid "~s invites you to the room ~s" msgstr "~s te invita a la sala ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4385 msgid "the password is" msgstr "la contraseña es" -#: mod_offline.erl:773 +#: mod_multicast.erl:259 +msgid "Multicast" +msgstr "Multicast" + +#: mod_multicast.erl:274 +msgid "ejabberd Multicast service" +msgstr "Servicio Multicast de ejabberd" + +#: mod_offline.erl:791 msgid "~s's Offline Messages Queue" msgstr "Cola de mensajes diferidos de ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:804 msgid "Time" msgstr "Fecha" -#: mod_offline.erl:787 +#: mod_offline.erl:805 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:806 msgid "To" msgstr "Para" -#: mod_offline.erl:789 +#: mod_offline.erl:807 msgid "Packet" msgstr "Paquete" -#: mod_offline.erl:967 +#: mod_offline.erl:985 msgid "Offline Messages:" msgstr "Mensajes diferidos:" -#: mod_offline.erl:971 +#: mod_offline.erl:989 msgid "Remove All Offline Messages" msgstr "Borrar todos los mensajes diferidos" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Módulo SOCKS5 Bytestreams para ejabberd" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Servicio de Publicar-Subscribir" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo de Publicar-Subscribir de ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Petición de subscriptor de PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Decidir si aprobar la subscripción de esta entidad." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Nodo ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Dirección del subscriptor" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "¿Deseas permitir a este Jabber ID que se subscriba a este nodo PubSub?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Enviar contenidos junto con las notificaciones de eventos" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Entregar notificaciones de eventos" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptores cuando cambia la configuración del nodo" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptores cuando el nodo se borra" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscriptores cuando los elementos se borran del nodo" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Persistir elementos al almacenar" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Un nombre sencillo para el nodo" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persisten" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Permitir subscripciones" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Especifica el modelo de acceso" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Grupos de contactos que pueden suscribirse" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Especificar el modelo del publicante" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Borra todos los elementos cuando el publicador relevante se desconecta" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Especifica el tipo del mensaje de evento" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Máximo tamaño del contenido en bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Cuando enviar el último elemento publicado" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Solo enviar notificaciones a los usuarios disponibles" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Las colecciones a las que un nodo está afiliado" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Necesitas un cliente con soporte de x:data y CAPTCHA para registrarte" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Escoge un nombre de usuario y contraseña para registrarte en este servidor" @@ -1465,7 +1487,7 @@ msgstr "Registro de Cuenta Jabber" msgid "Register a Jabber account" msgstr "Registrar una cuenta Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Borrar una cuenta Jabber" @@ -1479,7 +1501,7 @@ msgstr "" "(Jabber IDentificador) será de la forma: nombredeusuario@servidor. Por favor " "lee detenidamente las instrucciones para rellenar correctamente los campos." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nombre de usuario:" @@ -1492,11 +1514,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Caracteres no permitidos:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servidor:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1504,11 +1526,11 @@ msgstr "" "No le digas tu contraseña a nadie, ni siquiera a los administradores del " "servidor Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Puedes cambiar tu contraseña después, usando un cliente Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1516,7 +1538,7 @@ msgstr "" "Algunos clientes Jabber pueden recordar tu contraseña en la máquina. Usa esa " "opción solo si confías en que la máquina que usas es segura." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1525,113 +1547,113 @@ msgstr "" "Memoriza tu contraseña, o apúntala en un papel en un lugar seguro. En Jabber " "no hay un método automatizado para recuperar la contraseña si la olvidas." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verificación de la contraseña:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Registrar" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Contraseña antigua:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nueva contraseña:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Esta página te permite borrar tu cuenta Jabber en este servidor Jabber." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Borrar" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Subscripción" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Pendiente" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Borrar" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Lista de contactos de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Añadir Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Lista de contactos" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Grupos Compartidos" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nombre:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Descripción:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Miembros:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Mostrar grupos:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grupo " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber en Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Cumpleaños" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Ciudad" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "correo" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Apellido" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1639,46 +1661,52 @@ msgstr "" "Rellena el formulario para buscar usuarios Jabber. Añade * al final de un " "campo para buscar subcadenas." -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nombre completo" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segundo nombre" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nombre de la organización" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unidad de la organización" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Buscar usuarios en " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Necesitas un cliente con soporte de x:data para poder buscar" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Buscar vCard de usuario" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard para ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Buscar resultados por " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Rellena campos para buscar usuarios Jabber que concuerden" +#~ msgid "Delete" +#~ msgstr "Eliminar" + +#~ msgid "This room is not anonymous" +#~ msgstr "Sala no anónima" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Tu lista de privacidad activa ha denegado el encío de este paquete." From 0dbedb69a6a6a82e364b2595cc14eb64e6a13bb7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 27 Jul 2015 11:45:04 +0200 Subject: [PATCH 177/695] Recompile translations --- priv/msgs/es.msg | 9 ++- priv/msgs/he.msg | 169 ++++++++++++++++++++++++++++------------------- 2 files changed, 108 insertions(+), 70 deletions(-) diff --git a/priv/msgs/es.msg b/priv/msgs/es.msg index e9f4d0d7ae7..a5ebb840da3 100644 --- a/priv/msgs/es.msg +++ b/priv/msgs/es.msg @@ -60,7 +60,6 @@ {"Database Tables Configuration at ","Configuración de tablas de la base de datos en "}. {"December","diciembre"}. {"Default users as participants","Los usuarios son participantes por defecto"}. -{"Delete","Eliminar"}. {"Delete message of the day","Borrar mensaje del dia"}. {"Delete message of the day on all hosts","Borrar el mensaje del día en todos los dominios"}. {"Delete Selected","Eliminar los seleccionados"}. @@ -77,6 +76,7 @@ {"Either approve or decline the voice request.","Aprueba o rechaza la petición de voz."}. {"ejabberd IRC module","Módulo de IRC para ejabberd"}. {"ejabberd MUC module","Módulo de MUC para ejabberd"}. +{"ejabberd Multicast service","Servicio Multicast de ejabberd"}. {"ejabberd Publish-Subscribe module","Módulo de Publicar-Subscribir de ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Módulo SOCKS5 Bytestreams para ejabberd"}. {"ejabberd vCard module","Módulo vCard para ejabberd"}. @@ -164,6 +164,7 @@ {"Listened Ports at ","Puertos de escucha en "}. {"Listened Ports","Puertos de escucha"}. {"List of modules to start","Lista de módulos a iniciar"}. +{"List of rooms","Lista de salas"}. {"Low level update script","Script de actualización a bajo nivel"}. {"Make participants list public","La lista de participantes es pública"}. {"Make room CAPTCHA protected","Proteger la sala con CAPTCHA"}. @@ -189,6 +190,8 @@ {"Modules at ~p","Módulos en ~p"}. {"Modules","Módulos"}. {"Monday","lunes"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Salas de Charla"}. {"Name:","Nombre:"}. {"Name","Nombre"}. {"Never","Nunca"}. @@ -241,6 +244,7 @@ {"Path to File","Ruta al fichero"}. {"Pending","Pendiente"}. {"Period: ","Periodo: "}. +{"Permanent rooms","Salas permanentes"}. {"Persist items to storage","Persistir elementos al almacenar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Ten en cuenta que estas opciones solo harán copia de seguridad de la base de datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia de seguridad de tu base de datos SQL."}. @@ -258,6 +262,7 @@ {"Raw","Crudo"}. {"Really delete message of the day?","¿Está seguro de quere borrar el mensaje del dia?"}. {"Register a Jabber account","Registrar una cuenta Jabber"}. +{"Registered nicknames","Apodos registrados"}. {"Registered Users:","Usuarios registrados:"}. {"Registered Users","Usuarios registrados"}. {"Register","Registrar"}. @@ -338,7 +343,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","No importa si usas mayúsculas: macbeth es lo mismo que MacBeth y Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Esta página te permite crear una cuenta Jabber este servidor Jabber. Tu JID (Jabber IDentificador) será de la forma: nombredeusuario@servidor. Por favor lee detenidamente las instrucciones para rellenar correctamente los campos."}. {"This page allows to unregister a Jabber account in this Jabber server.","Esta página te permite borrar tu cuenta Jabber en este servidor Jabber."}. -{"This room is not anonymous","Sala no anónima"}. {"Thursday","jueves"}. {"Time delay","Retraso temporal"}. {"Time","Fecha"}. @@ -346,6 +350,7 @@ {"Too many unacked stanzas","Demasiados mensajes sin haber reconocido recibirlos"}. {"To","Para"}. {"To ~s","A ~s"}. +{"Total rooms","Salas totales"}. {"Transactions Aborted:","Transacciones abortadas:"}. {"Transactions Committed:","Transacciones finalizadas:"}. {"Transactions Logged:","Transacciones registradas:"}. diff --git a/priv/msgs/he.msg b/priv/msgs/he.msg index 7b5c5664208..b5b1eafff5b 100644 --- a/priv/msgs/he.msg +++ b/priv/msgs/he.msg @@ -11,9 +11,9 @@ {"Add User","הוסף משתמש"}. {"Administration of ","ניהול של "}. {"Administration","הנהלה"}. -{"A friendly name for the node","שם ידידותי עבור הממסר"}. +{"A friendly name for the node","שם ידידותי עבור הצומת"}. {"All activity","כל פעילות"}. -{"Allow this Jabber ID to subscribe to this pubsub node?","להתיר לכתובת JID זו להירשם אל ממסר PubSub זה?"}. +{"Allow this Jabber ID to subscribe to this pubsub node?","להתיר לכתובת JID זו להירשם לצומת PubSub זה?"}. {"Allow users to change the subject","התר למשתמשים לשנות את הנושא"}. {"Allow users to query other users","התר למשתמשים לתשאל משתמשים אחרים"}. {"Allow users to send invites","התר למשתמשים לשלוח הזמנות"}. @@ -23,13 +23,14 @@ {"Allow visitors to send status text in presence updates","התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות"}. {"Allow visitors to send voice requests","התר למבקרים לשלוח בקשות ביטוי"}. {"All Users","כל המשתמשים"}. -{"Announcements","מודעות"}. +{"Announcements","בשורות"}. {"anyone","לכל אחד"}. {"April","אפריל"}. {"August","אוגוסט"}. {"Backup Management","ניהול גיבוי"}. -{"Backup to File at ","גבה אל קובץ אצל "}. -{"Backup","גבה"}. +{"Backup of ~p","גיבוי של ~p"}. +{"Backup to File at ","גבה לקובץ אצל "}. +{"Backup","גיבוי"}. {"Bad format","פורמט רע"}. {"Birthday","יום הולדת"}. {"CAPTCHA web page","עמוד רשת CAPTCHA"}. @@ -37,10 +38,10 @@ {"Change User Password","שנה סיסמת משתמש"}. {"Characters not allowed:","תווים לא מורשים:"}. {"Chatroom configuration modified","תצורת חדר שיחה שונתה"}. -{"Chatroom is created","חדר שיחה נוצר"}. -{"Chatroom is destroyed","חדר שיחה הרוס"}. -{"Chatroom is started","חדר שיחה מותחל"}. -{"Chatroom is stopped","חדר שיחה הופסק"}. +{"Chatroom is created","חדר שיחה הינו נוצר"}. +{"Chatroom is destroyed","חדר שיחה הינו הרוס"}. +{"Chatroom is started","חדר שיחה הינו מותחל"}. +{"Chatroom is stopped","חדר שיחה הינו מופסק"}. {"Chatrooms","חדרי שיחה"}. {"Choose a username and password to register with this server","בחר שם משתמש וסיסמה להירשם עם שרת זה"}. {"Choose modules to stop","בחר מודולים להפסקה"}. @@ -54,27 +55,28 @@ {"Connections parameters","פרמטרים של חיבור"}. {"Country","ארץ"}. {"CPU Time:","זמן מחשב (CPU):"}. +{"Database Tables at ~p","טבלאות מסד נתונים אצל ~p"}. {"Database Tables Configuration at ","תצורת טבלאות מסד נתונים אצל "}. {"Database","מסד נתונים"}. {"December","דצמבר"}. {"Default users as participants","משתמשים משתמטים כמשתתפים"}. -{"Delete message of the day on all hosts","מחק הודעת היום בכל המארחים"}. -{"Delete message of the day","מחק הודעת היום"}. +{"Delete message of the day on all hosts","מחק את בשורת היום בכל המארחים"}. +{"Delete message of the day","מחק את בשורת היום"}. {"Delete Selected","מחק נבחרות"}. {"Delete User","מחק משתמש"}. -{"Delete","מחק"}. {"Deliver event notifications","מסירת התראות אירוע"}. -{"Deliver payloads with event notifications","מסירת מטען ייעוד (מטע״ד) יחד עם התראות אירוע"}. +{"Deliver payloads with event notifications","מסירת מטעני ייעוד (מטע״ד) יחד עם התראות אירוע"}. {"Description:","תיאור:"}. {"Disc only copy","העתק של תקליטור בלבד"}. {"Displayed Groups:","קבוצות מוצגות:"}. -{"Don't tell your password to anybody, not even the administrators of the Jabber server.","אל תגלה את הסיסמה שלך לאף אחד, אפילו לא למנהלים של שרת Jabber"}. -{"Dump Backup to Text File at ","השלך גיבוי אל קובץ טקסט אצל "}. -{"Dump to Text File","השלך אל קובץ טקסט"}. +{"Don't tell your password to anybody, not even the administrators of the Jabber server.","אל תגלה את הסיסמה שלך לאף אחד, אפילו לא למנהלים של שרת Jabber."}. +{"Dump Backup to Text File at ","השלך גיבוי לקובץ טקסט אצל "}. +{"Dump to Text File","השלך לקובץ טקסט"}. {"Edit Properties","ערוך מאפיינים"}. {"Either approve or decline the voice request.","או שתאשר או שתדחה את בקשת הביטוי."}. {"ejabberd IRC module","מודול IRC של ejabberd"}. {"ejabberd MUC module","מודול MUC של ejabberd"}. +{"ejabberd Multicast service","שירות שידור מרובב של ejabberd"}. {"ejabberd Publish-Subscribe module","מודול Publish-Subscribe של ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","מודול SOCKS5 Bytestreams של ejabberd"}. {"ejabberd vCard module","מודול vCard של ejabberd"}. @@ -86,25 +88,27 @@ {"End User Session","סיים סשן משתמש"}. {"Enter list of {Module, [Options]}","הזן רשימה של {מודול, [אפשרויות]}"}. {"Enter nickname you want to register","הזן שם כינוי אשר ברצונך לרושמו"}. -{"Enter path to backup file","הזן נתיב אל קובץ גיבוי"}. -{"Enter path to jabberd14 spool dir","הזן נתיב אל מדור סליל (spool dir) של jabberd14"}. -{"Enter path to jabberd14 spool file","הזן נתיב אל קובץ סליל (spool file) של jabberd14"}. -{"Enter path to text file","הזן נתיב אל קובץ טקסט"}. +{"Enter path to backup file","הזן נתיב לקובץ גיבוי"}. +{"Enter path to jabberd14 spool dir","הזן נתיב למדור סליל (spool dir) של jabberd14"}. +{"Enter path to jabberd14 spool file","הזן נתיב לקובץ סליל (spool file) של jabberd14"}. +{"Enter path to text file","הזן נתיב לקובץ טקסט"}. {"Enter the text you see","הזן את הטקסט אותו הינך רואה"}. -{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","הזן שם משתמש וקידודים בהם ברצונך להשתמש לשם התחברות אל שרתים של IRC. לחץ 'הבא' כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות."}. -{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לשם התחברות אל שרתים של IRC"}. +{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","הזן שם משתמש וקידודים בהם ברצונך להשתמש לצורך התחברות לשרתי IRC. לחץ 'הבא' כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות."}. +{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לצורך התחברות לשרתי IRC"}. +{"Erlang Jabber Server","שרת ג׳אבּר Erlang"}. {"Error","שגיאה"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","הוצא כתובות של Jabber מתוך אתגר CAPTCHA"}. -{"Export data of all users in the server to PIEFXIS files (XEP-0227):","ייצוא מידע של כל המשתמשים אשר מצויים בשרת זה אל קבצי PIEFXIS (‫XEP-0227):"}. -{"Export data of users in a host to PIEFXIS files (XEP-0227):","ייצוא מידע של כל המשתמשים בתוך מארח אל קבצי PIEFXIS (‫XEP-0227):"}. +{"Export all tables as SQL queries to a file:","יצא את כל טבלאות בתור שאילתות SQL לתוך קובץ:"}. +{"Export data of all users in the server to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך בשרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):"}. +{"Export data of users in a host to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך מארח לתוך קבצי PIEFXIS ‏(XEP-0227):"}. {"Family Name","שם משפחה"}. {"February","פברואר"}. {"Fill in fields to search for any matching Jabber User","מלא את שדות אלו כדי לחפש עבור כל משתמש Jabber מבוקש"}. -{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה כדי להתאים אל מחרוזת-משנה)"}. +{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה כדי להתאים למחרוזת-משנה)"}. {"Friday","יום שישי"}. {"From ~s","מאת ~s"}. -{"From","מן"}. +{"From","מאת"}. {"Full Name","שם מלא"}. {"Get Number of Online Users","השג מספר של משתמשים מקוונים"}. {"Get Number of Registered Users","השג מספר של משתמשים רשומים"}. @@ -125,12 +129,12 @@ {"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","אם ברצונך לציין פורטים, סיסמאות, קידודים אחרים עבור שרתים של IRC, מלא את רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, \"password\"}'. באופן משתמט שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה."}. {"Import Directory","ייבוא מדור"}. {"Import File","ייבוא קובץ"}. -{"Import user data from jabberd14 spool file:","ייבוא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:"}. +{"Import user data from jabberd14 spool file:","יבא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:"}. {"Import User from File at ","ייבוא משתמש מתוך קובץ אצל "}. -{"Import users data from a PIEFXIS file (XEP-0227):","ייבוא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):"}. -{"Import users data from jabberd14 spool directory:","ייבוא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:"}. +{"Import users data from a PIEFXIS file (XEP-0227):","יבא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):"}. +{"Import users data from jabberd14 spool directory:","יבא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:"}. {"Import Users from Dir at ","ייבוא משתמשים מתוך מדור אצל "}. -{"Import Users From jabberd14 Spool Files","ייבוא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14"}. +{"Import Users From jabberd14 Spool Files","יבא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14"}. {"Invalid affiliation: ~s","סינוף שגוי: ~s"}. {"Invalid role: ~s","תפקיד שגוי: ~s"}. {"IP addresses","כתובות IP"}. @@ -146,18 +150,22 @@ {"Jabber ID ~s is invalid","מזהה Jabber ‏~s הינו שגוי"}. {"Jabber ID","מזהה Jabber"}. {"January","ינואר"}. -{"Join IRC channel","הצטרף אל ערוץ IRC"}. +{"Join IRC channel","הצטרף לערוץ IRC"}. {"joins the room","נכנס/ת אל החדר"}. -{"Join the IRC channel here.","הצטרף אל ערוץ IRC כאן."}. -{"Join the IRC channel in this Jabber ID: ~s","הצטרף אל ערוץ IRC במזהה Jabber זה: ~s"}. +{"Join the IRC channel here.","הצטרף לערוץ IRC כאן."}. +{"Join the IRC channel in this Jabber ID: ~s","הצטרף לערוץ IRC במזהה Jabber זה: ~s"}. {"July","יולי"}. {"June","יוני"}. {"Last Activity","פעילות אחרונה"}. {"Last login","כניסה אחרונה"}. {"Last month","חודש אחרון"}. {"Last year","שנה אחרונה"}. -{"leaves the room","עוזב/ת אל החדר"}. +{"leaves the room","עוזב/ת את החדר"}. +{"Listened Ports at ","פורטים מואזנים אצל "}. +{"Listened Ports","פורטים מואזנים"}. {"List of modules to start","רשימה של מודולים להפעלה"}. +{"List of rooms","רשימה של חדרים"}. +{"Low level update script","תסריט עדכון Low level"}. {"Make participants list public","הפוך רשימת משתתפים אל פומבית"}. {"Make room CAPTCHA protected","הפוך חדר אל מוגן CAPTCHA"}. {"Make room members-only","הפוך חדר אל חברים-בלבד"}. @@ -168,7 +176,7 @@ {"March","מרץ"}. {"Maximum Number of Occupants","מספר מרבי של נוכחים"}. {"Max # of items to persist","מספר מרבי של פריטים לקיבוע"}. -{"Max payload size in bytes","גודל מרבי של מטען הייעוד ביחידות מידה של byte"}. +{"Max payload size in bytes","גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte"}. {"May","מאי"}. {"Members:","חברים:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","שנן את הסיסמה שלך, או רשום אותה בנייר שמור במקום בטוח. אצל Jabber אין דרך אוטומטית לשחזר את הסיסמה שלך במידה וזו תישמט מתוך זיכרונך."}. @@ -178,9 +186,12 @@ {"Minimum interval between voice requests (in seconds)","תדירות מינימלית בין בקשות ביטוי (בשניות)"}. {"moderators only","לאחראים בלבד"}. {"Modified modules","מודולים שהותאמו"}. +{"Modules at ~p","מודולים אצל ~p"}. {"Modules","מודולים"}. {"Module","מודול"}. {"Monday","יום שני"}. +{"Multicast","שידור מרובב"}. +{"Multi-User Chat","שיחה מרובת משתמשים"}. {"Name:","שם:"}. {"Name","שם"}. {"Never","אף פעם"}. @@ -188,17 +199,20 @@ {"Nickname Registration at ","רישום שם כינוי אצל "}. {"Nickname ~s does not exist in the room","שם כינוי ~s לא קיים בחדר"}. {"Nickname","שם כינוי"}. +{"No body provided for announce message","לא סופק גוף עבור הודעת בשורה"}. {"nobody","אף אחד"}. {"No Data","אין מידע"}. -{"Node ID","מזהה ממסר (NID)"}. -{"Node not found","ממסר לא נמצא"}. -{"Nodes","ממסרים"}. +{"Node ID","מזהה צומת (NID)"}. +{"Node not found","צומת לא נמצא"}. +{"Node ~p","צומת ~p"}. +{"Nodes","צמתים"}. {"No limit","ללא הגבלה"}. +{"None","אין"}. {"No resource provided","לא סופק משאב"}. {"Not Found","לא נמצא"}. -{"Notify subscribers when items are removed from the node","הודע מנויים כאשר פריטים מוסרים מתוך הממסר"}. -{"Notify subscribers when the node configuration changes","הודע מנויים כאשר תצורת הממסר משתנה"}. -{"Notify subscribers when the node is deleted","הודע מנויים כאשר הממסר נמחק"}. +{"Notify subscribers when items are removed from the node","הודע מנויים כאשר פריטים מוסרים מתוך הצומת"}. +{"Notify subscribers when the node configuration changes","הודע מנויים כאשר תצורת הצומת משתנה"}. +{"Notify subscribers when the node is deleted","הודע מנויים כאשר הצומת נמחק"}. {"November","נובמבר"}. {"Number of occupants","מספר של נוכחים"}. {"Number of online users","מספר של משתמשים מקוונים"}. @@ -211,7 +225,7 @@ {"Online Users:","משתמשים מקוונים:"}. {"Online Users","משתמשים מקוונים"}. {"Online","מקוון"}. -{"Only deliver notifications to available users","מסור התראות אל משתמשים זמינים בלבד"}. +{"Only deliver notifications to available users","מסור התראות למשתמשים זמינים בלבד"}. {"Only moderators and participants are allowed to change the subject in this room","רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה"}. {"Only moderators are allowed to change the subject in this room","רק אחראים רשאים לשנות את הנושא בחדר זה"}. {"Options","אפשרויות"}. @@ -220,34 +234,40 @@ {"Outgoing s2s Connections:","חיבורי s2s יוצאים:"}. {"Outgoing s2s Connections","חיבורי s2s יוצאים"}. {"Outgoing s2s Servers:","שרתי s2s יוצאים:"}. +{"Packet","חבילת מידע"}. {"Password ~b","סיסמה ~b"}. {"Password Verification:","אימות סיסמה:"}. {"Password Verification","אימות סיסמה"}. {"Password:","סיסמה:"}. {"Password","סיסמה"}. -{"Path to Dir","נתיב אל מדור"}. -{"Path to File","נתיב אל קובץ"}. +{"Path to Dir","נתיב למדור"}. +{"Path to File","נתיב לקובץ"}. +{"Pending","ממתינות"}. {"Period: ","משך זמן: "}. +{"Permanent rooms","חדרים קבועים"}. {"Persist items to storage","פריטים קבועים לאחסון"}. {"Ping","פינג"}. -{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","נא לשים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך בנפרד."}. +{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","אנא שים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך בנפרד."}. {"Pong","פונג"}. {"Port ~b","פורט ~b"}. {"Port","פורט"}. {"Present real Jabber IDs to","הצג כתובות JID ממשיות"}. +{"private, ","פרטי, "}. {"Protocol","פרוטוקול"}. {"Publish-Subscribe","‫Publish-Subscribe"}. {"PubSub subscriber request","בקשת מנוי PubSub"}. {"Purge all items when the relevant publisher goes offline","טיהור כל הפריטים כאשר המפרסם הרלוונטי "}. {"RAM and disc copy","העתק RAM וגם תקליטור"}. {"RAM copy","העתק RAM"}. -{"Really delete message of the day?","באמת למחוק את הודעת היום?"}. +{"Raw","גולמי"}. +{"Really delete message of the day?","באמת למחוק את בשורת היום?"}. {"Register a Jabber account","רשום חשבון Jabber"}. +{"Registered nicknames","שמות כינוי רשומים"}. {"Registered Users:","משתמשים רשומים:"}. {"Registered Users","משתמשים רשומים"}. {"Register","הרשם"}. {"Registration in mod_irc for ","רישום בתוך mod_irc עבור "}. -{"Remote copy","עותק מרוחק"}. +{"Remote copy","העתק מרוחק"}. {"Remove All Offline Messages","הסר את כל ההודעות הלא מקוונות"}. {"Remove User","הסר משתמש"}. {"Remove","הסר"}. @@ -269,69 +289,81 @@ {"Roster size","גודל רשימה"}. {"Roster","רשימה"}. {"RPC Call Error","שגיאת קריאת RPC"}. -{"Running Nodes","ממסרים שמורצים כעת"}. +{"Running Nodes","צמתים מורצים"}. {"~s access rule configuration","~s תצורת כללי גישה"}. {"Saturday","יום שבת"}. +{"Script check","בדיקת תסריט"}. {"Search Results for ","תוצאות חיפוש עבור "}. {"Search users in ","חיפוש משתמשים אצל "}. -{"Send announcement to all online users on all hosts","שלח מודעות אל כל המשתמשים המקוונים בכל המארחים"}. -{"Send announcement to all online users","שלח מודעות אל כל המשתמשים המקוונים"}. -{"Send announcement to all users on all hosts","שלח מודעות אל כל המשתמשים בכל המארחים"}. -{"Send announcement to all users","שלח מודעות אל כל המשתמשים"}. +{"Send announcement to all online users on all hosts","שלח בשורה לכל המשתמשים המקוונים בכל המארחים"}. +{"Send announcement to all online users","שלח בשורה לכל המשתמשים המקוונים"}. +{"Send announcement to all users on all hosts","שלח בשורה לכל המשתמשים בכל המארחים"}. +{"Send announcement to all users","שלח בשורה לכל המשתמשים"}. {"September","ספטמבר"}. {"Server ~b","שרת ~b"}. {"Server:","שרת:"}. -{"Set message of the day and send to online users","קבע הודעת היום ושלח אל משתמשים מקוונים"}. -{"Set message of the day on all hosts and send to online users","קבע הודעת היום בכל המארחים ושלח אל משתמשים מקוונים"}. +{"Set message of the day and send to online users","קבע את בשורת היום ושלח למשתמשים מקוונים"}. +{"Set message of the day on all hosts and send to online users","קבע את בשורת היום בכל המארחים ושלח למשתמשים מקוונים"}. {"Shared Roster Groups","קבוצות רשימה משותפות"}. {"Show Integral Table","הצג טבלה אינטגרלית"}. {"Show Ordinary Table","הצג טבלה רגילה"}. {"Shut Down Service","כבה שירות"}. -{"~s invites you to the room ~s","‫~s מזמינך אל החדר ~s"}. +{"~s invites you to the room ~s","‫~s מזמינך לחדר ~s"}. {"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה זו רק אם אתה סמוך כי המחשב שלך הינו מוגן."}. {"Specify the access model","ציין את מודל הגישה"}. {"Specify the event message type","ציין את טיפוס הודעת האירוע"}. {"Specify the publisher model","ציין את מודל הפרסום"}. {"~s's Offline Messages Queue","תור הודעות לא מקוונות של ~s"}. +{"Start Modules at ","התחל מודולים אצל "}. {"Start Modules","התחל מודולים"}. {"Start","התחל"}. -{"Statistics of ~p","סטטיסטיקות עבור ~p"}. +{"Statistics of ~p","סטטיסטיקות של ~p"}. {"Statistics","סטטיסטיקה"}. +{"Stop Modules at ","הפסק מודולים אצל "}. {"Stop Modules","הפסק מודולים"}. -{"Stopped Nodes","ממסרים שנפסקו"}. +{"Stopped Nodes","צמתים שנפסקו"}. {"Stop","הפסק"}. {"Storage Type","טיפוס אחסון"}. {"Store binary backup:","אחסן גיבוי בינארי:"}. {"Store plain text backup:","אחסן גיבוי טקסט גלוי (plain text):"}. {"Subject","נושא"}. -{"Submit","שליחה"}. +{"Submitted","נשלח"}. +{"Submit","שלח"}. {"Subscriber Address","כתובת מנוי"}. -{"Subscription","מִנּוּי"}. +{"Subscription","הרשמה"}. {"Sunday","יום ראשון"}. {"The CAPTCHA is valid.","‏CAPTCHA הינה בתוקף."}. +{"The collections with which a node is affiliated","האוספים עמם צומת מסונף"}. {"the password is","הסיסמה היא"}. {"The password of your Jabber account was successfully changed.","סיסמת חשבון Jabber שונתה בהצלחה."}. {"There was an error changing the password: ","אירעה שגיאה בשינוי הסיסמה: "}. {"There was an error creating the account: ","אירעה שגיאה ביצירת החשבון: "}. {"There was an error deleting the account: ","אירעה שגיאה במחיקת החשבון: "}. +{"This IP address is blacklisted in ~s","כתובת IP זו רשומה ברשימה שחורה בתוך ~s"}. +{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","חלק זה אינו ער לרישיות: macbeth הינה זהה כשם MacBeth וגם Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","עמוד זה מתיר ליצור חשבון Jabber בשרת Jabber זה. כתובת JID ‏(Jabber IDentifier) תגובש באופן של: username@server. נא לקרוא בזהירות את ההוראות למילוי השדות באופן נכון."}. {"This page allows to unregister a Jabber account in this Jabber server.","עמוד זה מתיר לך לבטל רישום של חשבון Jabber בשרת Jabber זה."}. -{"This room is not anonymous","חדר זה אינו אנונימי"}. {"Thursday","יום חמישי"}. {"Time delay","זמן שיהוי"}. {"Time","זמן"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה בשעה ~s UTC"}. +{"Too many unacked stanzas","יותר מדי סטנזות בלי אישורי קבלה"}. {"To ~s","אל ~s"}. -{"To","אל"}. -{"Transactions Aborted:","טרנזקציות בוטלו:"}. -{"Transactions Committed:","טרנזקציות בוצעו:"}. -{"Transactions Logged:","טרנזקציות נרשמו:"}. -{"Transactions Restarted:","טרנזקציות הותחלו מחדש:"}. +{"Total rooms","חדרים סה״כ"}. +{"To","לכבוד"}. +{"Transactions Aborted:","טרנזקציות שבוטלו:"}. +{"Transactions Committed:","טרנזקציות שבוצעו:"}. +{"Transactions Logged:","טרנזקציות שנרשמו:"}. +{"Transactions Restarted:","טרנזקציות שהותחלו מחדש:"}. {"Tuesday","יום שלישי"}. {"Unauthorized","לא מורשה"}. {"Unregister a Jabber account","בטל רישום חשבון Jabber"}. {"Unregister","בטל רישום"}. -{"Update message of the day (don't send)","עדכן הודעת היום (אל תשלח)"}. -{"Update message of the day on all hosts (don't send)","עדכן הודעת היום בכל המארחים (אל תשלח)"}. +{"Update message of the day (don't send)","עדכן את בשורת היום (אל תשלח)"}. +{"Update message of the day on all hosts (don't send)","עדכן את בשורת היום בכל המארחים (אל תשלח)"}. +{"Update plan","תכנית עדכון"}. +{"Update ~p","עדכון ~p"}. +{"Update script","תסריט עדכון"}. {"Update","עדכן"}. {"Uptime:","זמן פעילות:"}. {"Use of STARTTLS required","נדרש שימוש של STARTTLS"}. @@ -339,6 +371,7 @@ {"User Management","ניהול משתמשים"}. {"Username:","שם משתמש:"}. {"Users Last Activity","פעילות משתמשים אחרונה"}. +{"User ~s","משתמש ~s"}. {"Users","משתמשים"}. {"User","משתמש"}. {"Validate","הענק תוקף"}. @@ -356,4 +389,4 @@ {"You need an x:data capable client to search","עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי לחפש"}. {"Your Jabber account was successfully created.","חשבון Jabber נוצר בהצלחה."}. {"Your Jabber account was successfully deleted.","חשבון Jabber נמחק בהצלחה."}. -{"Your messages to ~s are being blocked. To unblock them, visit ~s","ההודעות שלך לערוץ ~s הינן חסומות. כדי למנוע את חסימתן, בקר בכתובת ~s"}. +{"Your messages to ~s are being blocked. To unblock them, visit ~s","ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s"}. From 1048e21643cb610f112f8dc95d32e3230b819361 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 28 Jul 2015 21:00:12 +0200 Subject: [PATCH 178/695] XEP-0198: Don't add tags to IQ stanzas --- src/ejabberd_c2s.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index e6f55c48993..d5c8c01c1c2 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -3017,6 +3017,8 @@ make_resume_id(StateData) -> {Time, _} = StateData#state.sid, jlib:term_to_base64({StateData#state.resource, Time}). +add_resent_delay_info(_State, #xmlel{name = <<"iq">>} = El, _Time) -> + El; add_resent_delay_info(#state{server = From}, El, Time) -> jlib:add_delay_info(El, From, Time, <<"Resent">>). From 8fe930c3d1fec87a30c23d67cec5363f0aa0abe5 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 28 Jul 2015 21:08:33 +0200 Subject: [PATCH 179/695] Also check for hint Check for the and hints in addition to and . XEP-0334 (0.1) mentions both variants, and unfortunately, both of them are in use. --- src/mod_muc_log.erl | 18 +++++++++++++----- src/mod_offline.erl | 18 +++++------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 14aef01e91c..65e604ba41d 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -241,10 +241,8 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %%% Internal functions %%-------------------------------------------------------------------- add_to_log2(text, {Nick, Packet}, Room, Opts, State) -> - case {xml:get_subtag(Packet, <<"no-store">>), - xml:get_subtag(Packet, <<"no-permanent-store">>)} - of - {false, false} -> + case has_no_permanent_store_hint(Packet) of + false -> case {xml:get_subtag(Packet, <<"subject">>), xml:get_subtag(Packet, <<"body">>)} of @@ -256,7 +254,7 @@ add_to_log2(text, {Nick, Packet}, Room, Opts, State) -> Message = {subject, xml:get_tag_cdata(SubEl)}, add_message_to_log(Nick, Message, Room, Opts, State) end; - {_, _} -> ok + true -> ok end; add_to_log2(roomconfig_change, _Occupants, Room, Opts, State) -> @@ -1255,6 +1253,16 @@ calc_hour_offset(TimeHere) -> fjoin(FileList) -> list_to_binary(filename:join([binary_to_list(File) || File <- FileList])). +has_no_permanent_store_hint(Packet) -> + xml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) + =/= false orelse + xml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) + =/= false orelse + xml:get_subtag_with_xmlns(Packet, <<"no-permanent-store">>, ?NS_HINTS) + =/= false orelse + xml:get_subtag_with_xmlns(Packet, <<"no-permanent-storage">>, ?NS_HINTS) + =/= false. + mod_opt_type(access_log) -> fun (A) when is_atom(A) -> A end; mod_opt_type(cssfile) -> fun iolist_to_binary/1; diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 280f39f6c4d..5165c8e6884 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -308,7 +308,7 @@ need_to_store(LServer, Packet) -> store_packet(From, To, Packet) -> case need_to_store(To#jid.lserver, Packet) of true -> - case has_no_storage_hint(Packet) of + case has_no_store_hint(Packet) of false -> case check_event(From, To, Packet) of true -> @@ -328,18 +328,10 @@ store_packet(From, To, Packet) -> false -> ok end. -has_no_storage_hint(Packet) -> - case xml:get_subtag(Packet, <<"no-store">>) of - #xmlel{attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of - ?NS_HINTS -> - true; - _ -> - false - end; - _ -> - false - end. +has_no_store_hint(Packet) -> + xml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) =/= false + orelse + xml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) =/= false. %% Check if the packet has any content about XEP-0022 or XEP-0085 check_event(From, To, Packet) -> From 04094b3dcf75e58e53d6f7afe88f006293427047 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 28 Jul 2015 21:34:02 +0200 Subject: [PATCH 180/695] Don't copy messages of type "normal" without body Don't carbon-copy messages of type "normal" that don't have a body element as an immediate subtag. Those messages are usually generated by clients or servers (as opposed to messages written by humans). This includes MAM messages, for example. --- src/mod_carboncopy.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 186aca5e374..42c77f15023 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -136,7 +136,7 @@ user_receive_packet(Packet, _C2SState, JID, _From, To) -> % - do not support "private" message mode, and do not modify the original packet in any way % - we also replicate "read" notifications check_and_forward(JID, To, Packet, Direction)-> - case is_chat_or_normal_message(Packet) andalso + case is_chat_message(Packet) andalso xml:get_subtag(Packet, <<"private">>) == false andalso xml:get_subtag(Packet, <<"no-copy">>) == false of true -> @@ -273,13 +273,16 @@ message_type(#xmlel{attrs = Attrs}) -> false -> <<"normal">> end. -is_chat_or_normal_message(#xmlel{name = <<"message">>} = Packet) -> +is_chat_message(#xmlel{name = <<"message">>} = Packet) -> case message_type(Packet) of <<"chat">> -> true; - <<"normal">> -> true; + <<"normal">> -> has_non_empty_body(Packet); _ -> false end; -is_chat_or_normal_message(_Packet) -> false. +is_chat_message(_Packet) -> false. + +has_non_empty_body(Packet) -> + xml:get_subtag_cdata(Packet, <<"body">>) =/= <<"">>. %% list {resource, cc_version} with carbons enabled for given user and host list(User, Server)-> From dfe30824455a77ffad4b7739e5b6dad58eef8d9d Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 30 Jul 2015 18:47:15 +0300 Subject: [PATCH 181/695] Update crypto calls --- test/ejabberd_SUITE.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 075a53fe227..47c4b9e753a 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -467,8 +467,8 @@ presence(Config) -> presence_broadcast(Config) -> Feature = <<"p1:tmp:", (randoms:get_string())/binary>>, - Ver = crypto:sha(["client", $/, "bot", $/, "en", $/, - "ejabberd_ct", $<, Feature, $<]), + Ver = crypto:hash(sha, ["client", $/, "bot", $/, "en", $/, + "ejabberd_ct", $<, Feature, $<]), B64Ver = base64:encode(Ver), Node = <<(?EJABBERD_CT_URI)/binary, $#, B64Ver/binary>>, Server = ?config(server, Config), From f37799223209e428310017829129dbf7f986bb1e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 2 Aug 2015 14:47:06 +0300 Subject: [PATCH 182/695] Do not crash SIP authentication on SCRAMed passwords --- src/mod_sip.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 7e7d2f30739..4827e0c3b14 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -263,8 +263,12 @@ check_auth(#sip{method = Method, hdrs = Hdrs, body = Body}, AuthHdr, _SIPSock) - case ejabberd_auth:get_password_s(LUser, LServer) of <<"">> -> false; - Password -> - esip:check_auth(Auth, Method, Body, Password) + Password when is_binary(Password) -> + esip:check_auth(Auth, Method, Body, Password); + _ScramedPassword -> + ?ERROR_MSG("unable to authenticate ~s@~s against SCRAM'ed " + "password", [LUser, LServer]), + false end; [] -> false From e3b7d43b76ecbca7c56f2e85c83fa6eaf5de6538 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Tue, 4 Aug 2015 09:48:59 +0200 Subject: [PATCH 183/695] Add split_jid/1 This is a convenience reverse of make_jid/1. It allows extracting the jid parts without relying on using the jid record structure, to abstract details. --- src/jlib.erl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/jlib.erl b/src/jlib.erl index 389783b2471..cc0f826ab6d 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -39,7 +39,7 @@ make_error_reply/2, make_error_element/2, make_correct_from_to_attrs/3, replace_from_to_attrs/3, replace_from_to/3, replace_from_attrs/2, replace_from/2, - remove_attr/2, make_jid/3, make_jid/1, string_to_jid/1, + remove_attr/2, make_jid/3, make_jid/1, split_jid/1, string_to_jid/1, jid_to_string/1, is_nodename/1, tolower/1, nodeprep/1, nameprep/1, resourceprep/1, jid_tolower/1, jid_remove_resource/1, jid_replace_resource/2, @@ -214,6 +214,13 @@ make_jid(User, Server, Resource) -> make_jid({User, Server, Resource}) -> make_jid(User, Server, Resource). +%% This is the reverse of make_jid/1 +-spec split_jid(jid()) -> {binary(), binary(), binary()} | error. +split_jid(#jid{user = U, server = S, resource = R}) -> + {U, S, R}; +split_jid(_) -> + error. + -spec string_to_jid(binary()) -> jid() | error. string_to_jid(S) -> From 3d4e8ffac69f7c08b9c44d6c842898574d5c06f8 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 4 Aug 2015 20:13:00 +0200 Subject: [PATCH 184/695] New hook: muc_filter_presence Add a hook that allows for modifying or dropping presence stanzas sent to MUC rooms. --- src/mod_muc_room.erl | 228 ++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 110 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index df06bce4f82..495852d5a30 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1035,117 +1035,125 @@ get_participant_data(From, StateData) -> end. process_presence(From, Nick, - #xmlel{name = <<"presence">>, attrs = Attrs} = Packet, + #xmlel{name = <<"presence">>, attrs = Attrs0} = Packet0, StateData) -> - Type = xml:get_attr_s(<<"type">>, Attrs), - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), - StateData1 = case Type of - <<"unavailable">> -> - case is_user_online(From, StateData) of - true -> - NewPacket = case - {(StateData#state.config)#config.allow_visitor_status, - is_visitor(From, StateData)} - of - {false, true} -> - strip_status(Packet); - _ -> Packet - end, - NewState = add_user_presence_un(From, NewPacket, - StateData), - case (?DICT):find(Nick, StateData#state.nicks) of - {ok, [_, _ | _]} -> ok; - _ -> send_new_presence(From, NewState) - end, - Reason = case xml:get_subtag(NewPacket, - <<"status">>) - of - false -> <<"">>; - Status_el -> - xml:get_tag_cdata(Status_el) - end, - remove_online_user(From, NewState, Reason); - _ -> StateData - end; - <<"error">> -> - case is_user_online(From, StateData) of - true -> - ErrorText = - <<"This participant is kicked from the " - "room because he sent an error presence">>, - expulse_participant(Packet, From, StateData, - translate:translate(Lang, - ErrorText)); - _ -> StateData - end; - <<"">> -> - case is_user_online(From, StateData) of - true -> - case is_nick_change(From, Nick, StateData) of - true -> - case {nick_collision(From, Nick, StateData), - mod_muc:can_use_nick(StateData#state.server_host, - StateData#state.host, - From, Nick), - {(StateData#state.config)#config.allow_visitor_nickchange, - is_visitor(From, StateData)}} - of - {_, _, {false, true}} -> - ErrText = - <<"Visitors are not allowed to change their " - "nicknames in this room">>, - Err = jlib:make_error_reply(Packet, - ?ERRT_NOT_ALLOWED(Lang, - ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, - Nick), - From, Err), - StateData; - {true, _, _} -> - Lang = xml:get_attr_s(<<"xml:lang">>, - Attrs), - ErrText = - <<"That nickname is already in use by another " - "occupant">>, - Err = jlib:make_error_reply(Packet, - ?ERRT_CONFLICT(Lang, - ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, - Nick), % TODO: s/Nick/""/ - From, Err), - StateData; - {_, false, _} -> - ErrText = - <<"That nickname is registered by another " - "person">>, - Err = jlib:make_error_reply(Packet, - ?ERRT_CONFLICT(Lang, - ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, - Nick), - From, Err), - StateData; - _ -> change_nick(From, Nick, StateData) - end; - _NotNickChange -> - Stanza = case - {(StateData#state.config)#config.allow_visitor_status, - is_visitor(From, StateData)} - of - {false, true} -> - strip_status(Packet); - _Allowed -> Packet - end, - NewState = add_user_presence(From, Stanza, - StateData), - send_new_presence(From, NewState), - NewState - end; - _ -> add_new_user(From, Nick, Packet, StateData) - end; - _ -> StateData - end, - close_room_if_temporary_and_empty(StateData1). + Type0 = xml:get_attr_s(<<"type">>, Attrs0), + IsOnline = is_user_online(From, StateData), + if Type0 == <<"">>; + IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) -> + case ejabberd_hooks:run_fold(muc_filter_presence, + StateData#state.server_host, + Packet0, + [StateData, + StateData#state.jid, + From, Nick]) of + drop -> + {next_state, normal_state, StateData}; + #xmlel{attrs = Attrs} = Packet -> + Type = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + StateData1 = case Type of + <<"unavailable">> -> + NewPacket = case + {(StateData#state.config)#config.allow_visitor_status, + is_visitor(From, StateData)} + of + {false, true} -> + strip_status(Packet); + _ -> Packet + end, + NewState = add_user_presence_un(From, NewPacket, + StateData), + case (?DICT):find(Nick, StateData#state.nicks) of + {ok, [_, _ | _]} -> ok; + _ -> send_new_presence(From, NewState) + end, + Reason = case xml:get_subtag(NewPacket, + <<"status">>) + of + false -> <<"">>; + Status_el -> + xml:get_tag_cdata(Status_el) + end, + remove_online_user(From, NewState, Reason); + <<"error">> -> + ErrorText = + <<"This participant is kicked from the " + "room because he sent an error presence">>, + expulse_participant(Packet, From, StateData, + translate:translate(Lang, + ErrorText)); + <<"">> -> + if not IsOnline -> + add_new_user(From, Nick, Packet, StateData); + true -> + case is_nick_change(From, Nick, StateData) of + true -> + case {nick_collision(From, Nick, StateData), + mod_muc:can_use_nick(StateData#state.server_host, + StateData#state.host, + From, Nick), + {(StateData#state.config)#config.allow_visitor_nickchange, + is_visitor(From, StateData)}} + of + {_, _, {false, true}} -> + ErrText = + <<"Visitors are not allowed to change their " + "nicknames in this room">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_NOT_ALLOWED(Lang, + ErrText)), + ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + Nick), + From, Err), + StateData; + {true, _, _} -> + Lang = xml:get_attr_s(<<"xml:lang">>, + Attrs), + ErrText = + <<"That nickname is already in use by another " + "occupant">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_CONFLICT(Lang, + ErrText)), + ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + Nick), % TODO: s/Nick/""/ + From, Err), + StateData; + {_, false, _} -> + ErrText = + <<"That nickname is registered by another " + "person">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_CONFLICT(Lang, + ErrText)), + ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + Nick), + From, Err), + StateData; + _ -> change_nick(From, Nick, StateData) + end; + _NotNickChange -> + Stanza = case + {(StateData#state.config)#config.allow_visitor_status, + is_visitor(From, StateData)} + of + {false, true} -> + strip_status(Packet); + _Allowed -> Packet + end, + NewState = add_user_presence(From, Stanza, + StateData), + send_new_presence(From, NewState), + NewState + end + end + end, + close_room_if_temporary_and_empty(StateData1) + end; + true -> + {next_state, normal_state, StateData} + end. close_room_if_temporary_and_empty(StateData1) -> case not (StateData1#state.config)#config.persistent From 13f7be682db03f5e09b93f5ca5e8daf73ac041a4 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 4 Aug 2015 21:16:45 +0200 Subject: [PATCH 185/695] Rename muc_filter_packet to muc_filter_message The hook is just triggered on groupchat messages, not on other types of stanzas. --- src/mod_muc_room.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 495852d5a30..f505c31559f 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -948,7 +948,7 @@ process_groupchat_message(From, case IsAllowed of true -> case - ejabberd_hooks:run_fold(muc_filter_packet, + ejabberd_hooks:run_fold(muc_filter_message, StateData#state.server_host, Packet, [StateData, From c0497d46afcb6e3dd7b744e364e756e0b7a36f7e Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 5 Aug 2015 00:05:11 +0200 Subject: [PATCH 186/695] mod_client_state: Throttle stanzas by default Enable the mod_client_state options "drop_chat_states" and "queue_presence" by default. These features are now well-tested in practice. --- ejabberd.yml.example | 4 +--- src/mod_client_state.erl | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index c57ef4657d4..b4278eed4ea 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -577,9 +577,7 @@ modules: mod_blocking: {} # requires mod_privacy mod_caps: {} mod_carboncopy: {} - mod_client_state: - drop_chat_states: true - queue_presence: false + mod_client_state: {} mod_configure: {} # requires mod_adhoc mod_disco: {} ## mod_echo: {} diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index bb0d962ff05..eb40db1095f 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -42,11 +42,11 @@ start(Host, Opts) -> QueuePresence = gen_mod:get_opt(queue_presence, Opts, fun(true) -> true; (false) -> false - end, false), + end, true), DropChatStates = gen_mod:get_opt(drop_chat_states, Opts, fun(true) -> true; (false) -> false - end, false), + end, true), if QueuePresence; DropChatStates -> ejabberd_hooks:add(c2s_post_auth_features, Host, ?MODULE, add_stream_feature, 50), From dc0934bff7fabfda0ddce1f9a10e7b815db51b64 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 5 Aug 2015 09:52:54 +0200 Subject: [PATCH 187/695] Update FSF address --- src/ejabberd_xmlrpc.erl | 7 +++---- src/gen_mod.erl | 7 +++---- src/mod_blocking.erl | 7 +++---- src/mod_mam.erl | 7 +++---- src/pubsub_migrate.erl | 7 +++---- 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index c852114506d..1d50bf45b56 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -17,10 +17,9 @@ %%% 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 +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- diff --git a/src/gen_mod.erl b/src/gen_mod.erl index 3dcf4fcfd86..bf48634f3b9 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -17,10 +17,9 @@ %%% 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 +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 609f1664c53..5737129953d 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -17,10 +17,9 @@ %%% 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 +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- diff --git a/src/mod_mam.erl b/src/mod_mam.erl index c3c8a2b927a..d0ac38d5438 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -18,10 +18,9 @@ %%% 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 +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%------------------------------------------------------------------- -module(mod_mam). diff --git a/src/pubsub_migrate.erl b/src/pubsub_migrate.erl index dc01b9af66b..35282d9735d 100644 --- a/src/pubsub_migrate.erl +++ b/src/pubsub_migrate.erl @@ -17,10 +17,9 @@ %%% 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 +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% %%%---------------------------------------------------------------------- From 3a5dd51b42c2d649f21b01e980565cb08558cb78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 5 Aug 2015 16:08:06 +0200 Subject: [PATCH 188/695] Use websocket pings also on old style connections --- src/ejabberd_http_ws.erl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index 66a0542d4ac..902c32f256b 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -263,10 +263,9 @@ setup_timers(StateData) -> Timer = erlang:start_timer(StateData#state.timeout, self(), []), cancel_timer(StateData#state.ping_timer), - PingTimer = case {StateData#state.ping_interval, StateData#state.rfc_compilant} of - {0, _} -> StateData#state.ping_timer; - {_, false} -> StateData#state.ping_timer; - {V, _} -> erlang:start_timer(V, self(), []) + PingTimer = case StateData#state.ping_interval of + 0 -> StateData#state.ping_timer; + V -> erlang:start_timer(V, self(), []) end, StateData#state{timer = Timer, ping_timer = PingTimer, pong_expected = false}. From 4125dfd166067b4c613bd8d49eef5f876fdb1b94 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Wed, 5 Aug 2015 19:17:58 +0300 Subject: [PATCH 189/695] mod_multicast changes: - catch exceptions - do ets:give_away for multicastp table on init - don't send multicasts to itself - don't check user@server for multicast support - handle empty disco items - ignore cdata in - properly check for subdomains --- src/mod_multicast.erl | 122 ++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 41 deletions(-) diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index b39a391be4a..0abf4215c61 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -153,24 +153,11 @@ handle_cast(_Msg, State) -> {noreply, State}. handle_info({route, From, To, #xmlel{name = <<"iq">>, attrs = Attrs} = 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); - reply -> - LServiceS = jts(To), - case xml:get_attr_s(<<"type">>, Attrs) of - <<"result">> -> - process_iqreply_result(From, LServiceS, Packet, State); - <<"error">> -> - process_iqreply_error(From, LServiceS, Packet) - end + case catch handle_iq(From, To, #xmlel{attrs = Attrs} = Packet, State) of + {'EXIT', Reason} -> + ?ERROR_MSG("Error when processing IQ stanza: ~p", + [Reason]); + _ -> ok end, {noreply, State}; %% XEP33 allows only 'message' and 'presence' stanza type @@ -188,11 +175,16 @@ handle_info({route, From, To, handle_info({route_trusted, From, Destinations, Packet}, #state{lservice = LServiceS, lserver = LServerS} = State) -> - route_trusted(LServiceS, LServerS, From, Destinations, - Packet), + case catch route_trusted(LServiceS, LServerS, From, Destinations, + Packet) of + {'EXIT', Reason} -> + ?ERROR_MSG("Error in route_trusted: ~p", [Reason]); + _ -> ok + end, {noreply, State}; handle_info({get_host, Pid}, State) -> - Pid ! {my_host, State#state.lservice}, {noreply, State}; + Pid ! {my_host, State#state.lservice}, + {noreply, State}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, State) -> @@ -210,6 +202,28 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %%% IQ Request Processing %%%------------------------ +handle_iq(From, To, #xmlel{attrs = Attrs} = 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); + reply -> + LServiceS = jts(To), + case xml:get_attr_s(<<"type">>, Attrs) of + <<"result">> -> + process_iqreply_result(From, LServiceS, Packet, State); + <<"error">> -> + process_iqreply_error(From, LServiceS, Packet) + end; + ok -> ok + end. + process_iq(From, #iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} = IQ, @@ -377,6 +391,9 @@ perform(From, Packet, AAttrs, LServiceS, group = Group, renewal = true, sender = From, packet = Packet, aattrs = AAttrs, addresses = Group#group.addresses}); +perform(_From, _Packet, _AAttrs, LServiceS, + {{ask, LServiceS, _}, _Group}) -> + ok; perform(From, Packet, AAttrs, LServiceS, {{ask, Server, not_renewal}, Group}) -> send_query_info(Server, LServiceS), @@ -411,7 +428,7 @@ strip_addresses_element(Packet) -> Els_stripped = lists:keydelete(<<"addresses">>, 2, Els), Packet_stripped = #xmlel{name = Name, attrs = Attrs, children = Els_stripped}, - {ok, Packet_stripped, AAttrs, Addresses}; + {ok, Packet_stripped, AAttrs, xml:remove_cdata(Addresses)}; _ -> throw(ewxmlns) end; _ -> throw(eadsele) @@ -646,7 +663,8 @@ check_relay(RS, LS, Gs) -> end. check_relay_required(RServer, LServerS, Groups) -> - case str:str(RServer, LServerS) > 0 of + case lists:suffix(str:tokens(LServerS, <<".">>), + str:tokens(RServer, <<".">>)) of true -> false; false -> check_relay_required(LServerS, Groups) end. @@ -830,29 +848,44 @@ get_limits_values(Values) -> %%%------------------------- process_discoitems_result(From, LServiceS, Els) -> - List = lists:foldl(fun (XML, Res) -> - case XML of - #xmlel{name = <<"item">>, attrs = Attrs} -> - Res ++ [xml:get_attr_s(<<"jid">>, Attrs)]; - _ -> Res - end - end, - [], Els), - [send_query_info(Item, LServiceS) || Item <- List], FromS = jts(From), - {found_waiter, Waiter} = search_waiter(FromS, LServiceS, - items), - delo_waiter(Waiter), - add_waiter(Waiter#waiter{awaiting = - {List, LServiceS, info}, - renewal = false}). + case search_waiter(FromS, LServiceS, items) of + {found_waiter, Waiter} -> + List = lists:foldl( + fun(XML, Res) -> + case XML of + #xmlel{name = <<"item">>, attrs = Attrs} -> + SJID = xml:get_attr_s(<<"jid">>, Attrs), + case jlib:string_to_jid(SJID) of + #jid{luser = <<"">>, + lresource = <<"">>} -> + [SJID | Res]; + _ -> Res + end; + _ -> Res + end + end, + [], Els), + case List of + [] -> + received_awaiter(FromS, Waiter, LServiceS); + _ -> + [send_query_info(Item, LServiceS) || Item <- List], + delo_waiter(Waiter), + add_waiter(Waiter#waiter{awaiting = + {List, LServiceS, info}, + renewal = false}) + end; + _ -> + ok + end. %%%------------------------- %%% Check protocol support: Receive response: Received awaiter %%%------------------------- received_awaiter(JID, Waiter, LServiceS) -> - {JIDs, LServiceS, info} = Waiter#waiter.awaiting, + {JIDs, LServiceS, _} = Waiter#waiter.awaiting, delo_waiter(Waiter), Group = Waiter#waiter.group, RServer = Group#group.server, @@ -984,8 +1017,12 @@ purge_loop(NM) -> %%%------------------------- create_pool() -> - catch ets:new(multicastp, - [duplicate_bag, public, named_table, {keypos, 2}]). + catch + begin + ets:new(multicastp, + [duplicate_bag, public, named_table, {keypos, 2}]), + ets:give_away(multicastp, whereis(ejabberd), ok) + end. add_waiter(Waiter) -> true = ets:insert(multicastp, Waiter). @@ -993,6 +1030,9 @@ add_waiter(Waiter) -> delo_waiter(Waiter) -> true = ets:delete_object(multicastp, Waiter). +-spec search_waiter(binary(), binary(), info | items) -> + {found_waiter, #waiter{}} | waiter_not_found. + search_waiter(JID, LServiceS, Type) -> Rs = ets:foldl(fun (W, Res) -> {JIDs, LServiceS1, Type1} = W#waiter.awaiting, From f5e857a5bd9bf59f0ac1c52384b41dc5e0a251a2 Mon Sep 17 00:00:00 2001 From: Matthias Rieber Date: Thu, 6 Aug 2015 08:44:15 +0200 Subject: [PATCH 190/695] typo --- src/mod_muc_room.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index f505c31559f..7b8d3e991fe 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1050,7 +1050,7 @@ process_presence(From, Nick, drop -> {next_state, normal_state, StateData}; #xmlel{attrs = Attrs} = Packet -> - Type = xml:get_attr_s(<<"xml:lang">>, Attrs), + Type = xml:get_attr_s(<<"type">>, Attrs), Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), StateData1 = case Type of <<"unavailable">> -> From 45a312a0eb32ccf5378aec0538fca6ffee25c5bb Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 6 Aug 2015 16:57:04 +0200 Subject: [PATCH 191/695] Remove obsolete pubsub migration command --- src/ejabberd_admin.erl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index a0b32304fc8..80342eecd27 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -187,11 +187,6 @@ commands() -> module = ?MODULE, function = delete_old_messages, args = [{days, integer}], result = {res, rescode}}, - #ejabberd_commands{name = rename_default_nodeplugin, tags = [mnesia], - desc = "Update PubSub table from old ejabberd trunk SVN to 2.1.0", - module = mod_pubsub, function = rename_default_nodeplugin, - args = [], result = {res, rescode}}, - #ejabberd_commands{name = export2odbc, tags = [mnesia], desc = "Export virtual host information from Mnesia tables to SQL files", module = ejd2odbc, function = export, From 5a1ac4faf1ea3e1b787dbf2b39f51ae467b17e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 6 Aug 2015 17:12:15 +0200 Subject: [PATCH 192/695] Add ability to override main config file options with data from included files --- src/ejabberd_config.erl | 60 ++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 2ea4c36e9e9..a7ffac7d1da 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -368,6 +368,44 @@ exit_or_halt(ExitText) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Support for 'include_config_file' +get_config_option_key(Name, Val) -> + if Name == listen -> + lists:keyfind(port, 1, Val); + is_tuple(Val) -> + element(1, Val); + true -> + Val + end. + +maps_to_lists(IMap) -> + maps:fold(fun(host_config, Map, Res) -> + [{host_config, [{Host, maps_to_lists(SMap)} || {Host,SMap} <- maps:values(Map)]} | Res]; + (Name, Map, Res) when is_map(Map) -> + [{Name, maps:values(Map)} | Res]; + (Name, Val, Res) -> + [{Name, Val} | Res] + end, [], IMap). + + +merge_configs(Terms, ResMap) -> + lists:foldl(fun({Name, Val}, Map) when is_list(Val) -> + Old = maps:get(Name, Map, #{}), + New = lists:foldl(fun(SVal, OMap) -> + NVal = if Name == host_config -> + {Host, Opts} = SVal, + {_, SubMap} = maps:get(Host, OMap, {Host, #{}}), + {Host, merge_configs(Opts, SubMap)}; + true -> + SVal + end, + maps:put(get_config_option_key(Name, SVal), NVal, OMap) + end, Old, Val), + maps:put(Name, New, Map); + ({Name, Val}, Map) -> + maps:put(Name, Val, Map) + end, ResMap, Terms). + + %% @doc Include additional configuration files in the list of terms. %% @spec ([term()]) -> [term()] include_config_files(Terms) -> @@ -385,25 +423,9 @@ include_config_files(Terms) -> include_config_file(File, Opts) end, lists:flatten(FileOpts)), - SpecialTerms = dict:from_list([{hosts, []}, {listen, []}, {modules, []}]), - PartDict = dict:store(rest, [], SpecialTerms), - Partition = fun(L) -> - lists:foldr(fun({Name, Val} = Pair, Dict) -> - case dict:find(Name, SpecialTerms) of - {ok, _} -> - dict:append_list(Name, Val, Dict); - _ -> - dict:append(rest, Pair, Dict) - end; - (Tuple, Dict2) -> - dict:append(rest, Tuple, Dict2) - end, PartDict, L) - end, - - Merged = dict:merge(fun(_Name, V1, V2) -> V1 ++ V2 end, - Partition(Terms1), Partition(Terms2)), - Rest = dict:fetch(rest, Merged), - dict:to_list(dict:erase(rest, Merged)) ++ Rest. + M1 = merge_configs(Terms1, #{}), + M2 = merge_configs(Terms2, M1), + maps_to_lists(M2). transform_include_option({include_config_file, File}) when is_list(File) -> case is_string(File) of From c71d57a05dec5bf427dcd603372efc9258b1bf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 6 Aug 2015 17:45:19 +0200 Subject: [PATCH 193/695] Handle merging of append_host_config as is done for host_config --- src/ejabberd_config.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index a7ffac7d1da..abb295a75fb 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -378,8 +378,8 @@ get_config_option_key(Name, Val) -> end. maps_to_lists(IMap) -> - maps:fold(fun(host_config, Map, Res) -> - [{host_config, [{Host, maps_to_lists(SMap)} || {Host,SMap} <- maps:values(Map)]} | Res]; + maps:fold(fun(Name, Map, Res) when Name == host_config orelse Name == append_host_config -> + [{Name, [{Host, maps_to_lists(SMap)} || {Host,SMap} <- maps:values(Map)]} | Res]; (Name, Map, Res) when is_map(Map) -> [{Name, maps:values(Map)} | Res]; (Name, Val, Res) -> @@ -391,7 +391,7 @@ merge_configs(Terms, ResMap) -> lists:foldl(fun({Name, Val}, Map) when is_list(Val) -> Old = maps:get(Name, Map, #{}), New = lists:foldl(fun(SVal, OMap) -> - NVal = if Name == host_config -> + NVal = if Name == host_config orelse Name == append_host_config -> {Host, Opts} = SVal, {_, SubMap} = maps:get(Host, OMap, {Host, #{}}), {Host, merge_configs(Opts, SubMap)}; From 40feed723d3b651ff19fdcd7fb31b1c3bad24943 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 6 Aug 2015 13:33:39 +0300 Subject: [PATCH 194/695] Add support for MUC MAM --- include/mod_muc_room.hrl | 3 +- sql/lite.sql | 2 + sql/mysql.sql | 2 + sql/pg.sql | 2 + src/mod_mam.erl | 242 ++++++++++++++++++++++++--------------- src/mod_muc.erl | 15 ++- src/mod_muc_room.erl | 128 ++++++++++++--------- 7 files changed, 246 insertions(+), 148 deletions(-) diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index 5fabbb9e8aa..c90a5c0288b 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -61,7 +61,8 @@ max_users = ?MAX_USERS_DEFAULT :: non_neg_integer() | none, logging = false :: boolean(), vcard = <<"">> :: binary(), - captcha_whitelist = (?SETS):empty() :: ?TGB_SET + captcha_whitelist = (?SETS):empty() :: ?TGB_SET, + mam = false :: boolean() }). -type config() :: #config{}. diff --git a/sql/lite.sql b/sql/lite.sql index 461686d1a04..89d68eadd32 100644 --- a/sql/lite.sql +++ b/sql/lite.sql @@ -279,6 +279,8 @@ CREATE TABLE archive ( xml text NOT NULL, txt text, id INTEGER PRIMARY KEY AUTOINCREMENT, + kind text, + nick text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ); diff --git a/sql/mysql.sql b/sql/mysql.sql index fab76b9a2a8..21e7b9b5277 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -93,6 +93,8 @@ CREATE TABLE archive ( xml text NOT NULL, txt text, id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, + kind varchar(10), + nick varchar(250), created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8; diff --git a/sql/pg.sql b/sql/pg.sql index 2a052d33793..09935691716 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -93,6 +93,8 @@ CREATE TABLE archive ( xml text NOT NULL, txt text, id SERIAL, + kind text, + nick text, created_at TIMESTAMP NOT NULL DEFAULT now() ); diff --git a/src/mod_mam.erl b/src/mod_mam.erl index d0ac38d5438..1d4dd1a5013 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -34,11 +34,12 @@ -export([user_send_packet/4, user_receive_packet/5, process_iq_v0_2/3, process_iq_v0_3/3, remove_user/2, - mod_opt_type/1]). + mod_opt_type/1, muc_process_iq/4, muc_filter_message/5]). -include_lib("stdlib/include/ms_transform.hrl"). -include("jlib.hrl"). -include("logger.hrl"). +-include("mod_muc_room.hrl"). -record(archive_msg, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', @@ -46,7 +47,9 @@ timestamp = now() :: erlang:timestamp() | '_' | '$1', peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', - packet = #xmlel{} :: xmlel() | '_'}). + packet = #xmlel{} :: xmlel() | '_', + nick = <<"">> :: binary(), + type = chat :: chat | groupchat}). -record(archive_prefs, {us = {<<"">>, <<"">>} :: {binary(), binary()}, @@ -75,19 +78,16 @@ start(Host, Opts) -> user_receive_packet, 500), ejabberd_hooks:add(user_send_packet, Host, ?MODULE, user_send_packet, 500), + ejabberd_hooks:add(muc_filter_message, Host, ?MODULE, + muc_filter_message, 50), + ejabberd_hooks:add(muc_process_iq, Host, ?MODULE, + muc_process_iq, 50), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), ok. -init_db(odbc, Host) -> - Muchost = gen_mod:get_module_opt_host(Host, mod_muc, - <<"conference.@HOST@">>), - ets:insert(ejabberd_modules, {ejabberd_module, {mod_mam, Muchost}, - [{db_type, odbc}]}), - mnesia:dirty_write({local_config, {modules,Muchost}, - [{mod_mam, [{db_type, odbc}]}]}); init_db(mnesia, _Host) -> mnesia:create_table(archive_msg, [{disc_only_copies, [node()]}, @@ -114,6 +114,10 @@ stop(Host) -> user_send_packet, 500), ejabberd_hooks:delete(user_receive_packet, Host, ?MODULE, user_receive_packet, 500), + ejabberd_hooks:delete(muc_filter_message, Host, ?MODULE, + muc_filter_message, 50), + ejabberd_hooks:delete(muc_process_iq, Host, ?MODULE, + muc_process_iq, 50), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_TMP), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_0), @@ -152,8 +156,7 @@ user_receive_packet(Pkt, C2SState, JID, Peer, _To) -> case should_archive(Pkt) of true -> NewPkt = strip_my_archived_tag(Pkt, LServer), - case store(C2SState, NewPkt, LUser, LServer, - Peer, true, recv) of + case store_msg(C2SState, NewPkt, LUser, LServer, Peer, recv) of {ok, ID} -> Archived = #xmlel{name = <<"archived">>, attrs = [{<<"by">>, LServer}, @@ -164,8 +167,6 @@ user_receive_packet(Pkt, C2SState, JID, Peer, _To) -> _ -> NewPkt end; - muc -> - Pkt; false -> Pkt end. @@ -174,29 +175,25 @@ user_send_packet(Pkt, C2SState, JID, Peer) -> LUser = JID#jid.luser, LServer = JID#jid.lserver, case should_archive(Pkt) of - S when (S==true) -> + true -> NewPkt = strip_my_archived_tag(Pkt, LServer), - store0(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), - LUser, LServer, Peer, S, send), + store_msg(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), + LUser, LServer, Peer, send), NewPkt; - S when (S==muc) -> - NewPkt = strip_my_archived_tag(Pkt, LServer), - case store0(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), - LUser, LServer, Peer, S, send) of - {ok, ID} -> - By = jlib:jid_to_string(Peer), - Archived = #xmlel{name = <<"archived">>, - attrs = [{<<"by">>, By}, {<<"xmlns">>, ?NS_MAM_TMP}, - {<<"id">>, ID}]}, - NewEls = [Archived|NewPkt#xmlel.children], - NewPkt#xmlel{children = NewEls}; - _ -> - NewPkt - end; false -> Pkt end. +muc_filter_message(Pkt, #state{config = Config} = MUCState, + RoomJID, From, FromNick) -> + if Config#config.mam -> + NewPkt = strip_my_archived_tag(Pkt, MUCState#state.server_host), + store_muc(MUCState, NewPkt, RoomJID, From, FromNick), + NewPkt; + true -> + Pkt + end. + % Query archive v0.2 process_iq_v0_2(#jid{lserver = LServer} = From, #jid{lserver = LServer} = To, @@ -217,7 +214,7 @@ process_iq_v0_2(#jid{lserver = LServer} = From, (_) -> [] end, SubEl#xmlel.children), - process_iq(From, To, IQ, SubEl, Fs); + process_iq(LServer, From, To, IQ, SubEl, Fs, chat); process_iq_v0_2(From, To, IQ) -> process_iq(From, To, IQ). @@ -225,7 +222,28 @@ process_iq_v0_2(From, To, IQ) -> process_iq_v0_3(#jid{lserver = LServer} = From, #jid{lserver = LServer} = To, #iq{type = set, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> - Fs = case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), + process_iq(LServer, From, To, IQ, SubEl, get_xdata_fields(SubEl), chat); +process_iq_v0_3(From, To, IQ) -> + process_iq(From, To, IQ). + +muc_process_iq(#iq{type = set, + sub_el = #xmlel{name = <<"query">>, + attrs = Attrs} = SubEl} = IQ, + MUCState, From, To) -> + case xml:get_attr_s(<<"xmlns">>, Attrs) of + ?NS_MAM_0 -> + LServer = MUCState#state.server_host, + Role = mod_muc_room:get_role(From, MUCState), + process_iq(LServer, From, To, IQ, SubEl, + get_xdata_fields(SubEl), {groupchat, Role}); + _ -> + IQ + end; +muc_process_iq(IQ, _MUCState, _From, _To) -> + IQ. + +get_xdata_fields(SubEl) -> + case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of {#xmlel{} = XData, false} -> jlib:parse_xdata_submit(XData); @@ -235,10 +253,7 @@ process_iq_v0_3(#jid{lserver = LServer} = From, [{<<"set">>, SubEl}]; {false, false} -> [] - end, - process_iq(From, To, IQ, SubEl, Fs); -process_iq_v0_3(From, To, IQ) -> - process_iq(From, To, IQ). + end. %%%=================================================================== %%% Internal functions @@ -276,7 +291,7 @@ process_iq(#jid{luser = LUser, lserver = LServer}, process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. -process_iq(From, To, IQ, SubEl, Fs) -> +process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> case catch lists:foldl( fun({<<"start">>, [Data|_]}, {_, End, With, RSM}) -> {{_, _, _} = jlib:datetime_string_to_timestamp(Data), @@ -301,7 +316,8 @@ process_iq(From, To, IQ, SubEl, Fs) -> {'EXIT', _} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; {Start, End, With, RSM} -> - select_and_send(From, To, Start, End, With, RSM, IQ) + select_and_send(LServer, From, To, Start, End, + With, RSM, IQ, MsgType) end. should_archive(#xmlel{name = <<"message">>} = Pkt) -> @@ -310,11 +326,7 @@ should_archive(#xmlel{name = <<"message">>} = Pkt) -> {<<"error">>, _} -> false; {<<"groupchat">>, _} -> - To = xml:get_attr_s(<<"to">>, Pkt#xmlel.attrs), - case (jlib:string_to_jid(To))#jid.resource of - <<"">> -> muc; - _ -> false - end; + false; {_, <<>>} -> %% Empty body false; @@ -370,43 +382,57 @@ should_archive_peer(C2SState, end end. -store0(C2SState, Pkt, LUser, LServer, Peer, Type, Dir) -> - case Type of - muc -> store(C2SState, Pkt, Peer#jid.luser, LServer, - jlib:jid_replace_resource(Peer, LUser), Type, Dir); - true -> store(C2SState, Pkt, LUser, LServer, Peer, Type, Dir) - end. +should_archive_muc(_MUCState, _Peer) -> + %% TODO + true. -store(C2SState, Pkt, LUser, LServer, Peer, Type, Dir) -> +store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> Prefs = get_prefs(LUser, LServer), case should_archive_peer(C2SState, Prefs, Peer) of true -> - do_store(Pkt, LUser, LServer, Peer, Type, Dir, + US = {LUser, LServer}, + store(Pkt, LServer, US, chat, Peer, <<"">>, Dir, gen_mod:db_type(LServer, ?MODULE)); false -> pass end. -do_store(Pkt, LUser, LServer, Peer, Type, _Dir, mnesia) -> +store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> + case should_archive_muc(MUCState, Peer) of + true -> + LServer = MUCState#state.server_host, + {U, S, _} = jlib:jid_tolower(RoomJID), + store(Pkt, LServer, {U, S}, groupchat, Peer, Nick, recv, + gen_mod:db_type(LServer, ?MODULE)); + false -> + pass + end. + +store(Pkt, _, {LUser, LServer}, Type, Peer, Nick, _Dir, mnesia) -> LPeer = {PUser, PServer, _} = jlib:jid_tolower(Peer), - LServer2 = case Type of muc -> Peer#jid.lserver; _ -> LServer end, TS = now(), ID = jlib:integer_to_binary(now_to_usec(TS)), case mnesia:dirty_write( - #archive_msg{us = {LUser, LServer2}, + #archive_msg{us = {LUser, LServer}, id = ID, timestamp = TS, peer = LPeer, bare_peer = {PUser, PServer, <<>>}, + type = Type, + nick = Nick, packet = Pkt}) of ok -> {ok, ID}; Err -> Err end; -do_store(Pkt, LUser, LServer, Peer, _Type, _Dir, odbc) -> +store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> TSinteger = now_to_usec(now()), ID = TS = jlib:integer_to_binary(TSinteger), + SUser = case Type of + chat -> LUser; + groupchat -> jlib:jid_to_string({LUser, LHost, <<>>}) + end, BarePeer = jlib:jid_to_string( jlib:jid_tolower( jlib:jid_remove_resource(Peer))), @@ -417,13 +443,15 @@ do_store(Pkt, LUser, LServer, Peer, _Type, _Dir, odbc) -> case ejabberd_odbc:sql_query( LServer, [<<"insert into archive (username, timestamp, " - "peer, bare_peer, xml, txt) values (">>, - <<"'">>, ejabberd_odbc:escape(LUser), <<"', ">>, + "peer, bare_peer, xml, txt, kind, nick) values (">>, + <<"'">>, ejabberd_odbc:escape(SUser), <<"', ">>, <<"'">>, TS, <<"', ">>, <<"'">>, ejabberd_odbc:escape(LPeer), <<"', ">>, <<"'">>, ejabberd_odbc:escape(BarePeer), <<"', ">>, <<"'">>, ejabberd_odbc:escape(XML), <<"', ">>, - <<"'">>, ejabberd_odbc:escape(Body), <<"');">>]) of + <<"'">>, ejabberd_odbc:escape(Body), <<"', ">>, + <<"'">>, jlib:atom_to_binary(Type), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(Nick), <<"');">>]) of {updated, _} -> {ok, ID}; Err -> @@ -507,34 +535,37 @@ get_prefs(LUser, LServer, odbc) -> error end. -select_and_send(#jid{lserver = LServer} = From, - To, Start, End, With, RSM, IQ) -> +select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType) -> DBType = case gen_mod:db_type(LServer, ?MODULE) of odbc -> {odbc, LServer}; DB -> DB end, - select_and_send(From, To, Start, End, With, RSM, IQ, - DBType). + select_and_send(LServer, From, To, Start, End, With, RSM, IQ, + MsgType, DBType). -select_and_send(From, To, Start, End, With, RSM, IQ, DBType) -> - {Msgs, IsComplete, Count} = select_and_start(From, To, Start, End, With, - RSM, DBType), +select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType, DBType) -> + {Msgs, IsComplete, Count} = select_and_start(LServer, From, To, Start, End, + With, RSM, MsgType, DBType), SortedMsgs = lists:keysort(2, Msgs), send(From, To, SortedMsgs, RSM, Count, IsComplete, IQ). -select_and_start(From, _To, StartUser, End, With, RSM, DB) -> - {JidRequestor, Start, With2} = case With of - {room, {LUserRoom, LServerRoom, <<>>} = WithJid} -> - JR = jlib:make_jid(LUserRoom,LServerRoom,<<>>), - St = StartUser, - {JR, St, WithJid}; +select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> + case MsgType of + chat -> + case With of + {room, {_, _, <<"">>} = WithJID} -> + select(LServer, jlib:make_jid(WithJID), Start, End, + WithJID, RSM, MsgType, DBType); _ -> - {From, StartUser, With} - end, - select(JidRequestor, Start, End, With2, RSM, DB). + select(LServer, From, Start, End, + With, RSM, MsgType, DBType) + end; + {groupchat, _Role} -> + select(LServer, To, Start, End, With, RSM, MsgType, DBType) + end. -select(#jid{luser = LUser, lserver = LServer} = JidRequestor, - Start, End, With, RSM, mnesia) -> +select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor, + Start, End, With, RSM, MsgType, mnesia) -> MS = make_matchspec(LUser, LServer, Start, End, With), Msgs = mnesia:dirty_select(archive_msg, MS), {FilteredMsgs, IsComplete} = filter_by_rsm(Msgs, RSM), @@ -543,12 +574,16 @@ select(#jid{luser = LUser, lserver = LServer} = JidRequestor, fun(Msg) -> {Msg#archive_msg.id, jlib:binary_to_integer(Msg#archive_msg.id), - msg_to_el(Msg, JidRequestor)} + msg_to_el(Msg, MsgType, JidRequestor)} end, FilteredMsgs), IsComplete, Count}; -select(#jid{luser = LUser, lserver = LServer} = JidRequestor, - Start, End, With, RSM, {odbc, Host}) -> - {Query, CountQuery} = make_sql_query(LUser, LServer, - Start, End, With, RSM), +select(LServer, #jid{luser = LUser} = JidRequestor, + Start, End, With, RSM, MsgType, {odbc, Host}) -> + User = case MsgType of + chat -> LUser; + {groupchat, _Role} -> jlib:jid_to_string(JidRequestor) + end, + {Query, CountQuery} = make_sql_query(User, LServer, + Start, End, With, RSM), % XXX TODO from XEP-0313: % To conserve resources, a server MAY place a reasonable limit on % how many stanzas may be pushed to a client in one request. If a @@ -573,24 +608,31 @@ select(#jid{luser = LUser, lserver = LServer} = JidRequestor, {Res, true} end, {lists:map( - fun([TS, XML, PeerBin]) -> + fun([TS, XML, PeerBin, Kind, Nick]) -> #xmlel{} = El = xml_stream:parse_element(XML), Now = usec_to_now(jlib:binary_to_integer(TS)), PeerJid = jlib:jid_tolower(jlib:string_to_jid(PeerBin)), + T = if Kind /= <<"">> -> + jlib:binary_to_atom(Kind); + true -> chat + end, {TS, jlib:binary_to_integer(TS), msg_to_el(#archive_msg{timestamp = Now, packet = El, + type = T, + nick = Nick, peer = PeerJid}, + MsgType, JidRequestor)} end, Res1), IsComplete, jlib:binary_to_integer(Count)}; _ -> {[], false, 0} end. -msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, peer = Peer}, - JidRequestor) -> +msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, + MsgType, JidRequestor) -> Delay = jlib:now_to_utc_string(TS), - Pkt = maybe_update_from_to(Pkt1, JidRequestor, Peer), + Pkt = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick), #xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}], children = [#xmlel{name = <<"delay">>, @@ -599,9 +641,9 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, peer = Peer}, xml:replace_tag_attr( <<"xmlns">>, <<"jabber:client">>, Pkt)]}. -maybe_update_from_to(Pkt, _JIDRequestor, undefined) -> +maybe_update_from_to(Pkt, _JIDRequestor, undefined, _Type, _Nick) -> Pkt; -maybe_update_from_to(Pkt, JidRequestor, Peer) -> +maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of <<"groupchat">> -> Pkt2 = xml:replace_tag_attr(<<"to">>, @@ -610,7 +652,23 @@ maybe_update_from_to(Pkt, JidRequestor, Peer) -> xml:replace_tag_attr(<<"from">>, jlib:jid_to_string(Peer), Pkt2); _ -> Pkt - end. + end; +maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, + Peer, {groupchat, Role}, Nick) -> + Items = case Role of + moderator -> + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_MUC_ADMIN}], + children = + [#xmlel{name = <<"item">>, + attrs = [{<<"jid">>, + jlib:jid_to_string(Peer)}]}]}]; + _ -> + [] + end, + Pkt1 = Pkt#xmlel{children = Items ++ Els}, + Pkt2 = jlib:replace_from(jlib:jid_replace_resource(JidRequestor, Nick), Pkt1), + jlib:remove_attr(<<"to">>, Pkt2). send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> QID = xml:get_tag_attr_s(<<"queryid">>, SubEl), @@ -737,7 +795,7 @@ make_matchspec(LUser, LServer, Start, End, none) -> Msg end). -make_sql_query(LUser, _LServer, Start, End, With, RSM) -> +make_sql_query(User, _LServer, Start, End, With, RSM) -> {Max, Direction, ID} = case RSM of #rsm_in{} -> {RSM#rsm_in.max, @@ -795,9 +853,9 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> _ -> [] end, - SUser = ejabberd_odbc:escape(LUser), + SUser = ejabberd_odbc:escape(User), - Query = [<<"SELECT timestamp, xml, peer" + Query = [<<"SELECT timestamp, xml, peer, kind, nick" " FROM archive WHERE username='">>, SUser, <<"'">>, WithClause, StartClause, EndClause, PageClause], @@ -808,7 +866,7 @@ make_sql_query(LUser, _LServer, Start, End, With, RSM) -> % ID can be empty because of % XEP-0059: Result Set Management % 2.5 Requesting the Last Page in a Result Set - [<<"SELECT timestamp, xml, peer FROM (">>, Query, + [<<"SELECT timestamp, xml, peer, kind, nick FROM (">>, Query, <<" ORDER BY timestamp DESC ">>, LimitClause, <<") AS t ORDER BY timestamp ASC;">>]; _ -> diff --git a/src/mod_muc.erl b/src/mod_muc.erl index e798790c5d1..725051e6652 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -345,6 +345,7 @@ init([Host, Opts]) -> persistent -> Bool; public -> Bool; public_list -> Bool; + mam -> Bool; password -> fun iolist_to_binary/1; title -> fun iolist_to_binary/1; allow_private_messages_from_visitors -> @@ -524,7 +525,8 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, attrs = [{<<"xmlns">>, XMLNS}], children = - iq_disco_info(Lang) ++ + iq_disco_info( + ServerHost, Lang) ++ Info}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)); @@ -767,7 +769,7 @@ register_room(Host, Room, Pid) -> mnesia:transaction(F). -iq_disco_info(Lang) -> +iq_disco_info(ServerHost, Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"conference">>}, @@ -788,7 +790,14 @@ iq_disco_info(Lang) -> #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_RSM}], children = []}, #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_VCARD}], children = []}]. + attrs = [{<<"var">>, ?NS_VCARD}], children = []}] ++ + case gen_mod:is_loaded(ServerHost, mod_mam) of + true -> + [#xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_MAM_0}]}]; + false -> + [] + end. iq_disco_items(Host, From, Lang, none) -> lists:zf(fun (#muc_online_room{name_host = diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 7b8d3e991fe..c1bbbe5c922 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -34,6 +34,7 @@ start_link/7, start/9, start/7, + get_role/2, route/4]). %% gen_fsm callbacks @@ -426,56 +427,67 @@ normal_state({route, From, <<"">>, #xmlel{name = <<"iq">>} = Packet}, StateData) -> case jlib:iq_query_info(Packet) of - #iq{type = Type, xmlns = XMLNS, lang = Lang, - sub_el = #xmlel{name = SubElName} = SubEl} = - IQ - when (XMLNS == (?NS_MUC_ADMIN)) or - (XMLNS == (?NS_MUC_OWNER)) - or (XMLNS == (?NS_DISCO_INFO)) - or (XMLNS == (?NS_DISCO_ITEMS)) - or (XMLNS == (?NS_VCARD)) - or (XMLNS == (?NS_CAPTCHA)) -> - Res1 = case XMLNS of - ?NS_MUC_ADMIN -> - process_iq_admin(From, Type, Lang, SubEl, StateData); - ?NS_MUC_OWNER -> - process_iq_owner(From, Type, Lang, SubEl, StateData); - ?NS_DISCO_INFO -> - process_iq_disco_info(From, Type, Lang, StateData); - ?NS_DISCO_ITEMS -> - process_iq_disco_items(From, Type, Lang, StateData); - ?NS_VCARD -> - process_iq_vcard(From, Type, Lang, SubEl, StateData); - ?NS_CAPTCHA -> - process_iq_captcha(From, Type, Lang, SubEl, StateData) - end, - {IQRes, NewStateData} = case Res1 of - {result, Res, SD} -> - {IQ#iq{type = result, - sub_el = - [#xmlel{name = SubElName, - attrs = - [{<<"xmlns">>, - XMLNS}], - children = Res}]}, - SD}; - {error, Error} -> - {IQ#iq{type = error, - sub_el = [SubEl, Error]}, - StateData} - end, - ejabberd_router:route(StateData#state.jid, From, - jlib:iq_to_xml(IQRes)), - case NewStateData of - stop -> {stop, normal, StateData}; - _ -> {next_state, normal_state, NewStateData} - end; - reply -> {next_state, normal_state, StateData}; - _ -> - Err = jlib:make_error_reply(Packet, - ?ERR_FEATURE_NOT_IMPLEMENTED), - ejabberd_router:route(StateData#state.jid, From, Err), - {next_state, normal_state, StateData} + reply -> + {next_state, normal_state, StateData}; + IQ0 -> + case ejabberd_hooks:run_fold( + muc_process_iq, + StateData#state.server_host, + IQ0, [StateData, From, StateData#state.jid]) of + ignore -> + {next_state, normal_state, StateData}; + #iq{type = T} = IQRes when T == error; T == result -> + ejabberd_router:route(StateData#state.jid, From, jlib:iq_to_xml(IQRes)), + {next_state, normal_state, StateData}; + #iq{type = Type, xmlns = XMLNS, lang = Lang, + sub_el = #xmlel{name = SubElName} = SubEl} = IQ + when (XMLNS == (?NS_MUC_ADMIN)) or + (XMLNS == (?NS_MUC_OWNER)) + or (XMLNS == (?NS_DISCO_INFO)) + or (XMLNS == (?NS_DISCO_ITEMS)) + or (XMLNS == (?NS_VCARD)) + or (XMLNS == (?NS_CAPTCHA)) -> + Res1 = case XMLNS of + ?NS_MUC_ADMIN -> + process_iq_admin(From, Type, Lang, SubEl, StateData); + ?NS_MUC_OWNER -> + process_iq_owner(From, Type, Lang, SubEl, StateData); + ?NS_DISCO_INFO -> + process_iq_disco_info(From, Type, Lang, StateData); + ?NS_DISCO_ITEMS -> + process_iq_disco_items(From, Type, Lang, StateData); + ?NS_VCARD -> + process_iq_vcard(From, Type, Lang, SubEl, StateData); + ?NS_CAPTCHA -> + process_iq_captcha(From, Type, Lang, SubEl, StateData) + end, + {IQRes, NewStateData} = + case Res1 of + {result, Res, SD} -> + {IQ#iq{type = result, + sub_el = + [#xmlel{name = SubElName, + attrs = + [{<<"xmlns">>, + XMLNS}], + children = Res}]}, + SD}; + {error, Error} -> + {IQ#iq{type = error, + sub_el = [SubEl, Error]}, + StateData} + end, + ejabberd_router:route(StateData#state.jid, From, jlib:iq_to_xml(IQRes)), + case NewStateData of + stop -> {stop, normal, StateData}; + _ -> {next_state, normal_state, NewStateData} + end; + _ -> + Err = jlib:make_error_reply(Packet, + ?ERR_FEATURE_NOT_IMPLEMENTED), + ejabberd_router:route(StateData#state.jid, From, Err), + {next_state, normal_state, StateData} + end end; normal_state({route, From, Nick, #xmlel{name = <<"presence">>} = Packet}, @@ -962,11 +974,11 @@ process_groupchat_message(From, FromNick), StateData#state.server_host, StateData#state.users, - Packet), + NewPacket), NewStateData2 = case has_body_or_subject(Packet) of true -> add_message_to_history(FromNick, From, - Packet, + NewPacket, NewStateData1); false -> NewStateData1 @@ -3531,6 +3543,13 @@ get_config(Lang, StateData, From) -> <<"captcha_protected">>, (Config#config.captcha_protected))]; false -> [] + end ++ + case gen_mod:is_loaded(StateData#state.server_host, mod_mam) of + true -> + [?BOOLXFIELD(<<"Enable message archiving">>, + <<"muc#roomconfig_mam">>, + (Config#config.mam))]; + false -> [] end ++ [?JIDMULTIXFIELD(<<"Exclude Jabber IDs from CAPTCHA challenge">>, @@ -3740,6 +3759,8 @@ set_xoption([{<<"muc#roomconfig_enablelogging">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(logging, Val); +set_xoption([{<<"muc#roomconfig_mam">>, [Val]}|Opts], Config) -> + ?SET_BOOL_XOPT(mam, Val); set_xoption([{<<"muc#roomconfig_captcha_whitelist">>, Vals} | Opts], @@ -3902,6 +3923,9 @@ set_opts([{Opt, Val} | Opts], StateData) -> StateData#state{config = (StateData#state.config)#config{logging = Val}}; + mam -> + StateData#state{config = + (StateData#state.config)#config{mam = Val}}; captcha_whitelist -> StateData#state{config = (StateData#state.config)#config{captcha_whitelist From 2392f09e99b722a4f9ecea358ad7ae18622ab30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 12 Aug 2015 11:53:54 +0200 Subject: [PATCH 195/695] Ejabberd now requires erlang R17+ --- .travis.yml | 1 - README | 2 +- configure.ac | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9424c811156..c058d82a3f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: erlang otp_release: - 17.4 - - R16B03 services: - riak diff --git a/README b/README index 31a76778b7a..884a2905795 100644 --- a/README +++ b/README @@ -106,7 +106,7 @@ To compile ejabberd you need: - GCC. - Libexpat 1.95 or higher. - Libyaml 0.1.4 or higher. - - Erlang/OTP R16B03 or higher. + - Erlang/OTP R17 or higher. - OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption. - Zlib 1.2.3 or higher, for Stream Compression support (XEP-0138). Optional. - PAM library. Optional. For Pluggable Authentication Modules (PAM). diff --git a/configure.ac b/configure.ac index 0a60de08821..564bc03d547 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.53) AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd]) -REQUIRE_ERLANG_MIN="5.9.1 (Erlang/OTP R15B01)" +REQUIRE_ERLANG_MIN="6.4 (Erlang/OTP R17)" REQUIRE_ERLANG_MAX="9.0.0 (No Max)" AC_CONFIG_MACRO_DIR([m4]) From ab0f488dda3f9efc260b30ebc3611a95a84dfcda Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 12 Aug 2015 12:40:37 +0200 Subject: [PATCH 196/695] Room response to disco#info node muc#traffic should be an error (EJAB-741) --- src/mod_muc_room.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index c1bbbe5c922..41d4a3dfad4 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -440,7 +440,7 @@ normal_state({route, From, <<"">>, ejabberd_router:route(StateData#state.jid, From, jlib:iq_to_xml(IQRes)), {next_state, normal_state, StateData}; #iq{type = Type, xmlns = XMLNS, lang = Lang, - sub_el = #xmlel{name = SubElName} = SubEl} = IQ + sub_el = #xmlel{name = SubElName, attrs = Attrs} = SubEl} = IQ when (XMLNS == (?NS_MUC_ADMIN)) or (XMLNS == (?NS_MUC_OWNER)) or (XMLNS == (?NS_DISCO_INFO)) @@ -453,7 +453,10 @@ normal_state({route, From, <<"">>, ?NS_MUC_OWNER -> process_iq_owner(From, Type, Lang, SubEl, StateData); ?NS_DISCO_INFO -> - process_iq_disco_info(From, Type, Lang, StateData); + case xml:get_attr(<<"node">>, Attrs) of + false -> process_iq_disco_info(From, Type, Lang, StateData); + {value, _} -> {error, ?ERR_SERVICE_UNAVAILABLE} + end; ?NS_DISCO_ITEMS -> process_iq_disco_items(From, Type, Lang, StateData); ?NS_VCARD -> From 8c9c556f1f4851535366ea1f20ae7c7dcc1e3fab Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 12 Aug 2015 13:26:24 +0200 Subject: [PATCH 197/695] Changed API of some mod_muc_admin command arguments With this commit, arguments change in two commands: * destroy_room: does not require Host argument * send_direct_invitation: instead of Room, now requires Name and Service --- src/mod_muc_admin.erl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 6aa3482dc7b..7d044434507 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -12,11 +12,11 @@ -behaviour(gen_mod). -export([start/2, stop/1, muc_online_rooms/1, - muc_unregister_nick/1, create_room/3, destroy_room/3, + muc_unregister_nick/1, create_room/3, destroy_room/2, create_rooms_file/1, destroy_rooms_file/1, rooms_unused_list/2, rooms_unused_destroy/2, get_user_rooms/2, get_room_occupants/2, - get_room_occupants_number/2, send_direct_invitation/4, + get_room_occupants_number/2, send_direct_invitation/5, change_room_option/4, get_room_options/2, set_room_affiliation/4, get_room_affiliations/2, web_menu_main/2, web_page_main/2, web_menu_host/3, @@ -77,8 +77,7 @@ commands() -> #ejabberd_commands{name = destroy_room, tags = [muc_room], desc = "Destroy a MUC room", module = ?MODULE, function = destroy_room, - args = [{name, binary}, {service, binary}, - {host, binary}], + args = [{name, binary}, {service, binary}], result = {res, rescode}}, #ejabberd_commands{name = create_rooms_file, tags = [muc], desc = "Create the rooms indicated in file", @@ -129,7 +128,7 @@ commands() -> desc = "Send a direct invitation to several destinations", longdesc = "Password and Message can also be: none. Users JIDs are separated with : ", module = ?MODULE, function = send_direct_invitation, - args = [{room, binary}, {password, binary}, {reason, binary}, {users, binary}], + args = [{name, binary}, {service, binary}, {password, binary}, {reason, binary}, {users, binary}], result = {res, rescode}}, #ejabberd_commands{name = change_room_option, tags = [muc_room], @@ -444,12 +443,12 @@ muc_create_room(ServerHost, {Name, Host, _}, DefRoomOpts) -> io:format("Creating room ~s@~s~n", [Name, Host]), mod_muc:store_room(ServerHost, Host, Name, DefRoomOpts). -%% @spec (Name::binary(), Host::binary(), ServerHost::binary()) -> +%% @spec (Name::binary(), Host::binary()) -> %% ok | {error, room_not_exists} %% @doc Destroy the room immediately. %% If the room has participants, they are not notified that the room was destroyed; %% they will notice when they try to chat and receive an error that the room doesn't exist. -destroy_room(Name, Service, _Server) -> +destroy_room(Name, Service) -> case mnesia:dirty_read(muc_online_room, {Name, Service}) of [R] -> Pid = R#muc_online_room.pid, @@ -461,7 +460,7 @@ destroy_room(Name, Service, _Server) -> destroy_room({N, H, SH}) -> io:format("Destroying room: ~s@~s - vhost: ~s~n", [N, H, SH]), - destroy_room(N, H, SH). + destroy_room(N, H). %%---------------------------- @@ -689,8 +688,9 @@ get_room_occupants_number(Room, Host) -> %%---------------------------- %% http://xmpp.org/extensions/xep-0249.html -send_direct_invitation(RoomString, Password, Reason, UsersString) -> - RoomJid = jlib:string_to_jid(RoomString), +send_direct_invitation(RoomName, RoomService, Password, Reason, UsersString) -> + RoomJid = jlib:make_jid(RoomName, RoomService, <<"">>), + RoomString = jlib:jid_to_string(RoomJid), XmlEl = build_invitation(Password, Reason, RoomString), UsersStrings = get_users_to_invite(RoomJid, binary_to_list(UsersString)), [send_direct_invitation(RoomJid, jlib:string_to_jid(list_to_binary(UserStrings)), XmlEl) From 279d4b00acbcd6d6aa3e1e72a7169a24b292af07 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 12 Aug 2015 17:18:41 +0200 Subject: [PATCH 198/695] Fix and document create_rooms_file and destroy_ --- src/mod_muc_admin.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 7d044434507..4741a23e18f 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -81,11 +81,13 @@ commands() -> result = {res, rescode}}, #ejabberd_commands{name = create_rooms_file, tags = [muc], desc = "Create the rooms indicated in file", + longdesc = "Provide one room JID per line. Rooms will be created after restart.", module = ?MODULE, function = create_rooms_file, args = [{file, string}], result = {res, rescode}}, #ejabberd_commands{name = destroy_rooms_file, tags = [muc], desc = "Destroy the rooms indicated in file", + longdesc = "Provide one room JID per line.", module = ?MODULE, function = destroy_rooms_file, args = [{file, string}], result = {res, rescode}}, @@ -502,7 +504,7 @@ split_roomjid(RoomJID) -> [Name, Host] = string:tokens(RoomJID, "@"), [_MUC_service_name | ServerHostList] = string:tokens(Host, "."), ServerHost = join(ServerHostList, "."), - {Name, Host, ServerHost}. + {list_to_binary(Name), list_to_binary(Host), list_to_binary(ServerHost)}. %% This function is copied from string:join/2 in Erlang/OTP R12B-1 %% Note that string:join/2 is not implemented in Erlang/OTP R11B From 994602c97d1d4cf013aa005bd0456a8bc094dc08 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 12 Aug 2015 20:23:28 +0200 Subject: [PATCH 199/695] Store and retrieve "mam" value in room configuration --- src/mod_muc_room.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 41d4a3dfad4..b7621829252 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -3985,6 +3985,7 @@ make_opts(StateData) -> ?MAKE_CONFIG_OPT(password), ?MAKE_CONFIG_OPT(anonymous), ?MAKE_CONFIG_OPT(logging), ?MAKE_CONFIG_OPT(max_users), ?MAKE_CONFIG_OPT(allow_voice_requests), + ?MAKE_CONFIG_OPT(mam), ?MAKE_CONFIG_OPT(voice_request_min_interval), ?MAKE_CONFIG_OPT(vcard), {captcha_whitelist, From ac6b436dcfbe414f16e39d59d0324404c3000709 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 13 Aug 2015 12:22:03 +0200 Subject: [PATCH 200/695] Prettify copyright links (thanks to GreenLunar)(#692) --- src/ejabberd_web_admin.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 45ad7b6dc54..7df7ee090d7 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -550,7 +550,12 @@ css(Host) -> "#FE8A02;\n padding: 1em;\n margin-right: " "1em;\n background: #FFE3C9;\n}\n\n*.alignrig" "ht {\n font-size: 10pt;\n text-align: " - "right;\n}\n\n">>. + "right;\n}\n\n#copyright a:link {\n color: " + "#ffffff;\n text-decoration: none;\n}\n" + "#copyright a:visited {\n color: #ffffff;\n " + "text-decoration: none;\n}\n#copyright a:hover" + " {\n color: #ffffff;\n text-decoration: " + "underline;\n}\n">>. favicon() -> jlib:decode_base64(<<"AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAA" From 3efd0ebc5acff8ff59aecd919b3e193be2edae8c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 13 Aug 2015 13:06:05 +0200 Subject: [PATCH 201/695] configure.ac: Don't insist on Erlang/OTP >= 17.5 The current ejabberd code works on Erlang/OTP 17.1 or newer. We now also let Travis CI test this version in addition to 17.5. --- .travis.yml | 3 ++- README | 2 +- configure.ac | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c058d82a3f3..a60bb3ac27d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: erlang otp_release: - - 17.4 + - 17.1 + - 17.5 services: - riak diff --git a/README b/README index 884a2905795..f03c194a7c9 100644 --- a/README +++ b/README @@ -106,7 +106,7 @@ To compile ejabberd you need: - GCC. - Libexpat 1.95 or higher. - Libyaml 0.1.4 or higher. - - Erlang/OTP R17 or higher. + - Erlang/OTP 17.1 or higher. - OpenSSL 0.9.8 or higher, for STARTTLS, SASL and SSL encryption. - Zlib 1.2.3 or higher, for Stream Compression support (XEP-0138). Optional. - PAM library. Optional. For Pluggable Authentication Modules (PAM). diff --git a/configure.ac b/configure.ac index 564bc03d547..d7842be3a40 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.53) AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd]) -REQUIRE_ERLANG_MIN="6.4 (Erlang/OTP R17)" +REQUIRE_ERLANG_MIN="6.1 (Erlang/OTP 17.1)" REQUIRE_ERLANG_MAX="9.0.0 (No Max)" AC_CONFIG_MACRO_DIR([m4]) From 6d16029716ef68a7b52168a74c368147b8328284 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 15 Aug 2015 17:01:47 +0200 Subject: [PATCH 202/695] Let ejabberdctl handle more shell metacharacters Closes #704. --- ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 79f443890c2..4704c85c4a5 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -405,7 +405,7 @@ ctl() ctlexec() { CONN_NAME=$1; shift - COMMAND=$(echo $@ | sed 's/;/\\;/g') + COMMAND=$(echo $@ | sed 's/["&$;\|<>()]/\\&/g') $EXEC_CMD "$ERL \ $NAME ${CONN_NAME} \ -noinput \ From f89db30d7740b38ce942c2e05cb6a6f16fa0812a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 17 Aug 2015 15:50:02 +0200 Subject: [PATCH 203/695] Catch errors when calling inet:peername in ejabberd_http --- src/ejabberd_http.erl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 1702e9be6a7..61ce6473411 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -160,7 +160,11 @@ init({SockMod, Socket}, Opts) -> default_host = DefaultHost, options = Opts, request_handlers = RequestHandlers}, - receive_headers(State). + try receive_headers(State) of + V -> V + catch + {error, _} -> State + end. become_controller(_Pid) -> ok. @@ -427,13 +431,17 @@ process_request(#state{request_method = Method, false -> make_bad_request(State); {LPath, LQuery, Data} -> - {ok, IPHere} = + PeerName = case SockMod of gen_tcp -> inet:peername(Socket); _ -> SockMod:peername(Socket) end, + IPHere = case PeerName of + {ok, V} -> V; + {error, _} = E -> throw(E) + end, XFF = proplists:get_value('X-Forwarded-For', RequestHeaders, []), IP = analyze_ip_xff(IPHere, XFF, Host), Request = #request{method = Method, From 6f0ee8331740f5b142d37789752c8a67883e80d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 19 Aug 2015 10:14:09 +0200 Subject: [PATCH 204/695] Don't overwrite listeners for different transports in config merging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this having listeners on same port for both tcp and udp would after config merging step left only one of them. Many thanks to Holger Weiß for noticing this. --- src/ejabberd_config.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index abb295a75fb..89e1399fac0 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -370,7 +370,10 @@ exit_or_halt(ExitText) -> get_config_option_key(Name, Val) -> if Name == listen -> - lists:keyfind(port, 1, Val); + case {lists:keyfind(port, 1, Val), lists:keyfind(transport, 1, Val)} of + {{_, Port}, false} -> {Port, tcp}; + {{_, Port2}, {_, Trans}} -> {Port2, Trans} + end; is_tuple(Val) -> element(1, Val); true -> From 775cf2d45911de322b3486b6f3c10717313fa58d Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 14 Aug 2015 16:42:10 +0300 Subject: [PATCH 205/695] Change namespace from muc#admin to muc#user --- src/mod_mam.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 1d4dd1a5013..bbe279cb909 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -658,7 +658,7 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, Items = case Role of moderator -> [#xmlel{name = <<"x">>, - attrs = [{<<"xmlns">>, ?NS_MUC_ADMIN}], + attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, From b570070834df7df615c2a59caabed0dabd29b6f4 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 19 Aug 2015 23:47:45 +0300 Subject: [PATCH 206/695] Fix case clause during S2S certificate checks --- src/ejabberd_s2s.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 74831fffb9a..3acf19a1d06 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -241,7 +241,7 @@ check_peer_certificate(SockMod, Sock, Peer) -> VerifyRes -> {error, p1_tls:get_cert_verify_string(VerifyRes, Cert)} end; - error -> + {error, _Reason} -> {error, <<"Cannot get peer certificate">>} end. From 6177ae3ffbdc3a9fc899d27e396caa7a5fc9aea2 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 20 Aug 2015 01:04:56 +0300 Subject: [PATCH 207/695] Improve S2S certificate checks --- src/ejabberd_s2s.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 3acf19a1d06..e1c9ab9dab7 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -242,7 +242,9 @@ check_peer_certificate(SockMod, Sock, Peer) -> {error, p1_tls:get_cert_verify_string(VerifyRes, Cert)} end; {error, _Reason} -> - {error, <<"Cannot get peer certificate">>} + {error, <<"Cannot get peer certificate">>}; + error -> + {error, <<"Cannot get peer certificate">>} end. %%==================================================================== From 247bd9eae500ed50e785e2cce8ff3a8a8539fbeb Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 21 Aug 2015 15:23:03 +0200 Subject: [PATCH 208/695] More eye-candy mod_http_bind help page (thanks to Marek Foss) --- src/mod_http_bind.erl | 159 +++++++++++++++++++++++++++++++++--------- 1 file changed, 127 insertions(+), 32 deletions(-) diff --git a/src/mod_http_bind.erl b/src/mod_http_bind.erl index 1c772ce1738..c3a62aa3c59 100644 --- a/src/mod_http_bind.erl +++ b/src/mod_http_bind.erl @@ -78,38 +78,6 @@ process(_Path, _Request) -> {400, ?HEADER, #xmlel{name = <<"h1">>, children = [{xmlcdata, <<"400 Bad Request">>}]}}. -get_human_html_xmlel() -> - Heading = <<"ejabberd ", - (iolist_to_binary(atom_to_list(?MODULE)))/binary>>, - #xmlel{name = <<"html">>, - attrs = - [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}], - children = - [#xmlel{name = <<"head">>, - children = - [#xmlel{name = <<"title">>, - children = [{xmlcdata, Heading}]}]}, - #xmlel{name = <<"body">>, - children = - [#xmlel{name = <<"h1">>, - children = [{xmlcdata, Heading}]}, - #xmlel{name = <<"p">>, - children = - [{xmlcdata, <<"An implementation of ">>}, - #xmlel{name = <<"a">>, - attrs = - [{<<"href">>, - <<"http://xmpp.org/extensions/xep-0206.html">>}], - children = - [{xmlcdata, - <<"XMPP over BOSH (XEP-0206)">>}]}]}, - #xmlel{name = <<"p">>, - children = - [{xmlcdata, - <<"This web page is only informative. To " - "use HTTP-Bind you need a Jabber/XMPP " - "client that supports it.">>}]}]}]}. - %%%---------------------------------------------------------------------- %%% BEHAVIOUR CALLBACKS %%%---------------------------------------------------------------------- @@ -148,3 +116,130 @@ mod_opt_type(max_inactivity) -> mod_opt_type(max_pause) -> fun (I) when is_integer(I), I > 0 -> I end; mod_opt_type(_) -> [max_inactivity, max_pause]. + + +%%%---------------------------------------------------------------------- +%%% Help Web Page +%%%---------------------------------------------------------------------- + +get_human_html_xmlel() -> + Heading = <<"ejabberd ", + (iolist_to_binary(atom_to_list(?MODULE)))/binary>>, + #xmlel{name = <<"html">>, + attrs = + [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}], + children = + [#xmlel{name = <<"head">>, + children = + [#xmlel{name = <<"title">>, + children = [{xmlcdata, Heading}]}, + #xmlel{name = <<"style">>, + children = [{xmlcdata, get_style_cdata()}]}]}, + #xmlel{name = <<"body">>, + children = + [#xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"container">>}], + children = get_container_children(Heading)}]}]}. + +get_container_children(Heading) -> + [#xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"section">>}], + children = + [#xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"block">>}], + children = + [#xmlel{name = <<"a">>, + attrs = [{<<"href">>, <<"https://www.ejabberd.im">>}], + children = + [#xmlel{name = <<"img">>, + attrs = [{<<"height">>, <<"32">>}, + {<<"src">>, get_image_src()}]}]}]}]}, + #xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"white section">>}], + children = + [#xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"block">>}], + children = + [#xmlel{name = <<"h1">>, children = [{xmlcdata, Heading}]}, + #xmlel{name = <<"p">>, children = + [{xmlcdata, <<"An implementation of ">>}, + #xmlel{name = <<"a">>, + attrs = [{<<"href">>, <<"http://xmpp.org/extensions/xep-0206.html">>}], + children = [{xmlcdata, <<"XMPP over BOSH (XEP-0206)">>}]}]}, + #xmlel{name = <<"p">>, children = + [{xmlcdata, <<"This web page is only informative. To " + "use HTTP-Bind you need a Jabber/XMPP " + "client that supports it.">>}]}]}]}, + #xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"section">>}], + children = + [#xmlel{name = <<"div">>, + attrs = [{<<"class">>, <<"block">>}], + children = + [#xmlel{name = <<"a">>, + attrs = [{<<"href">>, <<"https://www.ejabberd.im">>}, + {<<"title">>, <<"ejabberd XMPP server">>}], + children = [{xmlcdata, <<"ejabberd">>}]}, + {xmlcdata, <<" is maintained by ">>}, + #xmlel{name = <<"a">>, + attrs = [{<<"href">>, <<"https://www.process-one.net">>}, + {<<"title">>, <<"ProcessOne - Leader in Instant Messaging and Push Solutions">>}], + children = [{xmlcdata, <<"ProcessOne">>}]} ]}]} + ]. + +get_style_cdata() -> + <<" + body { + margin: 0; + padding: 0; + font-family: sans-serif; + color: #fff; + } + h1 { + font-size: 3em; + color: #444; + } + p { + line-height: 1.5em; + color: #888; + } + a { + color: #fff; + } + a:hover, + a:active { + text-decoration: underline; + } + .container { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: #424A55; + background-image: -webkit-linear-gradient(270deg, rgba(48,52,62,0) 24%, #30353e 100%); + background-image: linear-gradient(-180deg, rgba(48,52,62,0) 24%, #30353e 100%); + } + .section { + padding: 3em; + } + .white.section { + background: #fff; + border-bottom: 4px solid #41AFCA; + } + .white.section a { + text-decoration: none; + color: #41AFCA; + } + .white.section a:hover, + .white.section a:active { + text-decoration: underline; + } + .block { + margin: 0 auto; + max-width: 900px; + width: 100%; + }">>. + +get_image_src() -> + <<"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAABACAYAAACgPErgAAAVtklEQVR42uydeXhU1d2ADzuyCcii4FZBZdEqVYtaUGqlikVwaRWsrWBRKIh8KgXcEAX9VECtoljcURAJICJWQLaKLAEjIHtBSNhC9oQkk2SW+36/52P+iIE5d5kzk4Fn3ud5H/7gIbnD3PPOveeeuVedygD9xLlQMh9yJ0D+GeokJAg1xcEWzOWYj0DBaQm0fXdaMCu8bROgpJVKksQj0+F84OXw/jRd7KVOdbbCFI6jdDNktlAnESVQNwSzOI6yhZBaV1UzAXiB4wj8CBtbqiRJXDIILtgL+zmOb8aoU5Xh0MMiEr5x6iSiAIZYROLo/aoayYMeocjbNlklSeKC9VAjBDM5IcEQfNZFnYq8AM8SkcJV6iSiCGYRkT1LVDWSA08Tkfy9MLaeOsUA2ot9xJHiW2KK+LW4Mvxnijg1/Pd9xQvFGiqJLUOhcT5kE5Etg0/VYI3TBOvbkyxYKURk2dpqDZb2gyEjC1SjUyBQdcQe4mtimujDHWXiD+Lr4g1iXZXkhISgBZBLZIaoU5GR0I2IVDxxkgVrNhH5z+pqDZb2g+FAJjQ4aYMFtBAfEzdils3iP8TkhYkqlMEZFuQQmcHqVGUBTOI40lLhz02TwUoGKxJAI/FxMYPYckB8Smyikvw/vlM/WHqAP4ifiHPF0fBsYyUkg5UM1okAbhV/JL5sE29TSZLBOhHJYCWDVRXgNPFVqpfXxQbJYCWDlQxWMlgRAc4VV5EYrBZ/kQxWMljJYFVLsBomdLCAS8RdJBZ7xMuSwTIcLKCO2EG8VrxdvEfsLV4F1vkJstq9BlidwN8hVleSLLgUuFzsEv6zs9g4EYIFNBAvFi87tm3WZWI7oHZ8glWnkWbb6ortCG/bsT+tDsBpcYrVpeIhzBHAHJni5XGOd5PwvnKJif0DaCh2/Pn7y/linbgFKx/qrjkWpffEHZo3qVhMBWuC2EVVA4ehay6sAYJgBeDocuh9iYqCL+F04DbxLTFNPMzxWGI6WCuBJ8Rfxi5YK34WLKC5BX3FVzj22n8S/fwcX/i9+1wcLraLVbAqr8OqgNOA31nwPLBc3HWCNU1+cbe4WBwjXhbD08A9eOcn8SNxmHij+EuxQ3iwdxP/Jr4pbsU7+2J5ehiCNuI9FkwN78sZol+0xDSYd6OH75R2BcZasALYKwZO0IWd4fd3LIS6g1XHeLBWQV1gsLgJ9wTBWgSBm1ScuBYuAvI4jrx9cOEZyiXzoUUIxhbDPm+fvFlL4PPe5oO14FslvAjnrYeXgYO4p0T8UrzJbLB2HlbCZMqbfwOjgrDD41HLCrE/LK1pKFYNxFS8sVDsK1Y5ctQeRf42HLcy3JMmNjIc6+ss+ETMRUuRH9Zd7SBS9QMwCFiDNzZBYAT4G5dTUcuC7KiClQ3dj8B6osYSAzOgoq2KMatgChF5e5RyQQXcVwL7MMNXsKOTuWAd2FBG9uhyyMMI6XPBd7GZYOUd8pP+UCn8hBEOr4KCbgYG7Ju4Z43YU0VB+LRoLu6ZpgyQAhflw2e4Y7lYS0XADzdZ8ANGsLaX88PgACHvwfLBY4Afo4T2Q9lNMZ68W0lE/J8oB5RDkxDMwDhF+XC4v6tgxZdcKLov+mBhYR4/FD8VRTRu93CE97RYTxkCuFfMxR13qSjIhoE+Tx9qPh9Mb6WqcBRqBuBli5hguQ4WUGsPvGsRKyw/hAaoGJEPy4lI4Uxlw3XHzu/XEVNKHk3QYAmWWDEecmraBqtaCE6HrCYeJpX34Jwc8eYYXp3cjHPSxWbKA9/Da3im+CeY1kBV4gNoUQILiB/6YD0JNYFP4jMoGFINwZqhNHwKLbfB5ji9/kdMBss8vk9MBcs8pasht7GLSIzHOQfFX6kYApyFuw/FFz38jveJitxBqhI3QMsS2IiQMMFaDFOJHyF45fZECdYOqA0sIX5YMPkOk8Eyz96xpoJlnvIZDgduazEfZ+SJVyoNhqO1DWcUim1dfJf2DTxTVgxFY1Ql+kOtivDYSJhgTYX7cIx1EJgmDhSvEbuK12XAiHyYCxThCKsQHmiXCMHa5+5T+BBY74qVX39vcUIhbLBwSkUO7DonBsEqBCtFfBjoHt6+34mjLfg34HO4feL8mw0HqwKsr8XRwA2E9x3xYY693jzHvWfZCAdheAZnWG6+1wecKd4oDhFHicPFvm6WI4SXRBTijOcdzi3+BefkifPAehLoI14Pqcdt/1x3YyNb/BisYUC38PvbU3wivOQhGHWw+sK5ASjAltBB8D8MQe05NXCBBZOBCmxJXwbTa1RnsDbCL4Pgx5ajeeJjYDVXEZgDNSugVwhW44j1sw0GKwjrX4El2kGzHDqVwzvO1x3d2dhMsPbMgjnaRZGroW0OjHcY1VIYeZHNMoZ0nPFP5YDwIJwp5miWinwt3u7w5z3g4lS1sc2c1Tl+Z0eTRXBkLKy1PWp7Ga4EAthSXAhHn4BQa5vX2zUIX1rRBKvU0fluYDaUt3F5xa5rNmzFlsfurs5grYP52JK7AVZcpBxSCrU3wvPOPtgzuxsI1gG3l9/90Cfg6Ihm/ONRBssn3udyceNVftiBLXNnaAZHbxcLNZs6uPXMFJdHCF84OeICluIIfQTzHI3jrI0Q7Kwc4myaxEqDtR2VC9bCCMDvOliZ0NGCCv1pwb7XlEdmQCtgOVp2bYU69aojWB/AVUEIoWcpfNlMeQD4q/0bs/GL6IK1JR3Wd/T4/lxZDJloKTgMrzXzFqyDJfBNT+WB2dD2kO1Eb9AP/zrhAAQ+xhl/d7A6fm0U977qbvPzr3YYwlkqArnQ2f4swb8SZjZXDtkG3SxsWSZ6HRt9RJ+rYP0H/omWdVNUlGyDxpm2b/i4P1VHsPbYnhrl7IQ/NlNRAPzDfqnH0o4eg1UEEy+N8mkl3e1P378e4CFYFnzRR0VBVzgP26BumqyqANQX92JPhm5FOXC2uJXoKBR7KA3AQuzZLzaMcJbwqv2pfXFL5YKV8BFaCvfCH1uqKDgKA0NOgzUAGuRp7664eaUyxD3Qpkz7u0oWxDtY/aBhFhzUD7hBN6goeRVq7IRVNkEY4y1YRx5VBiiHV9ByaK77YOW+pwxQCn9DS/4W2Fy7SgCuEEPYM1ETkXriSsxwRLxQe7RhjyV2VVW4E+ofhj1oSe2rXDAaGhTBAbQM72vo6VDzHQXrX9r7nxeXwqrLYWcNoFa0hj8F7rQiTuAV5cHIFvEM1jvQ3UJH+QJliN9Dj5B2APkWuw/Wrm3QrJ6hZyC20q/C9qfDsgbOg1WYDxe2NbRtdfTfZbXKIbW9x8ns30QISA1xEmbZLDbRzJEdwp6hqgqvwVWWdt9avVy5ZDL8Wj9VstbYwUwpdALKbIP1HxhJRAJlwPfhHWWzATeJafpz9bd/H89grYBRaHn+RmWQn2CdZtsyYWhjd8HaPVQZZKl2HV7AgvEXOw9W1pvKIDNhGFrevbVKACY6vPLWSHN0NUp8ThxnyJfECzRHWSlermaugfvRcuQu5ZLv4F60pN+lDLIZUmyDtRRmklAUPBzPYK2GT3Vf4IX+jZRBPoYniUioHA62dx6sQAVkt1MGSYXeFjoC3ZwFKyRm/14Z5Bu4OKidZwsOqjL4P8eeZSqBAMZgz0JVhQ3wOhEpLoLxZyqXHIAJRKS0CF48UxnkWehnG6wj8BUJxfK3VZQUuAiW/ntRwa+UYR6BP+gH+f6eLoK1CQprKoMchIv82itNGfc5DFY+FLUyvG0NS2E/Ecl8qcrg/w573kuwYP0Re1JVFd7RfvAWbYIU1/vJ2/AhETm6HlJqKIOshA4hKNMGK5RwwZrygYFHqC9zGqygNlgrP4vBjQW7hcCKHKy9tzh/kGrqd8ow+6CVX3tPovShKkw2PKuJx2G4tKEyyF6o4YPvicjhN1UlHD5TcGKCBetG7Nkq/ixA+doPNv9i5YFp2iuE1mJlmBxoEbR7kKqVcMGaOU1FyTpYq7tbg/NgbZ+tDLMLrrcJVi9ViTLtKfsq48E6CK392p0m/e8qTDE8RUQOHobmRoN1AGqWQZomWFMq33FE/C/2vJBgwboee/aKdVzMfXk6U3hLGyyMBysXWga1i5jTBqmchAvWY31VlGRqbyrmn64qka8NVsj4/MZg6IPgNFj7tV9iLfsRVtdSBsmATgEIaoJ/mwqzEwYTkWABbDhLGSQdGpdp12OVPF7lmQO7HU1gJxDAI9izs+oRVlAfrH8rDyzQXoAp3gxv1zJ8UaVTSDtHec9f1bqEmXQPiuUfwjdR/Se8AG0sOEpEUidVmax8n4iU58OKFoaPsJ5xE6x/wwT9pPuTRifdv4K79Nv3QZdK8yb90PLazcogH8HlIQgQkfl3ewjWpwn2yLH92JOmhFgHqwSGE5EyH7x/vjJICtyjX362s6f6Cf6hX9tSOB8Q+SJGfimmQPogZYCXoD9avh1WZYAORcvwfsogpbDeTbBmwW1oKR6mDJIGs4iIvxAeOLPSpGxn/dGYb6rhJRdPod2jn7nGQ7DWaQJSQzxLbC22iqFtxDvE7ThjRTyCNQ1uRkvqYGWQQzBH/yV3+R7zFOhhab8u8smt6iThN1AjB1brd+rnuqhKvAFX6hdz/rgBLqqpDJAHPS2w3ARrIpzth2IiEtgBM+spA2RBB/33unZ9qyrxDNTLg52a11MAS842dDrYRH/XhfxDMLyhh2AViK0jBKum+K5YKObE0CLc8WE8gvUStC7XbtuWrXBeHWWA7tDJp933dq+F8TXVHmgS1M4LFByE/q3VScB826OrwG7IqqsqcQvU3Q+70OJ7SEVJO6iVARsQHAcrTBosR8vrI5UBNsBctBQ+raowD6ag5ev3lQFmw3i0FM9SgiZYOiJ+KHMs4iUkFk+aC5aeLbAULYERygBB+BIt+8ZV3lHfQ8uRRaDqqASmF7Sxf8xV6SR1AjbBi+gphPIuUcb0aQQvwfoWBqDFKoEXuqooWAID0RLyw56OJ7j319WAhZZp/aOMVTegDC0ZfaII1sdKA9CPxOLWeAVrMgy0Hxu9ukS5NvEh+33v6Q6VT4uusCCElpnz4Ie6KgFZAWctgTS0lPjg2osiLDRtFwAfWoKHIfRrj/NCI0oAr8EqgAZ+2IOew7DkWuWBAPQvBT9ayuZo5uUWo8cH6z1FKwTXFkEOWio2Q1ndKIJVILa1XYGeGBSJbeIVrObQKBPS0VJ6ABZ7itY2eLAIO1JmqKqUwzzsWQyB9soFwGliQxUj/HCNs/tiH5hqM2hfxxarCPwPughBI80dEBwHK3wUOMDCjtKjbp5GlAn1vodxgIWeoO6hDGvhmqDtzygXA0/BN3VcPF/yAYfzO3crQRcsE+uxgIfEUqqXVUowGyw9I2EY9uRCxV0uls803AwTsacC3uisqjIEOgMV2GLlAeMgdK7NbW47Aq+Ke8UD4jsw4yyDj9ruIE6yoAxbyo/AjjOVhnehVQFk4ojQIgjeDNSNsGO3FP9mwVYEE8FqAbUOwwoccWAh+HuCVS/C9jUNwZ+BNByx9A0Hd4+ciiOOpELx3WBFumNB/RD0smARjti5FPrVNBCsQvECB9G6SvwaZ/xX/F/xf8S5YojoGRXvYM2C+j7nT8uZC9ZvI42NhdA8AAOALTgi5TkVic/gSRxjFQDzxKFiH7G7eJv4WAhWBqCc49i/Gya2US7hWPzuFf8iTrBgGVCOY4r/5HCupF8AV2wDazrwiDhEfEFcKGYRxkiwwlRAeyAb5+wQPxFHioPEseLn4gEcU7gdLm3q4PubTVw+ay9DTBGfCm/bKPFTcSfOyYe+FyrBQLAQPnfzyHdxSvg1F4hlYrGYHn5d94hNTnC/qxK8Uya2Mx8se0rhCsCHc7aCVXnfG2fB/Ao4hGPSV8O59VQkfgs1N8IiYkrBK8oFW+E5wIdndkx2eVXkeYxgPljh7bs1CCHigr8Ull7u4r26pBgKiBtb7lCCqWCFeVi5AKgtthE7iL8QGykNwGi8s0AJcQ9WmOnwIHEjlAFp5yg7noNmQCoxo2yNizmWoUG8Yon73oOzayiXAG8mZLDC/BkGlIBFTMkvg1v6eFhPc31mzKNVIf59hBJiECy/2FvFCOCcKObBesQjWNV/8aFiPxR0cbNRrcVVxITgauWAR6H+IdiNZxZPinJdyKSEDFaY5dAXyCY2HIJPeyqPvAlXANuJDT74/n4leA6WPUfFXjEKVjMxD/css/m5c7TBMsgmGBGI2VG+9T0UtvdyI7cme+EzjPPhROWACmiJp0/q8lzY/RdlgFUwDCjGGFZYXbDSb3Fx4aGzH77DKBmrIPdCFSUcWyU9B6Pk7ICMbkowFiz9fNFAZRjgGjGIOwLi1UrDBv0R1hJlmCLoFYIMs2Mj8D74m6poAIZbkGtmg/gIbmumHLID5uOK0GzIb294B7skCAssoiYLsh6FdWIk/D7Ycp7LZ7vV2Qejifo9CmYBo+Hb2oY/jQcC+4iKUAnwCmxvrgTjwdLzttjS0L7U3uOjwqYoG3ZqF19WvKVigA/aBGEaUEFUWFsh+CeTa50uCMAUC3LwRioEb1MueRw62a/DsXLE9yH4GxVD/HCjBfPEYlxxdDsUjgPrbCXMprTF/oiPnip9QnnEgnND8KwFu3DHdigfC4vaqhgBNA3CwxZsxB37xFdhUSelQRssM+wVh4iNPb7+RhwLyhHcs8PJM/+OHLv1ziaOw5cNmReoGAL8KgRvBWC/5e4IZh2EBomnqVgQgrYWDBUXApkRlhaUillgLRVfFm8AaiqPAN3ENWJ+2ExxJVjTIHQXBM9UcSQI51twLzBNXMSxQOSIeeEdchNYC469dq6HH+qd4DYpvwA+FPeIeeF/86Ch9+g0C34HTBC/FLeK2eHfkyWmiZ+LT4rXhddqxYUQ1LLgGmCMOF/8QcwKb1tOeFsXhNcu3QyWLhDmg2XPLvFZ8UpRO8iAVuL14nPiTrxRLnZVDjkC54TveJAfdjEcuUzFia/h9FLoDbwifhV+3XmVxsZ6cQ5Yj0LoChVPkI0TO4q9wLoDuFW8TrxAbGr4d9WwoAVwhni6SiCA+mIzsXn4/6S2i3/bIPzvasdw++pW2r6mYi2VIAC1wtvUPLyNdZUGz8EyTyj8s78KnzK+LL4kviPOE9eJeUTP/R5f+xlgnZEIY8OC5pXGRg2VJEkSTbBOXsaoJEmSJIN1EvC0SvJ/7dSxigEAHIDxf5FisAilbNbbWGSi5OZ7BgZPcS/hAZTNwFtYSVltit2iU/c9gxv8u75ffa/wSQ4ruR+ahySHldyZJiHJYSW3pnZIcliJHekrJDmsxMM60JQqIUkJh3WhJX1SKSTpzcN60J1udKQNfdOIaiFJLwxrTwua0Zj61PtjXfqgDtWpEJL04rCetKKBM5GUeVgnGoYkJR1Wka60o0ZIUuJhVWlLzZCk5MMqUyv0r/wCSDD/4sxS1q8AAAAASUVORK5CYII=">>. From 94444c87e83fafff390d4a1a536ed9e6c7294589 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 19 Aug 2015 16:15:02 +0300 Subject: [PATCH 209/695] Remove MAM archives on MUC room destroy --- src/mod_mam.erl | 3 ++- src/mod_muc.erl | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index bbe279cb909..af4245f9009 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -34,7 +34,8 @@ -export([user_send_packet/4, user_receive_packet/5, process_iq_v0_2/3, process_iq_v0_3/3, remove_user/2, - mod_opt_type/1, muc_process_iq/4, muc_filter_message/5]). + remove_user/3, mod_opt_type/1, muc_process_iq/4, + muc_filter_message/5]). -include_lib("stdlib/include/ms_transform.hrl"). -include("jlib.hrl"). diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 725051e6652..e68472a29e3 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -200,13 +200,16 @@ forget_room(ServerHost, Host, Name) -> forget_room(LServer, Host, Name, gen_mod:db_type(LServer, ?MODULE)). -forget_room(_LServer, Host, Name, mnesia) -> +forget_room(LServer, Host, Name, mnesia) -> + remove_room_mam(LServer, Host, Name), F = fun () -> mnesia:delete({muc_room, {Name, Host}}) end, mnesia:transaction(F); -forget_room(_LServer, Host, Name, riak) -> +forget_room(LServer, Host, Name, riak) -> + remove_room_mam(LServer, Host, Name), {atomic, ejabberd_riak:delete(muc_room, {Name, Host})}; forget_room(LServer, Host, Name, odbc) -> + remove_room_mam(LServer, Host, Name), SName = ejabberd_odbc:escape(Name), SHost = ejabberd_odbc:escape(Host), F = fun () -> @@ -216,6 +219,22 @@ forget_room(LServer, Host, Name, odbc) -> end, ejabberd_odbc:sql_transaction(LServer, F). +remove_room_mam(LServer, Host, Name) -> + case gen_mod:is_loaded(LServer, mod_mam) of + true -> + U = jlib:nodeprep(Name), + S = jlib:nameprep(Host), + DBType = gen_mod:db_type(LServer, mod_mam), + if DBType == odbc -> + mod_mam:remove_user(jlib:jid_to_string({U, S, <<>>}), + LServer, DBType); + true -> + mod_mam:remove_user(U, S, DBType) + end; + false -> + ok + end. + process_iq_disco_items(Host, From, To, #iq{lang = Lang} = IQ) -> Rsm = jlib:rsm_decode(IQ), From 832f6d39f93a545bc1918aeb1d51ac464fea2176 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 24 Aug 2015 13:22:18 +0300 Subject: [PATCH 210/695] Always include RSM in final message --- src/mod_mam.erl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index af4245f9009..a3f56a8830a 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -714,17 +714,13 @@ send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> end. -make_rsm_out(_Msgs, none, _Count, _Attrs, ?NS_MAM_TMP) -> - []; -make_rsm_out(_Msgs, none, _Count, Attrs, ?NS_MAM_0) -> - [#xmlel{name = <<"fin">>, attrs = [{<<"xmlns">>, ?NS_MAM_0}|Attrs]}]; -make_rsm_out([], #rsm_in{}, Count, Attrs, NS) -> +make_rsm_out([], _, Count, Attrs, NS) -> Tag = if NS == ?NS_MAM_TMP -> <<"query">>; true -> <<"fin">> end, [#xmlel{name = Tag, attrs = [{<<"xmlns">>, NS}|Attrs], children = jlib:rsm_encode(#rsm_out{count = Count})}]; -make_rsm_out([{FirstID, _, _}|_] = Msgs, #rsm_in{}, Count, Attrs, NS) -> +make_rsm_out([{FirstID, _, _}|_] = Msgs, _, Count, Attrs, NS) -> {LastID, _, _} = lists:last(Msgs), Tag = if NS == ?NS_MAM_TMP -> <<"query">>; true -> <<"fin">> From 5bb137940c11fbd5d0c4da493e3a4560fbfe2d97 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 27 Aug 2015 22:16:11 +0200 Subject: [PATCH 211/695] Remove "--enable-json" flag The "--enable-json" flag currently has no effect. --- configure.ac | 15 +++------------ rebar.config.script | 4 ---- rel/reltool.config.script | 1 - vars.config.in | 1 - 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index d7842be3a40..d30a490d080 100644 --- a/configure.ac +++ b/configure.ac @@ -108,10 +108,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;; - no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false json=false elixir=false iconv=false debug=false lager=false tools=false ;; + yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; + no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -195,14 +195,6 @@ AC_ARG_ENABLE(redis, *) AC_MSG_ERROR(bad value ${enableval} for --enable-redis) ;; esac],[if test "x$redis" = "x"; then redis=false; fi]) -AC_ARG_ENABLE(json, -[AC_HELP_STRING([--enable-json], [enable JSON support for mod_bosh (default: no)])], -[case "${enableval}" in - yes) json=true ;; - no) json=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-json) ;; -esac],[if test "x$json" = "x"; then json=false; fi]) - AC_ARG_ENABLE(elixir, [AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])], [case "${enableval}" in @@ -276,7 +268,6 @@ AC_SUBST(pam) AC_SUBST(zlib) AC_SUBST(riak) AC_SUBST(redis) -AC_SUBST(json) AC_SUBST(elixir) AC_SUBST(iconv) AC_SUBST(debug) diff --git a/rebar.config.script b/rebar.config.script index a38d85898fb..43bb8f0efbe 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -97,8 +97,6 @@ CfgDeps = lists:flatmap( [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; ({riak, true}) -> [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; - ({json, true}) -> - [{jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}]; ({elixir, true}) -> [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; @@ -139,8 +137,6 @@ CfgXrefs = lists:flatmap( ({riak, true}) -> % used in map-reduce function called from riak vm ["(\"riak_object\":_/_)"]; - ({json, false}) -> - ["(\"jiffy\":_/_)"]; ({zlib, false}) -> ["(\"ezlib\":_/_)"]; ({http, false}) -> diff --git a/rel/reltool.config.script b/rel/reltool.config.script index 09dd8365765..7d495b8a403 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -36,7 +36,6 @@ DepConfiguredApps = lists:flatmap( ({pam, true}) -> [p1_pam]; ({zlib, true}) -> [p1_zlib]; ({stun, true}) -> [p1_stun]; - ({json, true}) -> [jiffy]; ({iconv, true}) -> [p1_iconv]; ({lager, true}) -> [lager, goldrush]; ({lager, false}) -> [p1_logger]; diff --git a/vars.config.in b/vars.config.in index 2ccd5c76f42..2cd5d8e9a6f 100644 --- a/vars.config.in +++ b/vars.config.in @@ -28,7 +28,6 @@ {zlib, @zlib@}. {riak, @riak@}. {redis, @redis@}. -{json, @json@}. {elixir, @elixir@}. {lager, @lager@}. {iconv, @iconv@}. From 3d5d1ecbe41666dccf9eaa184e9b19ccad2f32c3 Mon Sep 17 00:00:00 2001 From: oxpa Date: Fri, 28 Aug 2015 03:34:51 -0800 Subject: [PATCH 212/695] get_room_options will not crash in case of query for a non-existent room --- src/mod_muc_admin.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 4741a23e18f..b779f4e0b0c 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -816,8 +816,10 @@ change_option(Option, Value, Config) -> %%---------------------------- get_room_options(Name, Service) -> - Pid = get_room_pid(Name, Service), - get_room_options(Pid). + case get_room_pid(Name, Service) of + room_not_found -> []; + Pid -> get_room_options(Pid) + end. get_room_options(Pid) -> Config = get_room_config(Pid), From 9f62426343df4735827ac9715459d64299798c07 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 30 Aug 2015 23:26:37 +0200 Subject: [PATCH 213/695] Update MAM tests to always expect RSM in response --- test/ejabberd_SUITE.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 47c4b9e753a..a220ed37e19 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1688,7 +1688,8 @@ mam_query_all(Config, NS) -> body = [Text]}]}]}]}) end, Iter), if NS == ?NS_MAM_TMP -> - ?recv1(#iq{type = result, id = I, sub_els = []}); + ?recv1(#iq{type = result, id = I, + sub_els = [#mam_query{xmlns = NS, id = QID}]}); true -> ?recv1(#message{sub_els = [#mam_fin{complete = true, id = QID}]}) end. @@ -1724,7 +1725,8 @@ mam_query_with(Config, JID, NS) -> body = [Text]}]}]}]}) end, Iter), if NS == ?NS_MAM_TMP -> - ?recv1(#iq{type = result, id = I, sub_els = []}); + ?recv1(#iq{type = result, id = I, + sub_els = [#mam_query{xmlns = NS}]}); true -> ?recv1(#message{sub_els = [#mam_fin{complete = true}]}) end. From 190f76c676083f23b164112fd08e8dd0822f2c64 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 1 Sep 2015 11:37:07 +0300 Subject: [PATCH 214/695] Fetch MUC MAM messages from room history directly if it's not enabled in room configuration --- src/mod_mam.erl | 69 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index a3f56a8830a..c1015975940 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -236,7 +236,7 @@ muc_process_iq(#iq{type = set, LServer = MUCState#state.server_host, Role = mod_muc_room:get_role(From, MUCState), process_iq(LServer, From, To, IQ, SubEl, - get_xdata_fields(SubEl), {groupchat, Role}); + get_xdata_fields(SubEl), {groupchat, Role, MUCState}); _ -> IQ end; @@ -561,10 +561,47 @@ select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> select(LServer, From, Start, End, With, RSM, MsgType, DBType) end; - {groupchat, _Role} -> + {groupchat, _Role, _MUCState} -> select(LServer, To, Start, End, With, RSM, MsgType, DBType) end. +select(_LServer, JidRequestor, Start, End, _With, RSM, + {groupchat, _Role, #state{config = #config{mam = false}, + history = History}} = MsgType, + _DBType) -> + #lqueue{len = L, queue = Q} = History, + {Msgs0, _} = + lists:mapfoldl( + fun({Nick, Pkt, _HaveSubject, UTCDateTime, _Size}, I) -> + Now = datetime_to_now(UTCDateTime, I), + TS = now_to_usec(Now), + case match_interval(Now, Start, End) and + match_rsm(Now, RSM) of + true -> + {[{jlib:integer_to_binary(TS), TS, + msg_to_el(#archive_msg{ + type = groupchat, + timestamp = Now, + peer = undefined, + nick = Nick, + packet = Pkt}, + MsgType, + JidRequestor)}], I+1}; + false -> + {[], I+1} + end + end, 0, queue:to_list(Q)), + Msgs = lists:flatten(Msgs0), + case RSM of + #rsm_in{max = Max, direction = before} -> + {NewMsgs, IsComplete} = filter_by_max(lists:reverse(Msgs), Max), + {NewMsgs, IsComplete, L}; + #rsm_in{max = Max} -> + {NewMsgs, IsComplete} = filter_by_max(Msgs, Max), + {NewMsgs, IsComplete, L}; + _ -> + {Msgs, true, L} + end; select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor, Start, End, With, RSM, MsgType, mnesia) -> MS = make_matchspec(LUser, LServer, Start, End, With), @@ -581,7 +618,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor, Start, End, With, RSM, MsgType, {odbc, Host}) -> User = case MsgType of chat -> LUser; - {groupchat, _Role} -> jlib:jid_to_string(JidRequestor) + {groupchat, _Role, _MUCState} -> jlib:jid_to_string(JidRequestor) end, {Query, CountQuery} = make_sql_query(User, LServer, Start, End, With, RSM), @@ -655,9 +692,9 @@ maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> _ -> Pkt end; maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, - Peer, {groupchat, Role}, Nick) -> + Peer, {groupchat, Role, _MUCState}, Nick) -> Items = case Role of - moderator -> + moderator when Peer /= undefined -> [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = @@ -762,6 +799,18 @@ filter_by_max(Msgs, Len) when is_integer(Len), Len >= 0 -> filter_by_max(_Msgs, _Junk) -> {[], true}. +match_interval(Now, Start, End) -> + (Now >= Start) and (Now =< End). + +match_rsm(Now, #rsm_in{id = ID, direction = aft}) when ID /= <<"">> -> + Now1 = (catch usec_to_now(jlib:binary_to_integer(ID))), + Now > Now1; +match_rsm(Now, #rsm_in{id = ID, direction = before}) when ID /= <<"">> -> + Now1 = (catch usec_to_now(jlib:binary_to_integer(ID))), + Now < Now1; +match_rsm(_Now, _) -> + true. + make_matchspec(LUser, LServer, Start, End, {_, _, <<>>} = With) -> ets:fun2ms( fun(#archive_msg{timestamp = TS, @@ -884,6 +933,16 @@ usec_to_now(Int) -> Sec = Secs rem 1000000, {MSec, Sec, USec}. +now_to_iso({_, _, USec} = Now) -> + DateTime = calendar:now_to_universal_time(Now), + {ISOTimestamp, Zone} = jlib:timestamp_to_iso(DateTime, utc, USec), + <>. + +datetime_to_now(DateTime, USecs) -> + Seconds = calendar:datetime_to_gregorian_seconds(DateTime) - + calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}), + {Seconds div 1000000, Seconds rem 1000000, USecs}. + get_jids(Els) -> lists:flatmap( fun(#xmlel{name = <<"jid">>} = El) -> From e24bfe7b62017b33db17141d154e747e89035f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 1 Sep 2015 10:56:43 +0200 Subject: [PATCH 215/695] Fix problem with merging same port, different ip listeners in config files Also switch to function used by ejabberd_listener to extract that information instead of rolling our own code for that. --- src/ejabberd_config.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 89e1399fac0..e1768581073 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -370,10 +370,8 @@ exit_or_halt(ExitText) -> get_config_option_key(Name, Val) -> if Name == listen -> - case {lists:keyfind(port, 1, Val), lists:keyfind(transport, 1, Val)} of - {{_, Port}, false} -> {Port, tcp}; - {{_, Port2}, {_, Trans}} -> {Port2, Trans} - end; + [{Key, _, _}] = ejabberd_listener:validate_cfg([Val]), + Key; is_tuple(Val) -> element(1, Val); true -> From 14ddbce3a90fc99aa464a78a1db9c1dcd14d0dd4 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 1 Sep 2015 12:35:08 +0300 Subject: [PATCH 216/695] Do not forget to set from/to when fetching from MUC history --- src/mod_mam.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index c1015975940..730b2ba910d 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -679,11 +679,9 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, xml:replace_tag_attr( <<"xmlns">>, <<"jabber:client">>, Pkt)]}. -maybe_update_from_to(Pkt, _JIDRequestor, undefined, _Type, _Nick) -> - Pkt; maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of - <<"groupchat">> -> + <<"groupchat">> when Peer /= undefined -> Pkt2 = xml:replace_tag_attr(<<"to">>, jlib:jid_to_string(JidRequestor), Pkt), From b6bf1eba42a6ddfca299540d1df1a1af50efc0dd Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 2 Sep 2015 09:11:06 +0200 Subject: [PATCH 217/695] Upgrade version number to ejabberd 15.07 We forgot before previous release --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index ea45f871566..d6684c44a19 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.06.0", + version: "15.07777777.0", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", From 87f39c875076061fd19ab1fa5c31b4c4f8f70b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Wed, 2 Sep 2015 10:54:24 +0200 Subject: [PATCH 218/695] Update mix.exs Fix version number. --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index d6684c44a19..dee11997166 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.07777777.0", + version: "15.07.0", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", From 79d3b77de129530f893071390781a6ab137a2113 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 2 Sep 2015 11:38:16 +0200 Subject: [PATCH 219/695] Update mix.exs to comply with exrm release system --- mix.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index dee11997166..57330c04aa1 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,9 @@ defmodule Ejabberd.Mixfile do def application do [mod: {:ejabberd_app, []}, - applications: [:kernel, :stdlib]] + applications: [:ssl], + included_applications: [:p1_logger,:p1_yaml,:p1_tls,:p1_xml,:p1_stringprep,:p1_zlib,:p1_cache_tab,:mnesia,:p1_utils, + :p1_iconv,:esip,:p1_stun,:ehyperloglog,:p1_mysql,:p1_pgsql,:eredis]] end defp erlc_options do From e179727a0e1846b0e3e24a04fc199d82e6b73366 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 2 Sep 2015 12:48:19 +0200 Subject: [PATCH 220/695] ignore ejabberd release result directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 21f8cfadaa3..eb54d51e697 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ XmppAddr.hrl /test/*.beam /logs/ /priv/sql +/rel/ejabberd From 4ae7c81cfa044e8a44b3ece13d11818a48c9a3b2 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 2 Sep 2015 12:49:19 +0200 Subject: [PATCH 221/695] Allow building ejabberd with Elixir mix and building and ejabberd OTP release --- config/config.exs | 10 ++++++++++ mix.exs | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 config/config.exs diff --git a/config/config.exs b/config/config.exs new file mode 100644 index 00000000000..8b68e8dbf83 --- /dev/null +++ b/config/config.exs @@ -0,0 +1,10 @@ +use Mix.Config + +# This is standard path in the context of ejabberd release +config :ejabberd, + file: "running-config/ejabberd.yml", + log_path: 'log/ejabberd.log' + +# Customize Mnesia directory: +config :mnesia, + dir: 'mnesiadb/' diff --git a/mix.exs b/mix.exs index 57330c04aa1..99e00b0d883 100644 --- a/mix.exs +++ b/mix.exs @@ -41,7 +41,8 @@ defmodule Ejabberd.Mixfile do {:ehyperloglog, git: "https://github.com/vaxelfel/eHyperLogLog"}, {:p1_mysql, git: "https://github.com/processone/mysql"}, {:p1_pgsql, git: "https://github.com/processone/pgsql"}, - {:eredis, git: "https://github.com/wooga/eredis"} + {:eredis, git: "https://github.com/wooga/eredis"}, + {:exrm, "~> 0.19.2"} ] end end From eebd4bbd8f755962a43e4b9aa5ecb54eb913f210 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 2 Sep 2015 14:13:23 +0300 Subject: [PATCH 222/695] Remove unused function now_to_iso/1 --- src/mod_mam.erl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 730b2ba910d..b476ff68169 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -931,11 +931,6 @@ usec_to_now(Int) -> Sec = Secs rem 1000000, {MSec, Sec, USec}. -now_to_iso({_, _, USec} = Now) -> - DateTime = calendar:now_to_universal_time(Now), - {ISOTimestamp, Zone} = jlib:timestamp_to_iso(DateTime, utc, USec), - <>. - datetime_to_now(DateTime, USecs) -> Seconds = calendar:datetime_to_gregorian_seconds(DateTime) - calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}}), From 1bc2c8cbb16f0186953dbe5b7eb71660e1e3c5f7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 2 Sep 2015 13:46:03 +0200 Subject: [PATCH 223/695] Add verification of hide_sensitive_log_data global option --- src/ejabberd_config.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index e1768581073..5b97710a8d0 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -1164,6 +1164,8 @@ emit_deprecation_warning(Module, NewModule) -> [Module, NewModule]) end. +opt_type(hide_sensitive_log_data) -> + fun (H) when is_boolean(H) -> H end; opt_type(hosts) -> fun(L) when is_list(L) -> lists:map( @@ -1174,7 +1176,7 @@ opt_type(hosts) -> opt_type(language) -> fun iolist_to_binary/1; opt_type(_) -> - [hosts, language]. + [hide_sensitive_log_data, hosts, language]. -spec may_hide_data(string()) -> string(); (binary()) -> binary(). From 6740b1f0e1e96fb7ee04fd4046c180c35c9f370d Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 2 Sep 2015 16:02:46 +0300 Subject: [PATCH 224/695] Rename idna.erl to ejabberd_idna.erl (#702) --- src/{idna.erl => ejabberd_idna.erl} | 4 ++-- src/ejabberd_s2s.erl | 4 ++-- src/ejabberd_s2s_out.erl | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/{idna.erl => ejabberd_idna.erl} (99%) diff --git a/src/idna.erl b/src/ejabberd_idna.erl similarity index 99% rename from src/idna.erl rename to src/ejabberd_idna.erl index dd19ad988fb..bee3f87ed32 100644 --- a/src/idna.erl +++ b/src/ejabberd_idna.erl @@ -1,5 +1,5 @@ %%%---------------------------------------------------------------------- -%%% File : idna.erl +%%% File : ejabberd_idna.erl %%% Author : Alexey Shchepin %%% Purpose : Support for IDNA (RFC3490) %%% Created : 10 Apr 2004 by Alexey Shchepin @@ -23,7 +23,7 @@ %%% %%%---------------------------------------------------------------------- --module(idna). +-module(ejabberd_idna). -author('alexey@process-one.net'). diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index e1c9ab9dab7..ef17fc89f6d 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -225,7 +225,7 @@ check_peer_certificate(SockMod, Sock, Peer) -> {ok, Cert} -> case SockMod:get_verify_result(Sock) of 0 -> - case idna:domain_utf8_to_ascii(Peer) of + case ejabberd_idna:domain_utf8_to_ascii(Peer) of false -> {error, <<"Cannot decode remote server name">>}; AsciiPeer -> @@ -720,7 +720,7 @@ get_cert_domains(Cert) -> lresource = <<"">>} -> case - idna:domain_utf8_to_ascii(LD) + ejabberd_idna:domain_utf8_to_ascii(LD) of false -> []; diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 77e159cdc6c..65a60c40298 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -235,7 +235,7 @@ open_socket(init, StateData) -> [{StateData#state.myname, StateData#state.server, StateData#state.new, StateData#state.verify}]), AddrList = case - idna:domain_utf8_to_ascii(StateData#state.server) + ejabberd_idna:domain_utf8_to_ascii(StateData#state.server) of false -> []; ASCIIAddr -> get_addr_port(ASCIIAddr) From 06193d18b89c0d8a48dda757b7e2b68dd9ce4eda Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 2 Sep 2015 17:02:09 +0200 Subject: [PATCH 225/695] Better to keep config file in a different config directory --- config/config.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.exs b/config/config.exs index 8b68e8dbf83..4d378348059 100644 --- a/config/config.exs +++ b/config/config.exs @@ -2,7 +2,7 @@ use Mix.Config # This is standard path in the context of ejabberd release config :ejabberd, - file: "running-config/ejabberd.yml", + file: "config/ejabberd.yml", log_path: 'log/ejabberd.log' # Customize Mnesia directory: From 8d1ea87e027f78b4792984431e8997584b918df3 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 3 Sep 2015 16:27:42 +0200 Subject: [PATCH 226/695] Use hide_sensitive_log_data in eldap.erl --- src/eldap.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eldap.erl b/src/eldap.erl index 20a5b6139b3..dbd561afd14 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -824,7 +824,7 @@ send_command(Command, From, S) -> {Name, Request} = gen_req(Command), Message = #'LDAPMessage'{messageID = Id, protocolOp = {Name, Request}}, - ?DEBUG("~p~n", [{Name, Request}]), + ?DEBUG("~p~n", [{Name, ejabberd_config:may_hide_data(Request)}]), {ok, Bytes} = 'ELDAPv3':encode('LDAPMessage', Message), case (S#eldap.sockmod):send(S#eldap.fd, Bytes) of @@ -1147,7 +1147,7 @@ bind_request(Socket, S) -> authentication = {simple, S#eldap.passwd}}, Message = #'LDAPMessage'{messageID = Id, protocolOp = {bindRequest, Req}}, - ?DEBUG("Bind Request Message:~p~n", [Message]), + ?DEBUG("Bind Request Message:~p~n", [ejabberd_config:may_hide_data(Message)]), {ok, Bytes} = 'ELDAPv3':encode('LDAPMessage', Message), case (S#eldap.sockmod):send(Socket, Bytes) of From 5095fdb6b0ae6e227a907ac690447cbc353d82e9 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 3 Sep 2015 21:20:15 +0200 Subject: [PATCH 227/695] New XEP-0198 option: "max_resume_timeout" In the past, the "resume_timeout" option defined both the default resume timeout and the maximum resume timeout clients are permitted to request. Admins might want to allow clients to request a timeout value that's larger than the default, though. This can now be done by specifying the "max_resume_timeout" option. --- src/ejabberd_c2s.erl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index d5c8c01c1c2..10ff01b211c 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -110,6 +110,7 @@ mgmt_max_queue, mgmt_pending_since, mgmt_timeout, + mgmt_max_timeout, mgmt_resend, mgmt_stanzas_in = 0, mgmt_stanzas_out = 0, @@ -314,6 +315,10 @@ init([{SockMod, Socket}, Opts]) -> Timeout when is_integer(Timeout), Timeout >= 0 -> Timeout; _ -> 300 end, + MaxResumeTimeout = case proplists:get_value(max_resume_timeout, Opts) of + Max when is_integer(Max), Max >= ResumeTimeout -> Max; + _ -> ResumeTimeout + end, ResendOnTimeout = case proplists:get_value(resend_on_timeout, Opts) of Resend when is_boolean(Resend) -> Resend; if_offline -> if_offline; @@ -336,6 +341,7 @@ init([{SockMod, Socket}, Opts]) -> mgmt_state = StreamMgmtState, mgmt_max_queue = MaxAckQueue, mgmt_timeout = ResumeTimeout, + mgmt_max_timeout = MaxResumeTimeout, mgmt_resend = ResendOnTimeout}, {ok, wait_for_stream, StateData, ?C2S_OPEN_TIMEOUT}. @@ -2688,16 +2694,17 @@ perform_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) -> StateData end. -handle_enable(#state{mgmt_timeout = ConfigTimeout} = StateData, Attrs) -> +handle_enable(#state{mgmt_timeout = DefaultTimeout, + mgmt_max_timeout = MaxTimeout} = StateData, Attrs) -> Timeout = case xml:get_attr_s(<<"resume">>, Attrs) of ResumeAttr when ResumeAttr == <<"true">>; ResumeAttr == <<"1">> -> MaxAttr = xml:get_attr_s(<<"max">>, Attrs), case catch jlib:binary_to_integer(MaxAttr) of - Max when is_integer(Max), Max > 0, Max =< ConfigTimeout -> + Max when is_integer(Max), Max > 0, Max =< MaxTimeout -> Max; _ -> - ConfigTimeout + DefaultTimeout end; _ -> 0 From f56a9e400dd1857484c9898f0b746f0a44ad2ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 4 Sep 2015 12:42:53 +0200 Subject: [PATCH 228/695] Pass stream management options defined in http listener to http-bind and websocket --- include/ejabberd_http.hrl | 3 ++- src/ejabberd_http_bind.erl | 29 ++++++++++++++++++----------- src/ejabberd_http_ws.erl | 10 ++++++++-- src/ejabberd_websocket.erl | 6 ++++-- src/mod_http_bind.erl | 4 ++-- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/include/ejabberd_http.hrl b/include/ejabberd_http.hrl index 50c9d4ad727..404427d7f22 100644 --- a/include/ejabberd_http.hrl +++ b/include/ejabberd_http.hrl @@ -45,4 +45,5 @@ headers = [] :: [{atom() | binary(), binary()}], local_path = [] :: [binary()], q = [] :: [{binary() | nokey, binary()}], - buf :: binary()}). + buf :: binary(), + http_opts = [] :: list()}). diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index 620c8f1d37e..21c6887f00d 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -16,7 +16,7 @@ -behaviour(gen_fsm). %% External exports --export([start_link/3, +-export([start_link/4, init/1, handle_event/3, handle_sync_event/4, @@ -35,13 +35,13 @@ change_shaper/2, monitor/1, close/1, - start/4, + start/5, handle_session_start/8, handle_http_put/7, http_put/7, http_get/2, prepare_response/4, - process_request/2]). + process_request/3]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -140,17 +140,17 @@ %%%---------------------------------------------------------------------- %% TODO: If compile with no supervisor option, start the session without %% supervisor -start(XMPPDomain, Sid, Key, IP) -> +start(XMPPDomain, Sid, Key, IP, HOpts) -> ?DEBUG("Starting session", []), SupervisorProc = gen_mod:get_module_proc(XMPPDomain, ?PROCNAME_MHB), - case catch supervisor:start_child(SupervisorProc, [Sid, Key, IP]) of + case catch supervisor:start_child(SupervisorProc, [Sid, Key, IP, HOpts]) of {ok, Pid} -> {ok, Pid}; _ -> check_bind_module(XMPPDomain), {error, "Cannot start HTTP bind session"} end. -start_link(Sid, Key, IP) -> - gen_fsm:start_link(?MODULE, [Sid, Key, IP], ?FSMOPTS). +start_link(Sid, Key, IP, HOpts) -> + gen_fsm:start_link(?MODULE, [Sid, Key, IP, HOpts], ?FSMOPTS). send({http_bind, FsmRef, _IP}, Packet) -> gen_fsm:sync_send_all_state_event(FsmRef, @@ -197,7 +197,7 @@ peername({http_bind, _FsmRef, IP}) -> {ok, IP}. %% Entry point for data coming from client through ejabberd HTTP server: -process_request(Data, IP) -> +process_request(Data, IP, HOpts) -> Opts1 = ejabberd_c2s_config:get_c2s_limits(), Opts = [{xml_socket, true} | Opts1], MaxStanzaSize = case lists:keysearch(max_stanza_size, 1, @@ -221,7 +221,7 @@ process_request(Data, IP) -> (?NS_HTTP_BIND)/binary, "'/>">>}; XmppDomain -> Sid = p1_sha:sha(term_to_binary({now(), make_ref()})), - case start(XmppDomain, Sid, <<"">>, IP) of + case start(XmppDomain, Sid, <<"">>, IP, HOpts) of {error, _} -> {500, ?HEADER, <<" case check(LocalPath, Headers) of true -> @@ -101,7 +102,8 @@ socket_handoff(LocalPath, #request{method = 'GET', ip = IP, q = Q, path = Path, path = Path, headers = Headers, local_path = LocalPath, - buf = Buf}, + buf = Buf, + http_opts = HOpts}, connect(WS, HandlerModule); _ -> diff --git a/src/mod_http_bind.erl b/src/mod_http_bind.erl index c3a62aa3c59..fbf43e80fe8 100644 --- a/src/mod_http_bind.erl +++ b/src/mod_http_bind.erl @@ -64,9 +64,9 @@ process([], #request{method = 'POST', data = <<>>}) -> {400, ?HEADER, #xmlel{name = <<"h1">>, children = [{xmlcdata, <<"400 Bad Request">>}]}}; process([], - #request{method = 'POST', data = Data, ip = IP}) -> + #request{method = 'POST', data = Data, ip = IP, opts = Opts}) -> ?DEBUG("Incoming data: ~s", [Data]), - ejabberd_http_bind:process_request(Data, IP); + ejabberd_http_bind:process_request(Data, IP, Opts); process([], #request{method = 'GET', data = <<>>}) -> {200, ?HEADER, get_human_html_xmlel()}; process([], #request{method = 'OPTIONS', data = <<>>}) -> From 096d56235ba8393f445ea9c5005a9359c2af967c Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Sep 2015 13:16:56 +0200 Subject: [PATCH 229/695] Fix German translation (thanks to STPKITT)(#726) --- priv/msgs/de.msg | 2 +- priv/msgs/de.po | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/priv/msgs/de.msg b/priv/msgs/de.msg index 4c26793bbd1..a43e17f33f1 100644 --- a/priv/msgs/de.msg +++ b/priv/msgs/de.msg @@ -57,7 +57,7 @@ {"Database","Datenbank"}. {"Database Tables Configuration at ","Datenbanktabellen-Konfiguration auf "}. {"December","Dezember"}. -{"Default users as participants","Standardbenutzer als Teilnehmer"}. +{"Default users as participants","Benutzer werden standardmäßig vollwertige Teilnehmer"}. {"Delete","Löschen"}. {"Delete message of the day","Lösche Nachricht des Tages"}. {"Delete message of the day on all hosts","Lösche Nachricht des Tages auf allen Hosts"}. diff --git a/priv/msgs/de.po b/priv/msgs/de.po index 05a582e272a..7cc2ba14033 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -1207,7 +1207,7 @@ msgstr "Raum moderiert machen" #: mod_muc_room.erl:3436 msgid "Default users as participants" -msgstr "Standardbenutzer als Teilnehmer" +msgstr "Benutzer werden standardmäßig vollwertige Teilnehmer" #: mod_muc_room.erl:3439 msgid "Allow users to change the subject" From 5d59a534a35f781ad17875a7fc2c1ecafb87e44e Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Sep 2015 13:37:54 +0200 Subject: [PATCH 230/695] Run "make translations" and get updated PO files --- priv/msgs/ca.po | 847 ++++++++++++++++++++-------------------- priv/msgs/cs.po | 847 ++++++++++++++++++++-------------------- priv/msgs/de.po | 847 ++++++++++++++++++++-------------------- priv/msgs/ejabberd.pot | 840 ++++++++++++++++++++-------------------- priv/msgs/el.po | 847 ++++++++++++++++++++-------------------- priv/msgs/eo.po | 847 ++++++++++++++++++++-------------------- priv/msgs/es.po | 452 +++++++++++----------- priv/msgs/fr.po | 847 ++++++++++++++++++++-------------------- priv/msgs/gl.po | 847 ++++++++++++++++++++-------------------- priv/msgs/he.po | 452 +++++++++++----------- priv/msgs/id.po | 847 ++++++++++++++++++++-------------------- priv/msgs/it.po | 847 ++++++++++++++++++++-------------------- priv/msgs/ja.po | 853 +++++++++++++++++++++-------------------- priv/msgs/nl.po | 847 ++++++++++++++++++++-------------------- priv/msgs/no.po | 847 ++++++++++++++++++++-------------------- priv/msgs/pl.po | 847 ++++++++++++++++++++-------------------- priv/msgs/pt-br.po | 847 ++++++++++++++++++++-------------------- priv/msgs/pt.po | 851 ++++++++++++++++++++-------------------- priv/msgs/ru.po | 847 ++++++++++++++++++++-------------------- priv/msgs/sk.po | 847 ++++++++++++++++++++-------------------- priv/msgs/sv.po | 847 ++++++++++++++++++++-------------------- priv/msgs/th.po | 847 ++++++++++++++++++++-------------------- priv/msgs/tr.po | 847 ++++++++++++++++++++-------------------- priv/msgs/uk.po | 847 ++++++++++++++++++++-------------------- priv/msgs/vi.po | 847 ++++++++++++++++++++-------------------- priv/msgs/wa.po | 847 ++++++++++++++++++++-------------------- priv/msgs/zh.po | 847 ++++++++++++++++++++-------------------- 27 files changed, 11477 insertions(+), 10605 deletions(-) diff --git a/priv/msgs/ca.po b/priv/msgs/ca.po index bfb6bd21d3d..c2d1b477cb0 100644 --- a/priv/msgs/ca.po +++ b/priv/msgs/ca.po @@ -15,340 +15,341 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Lokalize 1.4\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "És obligatori utilitzar STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Recurs no disponible" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Reemplaçat per una nova connexió" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "Has sigut expulsat" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Introdueix el text que veus" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Els teus missatges per ~s s'estan bloquejant. Per desbloquejar-los, visita ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Si no veus la imatge CAPTCHA açí, visita la pàgina web." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Pàgina web del CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es vàlid." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "No autoritzat" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Web d'administració del ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administració" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Llista de Control d'Accés" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Enviat" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Format erroni" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "en format text" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Eliminar els seleccionats" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Regles d'Accés" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configuració de les Regles d'Accés ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Hosts virtuals" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Usuaris" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Usuaris conectats" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Última activitat d'usuari" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Període: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Últim mes" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Últim any" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Tota l'activitat" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Mostrar Taula Ordinaria" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Mostrar Taula Integral" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Estadístiques" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "No Trobat" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Node no trobat" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Afegir nou" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Usuaris registrats" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Usuari" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Contrasenya" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Afegir usuari" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Missatges offline" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Última activitat" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Mai" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Connectat" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Usuaris registrats:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Usuaris en línia:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Connexions d'eixida s2s" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Servidors d'eixida de s2s" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Cap" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Canviar Contrasenya" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Usuari " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Recursos connectats:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Contrasenya:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Eliminar usuari" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "No hi ha dades" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodes" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodes funcionant" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodes parats" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Node " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de dades" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar còpia de seguretat" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Ports a l'escolta" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Actualitzar" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Detindre" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Mòduls" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Error de cridada RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Taules de la base de dades en " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nom" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Tipus d'emmagatzematge" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elements" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memòria" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Error" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Còpia de seguretat de " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -358,489 +359,485 @@ msgstr "" "dades Mnesia. Si estàs utilitzant el mòdul d'ODBC també deus de fer una " "còpia de seguretat de la base de dades de SQL a part." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Guardar una còpia de seguretat binària:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Acceptar" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Restaurar una còpia de seguretat binària ara mateix." -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar una còpia de seguretat binària després de reiniciar el ejabberd " "(requereix menys memòria:" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Guardar una còpia de seguretat en format de text pla:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Restaurar una còpia de seguretat en format de text pla ara mateix:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar dades d'usuaris des d'un arxiu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar dades de tots els usuaris del servidor a arxius PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Exportar dades d'usuaris d'un host a arxius PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importar dades d'usuaris de l'arxiu de spool de jabberd14" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar dades d'usuaris del directori de spool de jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Ports a la escolta en " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Mòduls en " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Estadístiques de ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Temps en marxa" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Temps de CPU" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transaccions Realitzades:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transaccions Avortades" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transaccions reiniciades" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transaccions registrades" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Actualitzar" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Pla d'actualització" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Mòduls modificats" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script d'actualització" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Script d'actualització de baix nivell" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Comprovar script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Mòdul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opcions" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Eliminar" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Iniciar" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandaments" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Segur que vols eliminar el missatge del dia?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Assumpte" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Missatge" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "No hi ha proveedor per al missatge anunci" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Anuncis" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anunci a tots els usuaris" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Enviar anunci a tots els usuaris de tots els hosts" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Enviar anunci a tots els usuaris connectats" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Enviar anunci a tots els usuaris connectats a tots els hosts" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Configurar el missatge del dia i enviar a tots els usuaris" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Escriure missatge del dia en tots els hosts i enviar-ho als usuaris " "connectats" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Actualitzar el missatge del dia (no enviar)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Actualitza el missatge del dia en tots els hosts (no enviar)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Eliminar el missatge del dia" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Elimina el missatge del dis de tots els hosts" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configuració" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar mòduls" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Parar mòduls" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar a fitxer de text" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar fitxer" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directori" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar el Servei" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Apager el Servei" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Eliminar Usuari" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Finalitzar Sesió d'Usuari" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Obtenir Contrasenya d'usuari" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Canviar Contrasenya d'Usuari" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Obtenir la última connexió d'Usuari" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Obtenir Estadístiques d'Usuari" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Obtenir Número d'Usuaris Registrats" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Obtenir Número d'Usuaris Connectats" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gestió d'Usuaris" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Tots els usuaris" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Connexions s2s d'eixida" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestió de còpia de seguretat" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuaris de jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuració de la base de dades en " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecciona el tipus d'almacenament de les taules" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Còpia sols en disc" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Còpia en RAM i disc" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Còpia en RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Còpia remota" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Detindre mòduls en " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecciona mòduls a detindre" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar mòduls en " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introdueix llista de {mòdul, [opcions]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Llista de mòduls a iniciar" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Desar còpia de seguretat a fitxer en " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Introdueix ruta al fitxer de còpia de seguretat" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Ruta al fitxer" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura còpia de seguretat des del fitxer en " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exporta còpia de seguretat a fitxer de text en " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introdueix ruta al fitxer de text" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importa usuari des de fitxer en " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introdueix ruta al fitxer jabberd14 spool" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuaris des del directori en " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introdueix la ruta al directori de jabberd14 spools" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ruta al directori" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Temps de retard" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuració de la Llista de Control d'Accés" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Llistes de Control de Accés" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuració d'accesos" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Regles d'accés" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificació de la Contrasenya" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número d'Usuaris Registrats" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número d'usuaris connectats" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Últim login" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Tamany de la llista" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Adreça IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administració de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Acció en l'usuari" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Editar propietats" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -952,487 +949,519 @@ msgstr "Codificació pel servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Sales de xat" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necessites un client amb suport x:data per a poder registrar el Nickname" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registre del Nickname en " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Introdueix el nickname que vols registrar" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nickname" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "mòdul ejabberd MUC" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Sales de xat" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "Deixar la sala" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Usuaris registrats" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Configuració de la sala de xat modificada" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "Entrar a la sala" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "Deixar la sala" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "Has sigut banejat" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "Has sigut expulsat a causa d'un canvi d'afiliació" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "Has sigut expulsat perquè la sala ha canviat a sols membres" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "Has sigut expulsat perquè el sistema s'ha apagat" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "ara es conegut com" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " ha posat l'assumpte: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "La sala s'ha creat" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "La sala s'ha destruït" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "La sala s'ha iniciat" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "La sala s'ha aturat" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Dilluns" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Dimarts" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Dimecres" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Dijous" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Divendres" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Dissabte" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Diumenge" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Gener" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Febrer" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Març" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Maig" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Juny" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Juliol" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Agost" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Setembre" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Octubre" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Novembre" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Decembre" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Configuració de la sala" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Nombre d'ocupants" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Només els moderadors i participants poden canviar l'assumpte d'aquesta sala" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Només els moderadors poden canviar l'assumpte d'aquesta sala" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Aquesta sala no és anònima" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no és vàlid" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "El Nickname ~s no existeix a la sala" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiliació invàlida: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Rol invàlid: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Configuració de la sala ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Títol de la sala" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Descripció de la sala:" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Crear una sala persistent" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Crear una sala pública" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Crear una llista de participants pública" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Crear una sala amb contrasenya" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Número màxim d'ocupants" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Sense Llímit" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Presentar Jabber ID's reals a" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "només moderadors" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "qualsevol" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Crear una sala de \"només membres\"" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Crear una sala moderada" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Els usuaris són participants per defecte" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Permetre que els usuaris canviin el tema" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Permetre que els usuaris envien missatges privats" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Permetre als visitants enviar missatges privats a" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "ningú" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Permetre que els usuaris fagen peticions a altres usuaris" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Permetre que els usuaris envien invitacions" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permetre als visitants enviar text d'estat en les actualitzacions de " "presència" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Permetre als visitants canviar el Nickname" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Permetre als visitants enviar peticions de veu" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Interval mínim entre peticions de veu (en segons)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Crear una sala protegida per CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excloure Jabber IDs de la comprovació CAPTCHA" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Habilitar el registre de la conversa" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Necessites un client amb suport x:data per a configurar la sala" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Número d'ocupants" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privat" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Petició de veu" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Aprova o denega la petició de veu" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "JID del usuari " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Concedir veu a aquesta persona?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s et convida a la sala ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "la contrasenya és" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s's cua de missatges offline" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Data" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Per a" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paquet" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Missatges fora de línia:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Eliminar tots els missatges offline" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "mòdul ejabberd SOCKS5 Bytestreams" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publicar-subscriure't" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Mòdul ejabberd Publicar-Subscriure" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Petició de subscriptor PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Tria si aprova aquesta entitat de subscripció" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID del Node" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Adreça del Subscriptor" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Permetre que aquesta Jabber ID es puga subscriure a aquest node pubsub" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads junt a les notificacions d'events" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Entrega de notificacions d'events" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptors quan canvia la configuració del node" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptors quan el node és eliminat" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscriptors quan els elements són eliminats del node" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Persistir elements al guardar" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Un nom per al node" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Màxim # d'elements que persistixen" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Permetre subscripcions" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Especificar el model d'accés" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Llista de grups que tenen permés subscriures" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Especificar el model del publicant" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Eliminar tots els elements quan el publicant relevant es desconnecti" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Especifica el tipus de missatge d'event" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Màxim tamany del payload en bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Quan s'ha enviat l'última publicació" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Sols enviar notificacions als usuaris disponibles" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Les col.leccions amb les que un node està afiliat" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Necessites un client amb suport x:data i de CAPTCHA para poder registrar-te" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Tria nom d'usuari i contrasenya per a registrar-te en aquest servidor" @@ -1468,7 +1497,7 @@ msgstr "Registre de compte Jabber" msgid "Register a Jabber account" msgstr "Registrar un compte Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Anul·lar el registre d'un compte Jabber" @@ -1483,7 +1512,7 @@ msgstr "" "usuari@servidor. Si us plau, llegeix amb cura les instruccions per emplenar " "correctament els camps." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nom d'usuari:" @@ -1497,11 +1526,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Caràcters no permesos:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servidor:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1509,12 +1538,12 @@ msgstr "" "No li donis la teva contrasenya a ningú, ni tan sols als administradors del " "servidor Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" "Podràs canviar la teva contrasenya més endavant utilitzant un client Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1523,7 +1552,7 @@ msgstr "" "ordinador. Fes servir aquesta característica només si saps que el teu " "ordinador és segur." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1533,114 +1562,114 @@ msgstr "" "segur.A Jabber no hi ha una forma automatitzada de recuperar la teva " "contrasenya si la oblides." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verificació de la Contrasenya:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Registrar" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Antiga contrasenya:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nova Contrasenya:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Aquesta pàgina permet anul·lar el registre d'un compte Jabber en aquest " "servidor Jabber." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Anul·lar el registre" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Subscripció" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Pendent" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grups" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Borrar" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Llista de contactes de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Afegir Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Llista de contactes" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Grups de contactes compartits" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nom:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Descripció:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Membre:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Mostrar grups:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grup " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Erlang Jabber" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Aniversari" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Ciutat" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Pais" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Cognom" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1648,46 +1677,52 @@ msgstr "" "Emplena el formulari per a buscar usuaris Jabber. Afegix * al final d'un " "camp per a buscar subcadenes." -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nom complet" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segon nom" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nom de la organizació" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unitat de la organizació" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Cerca usuaris en " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Necessites un client amb suport x:data per a poder buscar" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Recerca de vCard d'usuari" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Mòdul ejabberd vCard" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Resultat de la búsqueda" -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Emplena camps per a buscar usuaris Jabber que concorden" +#~ msgid "Delete" +#~ msgstr "Eliminar" + +#~ msgid "This room is not anonymous" +#~ msgstr "Aquesta sala no és anònima" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "La teva llista de privacitat activa ha denegat l'encaminament d'aquesta " diff --git a/priv/msgs/cs.po b/priv/msgs/cs.po index afa1da561dc..ad9901c2828 100644 --- a/priv/msgs/cs.po +++ b/priv/msgs/cs.po @@ -8,339 +8,340 @@ msgstr "" "X-Language: Czech (čeština)\n" "X-Additional-Translator: Milos Svasek [DuxforD] from openheads.net\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Je vyžadováno STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Nebyl poskytnut žádný zdroj" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Nahrazeno novým spojením" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "byl(a) vyhozen(a) z místnosti" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Zadejte text, který vidíte" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Nesmíte posílat zprávy na ~s. Pro povolení navštivte ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Pokud zde nevidíte obrázek CAPTCHA, přejděte na webovou stránku." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Webová stránka CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "CAPTCHA souhlasí." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Nemáte oprávnění" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Webová administrace ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administrace" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Seznamy přístupových práv (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Odeslané" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Nesprávný formát" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Odeslat" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Zdroj" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Smazat vybrané" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Pravidla přístupů" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s konfigurace pravidla přístupu" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtuální hostitelé" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Uživatelé" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Online uživatelé" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Poslední aktivita uživatele" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Čas: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Poslední měsíc" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Poslední rok" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Všechny aktivity" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Zobrazit běžnou tabulku" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Zobrazit kompletní tabulku" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistiky" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Nenalezeno" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Uzel nenalezen" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Přidat nový" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Hostitel" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Registrovaní uživatelé" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Uživatel" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Heslo" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Přidat uživatele" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Offline zprávy" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Poslední aktivita" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nikdy" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Registrovaní živatelé:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Online uživatelé:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Odchozí s2s spojení:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Odchozí s2s servery:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nic" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Změnit heslo" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Uživatel " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Připojené zdroje:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Heslo:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Odstranit uživatele" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Žádná data" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Uzly" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Běžící uzly" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zastavené uzly" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Uzel " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databáze" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Zálohovat" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Otevřené porty" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Aktualizovat" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Restart" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Stop" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduly" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Chyba RPC volání" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Databázové tabulky na " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Jméno" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Typ úložiště" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Položek" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Paměť" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Chyba" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Záloha na " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -350,487 +351,483 @@ msgstr "" "Mnesia. Pokud používáte ODBC modul, musíte zálohovat svoji SQL databázi " "samostatně." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Uložit binární zálohu:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Okamžitě obnovit binární zálohu:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Obnovit binární zálohu při následujícím restartu ejabberd (vyžaduje méně " "paměti)" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Uložit zálohu do textového souboru:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Okamžitě obnovit zálohu z textového souboru:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importovat uživatele ze souboru ve formátu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "Exportovat všechny uživatele do souboru ve formátu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportovat uživatele na hostiteli do souboru ve formátu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importovat uživatele z jabberd14 spool souborů:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importovat uživatele z jabberd14 spool souborů:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Otevřené porty na " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduly na " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistiky ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Čas běhu:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Čas procesoru" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transakce potvrzena" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transakce zrušena" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transakce restartována" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transakce zaznamenána" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Aktualizovat " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Aktualizovat plán" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Aktualizované moduly" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Aktualizované skripty" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Nízkoúrovňový aktualizační skript" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Kontrola skriptu" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Nastavení" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Smazat" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Start" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Příkazy" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Skutečně smazat zprávu dne?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Předmět" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Tělo zprávy" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Zpráva neobsahuje text" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Oznámení" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Odeslat oznámení všem uživatelům" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Odeslat oznámení všem uživatelům na všech hostitelích" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Odeslat oznámení všem online uživatelům" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Odeslat oznámení všem online uživatelům na všech hostitelích" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Nastavit zprávu dne a odeslat ji online uživatelům" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "Nastavit zprávu dne a odeslat ji online uživatelům" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Aktualizovat zprávu dne (neodesílat)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Aktualizovat zprávu dne pro všechny hostitele (neodesílat)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Smazat zprávu dne" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Smazat zprávu dne na všech hostitelích" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Konfigurace" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Spustit moduly" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Zastavit moduly" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Obnovit" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Uložit do textového souboru" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Import souboru" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Import adresáře" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restartovat službu" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Vypnout službu" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Smazat uživatele" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Ukončit sezení uživatele" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Získat heslo uživatele" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Změnit heslo uživatele" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Získat čas podleního přihlášení uživatele" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Získat statistiky uživatele" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Získat počet registrovaných uživatelů" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Získat počet online uživatelů" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Správa uživatelů" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Všichni uživatelé" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Odchozí s2s spojení" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Správa zálohování" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importovat uživatele z jabberd14 spool souborů" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Pro ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Od ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Konfigurace databázových tabulek " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Vyberte typ úložiště pro tabulky" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Jen kopie disku" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Kopie RAM a disku" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Kopie RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Vzdálená kopie" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Zastavit moduly na " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Vyberte moduly, které mají být zastaveny" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Spustit moduly na " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Vložte seznam modulů {Modul, [Parametry]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Seznam modulů, které mají být spuštěné" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Záloha do souboru na " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Zadajte cestu k souboru se zálohou" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Cesta k souboru" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Obnovit zálohu ze souboru na " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Uložit zálohu do textového souboru na " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Zadajte cestu k textovému souboru" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importovat uživatele ze souboru na " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Zadejte cestu k spool souboru jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importovat uživatele z adresáře na " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Zadejte cestu k jabberd14 spool adresáři" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Cesta k adresáři" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Časový posun" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurace seznamu přístupových práv (ACL)" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Seznamy přístupových práv (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Konfigurace přístupů" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Pravidla přístupů" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Ověření hesla" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Počet registrovaných uživatelů" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Počet online uživatelů" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Poslední přihlášení" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Velikost seznamu kontaktů" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP adresy" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Zdroje" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administrace " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Akce aplikovaná na uživatele" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Upravit vlastnosti" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -939,482 +936,514 @@ msgstr "Kódování pro server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Konference" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Pro registraci přezdívky potřebujete klienta s podporou x:data" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registrace přezdívky na " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Zadejte přezdívku, kterou chcete zaregistrovat" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Přezdívka" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Konference" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "opustil(a) místnost" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Registrovaní uživatelé" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Nastavení diskuzní místnosti bylo změněno" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "vstoupil(a) do místnosti" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "opustil(a) místnost" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "byl(a) zablokován(a)" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "byl(a) vyhozen(a) kvůli změně přiřazení" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "byl(a) vyhozen(a), protože mísnost je nyní pouze pro členy" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "byl(a) vyhozen(a), protože dojde k vypnutí systému" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "se přejmenoval(a) na" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " změnil(a) téma na: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Konference vytvořena" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Konference zrušena" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Konference spuštěna" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Konference zastavena" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Pondělí" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Úterý" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Středa" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Čtvrtek" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Pátek" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sobota" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Neděle" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr ". ledna" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr ". února" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr ". března" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr ". dubna" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr ". května" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr ". června" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr ". července" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr ". srpna" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr ". září" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr ". října" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr ". listopadu" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr ". prosince" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Nastavení místnosti" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Jen moderátoři a účastníci mají povoleno měnit téma této místnosti" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Jen moderátoři mají povoleno měnit téma místnosti" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Tato místnost není anonymní" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s je neplatné" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Přezdívka ~s v místnosti neexistuje" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Neplatné přiřazení: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Neplatná role: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Konfigurace místnosti ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Název místnosti" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Popis místnosti" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Nastavit místnost jako stálou" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Nastavit místnost jako veřejnou" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Nastavit seznam účastníků jako veřejný" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Chránit místnost heslem" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Odhalovat skutečná Jabber ID" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "moderátorům" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "každému" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Zpřístupnit místnost jen členům" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Nastavit místnost jako moderovanou" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Uživatelé jsou implicitně členy" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Povolit uživatelům měnit téma místnosti" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Povolit uživatelům odesílat soukromé zprávy" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Povolit návštěvníkům odesílat soukromé zprávy" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "nikdo" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Povolit uživatelům odesílat požadavky (query) ostatním uživatelům" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Povolit uživatelům posílání pozvánek" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Povolit návštěvníkům posílat stavové zprávy ve statusu" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Povolit návštěvníkům měnit přezdívku" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Povolit uživatelům posílat žádosti o voice práva" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimální interval mezi žádostmi o voice práva (v sekundách)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Chránit místnost pomocí CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Vyloučit Jabber ID z procesu CAPTCHA ověřování" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Zaznamenávat konverzace" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Ke konfiguraci místnosti potřebujete klienta podporujícího x:data" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "soukromá, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Žádost o voice práva" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Povolit nebo odmítnout voice žádost." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Jabber ID uživatele" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Udělit voice práva této osobě?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s vás zve do místnosti ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "heslo je" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Fronta offline zpráv uživatele ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Čas" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Od" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Pro" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Offline zprávy:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Odstranit všechny offline zprávy" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Žádost odběratele PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Zvolte, zda chcete schválit odebírání touto entitou" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID uzlu" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Adresa odběratele" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Povolit tomuto Jabber ID odebírat tento pubsub uzel?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Doručovat náklad s upozorněním na událost" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Doručovat upozornění na události" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Upozornit odběratele na změnu nastavení uzlu" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Upozornit odběratele na smazání uzlu" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Upozornit odběratele na odstranění položek z uzlu" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Uložit položky natrvalo do úložiště" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Přívětivé jméno pro uzel" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Maximální počet položek, které je možné natrvalo uložit" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Povolit odebírání" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Uveďte přístupový model" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Skupiny kontaktů, které mohou odebírat" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Specifikovat model pro publikování" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Smazat všechny položky, pokud se příslušný poskytovatel odpojí" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Zvolte typ zpráv pro události" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Maximální náklad v bajtech" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Kdy odeslat poslední publikovanou položku" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Doručovat upozornění jen právě přihlášeným uživatelům" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Kolekce, se kterými je uzel spřízněn" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Pro registraci potřebujete klienta s podporou x:data a CAPTCHA" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Zadejte jméno uživatele a heslo pro registraci na tomto serveru" @@ -1450,7 +1479,7 @@ msgstr "Registrace účtu Jabberu" msgid "Register a Jabber account" msgstr "Zaregistrujte si účet Jabberu" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Zrušte registraci účtu Jabberu" @@ -1464,7 +1493,7 @@ msgstr "" "(Jabber IDentifikátor) bude mít tvar: uživatelskéjméno@server. Přečtěte si " "prosím pozorně instrukce pro vyplnění údajů." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Uživatelské jméno:" @@ -1477,22 +1506,22 @@ msgstr "" msgid "Characters not allowed:" msgstr "Nepřípustné znaky:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Nikdy nikomu nesdělujte své heslo, ani administrátorovi serveru Jabberu." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Později můžete své heslo změnit pomocí klienta Jabberu." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1500,7 +1529,7 @@ msgstr "" "Někteří klienti umí uložit vaše heslo na disk počítače. Tuto funkci " "používejte, pouze pokud věříte zabezpečení svého počítače." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1509,112 +1538,112 @@ msgstr "" "Svoje heslo si zapamatujte, nebo si jej poznamenejte na papírek a ten " "uschovejte v bezpečí. Jabber nemá žádný automatizovaný způsob obnovy hesla." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Ověření hesla:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Zaregistrovat se" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Současné heslo:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nové heslo:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Zde můžete zrušit registraci účtu na tomto serveru Jabberu." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Zrušit registraci" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Přihlášení" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Čekající" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Skupiny" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Ověřit" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Odstranit" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Seznam kontaktů " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Přidat Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Seznam kontaktů" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Skupiny pro sdílený seznam kontaktů" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Jméno:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Popis:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Členové:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Zobrazené skupiny:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Skupina " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Datum narození" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Město" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Země" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Příjmení" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1622,46 +1651,52 @@ msgstr "" "Pro vyhledání uživatele Jabberu vyplňte formulář (na konec přidejte znak * " "pro vyhledání podřetězce)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Celé jméno" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Druhé jméno" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Název firmy" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Oddělení" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Hledat uživatele v " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "K vyhledávání potřebujete klienta podporujícího x:data" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Hledání uživatelů podle vizitek" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modul" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Výsledky hledání pro " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Vyplňte políčka pro vyhledání uživatele Jabberu" +#~ msgid "Delete" +#~ msgstr "Smazat" + +#~ msgid "This room is not anonymous" +#~ msgstr "Tato místnost není anonymní" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Vaše nastavení soukromí znemožnilo směrování této stance." diff --git a/priv/msgs/de.po b/priv/msgs/de.po index 7cc2ba14033..5dfe2eec923 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -17,341 +17,342 @@ msgstr "" "X-Additional-Translator: Torsten Werner\n" "X-Additional-Translator: Marina Hahn\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Verwendung von STARTTLS erforderlich" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Keine Ressource angegeben" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Durch neue Verbindung ersetzt" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "wurde gekickt" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Geben sie den Text den sie sehen ein" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Ihre Nachrichten an ~s werden blockiert. Um dies zu ändern, besuchen sie ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "Wenn sie das CAPTCHA Bild nicht sehen, besuchen sie bitte die Webseite." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA Webseite" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Die Verifizierung ist gültig." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Nicht berechtigt" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web-Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Verwaltung" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Zugangskontroll-Listen (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Gesendet" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Ungültiges Format" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Senden" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Unformatiert" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Markierte löschen" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Zugangsregeln" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s Zugangsregel-Konfiguration" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtuelle Hosts" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Benutzer" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Angemeldete Benutzer" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Letzte Benutzeraktivität" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Zeitraum: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Letzter Monat" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Letztes Jahr" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Alle Aktivitäten" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Normale Tabelle anzeigen" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Vollständige Tabelle anzeigen" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistik" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Nicht gefunden" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Knoten nicht gefunden" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Neue hinzufügen" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Registrierte Benutzer" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Benutzer" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Passwort" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Benutzer hinzufügen" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Offline-Nachrichten" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Letzte Aktivität" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nie" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Angemeldet" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Registrierte Benutzer:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Angemeldete Benutzer:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Ausgehende s2s-Verbindungen:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Ausgehende s2s-Server:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Keine" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Passwort ändern" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Benutzer " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Verbundene Ressourcen:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Passwort:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Benutzer löschen" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Keine Daten" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Knoten" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Aktive Knoten" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Inaktive Knoten" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Knoten " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Datenbank" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Datensicherung" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Aktive Ports" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Aktualisieren" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Neustart" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Stoppen" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Module" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Fehler bei RPC-Aufruf" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Datenbanktabellen auf " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Vorname" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Speichertyp" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elemente" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Speicher" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Fehler" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Sicherung von " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -361,490 +362,486 @@ msgstr "" "sichern. Wenn sie das ODBC-Modul verwenden, müssen sie die SQL-Datenbank " "manuell sichern." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Speichere binäre Sicherung:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Stelle binäre Sicherung sofort wieder her:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Stelle binäre Sicherung beim nächsten ejabberd-Neustart wieder her (benötigt " "weniger Speicher):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Speichere Klartext-Sicherung:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Stelle Klartext-Sicherung sofort wieder her:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Benutzerdaten von einer PIEFXIS Datei (XEP-0227) importieren:" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Alle Benutzerdaten des Servers in PIEFXIS Dateien (XEP-0227) exportieren:" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Alle Benutzerdaten des Hosts in PIEFXIS Dateien (XEP-0227) exportieren:" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importiere Benutzer von jabberd14 Spool Datei:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importiere Benutzer von jabberd14 Spool Verzeichnis:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Aktive Ports bei" -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Module bei " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistiken von ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Betriebszeit:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "CPU-Zeit:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Durchgeführte Transaktionen:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Abgebrochene Transaktionen:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Neu gestartete Transaktionen:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Protokollierte Transaktionen:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Aktualisierung " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Aktualisierungsplan" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Geänderte Module" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Aktualisierungsscript" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Low level Aktualisierungsscript" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Script-Überprüfung" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokoll" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Optionen" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Löschen" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Starten" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Befehle" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Die Nachricht des Tages wirklich löschen?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Betreff" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Nachrichtentext" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Kein Text für die Ankündigung angegeben" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Ankündigungen" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Sende Ankündigung an alle Benutzer" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Sende Ankündigung an alle Benutzer auf allen Hosts" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Sende Ankündigung an alle angemeldeten Benutzer" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Sende Ankündigung an alle angemeldeten Benutzer auf allen Hosts" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Setze Nachricht des Tages und sende sie an alle angemeldeten Benutzer" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Setze Nachricht des Tages auf allen Hosts und sende sie an alle angemeldeten " "Benutzer" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Aktualisiere Nachricht des Tages (nicht senden)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Aktualisiere Nachricht des Tages auf allen Hosts (nicht senden)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Lösche Nachricht des Tages" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Lösche Nachricht des Tages auf allen Hosts" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Konfiguration" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Module starten" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Module stoppen" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Wiederherstellung" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Ausgabe in Textdatei" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Datei importieren" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Verzeichnis importieren" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Dienst neustarten" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Dienst herunterfahren" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Benutzer löschen" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Benutzer-Sitzung beenden" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Benutzer-Passwort abrufen" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Benutzer-Passwort ändern" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "letzte Anmeldezeit abrufen" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Benutzer-Statistiken abrufen" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Anzahl der registrierten Benutzer abrufen" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Anzahl der angemeldeten Benutzer abrufen" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Benutzerverwaltung" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Alle Benutzer" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Ausgehende s2s-Verbindungen" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Datensicherungsverwaltung" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importiere Benutzer aus jabberd14-Spool-Dateien" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "An ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Von ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Datenbanktabellen-Konfiguration auf " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Wähle Speichertyp der Tabellen" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Nur auf Festplatte" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM und Festplatte" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Nur RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Fernkopie" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Stoppe Module auf " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Wähle zu stoppende Module" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Starte Module auf " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Geben sie eine Liste bestehend aus {Modul, [Optionen]} ein" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Liste der zu startenden Module" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Datensicherung in die Datei " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Geben sie den Pfad zur Datensicherung ein" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Pfad zur Datei" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Datenwiederherstellung aus der Datei " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Ausgabe der Sicherung in diese Textdatei " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Geben sie den Pfad zur Textdatei ein" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Benutzer aus dieser Datei importieren " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Geben Sie den Pfad zur jabberd14-Spool-Datei ein" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Benutzer importieren aus dem Verzeichnis " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Geben Sie den Pfad zum jabberd14-Spool-Verzeichnis ein" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Pfad zum Verzeichnis" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Zeitverzögerung" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfiguration der Zugangskontrolllisten" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Zugangskontroll-Listen (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Zugangskonfiguration" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Zugangsregeln" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Passwort bestätigen" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Anzahl der registrierten Benutzer" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Anzahl der angemeldeten Benutzer" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Letzte Anmeldung" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Kontaktlistengröße" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP Adressen" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Ressourcen" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administration von " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Aktion auf Benutzer" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Einstellungen ändern" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -956,489 +953,521 @@ msgstr "Kodierung für Server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Chaträume" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um Ihren Benutzernamen " "zu registrieren" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registrieren des Benutzernames auf" -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Geben sie den zu registrierenden Benutzernamen ein" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Benutzername" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC-Modul" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Chaträume" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "verlässt den Raum" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Registrierte Benutzer" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Chatraum-Konfiguration geändert" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "betretet den Raum" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "verlässt den Raum" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "wurde gebannt" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "wurde wegen Änderung des Mitgliederstatus gekickt" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "wurde gekickt weil der Raum auf Nur-Mitglieder umgestellt wurde" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "wurde wegen Systemabschaltung gekickt" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "ist nun bekannt als" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " hat das Thema geändert auf: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Chatraum wurde erstellt" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Chatraum wurde entfernt" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Chatraum wurde gestartet" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Chatraum wurde beendet" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Montag" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Dienstag" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Mittwoch" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Donnerstag" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Freitag" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Samstag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Sonntag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Januar" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Februar" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "März" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "April" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Mai" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "August" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "September" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "November" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Dezember" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Raum-Konfiguration" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Teilnehmer in diesem Raum" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Nur Moderatoren und Mitglieder dürfen das Thema in diesem Raum ändern" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Nur Moderatoren dürfen das Thema in diesem Raum ändern" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Dieser Raum ist nicht anonym" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Die Jabber-ID ~s ist ungültig" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Der Benutzername ~s existiert im Raum nicht" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Ungültige Mitgliedschaft: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Ungültige Rolle: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Konfiguration für Raum ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Raumname" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Raum Beschreibung" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Raum persistent machen" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Raum öffentlich suchbar machen" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Teilnehmerliste öffentlich machen" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Raum mit Passwort schützen" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Maximale Anzahl von Teilnehmern" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Keine Begrenzung" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Echte Jabber-IDs anzeigen für" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "ausschliesslich Moderatoren" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "jeden" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Raum nur für Mitglieder zugänglich machen" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Raum moderiert machen" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Benutzer werden standardmäßig vollwertige Teilnehmer" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Erlaube Benutzern das Thema zu ändern" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Erlaube Benutzern private Nachrichten zu senden" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Erlaube Besuchern das Senden von privaten Nachrichten an" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "niemanden" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Erlaube Benutzern Informationen über andere Benutzer abzufragen" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Erlaube Benutzern Einladungen zu senden" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Erlaube Besuchern einen Text bei Statusänderung zu senden" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Erlaube Besuchern ihren Spitznamen zu ändern" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Anfragen von Sprachrechten für Benutzer erlauben" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Mindestdauer zwischen Anfragen für Sprachrechte (in Sekunden)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Raum mit Verifizierung (Captcha) versehen" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Von CAPTCHA Überprüfung ausgeschlossene Jabber IDs" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Protokollierung aktivieren" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um den Raum zu " "konfigurieren" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Anzahl der Teilnehmer" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Anfrage für Sprachrechte" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Diese Anfrage für Sprachrechte bestätigen oder ablehnen." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Benutzer JID" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Sprachrechte dieser Person erteilen?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s lädt Sie in den Raum ~s ein" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "das Passwort lautet" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s's Offline-Nachrichten-Warteschlange" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Zeit" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Von" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "An" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Offline-Nachrichten:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Alle Offline Nachrichten löschen" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5-Bytestreams-Modul" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe-Modul" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub-Abonnenten-Anfrage" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Wähle Sie, ob dieses Abonnement akzeptiert werden soll." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Knoten-ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Abonnenten-Adresse" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Dieser Jabber-ID das Abonnement dieses pubsub-Knotens erlauben?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Nachrichten mit Ereignis-Benachrichtigungen zustellen" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Ereignisbenachrichtigung zustellen" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Abonnenten benachrichtigen, wenn sich die Knotenkonfiguration ändert" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Abonnenten benachrichtigen, wenn der Knoten gelöscht wird" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Abonnenten benachrichtigen, wenn Einträge vom Knoten entfernt werden" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Einträge dauerhaft speichern" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Ein merkbarer Name für den Knoten" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Maximale Anzahl dauerhaft zu speichernder Einträge" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Ob Abonnements erlaubt sind" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Geben sie das Zugangsmodell an" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Kontaktlisten-Gruppen die abonnieren dürfen" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Geben sie das Publikationsmodell an" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Alle Einträge entfernen, wenn der relevante Veröffentlicher offline geht" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Geben sie den Ereignis-Nachrichtentyp an" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Maximale Nutzlastgrösse in Bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Wann soll das letzte veröffentlichte Objekt gesendet werden" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Benachrichtigungen nur an verfügbare Benutzer schicken" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Sammlungen, mit denen ein Knoten verknüpft ist" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Sie benötigen einen Client, der x:data und CAPTCHA unterstützt, um Ihren " "Benutzernamen zu registrieren" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Wählen sie zum Registrieren einen Benutzernamen und ein Passwort" @@ -1474,7 +1503,7 @@ msgstr "Jabber Konto Anmeldung" msgid "Register a Jabber account" msgstr "Jabber Konto registrieren" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Jabber Konto entfernen" @@ -1489,7 +1518,7 @@ msgstr "" "benutzername@server. Bitte lesen sie die Hinweise genau durch, um die Felder " "korrekt auszufüllen." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Benutzername:" @@ -1503,11 +1532,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Nicht erlaubte Zeichen:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1515,12 +1544,12 @@ msgstr "" "Geben sie niemandem ihr Passwort, auch nicht den Administratoren des Jabber " "Servers." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" "Sie können das Passwort später mit einem Jabber Client Programm ändern." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1529,7 +1558,7 @@ msgstr "" "Verwenden sie diese Möglichkeit nur auf Computern, die sie als sicher " "einstufen." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1539,113 +1568,113 @@ msgstr "" "sicher verwahren. Bei Jabber gibt es keine automatische Möglichkeit, das " "Passwort wiederherzustellen." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Passwort bestätigen:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Anmelden" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Aktuelles Passwort:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Neues Passwort:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Diese Seite erlaubt es, ein Jabber Konto von diesem Server zu entfernen." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Abmelden" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Abonnement" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "anhängig" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Gruppen" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validieren" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Entfernen" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Kontaktliste von " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Jabber-ID hinzufügen" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Kontaktliste" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Gruppen der gemeinsamen Kontaktliste" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Name:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Beschreibung:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Mitglieder:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Angezeigte Gruppen:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Gruppe " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Geburtsdatum" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Stadt" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-Mail" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nachname" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1653,49 +1682,55 @@ msgstr "" "Füllen Sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen " "(beenden Sie ein Feld mit *, um auch nach Teilzeichenketten zu suchen)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Vollständiger Name" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Zweiter Vorname" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisation" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Abteilung" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Benutzer suchen in " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um die Suche verwenden " "zu können" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard-Benutzer-Suche" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard-Modul" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Suchergebnisse für " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Füllen Sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen" +#~ msgid "Delete" +#~ msgstr "Löschen" + +#~ msgid "This room is not anonymous" +#~ msgstr "Dieser Raum ist nicht anonym" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "Ihre aktive Privacy Liste hat die Weiterleitung des Stanzas unterbunden." diff --git a/priv/msgs/ejabberd.pot b/priv/msgs/ejabberd.pot index ffe4a2e593c..877be09efad 100644 --- a/priv/msgs/ejabberd.pot +++ b/priv/msgs/ejabberd.pot @@ -1,823 +1,820 @@ msgid "" msgstr "" -"Project-Id-Version: 14.12.54\n" +"Project-Id-Version: 15.07.57\n" "X-Language: Language Name\n" "Last-Translator: Translator name and contact method\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 msgid "User ~s" msgstr "" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 msgid "Node ~p" msgstr "" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 msgid "Database Tables at ~p" msgstr "" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 msgid "Backup of ~p" msgstr "" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " "separately." msgstr "" -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "" -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 msgid "Modules at ~p" msgstr "" -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 msgid "Update ~p" msgstr "" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "" -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "" -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "" -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "" -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "" -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "" -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "" -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "" -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "" -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -916,482 +913,511 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "" -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +msgid "Total rooms" +msgstr "" + +#: mod_muc_admin.erl:249 +msgid "Permanent rooms" +msgstr "" + +#: mod_muc_admin.erl:250 +msgid "Registered nicknames" +msgstr "" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr "" -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" @@ -1427,7 +1453,7 @@ msgstr "" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1438,7 +1464,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "" @@ -1450,180 +1476,180 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "" -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "" -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" diff --git a/priv/msgs/el.po b/priv/msgs/el.po index 575718d5ffd..0e63ad5ed37 100644 --- a/priv/msgs/el.po +++ b/priv/msgs/el.po @@ -11,340 +11,341 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Greek (ελληνικά)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Απαιτείται χρήση STARTTLS " -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Δεν προμηθεύτικε πόρος" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Αντικαταστάθικε από νέα σύνδεση" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "αποβλήθηκε " -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Πληκτρολογήστε το κείμενο που βλέπετε" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Τα μηνύματά σας πρως ~s είναι αποκλεισμένα. Για αποδεσμεύση, επισκεφθείτε ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Εάν δεν βλέπετε την εικόνα CAPTCHA εδώ, επισκεφθείτε την ιστοσελίδα." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Ιστοσελίδα CAPTCHA " -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Το CAPTCHA είναι έγκυρο." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Χορίς Εξουσιοδότηση" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Διαχείριση" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Λίστες Ελέγχου Πρόσβασης" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Υποβλήθηκε" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Ακατάλληλη μορφή" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Υποβοβολή" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Ακατέργαστο" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Διαγραφή επιλεγμένων" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Κανόνες Πρόσβασης" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s διαμόρφωση κανόνα πρόσβασης" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "εικονικοί κεντρικοί υπολογιστές" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Χρήστες" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Συνδεμένοι χρήστες" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Τελευταία Δραστηριότητα Χρήστη" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Περίοδος: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Περασμένο μήνα" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Πέρυσι" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Όλες οι δραστηριότητες" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Δείτε Κοινό Πίνακα" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Δείτε Ολοκληρωτικό Πίνακα" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Στατιστικές" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Δεν Βρέθηκε" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Κόμβος δεν βρέθηκε" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Προσθήκη νέου" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Κεντρικός Υπολογιστής" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Εγγεγραμμένοι Χρήστες" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Χρήστης" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Κωδικός Πρόσβασης" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Προσθήκη Χρήστη" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Χωρίς Σύνδεση Μηνύματα" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Τελευταία Δραστηριότητα" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Ποτέ" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Συνδεδεμένο" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Εγγεγραμμένοι Χρήστες:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Online Χρήστες:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Εξερχόμενες S2S Συνδέσεις:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Εξερχόμενοι S2S διακομιστές:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Κανένα" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Αλλαγή κωδικού" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Χρήστης" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Συνδεδεμένοι Πόροι:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Κωδικός πρόσβασης:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Αφαίρεση χρήστη" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Κανένα στοιχείο" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Κόμβοι" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Ενεργοί Κόμβοι" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Σταματημένοι Κόμβοι" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Κόμβος" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Βάση δεδομένων" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Αποθήκευση Αντιγράφου Ασφαλείας" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Παρακολουθούμενες Θύρες" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Ενημέρωση" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Επανεκκίνηση" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Σταμάτημα" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Σφάλμα RPC Κλήσης" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Πίνακες βάσης δεδομένων στο " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Όνομα" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Τύπος Αποθήκευσης" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Στοιχεία" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Μνήμη" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Σφάλμα" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Αντιγράφο Ασφαλείας του " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -355,498 +356,494 @@ msgstr "" "ODBC, θα πρέπει επίσης να κάνετε χωριστά Αντιγράφο Ασφαλείας της SQL βάση " "δεδομένων σας ." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Αποθηκεύση δυαδικού αντιγράφου ασφαλείας:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Όλλα Καλά" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Επαναφορά δυαδικού αντιγράφου ασφαλείας αμέσως:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Επαναφορά δυαδικού αντιγράφου ασφαλείας μετά την επόμενη επανεκκίνηση του " "ejabberd (απαιτεί λιγότερη μνήμη):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Αποθηκεύση αντιγράφου ασφαλείας σε αρχείο κειμένου:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Επαναφορά αντιγράφου ασφαλείας από αρχείο κειμένου αμέσως:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Εισαγωγή δεδομένων χρηστών από ένα αρχείο PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Εξαγωγή δεδομένων όλων των χρηστών του διακομιστή σε PIEFXIS αρχεία " "(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Εξαγωγή δεδομένων των χρηστών κεντρικού υπολογιστή σε PIEFXIS αρχεία " "(XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Εισαγωγή δεδομένων χρήστη από το αρχείο σειράς jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Εισαγωγή δεδομένων χρηστών από κατάλογο αρχείων σειράς jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Παρακολουθούμενες Θύρες στο " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Modules στο " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Στατιστικές του ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Ώρα CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Παραδοθείς συναλλαγές:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Αποτυχημένες συναλλαγές:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Επανειλημμένες συναλλαγές:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Καταγραμμένες συναλλαγές:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Ενημέρωση" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Σχέδιο ενημέρωσης" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Τροποποιημένα modules" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Προγράμα ενημέρωσης" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Προγράμα ενημέρωσης χαμηλού επίπεδου " -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Script ελέγχου" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Θύρα" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Πρωτόκολλο" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Επιλογές" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Διαγραφή" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Εκκίνηση" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Εντολές" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Πινγκ" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Πονγκ" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Πραγματικά να διαγράψετε το μήνυμα της ημέρας;" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Θέμα" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Περιεχόμενο μηνυμάτως" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Δεν προμηθεύτικε περιεχόμενο ανακοινώσης" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Ανακοινώσεις" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Αποστολή ανακοίνωσης σε όλους τους χρήστες" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "" "Αποστολή ανακοίνωσης σε όλους τους χρήστες σε όλους τους κεντρικούς " "υπολογιστές" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Αποστολή ανακοίνωσης σε όλους τους συνδεδεμένους χρήστες" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Αποστολή ανακοίνωσης σε όλους τους συνδεδεμένους χρήστες σε όλους τους " "κεντρικούς υπολογιστές" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Ορίστε μήνυμα ημέρας και αποστολή στους συνδεδεμένους χρήστες" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Ορίστε μήνυμα ημέρας και άμεση αποστολή στους συνδεδεμένους χρήστες σε όλους " "τους κεντρικούς υπολογιστές" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Ενημέρωση μηνύματως ημέρας (χωρίς άμεση αποστολή)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" "Ενημέρωση μηνύματως ημέρας σε όλους τους κεντρικούς υπολογιστές (χωρίς άμεση " "αποστολή)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Διαγράψτε το μήνυμα της ημέρας" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Διαγράψτε το μήνυμα της ημέρας σε όλους τους κεντρικούς υπολογιστές" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Διαμόρφωση" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Εκκίνηση Modules" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "ΠαύσηModules" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Επαναφορά Αντιγράφου Ασφαλείας" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Αποθήκευση σε αρχείο κειμένου" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Εισαγωγή αρχείων" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Εισαγωγή κατάλογου αρχείων" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Επανεκκίνηση Υπηρεσίας" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Κλείσιμο Υπηρεσίας" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Διαγραφή Χρήστη" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Τερματισμός Συνεδρίας Χρήστη" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Έκθεση Κωδικού Πρόσβασης Χρήστη" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Αλλαγή Κωδικού Πρόσβασης Χρήστη" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Έκθεση Τελευταίας Ώρας Σύνδεσης Χρήστη" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Έκθεση Στατιστικών Χρήστη" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Έκθεση αριθμού εγγεγραμμένων χρηστών" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Έκθεση αριθμού συνδεδεμένων χρηστών" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Διαχείριση χρηστών" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Όλοι οι χρήστες" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Εξερχόμενες S2S Συνδέσεις" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Διαχείριση Αντιγράφου Ασφαλείας" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Εισαγωγή Χρηστών από αρχεία σειράς jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Πρώς ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Από ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Διαμόρφωση Πίνακων βάσης δεδομένων στο " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Επιλέξτε τύπο αποθήκευσης των πινάκων" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Αντίγραφο μόνο σε δίσκο" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Αντίγραφο μόνο σε RAM καί δίσκο" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Αντίγραφο σε RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Απομεμακρυσμένο αντίγραφο" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Παύση Modules στο " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Επιλέξτε modules για να σταματήσουν" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Εκκίνηση Modules στο " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Εισάγετε κατάλογο των (Module, [Επιλογές])" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Λίστα των Module για Εκκίνηση" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Αποθήκευση Αντιγράφου Ασφαλείας σε Αρχείο στο " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Εισάγετε τοποθεσία αρχείου αντιγράφου ασφαλείας" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Τοποθεσία Αρχείου" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Επαναφορά Αντιγράφου Ασφαλείας από αρχείο στο " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Αποθήκευση Αντιγράφου Ασφαλείας σε αρχείο κειμένου στο " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Εισάγετε Τοποθεσία Αρχείου Κειμένου" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Εισαγωγή χρηστών από αρχείο στο " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Εισάγετε τοποθεσία αρχείου σειράς jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Εισαγωγή χρηστών από κατάλογο αρχείων στο " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Εισάγετε κατάλογο αρχείων σειράς jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Τοποθεσία κατάλογου αρχείων" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Χρόνος καθυστέρησης" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Διαχείριση στις Λίστες Ελέγχου Πρόσβασης" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Λίστες Ελέγχου Πρόσβασης" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Διαμόρφωση Πρόσβασης" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Κανόνες Πρόσβασης" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Ταυτότητα Jabber" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Επαλήθευση κωδικού πρόσβασης" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Αριθμός εγγεγραμμένων χρηστών" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Αριθμός συνδεδεμένων χρηστών" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Τελευταία σύνδεση" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Μέγεθος Καταλόγου Επαφών" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Διευθύνσεις IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Πόροι" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Διαχείριση του" -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Eνέργεια για το χρήστη" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Επεξεργασία ιδιοτήτων" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -958,168 +955,192 @@ msgstr "Κωδικοποίηση για διακομιστή ~b" msgid "Server ~b" msgstr "Διακομιστής ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Αίθουσες σύνεδριασης" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για εγγραφή με ψευδώνυμο" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Εγγραφή με Ψευδώνυμο στο " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Πληκτρολογήστε το ψευδώνυμο που θέλετε να εγγραφείτε" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Ψευδώνυμο" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC module" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Αίθουσες σύνεδριασης" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "εγκαταλείπει την αίθουσα" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Εγγεγραμμένοι Χρήστες" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Διαμόρφωση Αίθουσaς σύνεδριασης τροποποιηθηκε" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "συνδέετε στην αίθουσα" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "εγκαταλείπει την αίθουσα" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "έχει απαγορευθεί" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "Έχει αποβληθεί λόγω αλλαγής υπαγωγής" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "αποβλήθηκε επειδή η αίθουσα αλλάξε γιά μέλη μόνο" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "αποβλήθηκε λόγω τερματισμού συστήματος" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "είναι τώρα γνωστή ως" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " έχει θέσει το θέμα σε: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Η αίθουσα σύνεδριασης δημιουργήθηκε" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Η αίθουσα σύνεδριασης διαγράφηκε" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Η αίθουσα σύνεδριασης έχει ξεκινήσει" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Η αίθουσα σύνεδριασης έχει σταματήσει" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Δευτέρα" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Τρίτη" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Τετάρτη" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Πέμπτη" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Παρασκευή" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Σάββατο" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Κυριακή" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Ιανουάριος" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Φεβρουάριος" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Μάρτιος" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Απρίλιος" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Μάιος" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Ιούνιος" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Ιούλιος" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Αύγουστος" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Σεπτέμβριος" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Οκτώβριος" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Νοέμβριος" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Δεκέμβριος" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Διαμόρφωση Αίθουσας σύνεδριασης" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Συμετεχόντες Αίθουσας σύνεδριασης" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1127,319 +1148,327 @@ msgstr "" "Μόνο οι συντονιστές και οι συμμετέχοντες μπορούν να αλλάξουν το θέμα αυτής " "της αίθουσας" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Μόνο οι συντονιστές μπορούν να αλλάξουν το θέμα αυτής της αίθουσας" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Η αίθουσα αυτή δεν είναι ανώνυμη" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Η Jabber Ταυτότητα ~s είναι άκυρη" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Ψευδώνυμο ~s δεν υπάρχει σε αυτή την αίθουσα" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Άκυρη υπαγωγή: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Άκυρος ρόλο: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Διαμόρφωση Αίθουσας σύνεδριασης ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Τίτλος Αίθουσας " -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Περιγραφή Αίθουσας" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Κάντε αίθουσα μόνιμη" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Κάντε την δημόσια αναζήτηση δυνατή για αυτή την αίθουσα" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Κάντε κοινό τον κατάλογο συμμετεχόντων" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Κάντε την αίθουσα προστατεύομενη με κωδικό πρόσβασης" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Μέγιστος αριθμός συμετεχόντων" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Χωρίς όριο" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Παρούσιαση πραγματικών ταυτοτήτων Jabber σε" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "συντονιστές μόνο" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "οποιοσδήποτε" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Κάντε την αίθουσα μόνο για μέλη" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Κάντε την αίθουσα εποπτεύονομενη" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Προεπιλογη χρήστων ως συμμετέχοντες" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Επιτρέψετε στους χρήστες να αλλάζουν το θέμα" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν ιδιωτικά μηνύματα" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν ιδιωτικά μηνύματα σε" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "κανείς" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Επιτρέπστε στους χρήστες να ερωτούν άλλους χρήστες" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν προσκλήσεις" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Επιτρέψτε στους επισκέπτες να αποστέλλουν κατάσταση στις ενημερώσεις " "παρουσίας" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Επιτρέψετε στους επισκέπτες να αλλάζου ψευδώνυμο" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Επιτρέψτε στους επισκέπτες να στέλνουν αιτήματα φωνής" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ελάχιστο χρονικό διάστημα μεταξύ αιτημάτων φωνής (σε δευτερόλεπτα)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Κάντε την αίθουσα CAPTCHA προστατεύονομενη" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Εξαίρεση από τις ταυτότητες Jabber, ή CAPTCHA πρόκληση" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Ενεργοποίηση καταγραφής" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε την αίθουσα " -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Αριθμός συμετεχόντων" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "ιδιωτικό," -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Αίτημα φωνής" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Είτε εγκρίνετε ή απορρίψτε το αίτημα φωνής." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "JID Χρήστη" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Παραχώρηση φωνής σε αυτό το άτομο;" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s σας προσκαλεί στην αίθουσα ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "ο κωδικός πρόσβασης είναι" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Η Σειρά Χωρίς Σύνδεση Μηνύματων τού ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Χρόνος" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Από" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Πρώς" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Πακέτο" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Χωρίς Σύνδεση Μηνύματα:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Αφαίρεση Όλων των Χωρίς Σύνδεση Μηνύματων" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Δημοσίευση-Εγγραφή" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd module Δημοσίευσης-Εγγραφής" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Αίτηση συνδρομητή Δημοσίευσης-Εγγραφής" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Επιλέξτε αν θα εγκρίθεί η εγγραφή αυτής της οντότητας." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Ταυτότητα Κόμβου" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Διεύθυνση Συνδρομητή" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" "Επιτρέπετε σε αυτή την Jabber Ταυτότητα να εγγραφεί σε αυτό τον κόμβο " "Δημοσίευσης-Εγγραφής;" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Κοινοποιήσεις με την παράδοση φορτίων" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Κοινοποιήσεις παράδοσης" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Ειδοποιηση στους συνδρομητές όταν αλλάζει η διαμόρφωση κόμβου" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Ειδοποιηση στους συνδρομητές όταν ο κόμβος διαγράφεται" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Ειδοποιηση στους συνδρομητές όταν αφαίρούντε στοιχεία από τον κόμβο" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Μονιμη αποθήκευση στοιχείων" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Ένα φιλικό όνομα για τον κόμβο" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Μέγιστος αριθμός μόνιμων στοιχείων" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Εάν επιτρέποντε συνδρομές" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Καθορίστε το μοντέλο πρόσβασης" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Ομάδες Καταλόγου Επαφών μπορούν να εγγραφούν" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Καθορίστε το μοντέλο εκδότη" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Διαγραφή όλων των στοιχείων όταν ο σχετικός εκδότης αποσυνδέεται" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Καθορίστε τον τύπο μηνύματος συμβάντος" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Μέγιστο μέγεθος φορτίου σε bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Πότε να αποσταλθεί το τελευταίο στοιχείο που δημοσιεύθηκε" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Παράδωση κοινοποιήσεων μόνο σε διαθέσιμους χρήστες" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Οι συλλογές με την οποία είναι ένας κόμβος συνδέεται" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Χρειάζεστε ένα x:data και CAPTCHA ικανό πελάτη για εγγραφή" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Επιλέξτε ένα όνομα χρήστη και κωδικό πρόσβασης για να εγγραφείτε σε αυτό τον " @@ -1477,7 +1506,7 @@ msgstr "Εγγραφή λογαριασμού Jabber" msgid "Register a Jabber account" msgstr "Καταχωρήστε έναν λογαριασμό Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Καταργήστε την εγγραφή ενός λογαριασμού Jabber" @@ -1492,7 +1521,7 @@ msgstr "" "όνομα_χρήστη@διακομιστής_Jabber. Παρακαλώ διαβάστε προσεκτικά τις οδηγίες " "για να συμπληρώσετε σωστά τα πεδία." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Όνομα χρήστη" @@ -1506,11 +1535,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Χαρακτήρες δεν επιτρέπονται:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Διακομιστής:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1518,13 +1547,13 @@ msgstr "" "Μην πείτε τον κωδικό πρόσβασής σας σε κανέναν, ακόμη και στους διαχειριστές " "του διακομιστή Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" "Μπορείτε αργότερα να αλλάξετε τον κωδικό πρόσβασής σας χρησιμοποιώντας έναν " "πελάτη Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1533,7 +1562,7 @@ msgstr "" "υπολογιστή σας. Χρησιμοποιήστε αυτό το χαρακτηριστικό μόνο εάν εμπιστεύεστε " "την ασφάλεια του υπολογιστή σας." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1543,114 +1572,114 @@ msgstr "" "τοποθετηθεί σε ασφαλές μέρος. Στο Jabber δεν υπάρχει αυτοματοποιημένος " "τρόπος για να ανακτήσετε τον κωδικό σας αν τον ξεχάσετε." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Επαλήθευση κωδικού πρόσβασης:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Καταχωρήστε" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Παλαιός κωδικός πρόσβασης:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Νέος κωδικός πρόσβασης:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Η σελίδα αυτή δίνει τη δυνατότητα να καταργήσετε την καταχώρηση ενός " "λογαριασμό Jabber σε αυτόν το διακομιστή Jabber." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Καταργήση εγγραφής" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Συνδρομή" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Εκκρεμεί" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Ομάδες" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Επαληθεύστε" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Αφαίρεστε" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Καταλόγος Επαφών τού" -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Προσθήκη Jabber Ταυτότητας" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Καταλόγος Επαφών" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Κοινές Ομάδες Καταλόγων Επαφών" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Όνομα:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Περιγραφή:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Μέλη:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Εμφανίσμενες Ομάδες:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Ομάδα" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Διακομιστής" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Γενέθλια" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Πόλη" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Χώρα" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Επώνυμο" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1659,47 +1688,53 @@ msgstr "" "ταιριάζει (Προσθέστε * στο τέλος τού πεδίου για να ταιριάξει σε μεγαλύτερες " "γραμματοσηρές)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Ονοματεπώνυμο" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Πατρώνυμο" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Όνομα Οργανισμού" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Μονάδα Οργανισμού" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Αναζήτηση χρηστών στο" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για αναζήτηση" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Αναζήτηση χρηστών" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard module" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Αποτελέσματα αναζήτησης για " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Συμπληρώστε τα πεδία για να αναζητήσετε οποιαδήποτε ταιριάζοντα Jabber χρήστη" +#~ msgid "Delete" +#~ msgstr "Διαγραφή" + +#~ msgid "This room is not anonymous" +#~ msgstr "Η αίθουσα αυτή δεν είναι ανώνυμη" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "Ο ενεργός κατάλογος απορρήτου, έχει αρνηθεί τη δρομολόγηση αυτής της " diff --git a/priv/msgs/eo.po b/priv/msgs/eo.po index a82461b7f04..ef64084c108 100644 --- a/priv/msgs/eo.po +++ b/priv/msgs/eo.po @@ -11,339 +11,340 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Esperanto\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Uzo de STARTTLS bezonata" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Neniu risurco donita" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Anstataŭigita je nova konekto" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "estas forpelita" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Enmetu montrita teksto" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Viaj mesaĝoj al ~s estas blokata. Por malbloki ilin, iru al ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Se vi ne vidas la CAPTCHA-imagon jene, vizitu la teksaĵ-paĝon." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA teksaĵ-paĝo" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "La CAPTCHA ĝustas" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Nepermesita" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Teksaĵa Administro" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administro" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Atingokontrol-listoj" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Sendita" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Malĝusta formo" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Sendu" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Kruda" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Forigu elektata(j)n" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Atingo-reguloj" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Agordo de atingo-reguloj de ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtual-gastigoj" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Uzantoj" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Konektataj Uzantoj" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Lasta aktiveco de uzanto" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Lasta monato" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Lasta jaro" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Ĉiu aktiveco" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Montru ordinaran tabelon" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Montru integran tabelon" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistikoj" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Ne trovita" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nodo ne trovita" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Aldonu novan" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Gastigo" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Registritaj uzantoj" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Uzanto" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Pasvorto" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Aldonu Uzanton" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Liverontaj mesaĝoj" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Lasta aktiveco" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Neniam" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Konektata" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Registritaj uzantoj:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Konektataj uzantoj:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Elirantaj s-al-s-konektoj:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Elirantaj s-al-s-serviloj" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nenio" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Ŝanĝu pasvorton" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Uzanto " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Konektataj risurcoj:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Pasvorto:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Forigu uzanton" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Neniu datumo" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodoj" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Funkciantaj Nodoj" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Neaktivaj Nodoj" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nodo " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Datumbazo" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Faru Sekurkopion" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Atentataj pordoj" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Ĝisdatigu" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Restartu" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Haltigu" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduloj" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Eraro de RPC-alvoko" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Datumbaz-tabeloj je " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nomo" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Konserv-tipo" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Eroj" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memoro" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Eraro" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Sekurkopio de " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -353,486 +354,482 @@ msgstr "" "Se vi uzas la ODBC-modulon, vi ankaŭ devas sekurkopii tiujn SQL-datumbazoj " "aparte." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Konservu duuman sekurkopion:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Bone" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Restaŭrigu duuman sekurkopion tuj:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "Restaŭrigu duuman sekurkopion post sekvonta ejabberd-restarto" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Skribu sekurkopion en plata tekstdosiero" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Restaŭrigu sekurkopion el plata tekstdosiero tuj" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importu uzanto-datumojn de PIEFXIS dosiero (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Eksportu datumojn de ĉiuj uzantoj en servilo al PIEFXIS dosieroj (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Eksportu datumoj de uzantoj en gastigo al PIEFXIS dosieroj (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Atentataj pordoj je " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduloj je " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistikoj de ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Daŭro de funkciado" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "CPU-tempo" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transakcioj enmetitaj" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transakcioj nuligitaj" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transakcioj restartitaj" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transakcioj protokolitaj" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Ĝisdatigu " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Ĝisdatigo-plano" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Ĝisdatigitaj moduloj" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Ĝisdatigo-skripto" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Bazanivela ĝisdatigo-skripto" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Skript-kontrolo" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Pordo" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokolo" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modulo" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Elektebloj" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Forigu" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Startu" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Ordonoj" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Sondaĵo" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Resondaĵo" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Ĉu vere forigi mesaĝon de la tago?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Temo" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Teksto de mesaĝo" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Neniu teksto donita por anonc-mesaĝo" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Anoncoj" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Sendu anoncon al ĉiu uzanto" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Sendu anoncon al ĉiu uzanto de ĉiu gastigo" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Sendu anoncon al ĉiu konektata uzanto" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Sendu anoncon al ĉiu konektata uzanto de ĉiu gastigo" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Enmetu mesaĝon de la tago kaj sendu al konektataj uzantoj" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Enmetu mesaĝon de la tago je ĉiu gastigo kaj sendu al konektataj uzantoj" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Ŝanĝu mesaĝon de la tago (ne sendu)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Ŝanĝu mesaĝon de la tago je ĉiu gastigo (ne sendu)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Forigu mesaĝo de la tago" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Forigu mesaĝo de la tago je ĉiu gastigo" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Agordo" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Startu Modulojn" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Haltigu Modulojn" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaŭru" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Skribu en plata tekst-dosiero" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importu dosieron" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importu dosierujo" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restartu Servon" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Haltigu Servon" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Forigu Uzanton" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Haltigu Uzant-seancon" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Montru pasvorton de uzanto" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Ŝanĝu pasvorton de uzanto" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Montru tempon de lasta ensaluto" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Montru statistikojn de uzanto" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Montru nombron de registritaj uzantoj" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Montru nombron de konektataj uzantoj" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Uzanto-administrado" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Ĉiuj Uzantoj" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Elirantaj s-al-s-konektoj" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Mastrumado de sekurkopioj" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Al ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Agordo de datumbaz-tabeloj je " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Elektu konserv-tipon de tabeloj" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Nur disk-kopio" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM- kaj disk-kopio" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM-kopio" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Fora kopio" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Haltigu modulojn je " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Elektu modulojn por fini" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Startu modulojn je " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Enmetu liston de {Modulo, [Elektebloj]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Listo de moduloj por starti" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Faru sekurkopion je " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Enmetu vojon por sekurkopio" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Voje de dosiero" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaŭrigu de dosiero el " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Skribu sekurkopion en plata teksto al " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Enmetu vojon al plata teksto" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importu uzanton de dosiero el " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Enmetu vojon al jabberd14-uzantdosiero" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importu uzantojn de dosierujo ĉe " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Enmetu vojon al jabberd14-uzantdosierujo" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Vojo al dosierujo" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Prokrasto" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Agordo de atingokontrolo" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Atingokontrol-listoj" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Agordo de atingo" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Atingo-reguloj" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Pasvortkontrolo" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Nombro de registritaj uzantoj" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Nombro de konektataj uzantoj" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Lasta ensaluto" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Kontaktlist-grando" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP-adresoj" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Risurcoj" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Mastrumado de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Ago je uzanto" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Redaktu atributojn" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -943,485 +940,517 @@ msgstr "Enkodigo por servilo ~b" msgid "Server ~b" msgstr "Servilo ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Babilejoj" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Vi bezonas klienton subtenante x:data-funkcio por registri kaŝnomon" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Kaŝnomo-registrado je " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Enmetu kaŝnomon kiun vi volas registri" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Kaŝnomo" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC-modulo" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Babilejoj" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "eliras la babilejo" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Registritaj uzantoj" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Agordo de babilejo ŝanĝita" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "eniras la babilejo" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "eliras la babilejo" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "estas forbarita" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "estas forpelita pro aparteneca ŝanĝo" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "estas forpelita ĉar la babilejo fariĝis sole por membroj" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "estas forpelita pro sistem-haltigo" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "nun nomiĝas" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " ŝanĝis la temon al: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Babilejo kreita" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Babilejo neniigita" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Babilejo lanĉita" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Babilejo haltita" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Lundo" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Mardo" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Merkredo" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Ĵaŭdo" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Vendredo" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sabato" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Dimanĉo" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Januaro" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Februaro" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Marĉo" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Aprilo" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Majo" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Junio" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Julio" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Aŭgusto" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Septembro" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Oktobro" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Decembro" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Babilejo-agordo" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Nur moderigantoj kaj partoprenantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Nur moderigantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Ĉi tiu babilejo ne estas anonima" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s estas nevalida" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Kaŝnomo ~s ne ekzistas en la babilejo" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Nevalida aparteneco: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Nevalida rolo: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Agordo de babilejo ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Babilejo-nomo" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Babilejo-priskribo" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Farigu babilejon daŭra" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Farigu babilejon publike trovebla" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Farigu partoprento-liston publika" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Farigu babilejon protektata per pasvorto" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Limigo de nombro de partoprenantoj" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Neniu limigo" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Montru verajn Jabber ID-ojn al" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "moderantoj sole" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "iu ajn" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Farigu babilejon sole por membroj" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Farigu babilejon moderigata" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Kutime farigu uzantojn kiel partpoprenantoj" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Permesu uzantojn ŝanĝi la temon" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Permesu uzantojn sendi privatajn mesaĝojn" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Permesu uzantojn sendi privatajn mesaĝojn al" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "neniu" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Permesu uzantojn informpeti aliajn uzantojn" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Permesu uzantojn sendi invitojn" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Permesu al vizitantoj sendi statmesaĝon en ĉeest-sciigoj" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Permesu al vizitantoj ŝanĝi siajn kaŝnomojn" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Permesu uzantojn sendi voĉ-petojn" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimuma intervalo inter voĉ-petoj (je sekundoj)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Farigu babilejon protektata per CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Esceptu Ĵabber-identigilojn je CAPTCHA-defio" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Ŝaltu protokoladon" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Vi bezonas klienton kun x:data-funkcio por agordi la babilejon" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privata, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Voĉ-peto" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Ĉu aprobu, aŭ malaprobu la voĉ-peton." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Uzant-JID" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Koncedu voĉon al ĉi-persono?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s invitas vin al la babilejo ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "la pasvorto estas" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Mesaĝo-atendovico de ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Tempo" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Ĝis" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pakaĵo" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Liverontaj mesaĝoj" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Forigu ĉiujn liverontajn mesaĝojn" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bajtfluo modulo" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Public-Abonado" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Public-Abonada modulo" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubAbo abonpeto" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Elektu ĉu permesi la abonon de ĉi tiu ento" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Nodo ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Abonanta adreso" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Ĉu permesi ĉi tiun Jabber ID aboni al la jena PubAbo-nodo" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Liveru aĵojn de event-sciigoj" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Liveru event-sciigojn" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Sciigu abonantoj kiam la agordo de la nodo ŝanĝas" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Sciigu abonantoj kiam la nodo estas forigita" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Sciigu abonantoj kiam eroj estas forigita de la nodo" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Savu erojn en konservado" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Kromnomo por ĉi tiu nodo" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Maksimuma kiomo de eroj en konservado" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Ĉu permesi aboni" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Specifu atingo-modelon" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Kontaktlist-grupoj kiuj rajtas aboni" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Enmetu publikadan modelon" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Forigu ĉiujn erojn kiam la rilata publikanto malkonektiĝas" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Specifu tipo de event-mesaĝo" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Maksimuma aĵo-grando je bajtoj" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Kiam sendi la laste publicitan eron" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Nur liveru sciigojn al konektataj uzantoj" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Aro kun kiu nodo estas filigita" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Vi bezonas klienton subtenante x:data-funkcio kaj CAPTCHA por registri " "kaŝnomon" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Elektu uzantnomon kaj pasvorton por registri je ĉi tiu servilo" @@ -1457,7 +1486,7 @@ msgstr "Ĵabber-konto registrado" msgid "Register a Jabber account" msgstr "Registru Ĵabber-konton" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Malregistru Ĵabber-konton" @@ -1471,7 +1500,7 @@ msgstr "" "(Ĵabber-IDentigilo) estos ĉi-tiel: uzantnomo@servilo. Bonvolu legu bone la " "instrukciojn por korekta enmetigo de la kampoj. " -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Uzantnomo" @@ -1483,11 +1512,11 @@ msgstr "Uskleco ne signifas: macbeth estas la sama ol MacBeth kaj Macbeth." msgid "Characters not allowed:" msgstr "Karaktroj ne permesata:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Servilo:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1495,11 +1524,11 @@ msgstr "" "Ne donu vian pasvorton al iun ajn, eĉ ne al la administrantoj de la Ĵabber-" "servilo." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Poste vi povas ŝanĝi vian pasvorton per Ĵabber-kliento." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1507,7 +1536,7 @@ msgstr "" "Kelkaj Ĵabber-klientoj povas memori vian pasvorton je via komputilo. Nur uzu " "tiun eblon se vi fidas ke via komputilo estas sekura." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1517,112 +1546,112 @@ msgstr "" "Ĵabber ne ekzistas aŭtomata metodo por reakiri vian pasvorton se vi forgesas " "ĝin." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Pasvortkontrolo:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Registru" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Malnova Pasvorto:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nova Pasvorto:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Jena pagxo ebligas malregistri Jxabber-konton je ĉi-servilo." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Malregistru" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Abono" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Atendanta" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupoj" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validigu" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Forigu" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Kontaktlisto de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Aldonu Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Kontaktlisto" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Komuna Kontaktlist-grupo" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nomo:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Priskribo:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Membroj:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Montrataj grupoj:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grupo " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang-a Jabber-Servilo" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Naskiĝtago" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Urbo" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Lando" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Retpoŝto" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Lasta Nomo" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1630,46 +1659,52 @@ msgstr "" "Kompletigu la formon por serĉi rekonata Jabber-uzanto (Aldonu * je la fino " "de la kampo por rekoni subĉenon" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Plena Nomo" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Meza Nomo" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organiz-nomo" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organiz-parto" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Serĉu uzantojn en " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Vi bezonas klienton kun x:data-funkcio por serĉado" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Serĉado de vizitkartoj" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard-modulo" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Serĉ-rezultoj de " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Kompletigu la formon por serĉi rekonata Jabber-uzanto" +#~ msgid "Delete" +#~ msgstr "Forigu" + +#~ msgid "This room is not anonymous" +#~ msgstr "Ĉi tiu babilejo ne estas anonima" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Via aktiva privatec-listo malpermesas enkursigi ĉi-tiun pakaĵon" diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 4a362847e24..05da1d8314d 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -14,24 +14,24 @@ msgstr "" "X-Language: Spanish (castellano)\n" "X-Generator: Poedit 1.6.10\n" -#: ejabberd_c2s.erl:522 ejabberd_c2s.erl:869 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Es obligatorio usar STARTTLS" -#: ejabberd_c2s.erl:620 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "No se ha proporcionado recurso" -#: ejabberd_c2s.erl:1395 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Reemplazado por una nueva conexión" -#: ejabberd_c2s.erl:1399 mod_configure.erl:1854 mod_muc_log.erl:476 -#: mod_muc_log.erl:479 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "ha sido expulsado" -#: ejabberd_c2s.erl:2484 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "Demasiados mensajes sin haber reconocido recibirlos" @@ -65,286 +65,286 @@ msgstr "No autorizado" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:600 ejabberd_web_admin.erl:611 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administración" -#: ejabberd_web_admin.erl:668 ejabberd_web_admin.erl:704 mod_configure.erl:196 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Control de Acceso" -#: ejabberd_web_admin.erl:672 ejabberd_web_admin.erl:708 -#: ejabberd_web_admin.erl:774 ejabberd_web_admin.erl:807 -#: ejabberd_web_admin.erl:848 ejabberd_web_admin.erl:1324 -#: ejabberd_web_admin.erl:1609 ejabberd_web_admin.erl:1769 -#: ejabberd_web_admin.erl:1803 ejabberd_web_admin.erl:1883 -#: ejabberd_web_admin.erl:2053 ejabberd_web_admin.erl:2082 -#: ejabberd_web_admin.erl:2179 mod_offline.erl:795 mod_roster.erl:1494 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 #: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Enviado" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 -#: ejabberd_web_admin.erl:849 ejabberd_web_admin.erl:1325 -#: ejabberd_web_admin.erl:1610 ejabberd_web_admin.erl:1770 -#: ejabberd_web_admin.erl:2054 ejabberd_web_admin.erl:2083 mod_roster.erl:1495 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 #: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Mal formato" -#: ejabberd_web_admin.erl:684 ejabberd_web_admin.erl:721 -#: ejabberd_web_admin.erl:786 ejabberd_web_admin.erl:856 -#: ejabberd_web_admin.erl:1872 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:713 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Crudo" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:818 mod_offline.erl:817 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 #: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Eliminar los seleccionados" -#: ejabberd_web_admin.erl:770 ejabberd_web_admin.erl:803 mod_configure.erl:198 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Reglas de Acceso" -#: ejabberd_web_admin.erl:844 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configuración de las Regla de Acceso ~s" -#: ejabberd_web_admin.erl:862 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Dominios Virtuales" -#: ejabberd_web_admin.erl:871 ejabberd_web_admin.erl:879 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Usuarios" -#: ejabberd_web_admin.erl:886 ejabberd_web_admin.erl:1270 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" -#: ejabberd_web_admin.erl:902 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Última actividad de los usuarios" -#: ejabberd_web_admin.erl:906 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Último mes" -#: ejabberd_web_admin.erl:920 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Último año" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Toda la actividad" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Mostrar Tabla Ordinaria" -#: ejabberd_web_admin.erl:928 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Mostrar Tabla Integral" -#: ejabberd_web_admin.erl:935 ejabberd_web_admin.erl:1780 -#: mod_muc_admin.erl:245 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Estadísticas" -#: ejabberd_web_admin.erl:945 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "No encontrado" -#: ejabberd_web_admin.erl:958 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nodo no encontrado" -#: ejabberd_web_admin.erl:1180 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Añadir nuevo" -#: ejabberd_web_admin.erl:1268 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Dominio" -#: ejabberd_web_admin.erl:1269 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Usuarios registrados" -#: ejabberd_web_admin.erl:1333 ejabberd_web_admin.erl:1388 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 #: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Usuario" -#: ejabberd_web_admin.erl:1338 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3353 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 #: mod_register.erl:272 msgid "Password" msgstr "Contraseña" -#: ejabberd_web_admin.erl:1347 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Añadir usuario" -#: ejabberd_web_admin.erl:1389 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Mensajes diferidos" -#: ejabberd_web_admin.erl:1390 ejabberd_web_admin.erl:1620 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Última actividad" -#: ejabberd_web_admin.erl:1408 ejabberd_web_admin.erl:1592 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 #: mod_configure.erl:1917 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1426 ejabberd_web_admin.erl:1603 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 #: mod_configure.erl:1927 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1482 ejabberd_web_admin.erl:1501 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Usuarios registrados:" -#: ejabberd_web_admin.erl:1485 ejabberd_web_admin.erl:1504 -#: ejabberd_web_admin.erl:2120 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Usuarios conectados:" -#: ejabberd_web_admin.erl:1488 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Conexiones S2S salientes:" -#: ejabberd_web_admin.erl:1491 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Servidores S2S salientes:" -#: ejabberd_web_admin.erl:1527 ejabberd_web_admin.erl:1727 -#: ejabberd_web_admin.erl:1737 ejabberd_web_admin.erl:2147 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Ninguno" -#: ejabberd_web_admin.erl:1584 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Cambiar contraseña" -#: ejabberd_web_admin.erl:1605 +#: ejabberd_web_admin.erl:1610 msgid "User ~s" msgstr "Usuario ~s" -#: ejabberd_web_admin.erl:1616 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1618 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contraseña:" -#: ejabberd_web_admin.erl:1625 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Eliminar usuario" -#: ejabberd_web_admin.erl:1673 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Sin datos" -#: ejabberd_web_admin.erl:1746 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1747 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" -#: ejabberd_web_admin.erl:1748 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detenidos" -#: ejabberd_web_admin.erl:1766 ejabberd_web_admin.erl:1791 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 msgid "Node ~p" msgstr "Nodo ~p" -#: ejabberd_web_admin.erl:1775 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" -#: ejabberd_web_admin.erl:1776 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar copia de seguridad" -#: ejabberd_web_admin.erl:1778 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Puertos de escucha" -#: ejabberd_web_admin.erl:1781 ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1785 ejabberd_web_admin.erl:2402 -#: ejabberd_web_admin.erl:2546 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1787 ejabberd_web_admin.erl:2406 -#: ejabberd_web_admin.erl:2550 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Detener" -#: ejabberd_web_admin.erl:1794 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1799 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Error en la llamada RPC" -#: ejabberd_web_admin.erl:1850 +#: ejabberd_web_admin.erl:1855 msgid "Database Tables at ~p" msgstr "Tablas de la base de datos en ~p" -#: ejabberd_web_admin.erl:1860 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nombre" -#: ejabberd_web_admin.erl:1861 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Tipo de almacenamiento" -#: ejabberd_web_admin.erl:1862 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1863 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1885 ejabberd_web_admin.erl:2056 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Error" -#: ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:1893 msgid "Backup of ~p" msgstr "Copia de seguridad de ~p" -#: ejabberd_web_admin.erl:1892 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -354,146 +354,146 @@ msgstr "" "datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia " "de seguridad de tu base de datos SQL." -#: ejabberd_web_admin.erl:1902 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Guardar copia de seguridad binaria:" -#: ejabberd_web_admin.erl:1909 ejabberd_web_admin.erl:1919 -#: ejabberd_web_admin.erl:1930 ejabberd_web_admin.erl:1939 -#: ejabberd_web_admin.erl:1949 ejabberd_web_admin.erl:1962 -#: ejabberd_web_admin.erl:1974 ejabberd_web_admin.erl:1990 -#: ejabberd_web_admin.erl:2006 ejabberd_web_admin.erl:2017 -#: ejabberd_web_admin.erl:2027 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Aceptar" -#: ejabberd_web_admin.erl:1912 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridad binaria:" -#: ejabberd_web_admin.erl:1922 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar copia de seguridad binaria en el siguiente reinicio de ejabberd " "(requiere menos memoria que si instantánea):" -#: ejabberd_web_admin.erl:1932 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Guardar copia de seguridad en texto plano:" -#: ejabberd_web_admin.erl:1942 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Restaurar copias de seguridad de texto plano inmediatamente:" -#: ejabberd_web_admin.erl:1952 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuarios desde un fichero PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1965 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos los usuarios del servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1977 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de los usuarios de un dominio a ficheros PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1993 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "Exportar todas las tablas a un fichero SQL:" -#: ejabberd_web_admin.erl:2009 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importar usuario de fichero spool de jabberd14:" -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar usuarios del directorio spool de jabberd14:" -#: ejabberd_web_admin.erl:2048 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Puertos de escucha en " -#: ejabberd_web_admin.erl:2077 +#: ejabberd_web_admin.erl:2082 msgid "Modules at ~p" msgstr "Módulos en ~p" -#: ejabberd_web_admin.erl:2108 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Estadísticas de ~p" -#: ejabberd_web_admin.erl:2112 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Tiempo desde el inicio:" -#: ejabberd_web_admin.erl:2116 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Tiempo consumido de CPU:" -#: ejabberd_web_admin.erl:2124 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transacciones finalizadas:" -#: ejabberd_web_admin.erl:2128 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transacciones abortadas:" -#: ejabberd_web_admin.erl:2132 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transacciones reiniciadas:" -#: ejabberd_web_admin.erl:2136 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transacciones registradas:" -#: ejabberd_web_admin.erl:2176 +#: ejabberd_web_admin.erl:2181 msgid "Update ~p" msgstr "Actualizar ~p" -#: ejabberd_web_admin.erl:2187 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plan de actualización" -#: ejabberd_web_admin.erl:2188 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Módulos modificados" -#: ejabberd_web_admin.erl:2189 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script de actualización" -#: ejabberd_web_admin.erl:2190 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Script de actualización a bajo nivel" -#: ejabberd_web_admin.erl:2191 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Comprobación de script" -#: ejabberd_web_admin.erl:2371 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2371 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Puerto" -#: ejabberd_web_admin.erl:2372 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocolo" -#: ejabberd_web_admin.erl:2373 ejabberd_web_admin.erl:2528 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2374 ejabberd_web_admin.erl:2529 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opciones" -#: ejabberd_web_admin.erl:2426 ejabberd_web_admin.erl:2562 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Iniciar" @@ -946,399 +946,403 @@ msgstr "Codificación del servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:776 mod_muc_admin.erl:319 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:969 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder registrar el apodo" -#: mod_muc.erl:979 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registro del apodo en " -#: mod_muc.erl:985 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Introduce el apodo que quieras registrar" -#: mod_muc.erl:986 mod_muc_room.erl:4228 mod_roster.erl:1436 mod_vcard.erl:490 -#: mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Apodo" -#: mod_muc.erl:1149 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_admin.erl:229 mod_muc_admin.erl:232 mod_muc_admin.erl:244 -#: mod_muc_admin.erl:318 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 msgid "Multi-User Chat" msgstr "Salas de Charla" -#: mod_muc_admin.erl:247 +#: mod_muc_admin.erl:248 msgid "Total rooms" msgstr "Salas totales" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Permanent rooms" msgstr "Salas permanentes" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Registered nicknames" msgstr "Apodos registrados" -#: mod_muc_admin.erl:252 +#: mod_muc_admin.erl:253 msgid "List of rooms" msgstr "Lista de salas" -#: mod_muc_log.erl:447 mod_muc_log.erl:456 +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Configuración de la sala modificada" -#: mod_muc_log.erl:459 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "entra en la sala" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "sale de la sala" -#: mod_muc_log.erl:469 mod_muc_log.erl:472 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "ha sido bloqueado" -#: mod_muc_log.erl:484 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "ha sido expulsado por un cambio de su afiliación" -#: mod_muc_log.erl:489 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "ha sido expulsado porque la sala es ahora solo para miembros" -#: mod_muc_log.erl:494 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "ha sido expulsado porque el sistema se va a detener" -#: mod_muc_log.erl:499 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "se cambia el nombre a" -#: mod_muc_log.erl:502 mod_muc_log.erl:841 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " ha puesto el asunto: " -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Se ha creado la sala" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Se ha destruido la sala" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Se ha iniciado la sala" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Se ha detenido la sala" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "lunes" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "martes" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "miércoles" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "jueves" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "viernes" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "sábado" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "domingo" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:560 msgid "January" msgstr "enero" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:561 msgid "February" msgstr "febrero" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:562 msgid "March" msgstr "marzo" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:563 msgid "April" msgstr "abril" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:564 msgid "May" msgstr "mayo" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:565 msgid "June" msgstr "junio" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:566 msgid "July" msgstr "julio" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:567 msgid "August" msgstr "agosto" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:568 msgid "September" msgstr "septiembre" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:569 msgid "October" msgstr "octubre" -#: mod_muc_log.erl:572 +#: mod_muc_log.erl:570 msgid "November" msgstr "noviembre" -#: mod_muc_log.erl:573 +#: mod_muc_log.erl:571 msgid "December" msgstr "diciembre" -#: mod_muc_log.erl:961 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Configuración de la sala" -#: mod_muc_log.erl:981 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Ocupantes de la sala" -#: mod_muc_room.erl:982 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Solo los moderadores y participantes pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:987 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:2728 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no es válido" -#: mod_muc_room.erl:2742 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "El apodo ~s no existe en la sala" -#: mod_muc_room.erl:2765 mod_muc_room.erl:3145 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiliación no válida: ~s" -#: mod_muc_room.erl:2816 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Rol no válido: ~s" -#: mod_muc_room.erl:3318 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Configuración para la sala ~s" -#: mod_muc_room.erl:3329 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Título de la sala" -#: mod_muc_room.erl:3331 mod_muc_room.erl:4065 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Descripción de la sala" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3345 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Sala públicamente visible" -#: mod_muc_room.erl:3348 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "La lista de participantes es pública" -#: mod_muc_room.erl:3350 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Proteger la sala con contraseña" -#: mod_muc_room.erl:3364 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3376 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Sin límite" -#: mod_muc_room.erl:3406 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Los Jabber ID reales pueden verlos" -#: mod_muc_room.erl:3420 mod_muc_room.erl:3483 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "solo moderadores" -#: mod_muc_room.erl:3430 mod_muc_room.erl:3493 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "cualquiera" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Sala sólo para miembros" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Sala moderada" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Los usuarios son participantes por defecto" -#: mod_muc_room.erl:3445 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Permitir a los usuarios cambiar el asunto" -#: mod_muc_room.erl:3448 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Permitir a los usuarios enviar mensajes privados" -#: mod_muc_room.erl:3456 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Permitir a los visitantes enviar mensajes privados a" -#: mod_muc_room.erl:3474 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "nadie" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Permitir a los usuarios consultar a otros usuarios" -#: mod_muc_room.erl:3502 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Permitir a los usuarios enviar invitaciones" -#: mod_muc_room.erl:3505 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir a los visitantes enviar texto de estado en las actualizaciones de " "presencia" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Permitir a los visitantes cambiarse el apodo" -#: mod_muc_room.erl:3512 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Permitir a los visitantes enviar peticiones de voz" -#: mod_muc_room.erl:3515 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalo mínimo entre peticiones de voz (en segundos)" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Proteger la sala con CAPTCHA" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir Jabber IDs de las pruebas de CAPTCHA" -#: mod_muc_room.erl:3537 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Guardar históricos" -#: mod_muc_room.erl:3547 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar la sala" -#: mod_muc_room.erl:4067 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4137 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4201 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Petición de voz" -#: mod_muc_room.erl:4206 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Aprueba o rechaza la petición de voz." -#: mod_muc_room.erl:4226 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Jabber ID del usuario" -#: mod_muc_room.erl:4230 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "¿Conceder voz a esta persona?" -#: mod_muc_room.erl:4373 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s te invita a la sala ~s" -#: mod_muc_room.erl:4385 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "la contraseña es" -#: mod_multicast.erl:259 +#: mod_multicast.erl:273 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:274 +#: mod_multicast.erl:288 msgid "ejabberd Multicast service" msgstr "Servicio Multicast de ejabberd" -#: mod_offline.erl:791 +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Cola de mensajes diferidos de ~s" -#: mod_offline.erl:804 +#: mod_offline.erl:796 msgid "Time" msgstr "Fecha" -#: mod_offline.erl:805 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:806 +#: mod_offline.erl:798 msgid "To" msgstr "Para" -#: mod_offline.erl:807 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paquete" -#: mod_offline.erl:985 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Mensajes diferidos:" -#: mod_offline.erl:989 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Borrar todos los mensajes diferidos" diff --git a/priv/msgs/fr.po b/priv/msgs/fr.po index ae9736b87d6..d7ba74f8a64 100644 --- a/priv/msgs/fr.po +++ b/priv/msgs/fr.po @@ -14,340 +14,341 @@ msgstr "" "X-Additional-Translator: Mickaël Rémond\n" "X-Additional-Translator: Vincent Ricard\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "L'utilisation de STARTTLS est impérative" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Aucune ressource fournie" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Remplacé par une nouvelle connexion" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "a été expulsé" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Tapez le texte que vous voyez" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Vos messages pour ~s sont bloqués. Pour les débloquer, veuillez visiter ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "SI vous ne voyez pas l'image CAPTCHA ici, visitez la page web." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Page web de CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Le CAPTCHA est valide" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Non autorisé" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Console Web d'administration de ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administration" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Droits (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Soumis" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Mauvais format" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Soumettre" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Brut" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Suppression des éléments sélectionnés" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Règles d'accès" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configuration des règles d'accès ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Serveurs virtuels" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Utilisateurs" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Utilisateurs en ligne" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Dernière activité des utilisateurs" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Période :" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Dernier mois" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Dernière année" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Toute activité" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Montrer la table ordinaire" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Montrer la table intégralement" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistiques" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Nœud non trouvé" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Noeud non trouvé" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Ajouter" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Serveur" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Utilisateurs enregistrés" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Utilisateur" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Mot de passe" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Ajouter un utilisateur" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Messages en attente" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Dernière Activité" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Jamais" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "En ligne" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Utilisateurs enregistrés:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Utilisateurs connectés:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Connexions s2s sortantes:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Serveurs s2s sortants" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Aucun" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Modifier le mot de passe" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Utilisateur " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Ressources connectées:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Mot de passe:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Supprimer l'utilisateur" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Aucune information disponible" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Noeuds" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Noeuds actifs" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Noeuds arrêtés" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Noeud " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de données" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sauvegarde" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Ports ouverts" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Mettre à jour" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Redémarrer" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Arrêter" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Erreur d'appel RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tables de base de données sur " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nom" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Type de stockage" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Éléments" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Mémoire" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Erreur" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Sauvegarde de " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -356,495 +357,491 @@ msgstr "" "Ces options sauvegardent uniquement la base de données interne Mnesia. Si " "vous utilisez le module ODBC vous devez sauvegarde votre base SQL séparément." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Sauvegarde binaire:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Restauration immédiate d'une sauvegarde binaire:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restauration de la sauvegarde binaire après redémarrage (nécessite moins de " "mémoire):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Sauvegarde texte:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Restauration immédiate d'une sauvegarde texte:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" "Importer les données utilisateurs à partir d'un fichier PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exporter les données de tous les utilisateurs du serveur vers un fichier " "PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exporter les données utilisateurs d'un hôte vers un fichier PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importer des utilisateurs depuis un fichier spool Jabberd 1.4:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importer des utilisateurs depuis un fichier spool Jabberd 1.4:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Ports ouverts sur " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Modules sur " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistiques de ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Temps depuis le démarrage :" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Temps CPU :" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transactions commitées :" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transactions annulées :" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transactions redémarrées :" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transactions journalisées :" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Mise à jour " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plan de mise à jour" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Modules mis à jour" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script de mise à jour" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Script de mise à jour de bas-niveau" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Validation du script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocole" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Options" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Supprimer" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Démarrer" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Commandes" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Confirmer la suppression du message du jour ?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Sujet" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corps du message" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Pas de corps de message pour l'annonce" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Annonces" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Envoyer l'annonce à tous les utilisateurs" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Envoyer une annonce à tous les utilisateurs de tous les domaines" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Envoyer l'annonce à tous les utilisateurs en ligne" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Envoyer l'annonce à tous les utilisateurs en ligne sur tous les serveurs" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Définir le message du jour et l'envoyer aux utilisateurs en ligne" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Définir le message du jour pour tous domaines et l'envoyer aux utilisateurs " "en ligne" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Mise à jour du message du jour (pas d'envoi)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" "Mettre à jour le message du jour sur tous les domaines (ne pas envoyer)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Supprimer le message du jour" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Supprimer le message du jour sur tous les domaines" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configuration" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Modules de démarrage" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Modules d'arrêt" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restauration" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Sauvegarder dans un fichier texte" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importer un fichier" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importer une répertoire" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Redémarrer le service" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Arrêter le service" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Supprimer l'utilisateur" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Terminer la session de l'utilisateur" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Récupérer le mot de passe de l'utilisateur" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Changer le mot de passe de l'utilisateur" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Récupérer la dernière date de connexion de l'utilisateur" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Récupérer les statistiques de l'utilisateur" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Récupérer le nombre d'utilisateurs enregistrés" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Récupérer le nombre d'utilisateurs en ligne" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gestion des utilisateurs" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Tous les utilisateurs" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Connexions s2s sortantes" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestion des sauvegardes" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importer des utilisateurs depuis un fichier spool Jabberd 1.4" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuration des tables de base de données sur " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Choisissez un type de stockage pour les tables" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copie sur disque uniquement" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copie en mémoire vive (RAM) et sur disque" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copie en mémoire vive (RAM)" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copie distante" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Arrêter les modules sur " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Sélectionnez les modules à arrêter" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Démarrer les modules sur " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Entrez une liste de {Module, [Options]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Liste des modules à démarrer" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Sauvegarde sur fichier sur " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Entrez le chemin vers le fichier de sauvegarde" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Chemin vers le fichier" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaurer la sauvegarde depuis le fichier sur " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Enregistrer la sauvegarde dans un fichier texte sur " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Entrez le chemin vers le fichier texte" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importer un utilisateur depuis le fichier sur " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Entrez le chemin vers le fichier spool jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importer des utilisateurs depuis le répertoire sur " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Entrez le chemin vers le répertoire de spool jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Chemin vers le répertoire" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Délais" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuration des droits (ACL)" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Droits (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuration d'accès" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Règles d'accès" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Vérification du mot de passe" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Nombre d'utilisateurs enregistrés" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Nombre d'utilisateurs en ligne" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Dernière connexion" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Taille de la liste de contacts" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Adresses IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Ressources" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administration de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Action sur l'utilisateur" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Modifier les propriétés" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -955,170 +952,194 @@ msgstr "Codage pour le serveur ~b" msgid "Server ~b" msgstr "Serveur ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Salons de discussion" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Vous avez besoin d'un client prenant en charge x:data pour enregistrer un " "pseudo" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Enregistrement d'un pseudo sur " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Entrez le pseudo que vous souhaitez enregistrer" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Pseudo" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Module MUC ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Salons de discussion" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "quitte le salon" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Utilisateurs enregistrés" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Configuration du salon modifiée" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "rejoint le salon" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "quitte le salon" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "a été banni" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "a été éjecté à cause d'un changement d'autorisation" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "a été éjecté car la salle est désormais réservée aux membres" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "a été éjecté en raison de l'arrêt du système" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "est maintenant connu comme" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " a changé le sujet pour: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Le salon de discussion est créé" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Le salon de discussion est détruit" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Le salon de discussion a démarré" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Le salon de discussion est stoppé" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Lundi" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Mardi" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Mercredi" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Jeudi" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Vendredi" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Samedi" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Dimanche" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Janvier" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Février" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Mars" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Avril" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Mai" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Juin" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Juillet" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Août" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Septembre" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Octobre" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Novembre" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Décembre" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Configuration du salon" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Occupants du salon" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1126,322 +1147,330 @@ msgstr "" "Seuls les modérateurs et les participants peuvent changer le sujet dans ce " "salon" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Seuls les modérateurs peuvent changer le sujet dans ce salon" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Ce salon n'est pas anonyme" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Le Jabber ID ~s n'est pas valide" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Le pseudo ~s n'existe pas dans ce salon" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Affiliation invalide : ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Role invalide : ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Configuration pour le salon ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Titre du salon" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Description :" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Rendre le salon persistant" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Rendre le salon public" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Rendre la liste des participants publique" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Protéger le salon par mot de passe" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Nombre maximum d'occupants" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Pas de limite" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Rendre le Jabber ID réel visible pour" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "modérateurs seulement" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "tout le monde" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Réserver le salon aux membres uniquement" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Rendre le salon modéré" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Les utilisateurs sont par défaut participant" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Autoriser les utilisateurs à changer le sujet" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Autoriser les utilisateurs à envoyer des messages privés" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Autoriser les utilisateurs à envoyer des messages privés" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "" "Permettre aux utilisateurs d'envoyer des requêtes aux autres utilisateurs" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Permettre aux utilisateurs d'envoyer des invitations" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Autoriser les visiteurs à envoyer un message d'état avec leur présence" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Autoriser les visiteurs à changer de pseudo" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permettre aux utilisateurs d'envoyer des invitations" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Protéger le salon par un CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Activer l'archivage" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "Vous avez besoin d'un client supportant x:data pour configurer le salon" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Nombre d'occupants" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privé" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Utilisateur " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s vous a invité dans la salle de discussion ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "le mot de passe est" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s messages en file d'attente" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Heure" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "A" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paquet" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Messages en attente :" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Effacer tous les messages hors ligne" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publication-Abonnement" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Module Publish-Subscribe d'ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Demande d'abonnement PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Accepter cet abonnement ?" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Identifiant du nœud" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Adresse de l'abonné" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Autoriser ce Jabber ID à s'abonner à ce nœud PubSub" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Inclure le contenu du message avec la notification" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Envoyer les notifications d'événement" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Avertir les abonnés lorsque la configuration du nœud change" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Avertir les abonnés lorsque le nœud est supprimé" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Avertir les abonnés lorsque des éléments sont supprimés sur le nœud" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Stockage persistant des éléments" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Un nom convivial pour le noeud" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Nombre maximum d'éléments à stocker" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Autoriser l'abonnement ?" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Définir le modèle d'accès" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Groupes de liste de contact autorisés à s'abonner" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Définir le modèle de publication" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Purger tous les items lorsque publieur est hors-ligne" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Définir le type de message d'événement" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Taille maximum pour le contenu du message en octet" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "A quel moment envoyer le dernier élément publié" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Envoyer les notifications uniquement aux utilisateurs disponibles" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Les collections avec lesquelle un nœud est affilié" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Vous avez besoin d'un client prenant en charge x:data et CAPTCHA pour " "enregistrer un pseudo" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Choisissez un nom d'utilisateur et un mot de passe pour s'enregistrer sur ce " @@ -1479,7 +1508,7 @@ msgstr "Enregistrement du Compte Jabber" msgid "Register a Jabber account" msgstr "Enregistrer un compte Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Effacer un compte Jabber" @@ -1494,7 +1523,7 @@ msgstr "" "Prière de lire avec attention les instructions pour remplir correctement ces " "champs." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nom d'utilisateur :" @@ -1507,11 +1536,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Caractères non-autorisés :" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Serveur :" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1519,13 +1548,13 @@ msgstr "" "Ne révélez votre mot de passe à personne, pas même l'administrateur de ce " "serveur." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" "Vous pouvez changer votre mot de passe plus tard en utilisant un client " "Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1534,7 +1563,7 @@ msgstr "" "ordinateur. N'utilisez cette fonctionnalité que si vous avez confiance en la " "sécurité de votre ordinateur." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1544,112 +1573,112 @@ msgstr "" "endroit secret. Dans Jabber il n'y a pas de mécanisme pour retrouver votre " "mot de passe si vous l'avez oublié." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Vérification du mot de passe :" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Enregistrer" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Ancien mot de passe:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nouveau mot de passe:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Cette page permet d'effacer un compte Jabber sur ce serveur Jabber." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Effacer" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Abonnement" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "En suspens" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Groupes" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Valider" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Enlever" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Liste de contact de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Ajouter un Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Liste de contacts" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Groupes de liste de contacts partagée" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nom :" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Description :" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Membres :" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Groupes affichés :" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Groupe " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Serveur Jabber Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Date d'anniversaire" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Ville" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Pays" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nom de famille" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1657,47 +1686,53 @@ msgstr "" "Remplissez le formulaire pour recherche un utilisateur Jabber (Ajouter * à " "la fin du champ pour chercher n'importe quelle fin de chaîne" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nom complet" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Autre nom" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nom de l'organisation" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unité de l'organisation" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Rechercher des utilisateurs " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "" "Vous avez besoin d'un client supportant x:data pour faire une recherche" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Recherche dans l'annnuaire" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Module vCard ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Résultats de recherche pour " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Remplissez les champs pour rechercher un utilisateur Jabber" +#~ msgid "Delete" +#~ msgstr "Supprimer" + +#~ msgid "This room is not anonymous" +#~ msgstr "Ce salon n'est pas anonyme" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Votre règle de flitrage active a empêché le routage de ce stanza." diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index aaff6b35828..df4e333bacd 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -7,340 +7,341 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Galician (galego)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "É obrigatorio usar STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Non se proporcionou recurso" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Substituído por unha nova conexión" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "foi expulsado" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Introduza o texto que ves" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "As súas mensaxes a ~s encóntranse bloqueadas. Para desbloquear, visite ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é válido." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Non autorizado" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Ejabberd Administrador Web" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administración" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Control de Acceso" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Enviado" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Mal formato" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Cru" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Eliminar os seleccionados" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Regras de Acceso" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configuración das Regra de Acceso ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Hosts Virtuais" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Usuarios" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Última actividade dos usuarios" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Último mes" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Último ano" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Toda a actividade" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Mostrar Táboa Ordinaria" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Mostrar Táboa Integral" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Non atopado" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nodo non atopado" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Engadir novo" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Usuarios rexistrados" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Usuario" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Contrasinal" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Engadir usuario" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Mensaxes diferidas" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Usuarios rexistrados:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Usuarios conectados:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Conexións S2S saíntes:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Servidores S2S saíntes:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Ningún" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Cambiar contrasinal" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Usuario " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Contrasinal:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Eliminar usuario" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Sen datos" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detidos" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nodo " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Gardar copia de seguridade" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Portos de escoita" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Deter" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Erro na chamada RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Táboas da base de datos en " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Tipo de almacenamiento" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Erro" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Copia de seguridade de " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -350,491 +351,487 @@ msgstr "" "Mnesia. Se está a utilizar o módulo de ODBC, tamén necesita unha copia de " "seguridade da súa base de datos SQL por separado." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Gardar copia de seguridade binaria:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Aceptar" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridade binaria:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar copia de seguridade binaria no seguinte reinicio de ejabberd " "(require menos memoria que se instantánea):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Gardar copia de seguridade en texto plano:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Restaurar copias de seguridade de texto plano inmediatamente:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuarios desde un fichero PIEFXIS" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importar usuario de fichero spool de jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar usuarios do directorio spool de jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Portos de escoita en " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Módulos en " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Estatísticas de ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Tempo desde o inicio:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Tempo consumido de CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transaccións finalizadas:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transaccións abortadas:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transaccións reiniciadas:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transaccións rexistradas:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plan de actualización" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Módulos Modificados" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script de actualización" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Script de actualización a baixo nivel" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Comprobación de script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Porto" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocolo" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opcións" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Eliminar" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Iniciar" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandos" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Está seguro de quere borrar a mensaxe do dia?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Asunto" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corpo da mensaxe" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Non se proporcionou corpo de mensaxe para o anuncio" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Anuncios" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anuncio a todos os usuarios" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Enviar anuncio a todos os usuarios en todos os dominios" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Enviar anuncio a todos los usuarios conectados" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Enviar anuncio a todos os usuarios conectados en todos os dominios" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Pór mensaxe do dia e enviar a todos os usuarios conectados" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Pór mensaxe do día en todos os dominios e enviar aos usuarios conectados" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Actualizar mensaxe do dia, pero non envialo" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Actualizar a mensaxe do día en todos os dominos (pero non envialo)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Borrar mensaxe do dia" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Borrar a mensaxe do día en todos os dominios" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configuración" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Detener módulos" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar a ficheiro de texto" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar ficheiro" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directorio" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar o servizo" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Deter o servizo" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Borrar usuario" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Pechar sesión de usuario" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Ver contrasinal de usuario" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Cambiar contrasinal de usuario" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Ver data da última conexión de usuario" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Ver estatísticas de usuario" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Ver número de usuarios rexistrados" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Ver número de usuarios conectados" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Administración de usuarios" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Todos os usuarios" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Conexións S2S saíntes" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Xestión de copia de seguridade" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuarios de ficheiros spool de jabberd-1.4" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuración de táboas da base de datos en " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecciona tipo de almacenamento das táboas" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copia en disco soamente" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copia en RAM e disco" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia en RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Deter módulos en " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecciona módulos a deter" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar módulos en " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduce lista de {Módulo, [Opcións]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista de módulos a iniciar" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Copia de seguridade de arquivos en " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Introduce ruta ao ficheiro de copia de seguridade" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Ruta ao ficheiro" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura copia de seguridade desde o ficheiro en " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exporta copia de seguridade a ficheiro de texto en " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduce ruta ao ficheiro de texto" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importa usuario desde ficheiro en " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introduce ruta ao ficheiro jabberd14 spool" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuarios desde o directorio en " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introduce a ruta ao directorio de jabberd14 spools" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ruta ao directorio" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Atraso temporal" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuración da Lista de Control de Acceso" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Control de Acceso" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuración de accesos" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Regras de acceso" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificación da contrasinal" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número de usuarios rexistrados" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número de usuarios conectados" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Última conexión" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Tamaño da lista de contactos" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Direccións IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administración de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Acción no usuario" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Editar propiedades" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -946,174 +943,198 @@ msgstr "Codificación de servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Rexistro do alcume en " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Introduce o alcume que queiras rexistrar" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Alcume" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Salas de charla" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "sae da sala" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Usuarios rexistrados" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Configuración de la sala modificada" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "entra en la sala" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "sae da sala" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "foi bloqueado" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "foi expulsado debido a un cambio de afiliación" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "foi expulsado, porque a sala cambiouse a só-membros" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "foi expulsado por mor dun sistema de peche" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "cámbiase o nome a" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " puxo o asunto: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 #, fuzzy msgid "Chatroom is created" msgstr "Salas de charla" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 #, fuzzy msgid "Chatroom is destroyed" msgstr "Salas de charla" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 #, fuzzy msgid "Chatroom is started" msgstr "Salas de charla" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 #, fuzzy msgid "Chatroom is stopped" msgstr "Salas de charla" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Luns" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Martes" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Mércores" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Xoves" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Venres" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sábado" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Domingo" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Xaneiro" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Febreiro" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Marzo" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Maio" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Xuño" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Xullo" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Setembro" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Outubro" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Decembro" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Configuración da Sala" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Ocupantes da sala" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1121,322 +1142,330 @@ msgstr "" "Só os moderadores e os participantes se lles permite cambiar o tema nesta " "sala" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Só os moderadores están autorizados a cambiar o tema nesta sala" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Sala non anónima" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s non é válido" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "O alcume ~s non existe na sala" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiliación non válida: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Rol non válido: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Configuración para a sala ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Descrición da sala" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Sala publicamente visible" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "A lista de participantes é pública" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Protexer a sala con contrasinal" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Sen límite" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Os Jabber ID reais poden velos" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "só moderadores" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "calquera" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Sala só para membros" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Facer sala moderada" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Os usuarios son participantes por defecto" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Permitir aos usuarios cambiar o asunto" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Permitir aos usuarios enviar mensaxes privadas" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir aos usuarios enviar mensaxes privadas" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Permitir aos usuarios consultar a outros usuarios" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Permitir aos usuarios enviar invitacións" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir aos visitantes enviar texto de estado nas actualizacións depresenza" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Permitir aos visitantes cambiarse o alcume" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir aos usuarios enviar invitacións" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Protexer a sala con CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Gardar históricos" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar a sala" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Usuario " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s invítache á sala ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "a contrasinal é" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Cola de mensaxes diferidas de ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Data" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Para" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paquete" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Mensaxes sen conexión:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Borrar Todas as Mensaxes Sen conexión" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publicar-Subscribir" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo de Publicar-Subscribir de ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Petición de subscriptor de PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Decidir se aprobar a subscripción desta entidade." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Nodo IDE" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Dirección do subscriptor" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Desexas permitir a este JabberID que se subscriba a este nodo PubSub?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads xunto coas notificacións de eventos" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Entregar notificacións de eventos" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptores cando cambia a configuración do nodo" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptores cando o nodo bórrase" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscriptores cando os elementos bórranse do nodo" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Persistir elementos ao almacenar" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Un nome para o nodo" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persisten" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Permitir subscripciones" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Especifica o modelo de acceso" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Lista de grupos autorizados a subscribir" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Especificar o modelo do publicante" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 #, fuzzy msgid "Specify the event message type" msgstr "Especifica o modelo de acceso" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Máximo tamaño do payload en bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Cando enviar o último elemento publicado" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Só enviar notificacións aos usuarios dispoñibles" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "As coleccións coas que un nodo está afiliado" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Escolle un nome de usuario e contrasinal para rexistrarche neste servidor" @@ -1473,7 +1502,7 @@ msgstr "" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1484,7 +1513,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "Nome de usuario en IRC" @@ -1497,144 +1526,144 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Servidor ~b" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Verificación da contrasinal" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Lista de contactos" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Contrasinal:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Contrasinal:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Subscripción" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Borrar" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Lista de contactos de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Engadir ID Jabber" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Lista de contactos" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Grupos Compartidos" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nome:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Descrición:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Membros:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Mostrar grupos:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grupo " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber en Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Aniversario" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Cidade" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Apelido" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1642,46 +1671,52 @@ msgstr "" "Enche o formulario para buscar usuarios Jabber. Engade * ao final dun campo " "para buscar subcadenas." -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segundo nome" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome da organización" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unidade da organización" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Buscar usuarios en " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Necesitas un cliente con soporte de x:data para poder buscar" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Procura de usuario en vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard para ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Buscar resultados por " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Rechea campos para buscar usuarios Jabber que concuerden" +#~ msgid "Delete" +#~ msgstr "Eliminar" + +#~ msgid "This room is not anonymous" +#~ msgstr "Sala non anónima" + #~ msgid "Access denied by service policy" #~ msgstr "Acceso denegado pola política do servizo" diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 5109c1b9a85..11e0bbe80bb 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -15,24 +15,24 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Source-Language: en\n" -#: ejabberd_c2s.erl:522 ejabberd_c2s.erl:869 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "נדרש שימוש של STARTTLS" -#: ejabberd_c2s.erl:620 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "לא סופק משאב" -#: ejabberd_c2s.erl:1395 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "הוחלף בחיבור חדש" -#: ejabberd_c2s.erl:1399 mod_configure.erl:1854 mod_muc_log.erl:476 -#: mod_muc_log.erl:479 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "נבעט/ה" -#: ejabberd_c2s.erl:2484 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "יותר מדי סטנזות בלי אישורי קבלה" @@ -69,291 +69,291 @@ msgstr "לא מורשה" msgid "ejabberd Web Admin" msgstr "מנהל רשת ejabberd" -#: ejabberd_web_admin.erl:600 ejabberd_web_admin.erl:611 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "הנהלה" -#: ejabberd_web_admin.erl:668 ejabberd_web_admin.erl:704 mod_configure.erl:196 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "רשימות בקרת גישה" -#: ejabberd_web_admin.erl:672 ejabberd_web_admin.erl:708 -#: ejabberd_web_admin.erl:774 ejabberd_web_admin.erl:807 -#: ejabberd_web_admin.erl:848 ejabberd_web_admin.erl:1324 -#: ejabberd_web_admin.erl:1609 ejabberd_web_admin.erl:1769 -#: ejabberd_web_admin.erl:1803 ejabberd_web_admin.erl:1883 -#: ejabberd_web_admin.erl:2053 ejabberd_web_admin.erl:2082 -#: ejabberd_web_admin.erl:2179 mod_offline.erl:795 mod_roster.erl:1494 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 #: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "נשלח" # פגום -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 -#: ejabberd_web_admin.erl:849 ejabberd_web_admin.erl:1325 -#: ejabberd_web_admin.erl:1610 ejabberd_web_admin.erl:1770 -#: ejabberd_web_admin.erl:2054 ejabberd_web_admin.erl:2083 mod_roster.erl:1495 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 #: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "פורמט רע" -#: ejabberd_web_admin.erl:684 ejabberd_web_admin.erl:721 -#: ejabberd_web_admin.erl:786 ejabberd_web_admin.erl:856 -#: ejabberd_web_admin.erl:1872 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "שלח" -#: ejabberd_web_admin.erl:713 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "גולמי" # נבחרים -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:818 mod_offline.erl:817 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 #: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "מחק נבחרות" # חוקי -#: ejabberd_web_admin.erl:770 ejabberd_web_admin.erl:803 mod_configure.erl:198 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "כללי גישה" -#: ejabberd_web_admin.erl:844 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s תצורת כללי גישה" # וירטואליים -#: ejabberd_web_admin.erl:862 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "מארחים מדומים" -#: ejabberd_web_admin.erl:871 ejabberd_web_admin.erl:879 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "משתמשים" -#: ejabberd_web_admin.erl:886 ejabberd_web_admin.erl:1270 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 #: mod_configure.erl:524 msgid "Online Users" msgstr "משתמשים מקוונים" -#: ejabberd_web_admin.erl:902 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "פעילות משתמשים אחרונה" -#: ejabberd_web_admin.erl:906 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "משך זמן: " -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "חודש אחרון" -#: ejabberd_web_admin.erl:920 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "שנה אחרונה" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "כל פעילות" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "הצג טבלה רגילה" -#: ejabberd_web_admin.erl:928 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "הצג טבלה אינטגרלית" -#: ejabberd_web_admin.erl:935 ejabberd_web_admin.erl:1780 -#: mod_muc_admin.erl:245 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "סטטיסטיקה" -#: ejabberd_web_admin.erl:945 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "לא נמצא" -#: ejabberd_web_admin.erl:958 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "צומת לא נמצא" -#: ejabberd_web_admin.erl:1180 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "הוסף חדש" -#: ejabberd_web_admin.erl:1268 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "מארח" -#: ejabberd_web_admin.erl:1269 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "משתמשים רשומים" -#: ejabberd_web_admin.erl:1333 ejabberd_web_admin.erl:1388 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 #: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "משתמש" -#: ejabberd_web_admin.erl:1338 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3353 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 #: mod_register.erl:272 msgid "Password" msgstr "סיסמה" -#: ejabberd_web_admin.erl:1347 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "הוסף משתמש" -#: ejabberd_web_admin.erl:1389 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "הודעות לא מקוונות" -#: ejabberd_web_admin.erl:1390 ejabberd_web_admin.erl:1620 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "פעילות אחרונה" -#: ejabberd_web_admin.erl:1408 ejabberd_web_admin.erl:1592 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 #: mod_configure.erl:1917 msgid "Never" msgstr "אף פעם" -#: ejabberd_web_admin.erl:1426 ejabberd_web_admin.erl:1603 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 #: mod_configure.erl:1927 msgid "Online" msgstr "מקוון" -#: ejabberd_web_admin.erl:1482 ejabberd_web_admin.erl:1501 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "משתמשים רשומים:" -#: ejabberd_web_admin.erl:1485 ejabberd_web_admin.erl:1504 -#: ejabberd_web_admin.erl:2120 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "משתמשים מקוונים:" -#: ejabberd_web_admin.erl:1488 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "חיבורי s2s יוצאים:" -#: ejabberd_web_admin.erl:1491 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "שרתי s2s יוצאים:" -#: ejabberd_web_admin.erl:1527 ejabberd_web_admin.erl:1727 -#: ejabberd_web_admin.erl:1737 ejabberd_web_admin.erl:2147 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "אין" -#: ejabberd_web_admin.erl:1584 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "שנה סיסמה" -#: ejabberd_web_admin.erl:1605 +#: ejabberd_web_admin.erl:1610 msgid "User ~s" msgstr "משתמש ~s" -#: ejabberd_web_admin.erl:1616 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "משאבים מחוברים:" -#: ejabberd_web_admin.erl:1618 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "סיסמה:" -#: ejabberd_web_admin.erl:1625 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "הסר משתמש" -#: ejabberd_web_admin.erl:1673 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "אין מידע" -#: ejabberd_web_admin.erl:1746 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "צמתים" -#: ejabberd_web_admin.erl:1747 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "צמתים מורצים" -#: ejabberd_web_admin.erl:1748 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "צמתים שנפסקו" -#: ejabberd_web_admin.erl:1766 ejabberd_web_admin.erl:1791 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 msgid "Node ~p" msgstr "צומת ~p" -#: ejabberd_web_admin.erl:1775 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "מסד נתונים" -#: ejabberd_web_admin.erl:1776 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "גיבוי" -#: ejabberd_web_admin.erl:1778 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "פורטים מואזנים" -#: ejabberd_web_admin.erl:1781 ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "עדכן" -#: ejabberd_web_admin.erl:1785 ejabberd_web_admin.erl:2402 -#: ejabberd_web_admin.erl:2546 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "אתחל" -#: ejabberd_web_admin.erl:1787 ejabberd_web_admin.erl:2406 -#: ejabberd_web_admin.erl:2550 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "הפסק" -#: ejabberd_web_admin.erl:1794 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "מודולים" -#: ejabberd_web_admin.erl:1799 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "שגיאת קריאת RPC" -#: ejabberd_web_admin.erl:1850 +#: ejabberd_web_admin.erl:1855 msgid "Database Tables at ~p" msgstr "טבלאות מסד נתונים אצל ~p" -#: ejabberd_web_admin.erl:1860 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "שם" -#: ejabberd_web_admin.erl:1861 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "טיפוס אחסון" -#: ejabberd_web_admin.erl:1862 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "אלמנטים" -#: ejabberd_web_admin.erl:1863 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "זיכרון" -#: ejabberd_web_admin.erl:1885 ejabberd_web_admin.erl:2056 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "שגיאה" -#: ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:1893 msgid "Backup of ~p" msgstr "גיבוי של ~p" # האינטגרלי לחוד -#: ejabberd_web_admin.erl:1892 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -363,146 +363,146 @@ msgstr "" "עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך " "בנפרד." -#: ejabberd_web_admin.erl:1902 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "אחסן גיבוי בינארי:" -#: ejabberd_web_admin.erl:1909 ejabberd_web_admin.erl:1919 -#: ejabberd_web_admin.erl:1930 ejabberd_web_admin.erl:1939 -#: ejabberd_web_admin.erl:1949 ejabberd_web_admin.erl:1962 -#: ejabberd_web_admin.erl:1974 ejabberd_web_admin.erl:1990 -#: ejabberd_web_admin.erl:2006 ejabberd_web_admin.erl:2017 -#: ejabberd_web_admin.erl:2027 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "אישור" # ללא דיחוי -#: ejabberd_web_admin.erl:1912 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "שחזר גיבוי בינארי לאלתר:" # לאחר אתחול בא של -#: ejabberd_web_admin.erl:1922 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "שחזר גיבוי בינארי לאחר האתחול הבא של ejabberd (מצריך פחות זיכרון):" # תמליל ברור -#: ejabberd_web_admin.erl:1932 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "אחסן גיבוי טקסט גלוי (plain text):" -#: ejabberd_web_admin.erl:1942 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "שחזר גיבוי טקסט גלוי (plain text) לאלתר:" -#: ejabberd_web_admin.erl:1952 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "יבא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1965 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "יצא מידע של כל המשתמשים שבתוך בשרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1977 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "יצא מידע של כל המשתמשים שבתוך מארח לתוך קבצי PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1993 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "יצא את כל טבלאות בתור שאילתות SQL לתוך קובץ:" -#: ejabberd_web_admin.erl:2009 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "יבא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:" -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "יבא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:" -#: ejabberd_web_admin.erl:2048 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "פורטים מואזנים אצל " -#: ejabberd_web_admin.erl:2077 +#: ejabberd_web_admin.erl:2082 msgid "Modules at ~p" msgstr "מודולים אצל ~p" -#: ejabberd_web_admin.erl:2108 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "סטטיסטיקות של ~p" -#: ejabberd_web_admin.erl:2112 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "זמן פעילות:" -#: ejabberd_web_admin.erl:2116 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "זמן מחשב (CPU):" # זיכרון דברים (דיני חוזים) -#: ejabberd_web_admin.erl:2124 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "טרנזקציות שבוצעו:" -#: ejabberd_web_admin.erl:2128 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "טרנזקציות שבוטלו:" -#: ejabberd_web_admin.erl:2132 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "טרנזקציות שהותחלו מחדש:" -#: ejabberd_web_admin.erl:2136 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "טרנזקציות שנרשמו:" -#: ejabberd_web_admin.erl:2176 +#: ejabberd_web_admin.erl:2181 msgid "Update ~p" msgstr "עדכון ~p" -#: ejabberd_web_admin.erl:2187 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "תכנית עדכון" # adjusted -#: ejabberd_web_admin.erl:2188 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "מודולים שהותאמו" -#: ejabberd_web_admin.erl:2189 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "תסריט עדכון" -#: ejabberd_web_admin.erl:2190 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "תסריט עדכון Low level" -#: ejabberd_web_admin.erl:2191 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "בדיקת תסריט" -#: ejabberd_web_admin.erl:2371 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "‫IP" -#: ejabberd_web_admin.erl:2371 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "פורט" -#: ejabberd_web_admin.erl:2372 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "פרוטוקול" -#: ejabberd_web_admin.erl:2373 ejabberd_web_admin.erl:2528 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "מודול" -#: ejabberd_web_admin.erl:2374 ejabberd_web_admin.erl:2529 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "אפשרויות" -#: ejabberd_web_admin.erl:2426 ejabberd_web_admin.erl:2562 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "התחל" @@ -962,403 +962,407 @@ msgstr "קידוד עבור שרת ~b" msgid "Server ~b" msgstr "שרת ~b" -#: mod_muc.erl:776 mod_muc_admin.erl:319 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "חדרי שיחה" # to register nickname -#: mod_muc.erl:969 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "עליך להשתמש בלקוח אשר תומך x:data בכדי לרשום את שם הכינוי" -#: mod_muc.erl:979 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "רישום שם כינוי אצל " # אותו ברצונך לרשום -#: mod_muc.erl:985 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "הזן שם כינוי אשר ברצונך לרושמו" -#: mod_muc.erl:986 mod_muc_room.erl:4228 mod_roster.erl:1436 mod_vcard.erl:490 -#: mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "שם כינוי" -#: mod_muc.erl:1149 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "מודול MUC של ejabberd" -#: mod_muc_admin.erl:229 mod_muc_admin.erl:232 mod_muc_admin.erl:244 -#: mod_muc_admin.erl:318 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 msgid "Multi-User Chat" msgstr "שיחה מרובת משתמשים" -#: mod_muc_admin.erl:247 +#: mod_muc_admin.erl:248 msgid "Total rooms" msgstr "חדרים סה״כ" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Permanent rooms" msgstr "חדרים קבועים" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Registered nicknames" msgstr "שמות כינוי רשומים" -#: mod_muc_admin.erl:252 +#: mod_muc_admin.erl:253 msgid "List of rooms" msgstr "רשימה של חדרים" -#: mod_muc_log.erl:447 mod_muc_log.erl:456 +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "תצורת חדר שיחה שונתה" -#: mod_muc_log.erl:459 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "נכנס/ת אל החדר" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "עוזב/ת את החדר" -#: mod_muc_log.erl:469 mod_muc_log.erl:472 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "נאסר/ה" -#: mod_muc_log.erl:484 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "נבעט/ה משום שינוי סינוף" -#: mod_muc_log.erl:489 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "נבעט/ה משום שהחדר שונה אל חברים-בלבד" -#: mod_muc_log.erl:494 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "נבעט/ה משום כיבוי מערכת" -#: mod_muc_log.erl:499 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "ידועה כעת בכינוי" -#: mod_muc_log.erl:502 mod_muc_log.erl:841 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " הגדיר/ה את הנושא אל: " -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "חדר שיחה הינו נוצר" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "חדר שיחה הינו הרוס" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "חדר שיחה הינו מותחל" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "חדר שיחה הינו מופסק" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "יום שני" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "יום שלישי" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "יום רביעי" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "יום חמישי" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "יום שישי" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "יום שבת" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "יום ראשון" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:560 msgid "January" msgstr "ינואר" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:561 msgid "February" msgstr "פברואר" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:562 msgid "March" msgstr "מרץ" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:563 msgid "April" msgstr "אפריל" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:564 msgid "May" msgstr "מאי" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:565 msgid "June" msgstr "יוני" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:566 msgid "July" msgstr "יולי" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:567 msgid "August" msgstr "אוגוסט" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:568 msgid "September" msgstr "ספטמבר" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:569 msgid "October" msgstr "אוקטובר" -#: mod_muc_log.erl:572 +#: mod_muc_log.erl:570 msgid "November" msgstr "נובמבר" -#: mod_muc_log.erl:573 +#: mod_muc_log.erl:571 msgid "December" msgstr "דצמבר" -#: mod_muc_log.erl:961 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "תצורת חדר" -#: mod_muc_log.erl:981 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "נוכחי חדר" -#: mod_muc_room.erl:982 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:987 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "רק אחראים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:2728 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "מזהה Jabber ‏~s הינו שגוי" -#: mod_muc_room.erl:2742 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "שם כינוי ~s לא קיים בחדר" -#: mod_muc_room.erl:2765 mod_muc_room.erl:3145 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "סינוף שגוי: ~s" -#: mod_muc_room.erl:2816 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "תפקיד שגוי: ~s" # תצורה של חדר -#: mod_muc_room.erl:3318 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "תצורת חדר ~s" -#: mod_muc_room.erl:3329 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "כותרת חדר" -#: mod_muc_room.erl:3331 mod_muc_room.erl:4065 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "תיאור חדר" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "הפוך חדר אל קבוע" -#: mod_muc_room.erl:3345 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "הפוך חדר אל בר חיפוש פומבי" -#: mod_muc_room.erl:3348 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "הפוך רשימת משתתפים אל פומבית" -#: mod_muc_room.erl:3350 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "הפוך חדר אל מוגן במילת מעבר" -#: mod_muc_room.erl:3364 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "מספר מרבי של נוכחים" -#: mod_muc_room.erl:3376 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "ללא הגבלה" # הצג כתובות JID ממשיות ל -#: mod_muc_room.erl:3406 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "הצג כתובות JID ממשיות" -#: mod_muc_room.erl:3420 mod_muc_room.erl:3483 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "לאחראים בלבד" -#: mod_muc_room.erl:3430 mod_muc_room.erl:3493 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "לכל אחד" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "הפוך חדר אל חברים-בלבד" # חדר מבוקר חדר תחת ביקורת -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "הפוך חדר אל מבוקר" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "משתמשים משתמטים כמשתתפים" # התרה -#: mod_muc_room.erl:3445 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "התר למשתמשים לשנות את הנושא" -#: mod_muc_room.erl:3448 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "התר למשתמשים לשלוח הודעות פרטיות" -#: mod_muc_room.erl:3456 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "התר למבקרים לשלוח הודעות פרטיות אל" -#: mod_muc_room.erl:3474 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "אף אחד" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "התר למשתמשים לתשאל משתמשים אחרים" -#: mod_muc_room.erl:3502 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "התר למשתמשים לשלוח הזמנות" -#: mod_muc_room.erl:3505 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "התר למבקרים לשנות שם כינוי" -#: mod_muc_room.erl:3512 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "התר למבקרים לשלוח בקשות ביטוי" -#: mod_muc_room.erl:3515 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "תדירות מינימלית בין בקשות ביטוי (בשניות)" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "הפוך חדר אל מוגן CAPTCHA" +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + # זהויות -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "הוצא כתובות של Jabber מתוך אתגר CAPTCHA" -#: mod_muc_room.erl:3537 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "אפשור רישום פעילות" -#: mod_muc_room.erl:3547 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר חדר" -#: mod_muc_room.erl:4067 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "מספר של נוכחים" -#: mod_muc_room.erl:4137 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "פרטי, " -#: mod_muc_room.erl:4201 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "בקשת ביטוי" # אשר או דחה -#: mod_muc_room.erl:4206 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "או שתאשר או שתדחה את בקשת הביטוי." -#: mod_muc_room.erl:4226 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "‏JID משתמש" -#: mod_muc_room.erl:4230 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "להעניק ביטוי לאישיות זו?" -#: mod_muc_room.erl:4373 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "‫~s מזמינך לחדר ~s" -#: mod_muc_room.erl:4385 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "הסיסמה היא" -#: mod_multicast.erl:259 +#: mod_multicast.erl:273 msgid "Multicast" msgstr "שידור מרובב" -#: mod_multicast.erl:274 +#: mod_multicast.erl:288 msgid "ejabberd Multicast service" msgstr "שירות שידור מרובב של ejabberd" -#: mod_offline.erl:791 +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "תור הודעות לא מקוונות של ~s" -#: mod_offline.erl:804 +#: mod_offline.erl:796 msgid "Time" msgstr "זמן" -#: mod_offline.erl:805 +#: mod_offline.erl:797 msgid "From" msgstr "מאת" -#: mod_offline.erl:806 +#: mod_offline.erl:798 msgid "To" msgstr "לכבוד" -#: mod_offline.erl:807 +#: mod_offline.erl:799 msgid "Packet" msgstr "חבילת מידע" -#: mod_offline.erl:985 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "הודעות לא מקוונות:" -#: mod_offline.erl:989 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "הסר את כל ההודעות הלא מקוונות" diff --git a/priv/msgs/id.po b/priv/msgs/id.po index be4034f9f98..a027b2bd5bb 100644 --- a/priv/msgs/id.po +++ b/priv/msgs/id.po @@ -11,342 +11,343 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Indonesian (Bahasa Indonesia)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Penggunaan STARTTLS diperlukan" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Tidak ada sumber daya yang disediakan" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Diganti dengan koneksi baru" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "telah dikick" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Masukkan teks yang Anda lihat" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Pesan Anda untuk ~s sedang diblokir. Untuk membuka blokir tersebut, kunjungi " "~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "Jika Anda tidak melihat gambar CAPTCHA disini, silahkan kunjungi halaman web." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA laman web" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Captcha ini benar." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Ditolak" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Admin Web ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administrasi" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Akses Daftar Pengendalian" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Ulangi masukan" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Format yang buruk" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Serahkan" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "mentah" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Hapus Yang Terpilih" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Aturan Akses" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s aturan akses konfigurasi" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtual Hosts" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Pengguna" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Pengguna Yang Online" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Aktifitas terakhir para pengguna" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periode:" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Akhir bulan" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Akhir tahun" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Semua aktifitas" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Tampilkan Tabel Normal" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Tampilkan Tabel Terpisah" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistik" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Tidak Ditemukan" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Node tidak ditemukan" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Tambah Baru" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Pengguna Terdaftar" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Pengguna" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Sandi" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Tambah Pengguna" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Pesan Offline" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Aktifitas Terakhir" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Tidak Pernah" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Pengguna Terdaftar:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Pengguna Online:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Koneksi s2s yang keluar:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Layanan s2s yang keluar:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Tak satupun" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Ubah Kata Sandi" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Pengguna" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Sumber Daya Terhubung:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Kata Sandi:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Hapus Pengguna" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Tidak Ada Data" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Node-node" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Menjalankan Node" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Menghentikan node" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Node" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Backup" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Port Terdeteksi" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Memperbarui" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Jalankan Ulang" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Hentikan" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modul" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Panggilan Kesalahan RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabel Database pada" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nama" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Jenis Penyimpanan" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elemen-elemen" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memori" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Kesalahan" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Cadangan dari" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -356,488 +357,484 @@ msgstr "" "database. Jika Anda menggunakan modul ODBC, anda juga perlu untuk membuat " "cadangan database SQL Anda secara terpisah." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Penyimpanan cadangan yang berpasangan:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "YA" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Segera mengembalikan cadangan yang berpasangan:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Mengembalikan cadangan yang berpasanagn setelah ejabberd berikutnya " "dijalankan ulang (memerlukan memori lebih sedikit):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Simpan cadangan teks biasa:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Segera mengembalikan cadangan teks biasa:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "impor data-data pengguna dari sebuah PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Ekspor data dari semua pengguna pada layanan ke berkas PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Ekspor data pengguna pada sebuah host ke berkas PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Impor data pengguna dari sekumpulan berkas jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Импорт пользовательских данных из буферной директории jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Mendeteksi Port-port di" -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "modul-modul di" -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "statistik dari ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Sampai saat:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Waktu CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transaksi yang dilakukan:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transaksi yang dibatalkan:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transaksi yang dijalankan ulang:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transaksi yang ditempuh:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Memperbarui " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Rencana Perubahan" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Modifikasi modul-modul" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Perbarui naskah" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Perbaruan naskah tingkat rendah" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Periksa naskah" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Pilihan-pilihan" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Hapus" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Mulai" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Perintah" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Benar-benar ingin menghapus pesan harian?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Subyek" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Isi Pesan" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Tidak ada isi pesan yang disediakan untuk mengirimkan pesan" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Pengumuman" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Kirim pengumuman untuk semua pengguna" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Kirim pengumuman untuk semua pengguna pada semua host" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Kirim pengumuman untuk semua pengguna yang online" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Kirim pengumuman untuk semua pengguna yang online pada semua host" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Mengatur pesan harian dan mengirimkan ke pengguna yang online" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Mengatur pesan harian pada semua host dan kirimkan ke pengguna yang online" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Rubah pesan harian (tidak dikirim)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Rubah pesan harian pada semua host (tidak dikirim)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Hapus pesan harian" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Hapus pesan harian pada semua host" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Pengaturan" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Memulai Modul" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Hentikan Modul" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Mengembalikan" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Dump menjadi File Teks" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Impor File" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Impor Direktori" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restart Layanan" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Shut Down Layanan" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Hapus Pengguna" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Akhir Sesi Pengguna" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Dapatkan User Password" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Ubah User Password" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Dapatkan Waktu Login Terakhir Pengguna " -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Dapatkan Statistik Pengguna" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Dapatkan Jumlah Pengguna Yang Terdaftar" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Dapatkan Jumlah User Yang Online" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Manajemen Pengguna" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Semua Pengguna" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Koneksi Keluar s2s" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Manajemen Backup" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Impor Pengguna Dari jabberd14 Spool File" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Kepada ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Dari ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Database Tabel Konfigurasi pada" -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Pilih jenis penyimpanan tabel" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Hanya salinan dari disc" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM dan disc salinan" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Salinan RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Salinan Remote" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Hentikan Modul pada" -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Pilih Modul untuk berhenti" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Mulai Modul pada" -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Masukkan daftar {Modul, [Options]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Daftar modul untuk memulai" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Backup ke File pada" -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Masukkan path untuk file cadangan" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Jalur ke File" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Kembalikan Backup dari File pada" -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Dump Backup ke File Teks di" -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Masukkan path ke file teks" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Impor Pengguna dari File pada" -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Masukkan path ke file jabberd14 spool" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Impor Pengguna dari Dir di" -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Masukkan path ke direktori spool jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Jalur ke Dir" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Waktu tunda" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurasi Daftar Akses Pengendalian" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Daftar Pengendalian Akses" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Akses Konfigurasi" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Akses peraturan" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verifikasi Sandi" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Jumlah pengguna terdaftar" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Jumlah pengguna online" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Terakhir Login" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Ukuran Daftar Kontak" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Alamat IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Sumber daya" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administrasi" -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Tindakan pada pengguna" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Ganti Properti" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -948,168 +945,192 @@ msgstr "Pengkodean untuk layanan ~b" msgid "Server ~b" msgstr "Layanan ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Ruangan Chat" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Anda memerlukan klien yang mendukung x:data untuk mendaftar julukan" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Pendaftaran Julukan pada" -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Masukkan nama julukan Anda jika ingin mendaftar" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nama Julukan" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC Module" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Ruangan Chat" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "meninggalkan ruangan" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Pengguna Terdaftar" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Konfigurasi ruang chat diubah" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "bergabung ke ruangan" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "meninggalkan ruangan" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "telah dibanned" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "telah dikick karena perubahan afiliasi" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "telah dikick karena ruangan telah diubah menjadi hanya untuk member" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "telah dikick karena sistem shutdown" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "sekarang dikenal sebagai" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr "telah menetapkan topik yaitu:" -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Ruang chat telah dibuat" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Ruang chat dilenyapkan" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Ruang chat dimulai" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Ruang chat dihentikan" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Senin" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Selasa" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Rabu" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Kamis" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Jumat" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sabtu" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Minggu" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Januari" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Februari" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Maret" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "April" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Mei" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Agustus" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "September" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Nopember" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Desember" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Konfigurasi Ruangan" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Penghuni Ruangan" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1117,320 +1138,328 @@ msgstr "" "Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan " "di ruangan ini" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "" "Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Ruangan ini tidak dikenal" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s tidak valid" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Nama Julukan ~s tidak berada di dalam ruangan" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiliasi tidak valid: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Peran tidak valid: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Pengaturan ruangan ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Nama Ruangan" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Keterangan ruangan" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Buat ruangan menjadi permanent" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Buat ruangan dapat dicari" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Buat daftar participant diketahui oleh public" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Buat ruangan yang dilindungi dengan kata sandi" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Maksimum Jumlah Penghuni" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Tidak terbatas" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Tampilkan Jabber ID secara lengkap" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "Hanya moderator" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "Siapapun" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Buat ruangan hanya untuk member saja" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Buat ruangan hanya untuk moderator saja" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "pengguna pertama kali masuk sebagai participant" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Perbolehkan pengguna untuk mengganti topik" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Perbolehkan pengguna untuk mengetahui pengguna lain" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Perbolehkan pengguna mengirimkan undangan" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Izinkan pengunjung untuk mengirim teks status terbaru" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Perbolehkan visitor mengganti nama julukan" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Perbolehkan pengguna mengirimkan undangan" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Buat ruangan dilindungi dengan CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Aktifkan catatan" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Jumlah Penghuni" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "pribadi, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Pengguna" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s mengundang anda ke ruangan ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "kata sandi yaitu:" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Antrian Pesan Offline ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Waktu" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Dari" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Kepada" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Pesan Offline:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Hapus Semua Pesan Offline" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "modul ejabberd SOCKS5 Bytestreams" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Setujui-Pertemanan" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Modul ejabberd Setujui-Pertemanan" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Permintaan pertemanan PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Pilih apakah akan menyetujui hubungan pertemanan ini." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID Node" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Alamat Pertemanan" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Izinkan ID Jabber ini untuk berlangganan pada node pubsub ini?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Memberikan muatan dengan pemberitahuan acara" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Memberikan pemberitahuan acara" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Beritahu pelanggan ketika ada perubahan konfigurasi node" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Beritahu pelanggan ketika node dihapus" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Beritahu pelanggan ketika item tersebut dikeluarkan dari node" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Pertahankan item ke penyimpanan" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Nama yang dikenal untuk node" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Max item untuk bertahan" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Apakah diperbolehkan untuk berlangganan" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Tentukan model akses" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Kelompok kontak yang diizinkan untuk berlangganan" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Tentukan model penerbitan" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Bersihkan semua item ketika penerbit yang relevan telah offline" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Tentukan jenis acara pesan" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Max kapasitas ukuran dalam bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Ketika untuk mengirim item terakhir yang dipublikasikan" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Hanya mengirimkan pemberitahuan kepada pengguna yang tersedia" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Koleksi dengan yang berafiliasi dengan sebuah node" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Anda memerlukan klien yang mendukung x:data dan CAPTCHA untuk mendaftar" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Pilih nama pengguna dan kata sandi untuk mendaftar dengan layanan ini" @@ -1466,7 +1495,7 @@ msgstr "Pendaftaran Akun Jabber" msgid "Register a Jabber account" msgstr "Daftarkan sebuah akun jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Nonaktifkan akun jabber" @@ -1480,7 +1509,7 @@ msgstr "" "JID Anda (Jabber Pengenal) akan berbentuk: namapengguna@layanan. Harap baca " "dengan seksama petunjuk-petunjuk untuk mengisi kolom dengan benar." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nama Pengguna:" @@ -1494,11 +1523,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Karakter tidak diperbolehkan:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Layanan:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1506,13 +1535,13 @@ msgstr "" "Jangan memberitahukan kata sandi Anda ke siapapun, bahkan para administrator " "dari layanan Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" "Anda dapat mengubah kata sandi anda dilain waktu dengan menggunakan klien " "Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1520,7 +1549,7 @@ msgstr "" "Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan " "fitur itu hanya jika Anda mempercayai komputer Anda aman." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1530,114 +1559,114 @@ msgstr "" "Didalam Jabber tidak ada cara otomatis untuk mendapatkan kembali password " "Anda jika Anda lupa." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verifikasi Kata Sandi:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Mendaftar" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Password Lama:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Password Baru:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Pada bagian ini memungkinkan Anda untuk membatalkan pendaftaran akun Jabber " "pada layanan Jabber ini." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Nonaktifkan" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Berlangganan" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Tertunda" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grup" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Mengesahkan" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Menghapus" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Kontak dari" -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Tambah Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Kontak" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Berbagi grup kontak" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nama:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Keterangan:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Anggota:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Tampilkan Grup:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grup" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Layanan Erlang Jabber" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Hari Lahir" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Kota" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Negara" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nama Keluarga (marga)" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1645,46 +1674,52 @@ msgstr "" "Isi formulir untuk pencarian pengguna Jabber yang cocok (Tambahkan * ke " "mengakhiri pengisian untuk menyamakan kata)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nama Lengkap" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Nama Tengah" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nama Organisasi" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unit Organisasi" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Pencarian pengguna dalam" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Anda memerlukan x:data klien untuk melakukan pencarian" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Pencarian Pengguna" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Modul ejabberd vCard" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Hasil Pencarian untuk" -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Isi kolom untuk mencari pengguna Jabber yang sama" +#~ msgid "Delete" +#~ msgstr "Hapus" + +#~ msgid "This room is not anonymous" +#~ msgstr "Ruangan ini tidak dikenal" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Daftar privasi aktif Anda telah menolak routing ztanza ini" diff --git a/priv/msgs/it.po b/priv/msgs/it.po index f1103f8b43f..2da104fb6d0 100644 --- a/priv/msgs/it.po +++ b/priv/msgs/it.po @@ -15,339 +15,340 @@ msgstr "" "X-Generator: Lokalize 1.2\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Utilizzo di STARTTLS obbligatorio" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Nessuna risorsa fornita" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Sostituito da una nuova connessione" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "è stata/o espulsa/o" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Immettere il testo visibile" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "I messaggi verso ~s sono bloccati. Per sbloccarli, visitare ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Se qui non vedi l'immagine CAPTCHA, visita la pagina web." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Pagina web CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Il CAPTCHA è valido." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Non autorizzato" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Amministrazione web ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Amministrazione" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Diritti di accesso (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Inviato" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Formato non valido" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Inviare" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Grezzo" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Eliminare gli elementi selezionati" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Regole di accesso" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configurazione delle regole di accesso per ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Host Virtuali" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Utenti" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Utenti online" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Ultima attività degli utenti" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periodo:" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Ultimo mese" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Ultimo anno" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Tutta l'attività" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Mostrare la tabella normale" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Mostrare la tabella integrale" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistiche" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Non trovato" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nodo non trovato" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Aggiungere nuovo" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Utenti registrati" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Utente" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Password" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Aggiungere un utente" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Messaggi offline" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Ultima attività" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Mai" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Utenti registrati:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Utenti connessi:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Connessioni s2s in uscita:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Server s2s in uscita" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nessuno" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Modificare la password" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Utente " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Risorse connesse:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Password:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Eliminare l'utente" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Nessuna informazione" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodi" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodi attivi" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodi arrestati" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nodo " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Salvare" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Porte in ascolto" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Aggiornare" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Riavviare" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Arrestare" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduli" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Errore di chiamata RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelle del database su " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Tipo di conservazione" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementi" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Errore" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Salvataggio di " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -357,491 +358,487 @@ msgstr "" "interno Mnesia. Se si sta utilizzando il modulo ODBC, è necessario salvare " "anche il proprio database SQL separatamente." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Conservare un salvataggio binario:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Recuperare un salvataggio binario adesso:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Recuperare un salvataggio binario dopo il prossimo riavvio di ejabberd " "(necessita di meno memoria):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Conservare un salvataggio come semplice testo:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Recuperare un salvataggio come semplice testo adesso:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importare i dati utenti da un file PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Esportare i dati di tutti gli utenti nel server in file PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Esportare i dati degli utenti di un host in file PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importare i dati utente da file di spool di jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importare i dati utenti da directory di spool di jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Porte in ascolto su " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduli su " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistiche di ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Tempo dall'avvio:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Tempo CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transazioni avvenute:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transazioni abortite:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transazioni riavviate:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transazioni con log:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Aggiornare " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Piano di aggiornamento" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Moduli modificati" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script di aggiornamento" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Script di aggiornamento di basso livello" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Verifica dello script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Porta" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocollo" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modulo" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opzioni" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Eliminare" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Avviare" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandi" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Si conferma l'eliminazione del messaggio del giorno (MOTD)?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Oggetto" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corpo del messaggio" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Nessun corpo fornito per il messaggio di annuncio" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Annunci" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Inviare l'annuncio a tutti gli utenti" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Inviare l'annuncio a tutti gli utenti su tutti gli host" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Inviare l'annuncio a tutti gli utenti online" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Inviare l'annuncio a tutti gli utenti online su tutti gli host" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "" "Impostare il messaggio del giorno (MOTD) ed inviarlo agli utenti online" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Impostare il messaggio del giorno (MOTD) su tutti gli host e inviarlo agli " "utenti online" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Aggiornare il messaggio del giorno (MOTD) (non inviarlo)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" "Aggiornare il messaggio del giorno (MOTD) su tutti gli host (non inviarlo)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Eliminare il messaggio del giorno (MOTD)" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Eliminare il messaggio del giorno (MOTD) su tutti gli host" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configurazione" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Avviare moduli" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Arrestare moduli" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Recuperare" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Trascrivere su file di testo" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importare un file" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importare una directory" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Riavviare il servizio" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Terminare il servizio" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Eliminare l'utente" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Terminare la sessione dell'utente" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Ottenere la password dell'utente" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Cambiare la password dell'utente" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Ottenere la data di ultimo accesso dell'utente" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Ottenere le statistiche dell'utente" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Ottenere il numero di utenti registrati" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Ottenere il numero di utenti online" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gestione degli utenti" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Tutti gli utenti" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Connessioni s2s in uscita" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestione dei salvataggi" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importare utenti da file di spool di jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Da ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configurazione delle tabelle del database su " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selezionare una modalità di conservazione delle tabelle" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copia su disco soltanto" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copia in memoria (RAM) e su disco" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia in memoria (RAM)" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Arrestare moduli su " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selezionare i moduli da arrestare" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Avviare moduli su " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Immettere un elenco di {Modulo, [Opzioni]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Elenco dei moduli da avviare" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Salvataggio sul file " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Immettere il percorso del file di salvataggio" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Percorso del file" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Recuperare il salvataggio dal file " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Trascrivere il salvataggio sul file di testo " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Immettere il percorso del file di testo" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importare un utente dal file " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Immettere il percorso del file di spool di jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importare utenti dalla directory " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Immettere il percorso della directory di spool di jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Percorso della directory" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Ritardo" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configurazione dei diritti di accesso (ACL)" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Diritti di accesso (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configurazione dell'accesso" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Regole di accesso" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID (Jabber ID)" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verifica della password" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Numero di utenti registrati" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Numero di utenti online" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Ultimo accesso" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Dimensione della lista dei contatti" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Indirizzi IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Risorse" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Amministrazione di " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Azione sull'utente" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Modificare le proprietà" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -953,168 +950,192 @@ msgstr "Codifica per il server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Stanze" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Per registrare il nickname è necessario un client che supporti x:data" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registrazione di un nickname su " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Immettere il nickname che si vuole registrare" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nickname" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Modulo MUC per ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Stanze" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "esce dalla stanza" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Utenti registrati" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Configurazione della stanza modificata" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "entra nella stanza" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "esce dalla stanza" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "è stata/o bandita/o" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "è stato espulso a causa di un cambiamento di appartenenza" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "è stato espulso per la limitazione della stanza ai soli membri" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "è stato espulso a causa dello spegnimento del sistema" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "è ora conosciuta/o come" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " ha modificato l'oggetto in: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "La stanza è creata" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "La stanza è eliminata" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "La stanza è avviata" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "La stanza è arrestata" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Lunedì" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Martedì" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Mercoledì" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Giovedì" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Venerdì" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sabato" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Domenica" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Gennaio" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Febbraio" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Marzo" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Aprile" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Maggio" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Giugno" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Luglio" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Settembre" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Ottobre" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Novembre" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Dicembre" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Configurazione della stanza" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Presenti nella stanza" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1122,320 +1143,328 @@ msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai " "moderatori e ai partecipanti" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Questa stanza non è anonima" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Il Jabber ID ~s non è valido" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Il nickname ~s non esiste nella stanza" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Affiliazione non valida: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Ruolo non valido: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Configurazione per la stanza ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Titolo della stanza" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Descrizione della stanza" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Rendere la stanza persistente" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Rendere la sala visibile al pubblico" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Rendere pubblica la lista dei partecipanti" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Rendere la stanza protetta da password" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Numero massimo di occupanti" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Nessun limite" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Rendere visibile il Jabber ID reale a" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "moderatori soltanto" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "tutti" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Rendere la stanza riservata ai membri" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Rendere la stanza moderata" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Definire per default gli utenti come partecipanti" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Consentire agli utenti di cambiare l'oggetto" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Consentire agli utenti l'invio di messaggi privati" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Consentire agli ospiti l'invio di messaggi privati a" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "nessuno" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Consentire agli utenti query verso altri utenti" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Consentire agli utenti l'invio di inviti" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Consentire ai visitatori l'invio di testo sullo stato in aggiornamenti sulla " "presenza" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Consentire ai visitatori di cambiare il nickname" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Consentire agli ospiti l'invio di richieste di parola" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervallo minimo fra due richieste di parola (in secondi)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Rendere la stanza protetta da CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Escludi degli ID Jabber dal passaggio CAPTCHA" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Abilitare i log" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "Per la configurazione della stanza è necessario un client che supporti x:data" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Numero di presenti" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privato, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Richiesta di parola" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Approva oppure respingi la richiesta di parola." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "JID utente" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Dare parola a questa persona?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s ti invita nella stanza ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "la password è" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Coda di ~s messaggi offline" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Ora" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Da" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "A" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pacchetto" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Messaggi offline:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Eliminare tutti i messaggi offline" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Modulo SOCKS5 Bytestreams per ejabberd" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Pubblicazione-Iscrizione" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Modulo Pubblicazione/Iscrizione (PubSub) per ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Richiesta di iscrizione per PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Scegliere se approvare l'iscrizione per questa entità" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID del nodo" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Indirizzo dell'iscritta/o" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Consentire a questo Jabber ID l'iscrizione a questo nodo pubsub?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Inviare il contenuto del messaggio con la notifica dell'evento" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Inviare notifiche degli eventi" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Notificare gli iscritti quando la configurazione del nodo cambia" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Notificare gli iscritti quando il nodo è cancellato" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Notificare gli iscritti quando sono eliminati degli elementi dal nodo" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Conservazione persistente degli elementi" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Un nome comodo per il nodo" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Numero massimo di elementi da conservare persistentemente" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Consentire iscrizioni?" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Specificare il modello di accesso" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Gruppi roster abilitati alla registrazione" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Definire il modello di pubblicazione" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Cancella tutti gli elementi quando chi li ha pubblicati non è più online" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Specificare il tipo di messaggio di evento" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Dimensione massima del contenuto del messaggio in byte" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Quando inviare l'ultimo elemento pubblicato" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Inviare le notifiche solamente agli utenti disponibili" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Le collezioni a cui è affiliato un nodo" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "La registrazione richiede un client che supporti x:data e CAPTCHA" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Scegliere un nome utente e una password per la registrazione con questo " @@ -1473,7 +1502,7 @@ msgstr "Registrazione account Jabber" msgid "Register a Jabber account" msgstr "Registra un account Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Elimina un account Jabber" @@ -1487,7 +1516,7 @@ msgstr "" "Il tuo JID (Jabber IDentifier) avrà la forma: nome_utente@server. Leggi " "attentamente le istruzioni per compilare i campi correttamente." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nome utente:" @@ -1501,11 +1530,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Caratteri non consentiti:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1513,11 +1542,11 @@ msgstr "" "Non comunicare la tua password a nessuno, neppure agli amministratori del " "server Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Potrai in seguito cambiare la password utilizzando un client Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1525,7 +1554,7 @@ msgstr "" "Alcuni client Jabber possono conservare la password nel tuo computer. " "Utilizza tale funzione soltanto se ritieni che il tuo computer sia sicuro." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1535,114 +1564,114 @@ msgstr "" "luogo sicuro. Jabber non prevede una modalità automatica per il recupero di " "una password dimenticata." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Verifica della password:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Registra" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Vecchia password:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nuova password:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Questa pagina consente di eliminare un account Jabber da questo server " "Jabber." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Elimina" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Iscrizione" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Gruppi" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validare" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Eliminare" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Lista dei contatti di " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Aggiungere un Jabber ID (Jabber ID)" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Lista dei contatti" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Gruppi di liste di contatti comuni" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nome:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Descrizione:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Membri:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Gruppi visualizzati:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Gruppo " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Compleanno" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Città" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Paese" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Cognome" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1650,47 +1679,53 @@ msgstr "" "Riempire il modulo per la ricerca di utenti Jabber corrispondenti ai criteri " "(Aggiungere * alla fine del campo per la ricerca di una sottostringa" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Altro nome" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome dell'organizzazione" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unità dell'organizzazione" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Cercare utenti in " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Per effettuare ricerche è necessario un client che supporti x:data" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Ricerca di utenti per vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Modulo vCard per ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Risultati della ricerca per " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Riempire i campi per la ricerca di utenti Jabber corrispondenti ai criteri" +#~ msgid "Delete" +#~ msgstr "Eliminare" + +#~ msgid "This room is not anonymous" +#~ msgstr "Questa stanza non è anonima" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "In base alla tua attuale lista privacy questa stanza è stata esclusa " diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index b91ecc09ea2..461aa024f31 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -10,337 +10,338 @@ msgstr "" "X-Additional-Translator: Tsukasa Hamano \n" "X-Additional-Translator: Mako N \n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "STARTTLS の使用が必要です" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "リソースが提供されませんでした" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "新しいコネクションによって置き換えられました" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "はキックされました" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "多くのスタンザが応答していません" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "見えているテキストを入力してください" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "~s 宛のメッセージはブロックされています。解除するにはこちらを見てください ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "ここに CAPTCHA 画像が表示されない場合、ウェブページを参照してください。" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA ウェブページ" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "CAPTCHA は有効です。" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "認証されていません" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd ウェブ管理" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "管理" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "アクセスコントロールリスト" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "送信完了" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "不正なフォーマット" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "送信" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Raw" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "選択した項目を削除" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "アクセスルール" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s アクセスルール設定" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "バーチャルホスト" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "ユーザー" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "オンラインユーザー" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "ユーザーの活動履歴" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "期間: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "先月" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "去年" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "すべて" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "通常の表を表示" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "累積の表を表示" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "統計" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "見つかりません" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "ノードが見つかりません" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "新規追加" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "ホスト" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "登録ユーザー" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "ユーザー" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "パスワード" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "ユーザーを追加" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "オフラインメッセージ" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "活動履歴" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "なし" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "オンライン" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "登録ユーザー:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "オンラインユーザー:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "外向き s2s コネクション:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "外向き s2s サービス:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "なし" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "パスワードを変更" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 msgid "User ~s" msgstr "ユーザー ~s" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "接続リソース:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "パスワード" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "ユーザーを削除" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "データなし" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "ノード" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "起動ノード" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "停止ノード" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 msgid "Node ~p" msgstr "ノード ~p" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "データーベース" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "バックアップ" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Listen ポート" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "更新" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "再起動" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "停止" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "モジュール" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "RPC 呼び出しエラー" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 msgid "Database Tables at ~p" msgstr "データーベーステーブル: ~p" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "名" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "ストレージタイプ" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "要素" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "メモリ" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "エラー" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 msgid "Backup of ~p" msgstr "バックアップ: ~p" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -350,484 +351,481 @@ msgstr "" "ことに注意してください。もし ODBC モジュールを使用している場合は、SQL デー" "ターベースのバックアップを別に行う必要があります。" -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "バイナリバックアップを保存:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "直ちにバイナリバックアップからリストア:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "ejabberd の再起動時にバイナリバックアップからリストア (メモリ少):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "プレーンテキストバックアップを保存:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "直ちにプレーンテキストバックアップからリストア:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "ユーザーデータを PIEFXIS ファイルからインポート (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "サーバーにあるすべてのユーザーデータを PIEFXIS ファイルにエクスポート " "(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "ホストのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "すべてのテーブルをSQL形式でファイルにエクスポート: " -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "ユーザーデータを jabberd14 Spool ファイルからインポート:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "ユーザーデータを jabberd14 Spool ディレクトリからインポート:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Listen ポート " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 msgid "Modules at ~p" msgstr "モジュール ~p" -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "~p の統計" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "起動時間:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "CPU時間:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "トランザクションのコミット:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "トランザクションの失敗:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "トランザクションの再起動:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "トランザクションのログ: " -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 msgid "Update ~p" msgstr "更新 ~p" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "更新計画" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "更新されたモジュール" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "スクリプトの更新" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "低レベル更新スクリプト" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "スクリプトチェック" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "ポート" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "プロトコル" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "モジュール" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "オプション" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "削除" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "開始" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "コマンド" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "本当にお知らせメッセージを削除しますか ?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "件名" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "本文" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "アナウンスメッセージはありませんでした" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "アナウンス" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "すべてのユーザーにアナウンスを送信" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "全ホストのユーザーにアナウンスを送信" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "すべてのオンラインユーザーにアナウンスを送信" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "全ホストのオンラインユーザーにアナウンスを送信" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "お知らせメッセージを設定し、オンラインユーザーに送信" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "全ホストのお知らせメッセージを設定し、オンラインユーザーに送信" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "お知らせメッセージを更新 (送信しない)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "全ホストのお知らせメッセージを更新 (送信しない)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "お知らせメッセージを削除" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "全ホストのお知らせメッセージを削除" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "設定" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "モジュールを起動" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "モジュールを停止" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "リストア" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "テキストファイルに出力" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "ファイルからインポート" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "ディレクトリインポート" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "サービスを再起動" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "サービスを停止" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "ユーザーを削除" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "エンドユーザーセッション" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "パスワードを取得" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "パスワードを変更" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "最終ログイン時間を取得" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "ユーザー統計を取得" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "登録ユーザー数を取得" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "オンラインユーザー数を取得" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ユーザー管理" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "全ユーザー" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "外向き s2s コネクション" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "バックアップ管理" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "jabberd14 Spool ファイルからユーザーをインポート" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "宛先 ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "差出人 ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "データーベーステーブル設定 " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "テーブルのストレージタイプを選択" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "ディスクだけのコピー" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM, ディスクコピー" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM コピー" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "リモートコピー" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "モジュールを停止: " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "停止するモジュールを選択" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "モジュールを開始: " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "{モジュール, [オプション]}のリストを入力してください" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "起動モジュールの一覧" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "ファイルにバックアップ: " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "バックアップファイルのパスを入力してください" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "ファイルのパス" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "ファイルからバックアップをリストア: " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "テキストファイルにバックアップ: " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "テキストファイルのパスを入力してください" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "ファイルからユーザーをインポート: " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "jabberd14 spool ファイルのパスを入力してください" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "ディレクトリからユーザーをインポート: " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "jabberd14 spool ディレクトリのディレクトリを入力してください" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "ディレクトリのパス" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "遅延時間" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "アクセスコントロールリスト設定" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "アクセスコントロールリスト" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "アクセス設定" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "アクセスルール" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "パスワード (確認)" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "登録ユーザー数" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "オンラインユーザー数" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "最終ログイン" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "名簿サイズ" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP アドレス" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "リソース" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "管理: " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "ユーザー操作" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "プロパティを編集" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" -msgstr "~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。" +msgstr "" +"~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "このIPアドレスはアクセスを禁止されています ~s" @@ -937,483 +935,515 @@ msgstr "サーバーのエンコーディング ~b" msgid "Server ~b" msgstr "サーバー ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "チャットルーム" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "ニックネームを登録するには x:data をサポートするクライアントが必要です" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "ニックネーム登録: " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "登録するニックネームを入力してください" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "ニックネーム" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUCモジュール" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "チャットルーム" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "がチャットルームから退出しました" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "登録ユーザー" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "チャットルームの設定が変更されました" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "がチャットルームに参加しました" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "がチャットルームから退出しました" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "はバンされました" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "は分掌が変更されたためキックされました" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "はチャットルームがメンバー制に変更されたためキックされました" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "はシステムシャットダウンのためキックされました" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "は名前を変更しました: " -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " は件名を設定しました: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "チャットルームを作りました" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "チャットルームを終了しました" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "チャットルームを開始しました" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "チャットルームを停止しました" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "月曜日" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "火曜日" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "水曜日" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "木曜日" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "金曜日" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "土曜日" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "日曜日" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "1月" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "2月" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "3月" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "4月" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "5月" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "6月" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "7月" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "8月" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "9月" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "10月" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "11月" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "12月" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "チャットルームの設定" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "在室者" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "モデレーターと参加者のみがチャットルームの件名を変更できます" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "モデレーターのみがチャットルームの件名を変更できます" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "このチャットルームは非匿名です" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s は無効です" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "ニックネーム ~s はこのチャットルームにいません" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "無効な分掌です: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "無効な役です: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "チャットルーム ~s の設定" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "チャットルームのタイトル" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "チャットルームの説明" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "チャットルームを永続化" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "チャットルームを検索可" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "参加者一覧を公開" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "チャットルームをパスワードで保護" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "最大在室者数" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "制限なし" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "本当の Jabber ID を公開" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "モデレーターにのみ" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "誰にでも" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "チャットルームをメンバーのみに制限" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "チャットルームをモデレート化" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "デフォルトのユーザーは参加者" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "ユーザーによる件名の変更を許可" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "ユーザーによるプライベートメッセージの送信を許可" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "傍聴者によるプライベートメッセージの送信を次の相手に許可" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "誰にも許可しない" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "ユーザーによる他のユーザーへのクエリーを許可" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "ユーザーによる招待を許可" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "傍聴者によるプレゼンス更新のステータス文の送信を許可" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "傍聴者のニックネームの変更を許可" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "傍聴者による発言権の要求を許可" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "発言権の要求の最小時間間隔 (秒)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "チャットルームを CAPTCHA で保護" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA 試験を免除する Jabber ID" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "ロギングを有効" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "チャットルームを設定するには x:data をサポートするクライアントが必要です" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "在室者の数" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "プライベート、" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "発言権を要求" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "発言権の要求を承認または却下します。" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "ユーザー JID" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "この人に発言権を与えますか ?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s はあなたをチャットルーム ~s に招待しています" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "パスワードは" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s' のオフラインメッセージキュー" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "時間" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "差出人" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "宛先" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "パケット" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "オフラインメッセージ:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "すべてのオフラインメッセージを削除" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams モジュール" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe モジュール" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub 購読者のリクエスト" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "このエントリを承認するかどうかを選択してください" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ノードID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "購読者のアドレス" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "この Jabber ID に、この pubsubノードの購読を許可しますか ?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "イベント通知と同時にペイロードを配送する" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "イベント通知を配送する" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "ノード設定に変更があった時に購読者へ通知する" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "ノードが削除された時に購読者へ通知する" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "アイテムがノードから消された時に購読者へ通知する" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "アイテムをストレージに保存する" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "ノードのフレンドリネーム" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "アイテムの最大保存数" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "購読を許可するかどうか" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "アクセスモデルを設定する" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "名簿グループは購読を許可しました" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "公開モデルを指定する" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "公開者がオフラインになるときに、すべてのアイテムを削除" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "イベントメッセージ種別を設定" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "最大ぺイロードサイズ (byte)" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "最後の公開アイテムを送信するタイミングで" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "有効なユーザーにのみ告知を送信する" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "提携されたノードの集合です" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "登録を行うには x:data と CAPTCHA をサポートするクライアントが必要です" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "サーバーに登録するユーザー名とパスワードを選択してください" @@ -1449,7 +1479,7 @@ msgstr "Jabber アカウント登録" msgid "Register a Jabber account" msgstr "Jabber アカウントを登録" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Jabber アカウントを削除" @@ -1463,7 +1493,7 @@ msgstr "" "(JabberID) は username@server のような形式になります。注意事項どおり、正しく" "項目を記入してください。" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "ユーザー名:" @@ -1476,11 +1506,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "使用できない文字:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "サーバー:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1488,11 +1518,11 @@ msgstr "" "パスワードは誰にも教えないようにしてください。Jabber サーバーの管理者があなた" "にパスワードを尋ねることはありません。" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "あなたは後で Jabber クライアントを使用してパスワードを変更できます。" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1500,7 +1530,7 @@ msgstr "" "Jabber クライアントはコンピューターにパスワードを記憶できます。コンピューター" "が安全であると信頼できる場合にのみ、この機能を使用してください。" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1510,158 +1540,165 @@ msgstr "" "パスワードを忘れてしまった場合、Jabber ではパスワードのリカバリを自動的に行う" "ことはできません。" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "パスワード (確認):" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "登録" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "古いパスワード:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "新しいパスワード:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "ここはこの Jabber サーバーのアカウントを削除するページです。" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "削除" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "認可" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "保留" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "グループ" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "検証" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "削除" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "名簿: " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Jabber ID を追加" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "名簿" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "共有名簿グループ" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "名前:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "説明:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "メンバー:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "表示グループ" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "グループ" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "誕生日" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "都道府県" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "国" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "メールアドレス" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "姓" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "" -"項目を入力してユーザーを検索を行えます (* を使用すると部分文字列にマッチします)" +"項目を入力してユーザーを検索を行えます (* を使用すると部分文字列にマッチしま" +"す)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "氏名" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "ミドルネーム" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "会社名" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "部署名" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "ユーザーの検索: " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "検索を行うためには x:data をサポートするクライアントが必要です" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard検索" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard モジュール" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "検索結果: " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "項目を入力してユーザーを検索してください" +#~ msgid "Delete" +#~ msgstr "削除" + +#~ msgid "This room is not anonymous" +#~ msgstr "このチャットルームは非匿名です" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "あなたのプライバシーリストはこのスタンザのルーティングを拒否しました。" diff --git a/priv/msgs/nl.po b/priv/msgs/nl.po index 05e423523bc..22f02d0d8bd 100644 --- a/priv/msgs/nl.po +++ b/priv/msgs/nl.po @@ -12,340 +12,341 @@ msgstr "" "X-Language: Dutch (nederlands)\n" "X-Additional-Translator: Sander Devrieze\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Gebruik van STARTTLS is vereist" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Geen bron opgegeven" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Vervangen door een nieuwe verbinding" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "werd gekicked" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Voer de getoonde tekst in" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Uw berichten aan ~s worden geblokkeerd. Om ze te deblokkeren, ga naar ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Als U het CAPTCHA-plaatje niet ziet, bezoek dan de webpagina." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA webpagina." -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "De geautomatiseerde Turing-test is geslaagd." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Niet geautoriseerd" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Webbeheer" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Beheer" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Access control lists" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Verzonden" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Slecht formaat" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Verzenden" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Ruw" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Geselecteerde verwijderen" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Access rules" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Access rules op ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtuele hosts" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Gebruikers" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Online gebruikers" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Laatste activiteit van gebruikers" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periode: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Afgelopen maand" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Afgelopen jaar" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Alle activiteit" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Deel van tabel laten zien" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Volledige tabel laten zien" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistieken" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Niet gevonden" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Node niet gevonden" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Toevoegen" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Geregistreerde gebruikers" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Gebruiker" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Wachtwoord" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Gebruiker toevoegen" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Offline berichten" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Laatste activiteit" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nooit" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Geregistreerde gebruikers:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Online gebruikers:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Uitgaande s2s-verbindingen:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Uitgaande s2s-verbindingen:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Geen" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Wachtwoord wijzigen" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Gebruiker " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Verbonden bronnen:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Wachtwoord:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Gebruiker verwijderen" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Geen gegevens" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodes" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Draaiende nodes" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Gestopte nodes" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Node " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Backup" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Openstaande poorten" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Bijwerken" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Herstarten" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Stoppen" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "RPC-oproepfout" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Databasetabellen van " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Naam" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Opslagmethode" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementen" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Geheugen" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Fout" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Backup maken van " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -355,491 +356,487 @@ msgstr "" "Mnesia. Als U de ODBC module gebruikt dan moeten daarvan afzonderlijke " "backups gemaakt worden." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Binaire backup maken:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Binaire backup direct herstellen:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Binaire backup herstellen na herstart van ejabberd (vereist minder geheugen):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Backup naar een tekstbestand schrijven:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Backup in een tekstbestand direct herstellen:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importeer gebruikersdata van een PIEFXIS-bestand (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exporteer data van alle gebruikers in de server naar PIEFXIS-bestanden " "(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exporteer data van alle gebruikers van een host naar PIEXFIS-bestanden " "(XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importeer gebruikersdata via spool-bestanden van jabberd14" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importeer gebruikersdata via spool-bestanden van jabberd14" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Openstaande poorten op " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Modules op " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistieken van ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Processortijd:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Bevestigde transacties:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Afgebroken transacties:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Herstarte transacties:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Gelogde transacties:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Opwaarderen van " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plan voor de opwaardering" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Gewijzigde modules" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script voor de opwaardering" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Lowlevel script voor de opwaardering" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Controle van script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Poort" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opties" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Verwijderen" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Starten" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Commando's" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Wilt u het bericht van de dag verwijderen?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Onderwerp" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Bericht" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "De mededeling bevat geen bericht" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Mededelingen" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Mededeling verzenden naar alle gebruikers" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Stuur aankondiging aan alle gebruikers op alle hosts" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Mededeling verzenden naar alle online gebruikers" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Mededeling verzenden naar alle online gebruikers op alle virtuele hosts" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Bericht van de dag instellen en verzenden naar online gebruikers" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Stel bericht-van-de-dag in op alle hosts en stuur naar aanwezige gebruikers" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Bericht van de dag bijwerken (niet verzenden)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Verander bericht-van-de-dag op alle hosts (niet versturen)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Bericht van de dag verwijderen" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Verwijder bericht-van-de-dag op alle hosts" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Instellingen" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Modules starten" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Modules stoppen" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Binaire backup direct herstellen" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Backup naar een tekstbestand schrijven" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Bestand importeren" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Directory importeren" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Herstart Service" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Stop Service" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Verwijder Gebruiker" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Verwijder Gebruikers-sessie" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Gebruikerswachtwoord Opvragen" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Verander Gebruikerswachtwoord" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Tijd van Laatste Aanmelding Opvragen" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Gebruikers-statistieken Opvragen" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Aantal Geregistreerde Gebruikers Opvragen" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Aantal Aanwezige Gebruikers Opvragen" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gebruikersbeheer" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Alle gebruikers" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Uitgaande s2s-verbindingen" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Backup" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importeer gebruikers via spool-bestanden van jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Naar ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Van ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Instellingen van databasetabellen op " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Opslagmethode voor tabellen kiezen" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Harde schijf" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM en harde schijf" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Op andere nodes in de cluster" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Modules stoppen op " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecteer de modules die u wilt stoppen" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Modules starten op " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Voer lijst met op te starten modules als volgt in: {Module, [Opties]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lijst met op te starten modules" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Binaire backup maken op " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Voer pad naar backupbestand in" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Pad naar bestand" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Binaire backup direct herstellen op " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Backup naar een tekstbestand schrijven op " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Voer pad naar backupbestand in" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importeer gebruiker via bestand op " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Voer pad naar jabberd14-spool-bestand in" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Gebruikers importeren vanaf directory op " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Voer pad naar jabberd14-spool-directory in" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Pad naar directory" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Vertraging" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Instellingen van access control lists" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Access control lists" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Toegangsinstellingen" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Access rules" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Wachtwoord Bevestiging" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Aantal Geregistreerde Gebruikers" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Aantal Aanwezige Gebruikers" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Laatste Aanmelding" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Contactlijst Groote" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP-adres" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Bronnen" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Beheer van " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Actie op gebruiker" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Eigenschappen bewerken" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -951,171 +948,195 @@ msgstr "Karakterset voor server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Groepsgesprekken" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "U hebt een client nodig die x:data ondersteunt om een bijnaam te registreren" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registratie van een bijnaam op " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Voer de bijnaam in die u wilt registreren" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Bijnaam" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd's MUC module" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Groepsgesprekken" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "verliet de chatruimte" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Geregistreerde gebruikers" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "De instellingen van de chatruimte werden veranderd" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "betrad de chatruimte" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "verliet de chatruimte" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "werd verbannen" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "is weggestuurd vanwege een affiliatieverandering" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" "is weggestuurd omdat de chatruimte vanaf heden alleen toegankelijk is voor " "leden" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "is weggestuurd omdat het systeem gestopt wordt" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "heet nu" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " veranderde het onderwerp in: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Gespreksruimte gecreëerd" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Gespreksruimte vernietigd" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Gespreksruimte gestart" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Gespreksruimte gestopt" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Maandag" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Dinsdag" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Woensdag" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Donderdag" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Vrijdag" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Zaterdag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Zondag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Januari" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Februari" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Maart" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "April" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Mei" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Augustus" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "September" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "November" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "December" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Instellingen van de chatruimte" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1123,319 +1144,327 @@ msgstr "" "Alleen moderators en deelnemers mogen het onderwerp van deze chatruimte " "veranderen" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Alleen moderators mogen het onderwerp van deze chatruimte veranderen" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Deze chatruimte is niet anoniem" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "De Jabber ID ~s is ongeldig" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "De bijnaam ~s bestaat niet in deze chatruimte" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Ongeldige affiliatie: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Ongeldige rol: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Instellingen van chatruimte ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Naam van de chatruimte" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Beschrijving" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Chatruimte blijvend maken" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Chatruimte doorzoekbaar maken" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Deelnemerslijst publiek maken" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Chatruimte beveiligen met een wachtwoord" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Maximum aantal aanwezigen" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Geen limiet" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Jabber ID's kunnen achterhaald worden door" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "moderators" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "iedereen" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Chatruimte enkel toegankelijk maken voor leden" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Chatruimte gemodereerd maken" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Gebruikers standaard instellen als deelnemers" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Sta gebruikers toe het onderwerp te veranderen" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Gebruikers mogen privéberichten verzenden" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Gebruikers mogen privéberichten verzenden aan" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "niemand" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Gebruikers mogen naar andere gebruikers verzoeken verzenden" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Gebruikers mogen uitnodigingen verzenden" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Sta bezoekers toe hun statusbericht in te stellen" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Sta bezoekers toe hun naam te veranderen" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Gebruikers mogen stemaanvragen verzenden" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimale interval tussen stemaanvragen (in seconden)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Chatruimte beveiligen met een geautomatiseerde Turing test" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Geen CAPTCHA test voor Jabber IDs" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Logs aanzetten" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "U hebt een client nodig die x:data ondersteunt om deze chatruimte in te " "stellen" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Stemaanvraag" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Keur stemaanvraag goed of af." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "JID Gebruiker" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Stemaanvraag honoreren voor deze persoon?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s nodigt je uit voor het groepsgesprek ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "het wachtwoord is" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "offline berichten van ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Tijd" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Van" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Aan" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pakket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Offline berichten:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Verwijder alle offline berichten" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe module" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub abonnee verzoek" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Beslis of dit verzoek tot abonneren zal worden goedgekeurd" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Node ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Abonnee Adres" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Deze gebruiker toestaan te abonneren op deze pubsub node?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Berichten bezorgen samen met gebeurtenisnotificaties" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Gebeurtenisbevestigingen Sturen" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Abonnees informeren wanneer de instellingen van de node veranderen" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Abonnees informeren wanneer de node verwijderd word" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Abonnees informeren wanneer items verwijderd worden uit de node" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Items in het geheugen bewaren" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Bijnaam voor deze knoop" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Maximum aantal in het geheugen te bewaren items" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Abonnementsaanvraag toestaan" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Geef toegangsmodel" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Contactlijst-groepen die mogen abonneren" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Publicatietype opgeven" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Verwijder alle items wanneer de gerelateerde publiceerder offline gaat" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Geef type van eventbericht" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Maximumgrootte van bericht in bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Wanneer het laatst gepubliceerde item verzonden moet worden" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Notificaties alleen verzenden naar online gebruikers" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "De collecties waar een node mee is gerelateerd" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "U hebt een client nodig die x:data en CAPTCHA ondersteunt om een bijnaam te " "registreren" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Kies een gebruikersnaam en een wachtwoord om u te registreren op deze server" @@ -1472,7 +1501,7 @@ msgstr "Jabber-account registratie" msgid "Register a Jabber account" msgstr "Registreer een Jabber-account" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Opheffen van Jabber-account" @@ -1487,7 +1516,7 @@ msgstr "" "gebruikersnaam@server. Lees de instructies zorgvuldig teneinde de velden " "correct in te vullen." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Gebruikersnaam:" @@ -1500,11 +1529,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Niet-toegestane karakters:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1512,11 +1541,11 @@ msgstr "" "Geef Uw wachtwoord aan niemand, zelfs niet aan de beheerders van deze Jabber-" "server." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "U can het wachtwoord later veranderen met een Jabber-client." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1525,7 +1554,7 @@ msgstr "" "Gebruik deze mogelijkheid alleen als U vertrouwd dat Uw computer afdoende " "beveiligd is." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1535,114 +1564,114 @@ msgstr "" "plaats. Met Jabber is er geen geautomatiseerde manier om het wachtwoord " "terug te halen als U het vergeet." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Wachtwoord Bevestiging:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Registreer" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Oud Wachtwoord:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nieuw Wachtwoord:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Deze pagina maakt het mogelijk een Jabber-account op deze server op te " "heffen." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Opheffen" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Inschrijving" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Bezig" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Groepen" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Bevestigen" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Verwijderen" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Roster van " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Jabber ID toevoegen" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Roster" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Gedeelde rostergroepen" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Naam:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Beschrijving:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Groepsleden:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Weergegeven groepen:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Groep " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Geboortedatum" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Plaats" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Achternaam" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1650,46 +1679,52 @@ msgstr "" "Gebruik de velden om te zoeken (Voeg achteraan het teken * toe om te zoeken " "naar alles wat met het eerste deel begint.)." -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Volledige naam" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Tussennaam" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisatie" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Afdeling" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Gebruikers zoeken in " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "U hebt een client nodig die x:data ondersteunt om te zoeken" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Gebruikers zoeken" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd's vCard-module" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Zoekresultaten voor " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Vul de velden in om te zoeken naar Jabber-gebruikers op deze server" +#~ msgid "Delete" +#~ msgstr "Verwijderen" + +#~ msgid "This room is not anonymous" +#~ msgstr "Deze chatruimte is niet anoniem" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Uw actieve privacy-lijst verbied het routeren van dit stanza." diff --git a/priv/msgs/no.po b/priv/msgs/no.po index 6d47c65404a..3e83bd90dd4 100644 --- a/priv/msgs/no.po +++ b/priv/msgs/no.po @@ -11,339 +11,340 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Norwegian (bokmål)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Bruk av STARTTLS kreves" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Ingen ressurs angitt" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Erstattet av en ny tilkobling" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "har blitt kastet ut" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Skriv inn teksten du ser" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Dine meldinger til ~s blir blokkert. For å åpne igjen, besøk ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Dersom du ikke ser CAPTCHA bilde her, besøk web siden. " -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA web side" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Captchaen er ikke gyldig" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Uautorisert" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administrasjon" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Tilgangskontrollister" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Innsendt" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Feil format" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Send" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Rå" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Slett valgte" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Tilgangsregler" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "tilgangsregel konfigurasjon for ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtuella Maskiner" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Brukere" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Tilkoblede Brukere" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Brukers Siste Aktivitet" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periode: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Siste måned" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Siste året" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "All aktivitet" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Vis Ordinær Tabell" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Vis Integral Tabell" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistikk" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Finnes Ikke" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Noden finnes ikke" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Legg til ny" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Maskin" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Registrerte Brukere" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Bruker" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Passord" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Legg til Bruker" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Frakoblede Meldinger" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Siste Aktivitet" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Aldri" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Tilkoblet" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Registrerte Brukere:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Tilkoblede Brukere:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Utgående s2s Koblinger" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Utgående s2s Tjenere" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Ingen" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Endre Passord" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Bruker " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Tilkoblede Ressurser:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Passord:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Fjern Bruker" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Ingen Data" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Noder" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Kjørende Noder" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Stoppede Noder" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Node " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sikkerhetskopier" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Lyttende Porter" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Oppdatere" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Starte på nytt" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Stoppe" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduler" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "RPC Kall Feil" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Database Tabeller på " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Navn" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Lagringstype" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementer" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Minne" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Feil" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Sikkerhetskopi av " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -353,485 +354,481 @@ msgstr "" "databasen. Dersom du bruker ODBC modulen må du også ta backup av din SQL " "database." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Lagre binær sikkerhetskopi:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Gjenopprette binær backup umiddelbart:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Gjenopprette binær backup etter neste ejabberd omstart (krever mindre minne):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Lagre rentekst sikkerhetskopi:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Gjenopprette rentekst sikkerhetskopi umiddelbart:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importer brukeres data fra en PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "Eksporter data om alle brukere i en server til PIEFXIS filer" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Eksporter data om alle brukere i en host til PIEFXIS filer (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importer bruker data fra jabberd14 spoolfiler:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importer brukeres data fra jabberd14 spoolfil katalog:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Lyttende Porter på " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduler på " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistikk for ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Oppetid:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "CPU Tid:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Sendte Transaksjoner:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Avbrutte Transasksjoner:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Omstartede Transasksjoner:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Loggede Transasksjoner:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Oppdater " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Oppdaterings plan" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Endrede moduler" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Oppdaterings skript" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Lavnivå oppdaterings skript" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Skript sjekk" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokoll" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Alternativer" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Slett" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Start" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Kommandoer" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Virkelig slette melding for dagen?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Tittel" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Meldingskropp" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Ingen meldingskropp gitt for kunngjørings melding" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Kunngjøringer" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Send kunngjøring til alle brukere" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Send kunngjøring til alle brukere på alle maskiner" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Send kunngjøring alle tilkoblede brukere" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Send kunngjøring til alle tilkoblede brukere på alle " -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Angi melding for dagen og send til tilkoblede brukere" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "Angi melding for dagen på alle maskiner og send til " -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Oppdater melding for dagen (ikke send)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Oppdater melding for dagen på alle maskiner (ikke send)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Slett melding for dagen" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Slett melding for dagen på alle maskiner" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Konfigurasjon" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Start Moduler" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Stop Moduler" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Gjenopprett" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Dump til Tekstfil" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importer File" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importer Katalog" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Start Tjeneste på Nytt" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Avslutt Tjeneste" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Slett Bruker" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Avslutt Bruker Sesjon" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Hent Brukers Passord" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Endre Brukers Passord" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Vis Brukers Siste Påloggings Tidspunkt" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Vis Bruker Statistikk" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Vis Antall Registrerte Brukere" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Vis Antall Tilkoblede Brukere" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Bruker Behandling" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Alle Brukere" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Utgående s2s Koblinger" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Håndtere Sikkerehetskopiering" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importer Brukere Fra jabberd14 Spoolfiler" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Til ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Fra ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Database Tabell Konfigurasjon på " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Velg lagringstype for tabeller" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Kun diskkopi" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM og diskkopi" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM kopi" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Lagres ikke lokalt" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Stopp Moduler på " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Velg hvilke moduler som skal stoppes" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Start Moduler på " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Skriv inn en liste av {Module, [Options]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Liste over moduler som skal startes" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Sikkerhetskopiere til Fil på " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Skriv inn sti til sikkerhetskopi filen" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Sti til Fil" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Gjenopprett fra Sikkerhetsopifil på " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Dump Sikkerhetskopi til Tekstfil på " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Skriv inn sti til tekstfil" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importer Bruker fra Fil på " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Skriv inn sti til jabberd14 spoolfil" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importer Brukere fra Katalog på " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Skriv inn sti til jabberd14 spoolkatalog" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Sti til Katalog" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Tids forsinkelse" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurasjon for Tilgangskontroll lister" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Tilgangskontroll lister" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Tilgangskonfigurasjon" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Tilgangsregler" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Passord Bekreftelse" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Antall registrerte brukere" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Antall tilkoblede brukere" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Siste pålogging" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Kontaktliste størrelse" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP adresser" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Ressurser" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administrasjon av " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Handling på bruker" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Redigere Egenskaper" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -941,483 +938,515 @@ msgstr "Tekstkoding for server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Samtalerom" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Du trenger en klient som støtter x:data for å registrere kallenavnet" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registrer Kallenavn på " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Skriv inn kallenavnet du ønsker å registrere" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Kallenavn" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Samtalerom" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "forlater rommet" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Registrerte Brukere" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Samtalerommets konfigurasjon er endret" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "kommer inn i rommet" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "forlater rommet" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "har blitt bannlyst" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "har blitt kastet ut på grunn av en tilknytnings endring" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" "har blitt kastet ut på grunn av at rommet er endret til kun-for-medlemmer" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "har blitt kastet ut på grunn av at systemet avslutter" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "er nå kjent som" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " har satt emnet til: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Samtalerom er opprettet" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Samtalerom er fjernet" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Samtalerom er startet" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Samtalerom er stoppet" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "mandag" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "tirsdag" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "onsdag" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "torsdag" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "fredag" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "lørdag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "søndag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "januar" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "februar" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "mars" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "april" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "mai" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "juni" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "juli" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "august" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "september" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "oktober" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "november" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "desember" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Rom Konfigurasjon" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Samtalerom Deltakere" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Bare redaktører og deltakere kan endre emnet i dette rommet" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Bare ordstyrer tillates å endre emnet i dette rommet" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Dette rommet er ikke anonymt" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Ugyldig Jabber ID ~s" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Kallenavn ~s eksisterer ikke i dette rommet" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Ugyldig rang: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Ugyldig rolle: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Konfigurasjon for rom ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Romtittel" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Rom beskrivelse" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Gjør rommet permanent" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Gjør rommet offentlig søkbart" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Gjør deltakerlisten offentlig" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Passordbeskytt rommet" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Maksimum Antall Deltakere" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Ingen grense" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Presenter ekte Jabber IDer til" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "kun for redaktører" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "hvem som helst" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Gjør rommet tilgjengelig kun for medlemmer" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Gjør rommet redaktørstyrt" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Standard brukere som deltakere" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Tillat brukere å endre emne" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Tillat brukere å sende private meldinger" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Tillat brukere å sende private meldinger til" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "ingen" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Tillat brukere å sende forespørsel til andre brukere" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Tillat brukere å sende invitasjoner" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Tillat besøkende å sende status tekst i " -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Tillat besøkende å endre kallenavn" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Tillat brukere å sende lyd forespørsler" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimums interval mellom lyd forespørsler (i sekunder)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Gjør rommet CAPTCHA beskyttet" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Ekskluder Jabber IDer fra CAPTCHA utfordring" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Slå på logging" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Du trenger en klient som støtter x:data for å " -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Antall deltakere" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Lyd forespørsel" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Enten godkjenn eller forby lyd forespørselen" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Bruker JID" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Gi lyd til denne personen?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s inviterer deg til rommet ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "passordet er" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~ss kø for Frakoblede Meldinger" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Tid" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Fra" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Til" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pakke" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Frakoblede Meldinger:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Fjern Alle Frakoblede Meldinger" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub abonements forespørsel" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Velg om du vil godkjenne denne eksistensens abonement" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Node ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Abonnements Adresse" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Tillat denne Jabber ID å abonnere på denne pubsub " -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Send innhold sammen med kunngjøringer" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Lever begivenhets kunngjøringer" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Informer abonnenter når node konfigurasjonen endres" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Informer abonnenter når noden slettes" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Informer abonnenter når elementer fjernes fra noden" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Vedvarende elementer til lagring" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Et vennlig navn for noden" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Høyeste # elementer som skal lagres" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Om man skal tillate abonnenter" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Spesifiser aksess modellen" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Kontaktliste grupper som tillates å abonnere" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Angi publiserings modell" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Rydd alle elementer når den aktuelle utgiveren logger av" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Spesifiser hendelsesbeskjed type" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Største innholdsstørrelse i byte" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Når skal siste publiserte artikkel sendes" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Send kunngjøringer bare til tilgjengelige brukere" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Samlingene som en node er assosiert med" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Du trenger en klient som støtter x:data og CAPTCHA for registrering " -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Velg et brukernavn og passord for å registrere på " @@ -1453,7 +1482,7 @@ msgstr "Jabber Konto Registrering" msgid "Register a Jabber account" msgstr "Registrer en Jabber konto" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Avregistrer en Jabber konto" @@ -1467,7 +1496,7 @@ msgstr "" "(Jabber ID) vil være i formatet: brukernavn@server. Vennligst les " "instruksjonene nøye slik at du fyller ut skjemaet riktig." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Brukernavn:" @@ -1481,11 +1510,11 @@ msgstr "" msgid "Characters not allowed:" msgstr "Ikke godtatte tegn:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Server:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1493,11 +1522,11 @@ msgstr "" "Ikke fortell passordet til noen, ikke en gang til administratoren av Jabber " "serveren." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Du kan når som helst endre passordet via en Jabber klient." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1505,7 +1534,7 @@ msgstr "" "Noen Jabber klienter kan lagre passordet på datamaskinen. Bruk bare den " "funksjonen dersom du er sikker på at maskinen er trygg." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1515,113 +1544,113 @@ msgstr "" "Jabber er det ingen automatisert måte å gjenskape passordet om du glemmer " "det. " -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Passord Bekreftelse:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Registrer" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Gammelt Passord:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nytt Passord:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Denne siden lar deg avregistrere en Jabber konto på denne Jabber serveren." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Avregistrer" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Abonnement" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Ventende" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupper" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Bekrefte gyldighet" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Fjern" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Kontaktliste for " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Legg til Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Kontaktliste" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Delte Kontaktgrupper" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Navn:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Beskrivelse:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Medlemmer:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Viste grupper:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Gruppe " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Fødselsdag" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "By" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Epost" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Etternavn" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1629,46 +1658,52 @@ msgstr "" "Fyll inn skjemaet for å søke etter Jabber bruker (Legg til * på slutten av " "feltet for å treffe alle som starter slik)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Fullstendig Navn" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Mellomnavn" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisasjonsnavn" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organisasjonsenhet" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Søk etter brukere i " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Du tregner en klient som støtter x:data for å kunne " -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Bruker Søk" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modul" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Søke Resultater for " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Fyll inn felt for å søke etter Jabber brukere" +#~ msgid "Delete" +#~ msgstr "Slett" + +#~ msgid "This room is not anonymous" +#~ msgstr "Dette rommet er ikke anonymt" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Din aktive privat liste har blokkert rutingen av denne strofen." diff --git a/priv/msgs/pl.po b/priv/msgs/pl.po index 46c9f741fbe..b62633fbfaf 100644 --- a/priv/msgs/pl.po +++ b/priv/msgs/pl.po @@ -15,339 +15,340 @@ msgstr "" "X-Additional-Translator: Andrzej Smyk\n" "X-Additional-Translator: Mateusz Gajewski\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Wymagane jest użycie STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Nie podano zasobu" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Połączenie zostało zastąpione" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "został wyrzucony" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Przepisz tekst z obrazka" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Twoje wiadomości do ~s są blokowane. Aby je odblokować, odwiedź ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Jeśli nie widzisz obrazka CAPTCHA, odwiedź stronę internetową." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Strona internetowa CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Captcha jest poprawna." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Nie autoryzowano" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd: Panel Administracyjny" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administracja" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Lista dostępowa" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Wprowadzone" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Błędny format" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Wyślij" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Żródło" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Usuń zaznaczone" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Zasady dostępu" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s konfiguracja zasad dostępu" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Wirtualne Hosty" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Użytkownicy" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Użytkownicy zalogowani" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Ostatnia aktywność użytkowników" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Przedział czasu: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Miniony miesiąc" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Miniony rok" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Cała aktywność" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Pokaż zwykłą tabelę" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Pokaż tabelę całkowitą" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statystyki" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Nie znaleziono" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Węzeł nie został znaleziony" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Dodaj nowe" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Użytkownicy zarejestrowani" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Użytkownik" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Hasło" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Dodaj użytkownika" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Wiadomości offline" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Ostatnia aktywność" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nigdy" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Dostępny" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Użytkownicy zarejestrowani:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Użytkownicy zalogowani:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Wychodzące połączenia s2s:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Serwery zewnętrzne s2s:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Brak" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Zmień hasło" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Użytkownik " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Zasoby zalogowane:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Hasło:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Usuń użytkownika" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Brak danych" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Węzły" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Uruchomione węzły" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zatrzymane węzły" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Węzeł " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Baza danych" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Wykonaj kopie" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Porty nasłuchujące" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Aktualizuj" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Uruchom ponownie" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Zatrzymaj" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduły" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Błąd żądania RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabele bazy na " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Imię" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Typ bazy" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementy" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Pamięć" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Błąd" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Kopia zapasowa " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -357,493 +358,489 @@ msgstr "" "Jeśli korzystasz z modułu ODBC, musisz wykonać kopie bazy we własnym " "zakresie." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Zachowaj kopię binarną:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Natychmiast odtwórz kopię binarną:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Odtwórz kopię binarną podczas następnego uruchomienia ejabberd (wymaga mniej " "zasobów):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Zachowaj kopię w postaci tekstowej:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Natychmiast odtwórz kopię z postaci tekstowej:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importuj dane użytkowników z pliku w formacie PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Eksportuj dane wszystkich użytkowników serwera do plików w formacie PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Eksportuj dane użytkowników z hosta do plików w formacie PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importuj dane użytkownika z pliku roboczego serwera jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importuj użytkowników z katalogu roboczego serwera jabberd14" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Porty nasłuchujące na " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduły na " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statystyki ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Czas pracy:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Czas CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transakcje zakończone:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transakcje anulowane:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transakcje uruchomione ponownie:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transakcje zalogowane:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Uaktualnij " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plan aktualizacji" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Zmodyfikowane moduły" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Skrypt aktualizacji" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Skrypt aktualizacji niskiego poziomu" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Sprawdź skrypt" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokół" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Moduł" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opcje" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Usuń" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Uruchom" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Polecenia" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Na pewno usunąć wiadomość dnia?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Temat" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Treść wiadomości" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Brak treści powiadomienia" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Powiadomienia" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Wyślij powiadomienie do wszystkich użytkowników" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Wyślij powiadomienie do wszystkich użytkowników na wszystkich hostach" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Wyślij powiadomienie do wszystkich zalogowanych użytkowników" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Wyślij powiadomienie do wszystkich zalogowanych użytkowników na wszystkich " "hostach" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Wyślij wiadomość dnia do wszystkich zalogowanych użytkowników" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Ustaw wiadomość dnia dla wszystkich hostów i wyślij do zalogowanych " "uzytkowników" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Aktualizuj wiadomość dnia (bez wysyłania)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Aktualizuj wiadomość dnia na wszystkich hostach (bez wysyłania)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Usuń wiadomość dnia" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Usuń wiadomość dnia ze wszystkich hostów" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Konfiguracja" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Uruchom moduły" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Zatrzymaj moduły" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Przywróć z kopii" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Wykonaj kopie do pliku tekstowego" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importuj plik" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importuj katalog" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Restart usługi" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Wyłącz usługę" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Usuń użytkownika" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Zakończ sesję uzytkownika" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Pobierz hasło użytkownika" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Zmień hasło użytkownika" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Pokaż czas ostatniego zalogowania uzytkownika" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Pobierz statystyki użytkownika" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Pokaż liczbę zarejestrowanych użytkowników" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Pokaż liczbę zalogowanych użytkowników" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Zarządzanie użytkownikami" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Wszyscy użytkownicy" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Wychodzące połączenia s2s" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Zarządzanie kopiami zapasowymi" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importuj użytkowników z plików roboczych serwera jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Do ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Od ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Konfiguracja tabel bazy na " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Wybierz typ bazy dla tablel" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Kopia tylko na dysku" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Kopia na dysku i w pamięci RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Kopia w pamięci RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Kopia zdalna" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Zatrzymaj moduły na " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Wybierz moduły do zatrzymania" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Uruchom moduły na " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Wprowadź listę {Moduł, [Opcje]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista modułów do uruchomienia" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Zapisz kopię w pliku na " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Wprowadź scieżkę do pliku kopii zapasowej" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Scieżka do pliku" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Odtwórz bazę danych z kopii zapasowej na " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Zapisz kopię zapasową w pliku tekstowym na " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Wprowadź scieżkę do pliku tekstowego" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importuj użytkownika z pliku na " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Wprowadź ścieżkę do roboczego pliku serwera jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importuj użytkowników z katalogu na " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Wprowadź ścieżkę do roboczego katalogu serwera jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Ścieżka do katalogu" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Opóźnienie" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfiguracja listy dostępowej" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listy dostępowe" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Konfiguracja dostępu" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Reguły dostępu" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Weryfikacja hasła" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Liczba zarejestrowanych użytkowników" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Liczba zalogowanych użytkowników" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Ostatnie logowanie" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Rozmiar listy kontaktów" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Adresy IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Zasoby" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Zarządzanie " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Wykonaj na użytkowniku" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Edytuj właściwości" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -953,482 +950,514 @@ msgstr "Kodowanie znaków dla serwera ~b" msgid "Server ~b" msgstr "Serwer ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Pokoje rozmów" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Potrzebujesz klienta obsługującego x:data aby zarejestrować nick" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Rejestracja nazwy użytkownika na " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Wprowadz nazwę użytkownika którego chcesz zarejestrować" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nazwa użytkownika" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Moduł MUC" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Pokoje rozmów" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "opuszcza pokój" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Użytkownicy zarejestrowani" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Konfiguracja pokoju zmodyfikowana" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "dołącza do pokoju" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "opuszcza pokój" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "został wykluczony" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "został wyrzucony z powodu zmiany przynależności" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "został wyrzucony z powodu zmiany pokoju na \"Tylko dla Członków\"" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "został wyrzucony z powodu wyłączenia systemu" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "jest teraz znany jako" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " zmienił temat na: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Pokój został stworzony" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Pokój został usunięty" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Pokój został uruchomiony" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Pokój został zatrzymany" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Poniedziałek" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Wtorek" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Środa" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Czwartek" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Piątek" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sobota" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Niedziela" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Styczeń" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Luty" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Marzec" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Kwiecień" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Maj" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Czerwiec" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Lipiec" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Sierpień" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Wrzesień" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Październik" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Listopad" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Grudzień" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Konfiguracja pokoju" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Lista uczestników" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Tylko moderatorzy i uczestnicy mogą zmienić temat tego pokoju" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Tylko moderatorzy mogą zmienić temat tego pokoju" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Ten pokój nie jest anonimowy" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s jest niepoprawny" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Nie ma nicka ~s w tym pokoju" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Nieprawidłowa przynależność: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Nieprawidłowa rola: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Konfiguracja pokoju ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Tytuł pokoju" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Opis pokoju" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Utwórz pokój na stałe" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Pozwól wyszukiwać pokój" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Upublicznij listę uczestników" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Pokój zabezpieczony hasłem" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Maksymalna liczba uczestników" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Prawdziwe Jabber ID widoczne dla" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "tylko moderatorzy" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "wszystkich" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Pokój tylko dla członków" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Pokój moderowany" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Domyślni użytkownicy jako uczestnicy" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Pozwól użytkownikom zmieniać temat" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Pozwól użytkownikom wysyłać prywatne wiadomości" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Pozwól użytkownikom wysyłać prywatne wiadomości" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "nikt" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Pozwól użytkownikom pobierać informacje o innych użytkownikach" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Pozwól użytkownikom wysyłać zaproszenia" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Pozwól uczestnikom na wysyłanie statusów opisowych" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Pozwól uczestnikom na zmianę nicka" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Pozwól użytkownikom wysyłać zaproszenia" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimalny odstęp między żądaniami głosowymi (w sekundach)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Pokój zabezpieczony captchą" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Pomiń Jabber ID z żądania CAPTCHA" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Włącz logowanie" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Potrzebujesz klienta obsługującego x:data aby skonfigurować pokój" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Liczba uczestników" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "prywatny, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Żądanie głosowe" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Zatwierdź lub odrzuć żądanie głosowe" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Użytkownik " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Udzielić głosu tej osobie?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s zaprasza Cię do pokoju ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "hasło to:" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Kolejka wiadomości offline użytkownika ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Czas" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Od" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Do" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pakiet" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Wiadomości offline:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Usuń wszystkie wiadomości typu 'Offline'" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Moduł SOCKS5 Bytestreams" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "PubSub" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Moduł Publish-Subscribe" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Żądanie subskrybcji PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Wybierz, czy akceptować subskrypcję tej jednostki" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID węzła" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Adres subskrybenta" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Pozwól temu Jabber ID na zapisanie się do tego węzła PubSub" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Dostarczaj zawartość publikacji wraz z powiadomieniami o zdarzeniach" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Dostarczaj powiadomienia o zdarzeniach" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Informuj subskrybentów o zmianach konfiguracji węzła" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Informuj subskrybentów o usunięciu węzła" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Informuj subskrybentów o usunięciu elementów węzła" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Przechowuj na stałe dane PubSub" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Przyjazna nazwa węzła" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Maksymalna liczba przechowywanych przedmiotów" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Czy pozwolić na subskrypcje" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Określ model dostępu" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Grupy kontaktów uprawnione do subskrypcji" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Określ model publikującego" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Usuń wszystkie elementy w momencie kiedy publikujący rozłączy się" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Określ typ wiadomości" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Maksymalna wielkość powiadomienia w bajtach" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Kiedy wysłać ostatnio opublikowaną rzecz" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Dostarczaj powiadomienia tylko dostępnym użytkownikom" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Grupy, do których należy węzeł" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Potrzebujesz klienta obsługującego x:data aby zarejestrować nick" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Wybierz nazwę użytkownika i hasło aby zarejestrować się na tym serwerze" @@ -1465,7 +1494,7 @@ msgstr "Zakładanie konta Jabber" msgid "Register a Jabber account" msgstr "Załóż konto Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Usuń konto Jabber" @@ -1479,7 +1508,7 @@ msgstr "" "(Jabber IDentyfikator) będzie miał postać: nazwa_użytkownika@serwer. " "Przeczytaj dokładnie instrukcję i wypełnij pola." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Nazwa użytkownika:" @@ -1493,22 +1522,22 @@ msgstr "" msgid "Characters not allowed:" msgstr "Te znaki są niedozwolone:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Serwer:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" "Nie podawaj swojego hasła nikomu, nawet administratorowi serwera Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Możesz później zmienić swoje hasło za pomocą dowolnego klienta Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1516,7 +1545,7 @@ msgstr "" "Niektóre klienty Jabber mogą zapisywać Twoje hasło na komputerze. Używaj tej " "opcji tylko jeśli ufasz komputerowi na którym pracujesz." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1525,112 +1554,112 @@ msgstr "" "Zapamiętaj swoje hasło lub zapisz je na kartce i zachowaj w bezpiecznym " "miejscu. Na Jabberze nie ma zautomatyzowanego systemu odzyskiwania haseł." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Weryfikacja hasła:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Zarejestruj" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Stare hasło:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nowe hasło:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Ta strona pozwala usunąć konto Jabber z tego serwera." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Wyrejestruj" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Subskrypcja" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Oczekuje" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupy" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Potwierdź" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Usuń" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Lista kontaktów " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Dodaj Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Lista kontaktów" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Wspólne grupy kontaktów" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nazwa:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Opis:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Członkowie:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Wyświetlane grupy:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grupa " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Data urodzenia" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Miasto" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Państwo" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Nazwisko" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1638,46 +1667,52 @@ msgstr "" "Wypełnij formularz aby wyszukać użytkowników Jabbera (dodaj * na koniec " "zapytania aby wyszukać po fragmencie)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Pełna nazwa" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Drugie imię" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nazwa organizacji" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Dział" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Wyszukaj użytkowników w " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Potrzebujesz klienta obsługującego x:data aby wyszukiwać" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Wyszukiwanie vCard użytkowników" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Moduł vCard ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Wyniki wyszukiwania dla " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Wypełnij pola aby znaleźć pasujących użytkowników Jabbera" +#~ msgid "Delete" +#~ msgstr "Usuń" + +#~ msgid "This room is not anonymous" +#~ msgstr "Ten pokój nie jest anonimowy" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Aktualna lista prywatności zabrania przesyłania tej stanzy" diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index 04f201b1e1b..1121c6e0bc6 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -11,340 +11,341 @@ msgstr "" "X-Additional-Translator: Felipe Brito Vasconcellos\n" "X-Additional-Translator: Victor Hugo dos Santos\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "É obrigatório uso de STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Nenhum recurso foi informado" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Substituído por nova conexão" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "foi removido" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Insira o texto que você vê" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Suas mensagens para ~s estão bloqueadas. Para desbloquea-las, visite: ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é inválido." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Não Autorizado" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administração" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Controle de Acesso" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Submetido" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Formato incorreto" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Intocado" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Remover os selecionados" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Regras de Acesso" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configuração da Regra de Acesso ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Hosts virtuais" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Usuários" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Usuários conectados" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Ultimas atividades dos usuários" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Período: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Último mês" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Último ano" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Todas atividades" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Mostrar Tabela Ordinária" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Mostrar Tabela Integral" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Não encontrado" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nó não encontrado" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Adicionar novo" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Máquina" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Usuários Registrados" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Usuário" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Senha" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Adicionar usuário" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Mensagens offline" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Última atividade" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Usuários registrados" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Usuários online" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Conexões que partem de s2s" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Servidores que partem de s2s" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nenhum" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Mudar senha" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Usuário " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Senha:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Remover usuário" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Nenhum dado" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nós" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nos em execução" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nos parados" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nó" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de dados" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Salvar cópia de segurança" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Portas escutadas" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Atualizar" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Parar" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Erro de chamada RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelas de base de dados em " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Tipo de armazenamento" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memória" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Erro" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Backup de " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -354,490 +355,486 @@ msgstr "" "você esteja utilizando o modulo ODBC, você precisará fazer backup de sua " "base de dados SQL separadamente." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Armazenar backup binário:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Restaurar backup binário imediatamente" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar backup binário após próximo reinicialização do ejabberd (requer " "menos memória):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Armazenar backup em texto:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Restaurar backup formato texto imediatamente:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuários de um arquivo PIEFXIS (XEP-0227): " -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar todos os dados de todos os usuários no servidor, para arquivos " "formato PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar dados dos usuários em um host, para arquivos PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importar dados dos usuários de uma fila jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar dados dos usuários de um diretório-fila jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Portas ouvintes em " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Módulos em " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Estatísticas de ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Tempo de CPU" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transações salvas:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transações abortadas:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transações reiniciadas:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transações de log:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Atualizar " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plano de Atualização" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Módulos atualizados" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Script de atualização" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Script de atualização low level" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Verificação de Script" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Porta" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Porta" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opções" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Eliminar" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Iniciar" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandos" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Deletar realmente a mensagem do dia?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Assunto" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Corpo da mensagem" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Nenhum corpo de texto fornecido para anunciar mensagem" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Anúncios" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Enviar anúncio a todos os usuários" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Enviar aviso para todos os usuários em todos os hosts" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Enviar anúncio a todos os usuárions online" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Enviar anúncio a todos usuários online em todas as máquinas" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Definir mensagem do dia e enviar a todos usuários online" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Definir mensagem do dia em todos os hosts e enviar para os usuários online" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Atualizar mensagem do dia (não enviar)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Atualizar a mensagem do dia em todos os host (não enviar)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Apagar mensagem do dia" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Apagar a mensagem do dia em todos os hosts" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configuração" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Parar módulos" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar para arquivo de texto" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar arquivo" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar diretório" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reiniciar Serviço" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Parar Serviço" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Deletar Usuário" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Terminar Sessão do Usuário" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Obter Senha do Usuário" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Alterar Senha do Usuário" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Obter a Data do Último Login" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Obter Estatísticas do Usuário" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Obter Número de Usuários Registrados" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Obter Número de Usuários Online" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Gerenciamento de Usuários" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Todos os usuários" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Conexões que partam de s2s" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestão de Backup" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuários de arquivos jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Para ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Configuração de Tabelas de Base de dados em " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Selecione o tipo de armazenamento das tabelas" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Somente copia em disco" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copias na RAM e disco rígido" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copia em RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copia remota" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Parar módulos em " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Selecione módulos a parar" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar módulos em " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduza lista de {módulo, [opções]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Listas de módulos para inicializar" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Salvar backup para arquivo em " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Introduza o caminho do arquivo de backup" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Caminho do arquivo" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaurar backup a partir do arquivo em " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exportar backup para texto em " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduza caminho para o arquivo texto" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importar usuário a partir do arquivo em " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Insira o caminho para a fila (arquivo) do jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar usuários a partir do diretório em " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introduza o caminho para o diretório de fila do jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Caminho para o diretório" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Intervalo (Tempo)" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuração da Lista de Controle de Acesso" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Controle de Acesso" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuração de Acesso" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Regras de acesso" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Verificação de Senha" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Número de usuários registrados" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Número de usuários online" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Último login" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Tamanho da Lista" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Endereços IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administração de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Ação no usuário" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Editar propriedades" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -950,171 +947,195 @@ msgstr "Codificação para o servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Salas de Chat" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Você precisa de um cliente com suporte de x:data para poder registrar o nick" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registro do apelido em " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Introduza o apelido que quer registrar" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Apelido" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Salas de Chat" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "Sair da sala" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Usuários Registrados" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Configuração da sala de bate-papo modificada" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "Entrar na sala" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "Sair da sala" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "foi banido" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "foi desconectado porque por afiliação inválida" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" "foi desconectado porque a política da sala mudou, só membros são permitidos" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "foi desconectado porque o sistema foi desligado" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "é agora conhecido como" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " a posto o assunto: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "A sala de chat está criada" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "A sala de chat está destruída" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "A sala de chat está inciada" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "A sala de chat está parada" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Segunda" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Terça" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Quarta" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Quinta" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Sexta" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sábado" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Domingo" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Janeiro" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Fevereiro" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Março" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Maio" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Junho" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Julho" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Setembro" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Outubro" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Dezembro" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Configuração de salas" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1122,320 +1143,328 @@ msgstr "" "Somente os moderadores e os participamentes podem alterar o assunto desta " "sala" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Somente os moderadores podem alterar o assunto desta sala" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Essa sala não é anônima" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s não es válido" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "O nick ~s não existe em la sala" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiliação não válida: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Cargo (role) é não válido: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Configuração para ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Descrição da Sala" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Tornar sala persistente" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Tornar sala pública possível de ser encontrada" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Tornar pública a lista de participantes" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Tornar protegida a senha da sala" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Número máximo de participantes" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Ilimitado" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Tornar o Jabber ID real visível por" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "apenas moderadores" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "qualquer um" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Tornar sala apenas para membros" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Tornar a sala moderada" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Usuários padrões como participantes" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Permitir a usuários modificar o assunto" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Permitir a usuários enviarem mensagens privadas" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir a usuários enviarem mensagens privadas" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "ninguém" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Permitir a usuários pesquisar informações sobre os demais" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Permitir a usuários envio de convites" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Permitir atualizações de status aos visitantes" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Permitir mudança de apelido aos visitantes" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir a usuários envio de convites" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "O intervalo mínimo entre requisições de voz (em segundos)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Tornar protegida a senha da sala" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir IDs Jabber de serem submetidos ao CAPTCHA" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Permitir criação de logs" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Necessitas um cliente com suporte de x:data para configurar la sala" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privado, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Requisição de voz" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Você deve aprovar/desaprovar a requisição de voz." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Usuário " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s convidou você para a sala ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "a senha é" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s's Fila de Mensagens Offline" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Fecha" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Para" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pacote" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Mensagens offline" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Remover Todas as Mensagens Offline" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Modulo ejabberd SOCKS5 Bytestreams" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publicação de Tópico" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo para Publicar Tópicos do ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub requisição de assinante" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Aprovar esta assinatura." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID do Tópico" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Endereço dos Assinantes" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Autorizar este Jabber ID para a inscrição neste tópico pubsub?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads junto com as notificações de eventos" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Entregar as notificações de evento" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscritores quando cambia la configuração do nodo" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscritores quando o nodo se elimine" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscritores quando os elementos se eliminem do nodo" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Persistir elementos ao armazenar" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Um nome familiar para o nó" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persistem" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Permitir subscrições" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Especificar os modelos de acesso" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Listar grupos autorizados" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Especificar o modelo do publicante" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Descartar todos os itens quando o publicante principal estiver offline" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Especificar o tipo de mensagem para o evento" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Máximo tamanho do payload em bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Quando enviar o último tópico publicado" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Solo enviar notificações aos usuários disponíveis" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "As coleções com as quais o nó está relacionado" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Você precisa de um cliente com suporte de x:data para poder registrar o nick" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Escolha um nome de usuário e senha para registrar-se neste servidor" @@ -1471,7 +1500,7 @@ msgstr "Registros de Contas Jabber" msgid "Register a Jabber account" msgstr "Registrar uma conta Jabber" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Deletar conta Jabber" @@ -1486,7 +1515,7 @@ msgstr "" "favor, leia cuidadosamente as instruções para preencher corretamente os " "campos." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "Nome de usuário no IRC" @@ -1500,12 +1529,12 @@ msgstr "" msgid "Characters not allowed:" msgstr "Caracteres não aceitos:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Servidor ~b" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." @@ -1513,11 +1542,11 @@ msgstr "" "Não revele o seu computador a ninguém, mesmo para o administrador deste " "servidor Jabber." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Mais tarde você pode alterar a sua senha usando um cliente Jabber." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1525,7 +1554,7 @@ msgstr "" "Alguns clientes jabber podem salvar a sua senha no seu computador. Use " "recurso somente se você considera este computador seguro o suficiente." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1535,117 +1564,117 @@ msgstr "" "seguro. Jabber não é uma maneira automatizada para recuperar a sua senha, se " "você a esquecer eventualmente." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Verificação de Senha" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Lista de contatos" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Senha Antiga:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Nova Senha:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Esta página aceita para deletar uma conta Jabber neste servidor." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Deletar registro" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Subscrição" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Remover" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Lista de contatos de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Adicionar ID jabber" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Lista de contatos" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Grupos Shared Roster" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Nome:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Descrição:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Miembros:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 #, fuzzy msgid "Displayed Groups:" msgstr "Grupos Indicados:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grupo " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber em Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Aniversário" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Cidade" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Sobrenome" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1653,46 +1682,52 @@ msgstr "" "Preencha o formulário para buscar usuários Jabber. Agrega * ao final de um " "campo para buscar sub-palavras." -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Nome do meio" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome da organização" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Departamento/Unidade" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Procurar usuários em " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Necessitas um cliente com suporte de x:data para poder buscar" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Busca de Usuário vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard para ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Resultados de pesquisa para " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Preencha campos para buscar usuários Jabber que concordem" +#~ msgid "Delete" +#~ msgstr "Eliminar" + +#~ msgid "This room is not anonymous" +#~ msgstr "Essa sala não é anônima" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Sua lista de privacidade ativa negou o roteamento deste." diff --git a/priv/msgs/pt.po b/priv/msgs/pt.po index 45c4a625fe5..8b5572ae5a1 100644 --- a/priv/msgs/pt.po +++ b/priv/msgs/pt.po @@ -7,877 +7,874 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Portuguese (português)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Não foi passado nenhum recurso" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 #, fuzzy msgid "Enter the text you see" msgstr "Introduza caminho para o ficheiro de texto" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 #, fuzzy msgid "ejabberd Web Admin" msgstr "Administração do ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 #, fuzzy msgid "Administration" msgstr "Administração de " -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Controlo de Acesso" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 #, fuzzy msgid "Submitted" msgstr "enviado" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 #, fuzzy msgid "Bad format" msgstr "formato inválido" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 #, fuzzy msgid "Raw" msgstr "modo texto" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Eliminar os seleccionados" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Regras de Acesso" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Configuração das Regra de Acesso ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 #, fuzzy msgid "Virtual Hosts" msgstr "Servidores virtuales" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Utilizadores" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Utilizadores ligados" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 #, fuzzy msgid "Users Last Activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 #, fuzzy msgid "All activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 #, fuzzy msgid "Not Found" msgstr "Nodo não encontrado" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nodo não encontrado" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Adicionar novo" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 #, fuzzy msgid "Host" msgstr "Nome do servidor" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 #, fuzzy msgid "Registered Users" msgstr "Utilizadores registados" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Utilizador" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Palavra-chave" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Adicionar utilizador" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 #, fuzzy msgid "Offline Messages" msgstr "Mensagens diferidas" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Ligado" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 #, fuzzy msgid "Registered Users:" msgstr "Utilizadores registados" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 #, fuzzy msgid "Online Users:" msgstr "Utilizadores ligados" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 #, fuzzy msgid "Outgoing s2s Connections:" msgstr "Conexões S2S para fora" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 #, fuzzy msgid "Outgoing s2s Servers:" msgstr "Servidores S2S de saída" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nenhum" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Mudar palavra-chave" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Utilizador" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Palavra-chave:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Eliminar utilizador" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos a correr" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos parados" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nodo" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar cópia de segurança" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 #, fuzzy msgid "Listened Ports" msgstr "Portas em escuta em " -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Parar" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 #, fuzzy msgid "RPC Call Error" msgstr "Erro na chamada RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelas da BD em " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Tipo de armazenagem" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memória" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Guardar cópia de segurança" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " "separately." msgstr "" -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 #, fuzzy msgid "Store binary backup:" msgstr "Armazenar uma cópia de segurança no ficheiro" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Restore binary backup immediately:" msgstr "Recuperar uma cópia de segurança a partir de ficheiro" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 #, fuzzy msgid "Restore plain text backup immediately:" msgstr "Recuperar uma cópia de segurança a partir de ficheiro" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "Importar utilizadores a partir de ficheiros da spool do jabberd14" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Importar utilizadores a partir de ficheiros da spool do jabberd14" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Portas em escuta em " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Parar módulos em " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 #, fuzzy msgid "Statistics of ~p" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 #, fuzzy msgid "Uptime:" msgstr "Tempo de funcionamento" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 #, fuzzy msgid "CPU Time:" msgstr "Tempo de processador consumido" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 #, fuzzy msgid "Transactions Committed:" msgstr "Transacções realizadas" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 #, fuzzy msgid "Transactions Aborted:" msgstr "Transacções abortadas" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 #, fuzzy msgid "Transactions Restarted:" msgstr "Transacções reiniciadas" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 #, fuzzy msgid "Transactions Logged:" msgstr "Transacções armazenadas" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 #, fuzzy msgid "Update plan" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 #, fuzzy msgid "Modified modules" msgstr "Iniciar módulos" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 #, fuzzy msgid "Update script" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Porta" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 #, fuzzy msgid "Protocol" msgstr "Porta" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Opções" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Eliminar" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 #, fuzzy msgid "Start" msgstr "Reiniciar" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 #, fuzzy msgid "Ping" msgstr "Pendente" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 #, fuzzy msgid "Subject" msgstr "Enviar" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "" -#: mod_announce.erl:689 +#: mod_announce.erl:680 #, fuzzy msgid "Delete message of the day" msgstr "Eliminar os seleccionados" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Configuração" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Iniciar módulos" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Parar módulos" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Restaurar" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Exportar para ficheiro de texto" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importar ficheiro" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importar directório" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 #, fuzzy msgid "Restart Service" msgstr "Reiniciar" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 #, fuzzy msgid "Delete User" msgstr "Eliminar" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 #, fuzzy msgid "Get User Password" msgstr "Palavra-chave" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 #, fuzzy msgid "Change User Password" msgstr "Mudar palavra-chave" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 #, fuzzy msgid "Get User Statistics" msgstr "Estatísticas" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 #, fuzzy msgid "Get Number of Registered Users" msgstr "Utilizadores registados" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 #, fuzzy msgid "Get Number of Online Users" msgstr "Utilizadores ligados" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 #, fuzzy msgid "User Management" msgstr "Gestão da BD" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Todos os utilizadores" -#: mod_configure.erl:527 +#: mod_configure.erl:526 #, fuzzy msgid "Outgoing s2s Connections" msgstr "Conexões S2S para fora" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Gestão de cópias de segurança" -#: mod_configure.erl:618 +#: mod_configure.erl:617 #, fuzzy msgid "Import Users From jabberd14 Spool Files" msgstr "Importar utilizadores a partir de ficheiros da spool do jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "A ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 #, fuzzy msgid "Database Tables Configuration at " msgstr "Configuração de tabelas da BD em " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Seleccione o tipo de armazenagem das tabelas" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Cópia apenas em disco" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Cópia em RAM e em disco" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Cópia em RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Cópia remota" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Parar módulos em " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Seleccione os módulos a parar" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Iniciar os módulos em " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Introduza lista de {módulos, [opções]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista de módulos a iniciar" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Guardar cópia de segurança para ficheiro em " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Introduza o caminho do ficheiro de cópia de segurança" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Caminho do ficheiro" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Restaura cópia de segurança a partir do ficheiro em " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Exporta cópia de segurança para ficheiro de texto em " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Introduza caminho para o ficheiro de texto" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importar utilizador a partir do ficheiro em " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Introduza o caminho para o ficheiro de spool do jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importar utilizadores a partir do directório em " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Introduza o caminho para o directório de spools do jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Caminho para o directório" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Configuração da Lista de Controlo de Acesso" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Listas de Controlo de Acesso" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Configuração de acessos" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Regras de acesso" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 #, fuzzy msgid "Number of registered users" msgstr "Utilizadores registados" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 #, fuzzy msgid "Number of online users" msgstr "Utilizadores ligados" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 #, fuzzy msgid "Roster size" msgstr "Lista de contactos" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 #, fuzzy msgid "Resources" msgstr "Restaurar" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administração de " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Acção no utilizador" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Editar propriedades" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -992,519 +989,549 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "É necessário um cliente com suporte de x:data para poder registar a alcunha" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registo da alcunha em " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Introduza a alcunha que quer registar" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Alcunha" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Módulo MUC de ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +msgid "Total rooms" +msgstr "" + +#: mod_muc_admin.erl:249 +msgid "Permanent rooms" +msgstr "" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Utilizadores registados" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 #, fuzzy msgid "Chatroom configuration modified" msgstr "Configuração para " -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " colocou o tópico: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 #, fuzzy msgid "Chatroom is created" msgstr "Configuração para " -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 #, fuzzy msgid "November" msgstr "Nunca" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 #, fuzzy msgid "Room Configuration" msgstr "Configuração" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Só os moderadores e os participantes podem mudar o tópico desta sala" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Só os moderadores podem mudar o tópico desta sala" -#: mod_muc_room.erl:1868 -#, fuzzy -msgid "This room is not anonymous" -msgstr "Tornar a sala anónima?" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s não é válido" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "A alcunha ~s não existe na sala" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiliação inválida: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Papel inválido: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 #, fuzzy msgid "Configuration of room ~s" msgstr "Configuração para " -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 #, fuzzy msgid "Room description" msgstr "Subscrição" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 #, fuzzy msgid "Make room persistent" msgstr "Tornar a sala permanente?" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 #, fuzzy msgid "Make room public searchable" msgstr "Tornar a sala publicamente visível?" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 #, fuzzy msgid "Make participants list public" msgstr "Tornar pública a lista de participantes?" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 #, fuzzy msgid "Make room password protected" msgstr "Proteger a sala com palavra-chave?" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 #, fuzzy msgid "anyone" msgstr "Nenhum" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 #, fuzzy msgid "Make room members-only" msgstr "Tornar a sala exclusiva a membros?" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Tornar a sala moderada" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 #, fuzzy msgid "Default users as participants" msgstr "Os utilizadores são membros por omissão?" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 #, fuzzy msgid "Allow users to change the subject" msgstr "Permitir aos utilizadores mudar o tópico?" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 #, fuzzy msgid "Allow users to send private messages" msgstr "Permitir que os utilizadores enviem mensagens privadas?" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir que os utilizadores enviem mensagens privadas?" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 #, fuzzy msgid "Allow users to query other users" msgstr "Permitir aos utilizadores consultar outros utilizadores?" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 #, fuzzy msgid "Allow users to send invites" msgstr "Permitir que os utilizadores enviem convites?" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Permitir aos utilizadores mudar o tópico?" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir que os utilizadores enviem convites?" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Proteger a sala com palavra-chave?" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 #, fuzzy msgid "Enable logging" msgstr "Guardar históricos?" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "É necessário um cliente com suporte de x:data para configurar a sala" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Utilizador" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 #, fuzzy msgid "the password is" msgstr "Mudar palavra-chave" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +#, fuzzy +msgid "ejabberd Multicast service" +msgstr "Utilizadores do ejabberd" + +#: mod_offline.erl:783 #, fuzzy msgid "~s's Offline Messages Queue" msgstr "~s fila de mensagens diferidas" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Data" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "De" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Para" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Pacote" -#: mod_offline.erl:967 +#: mod_offline.erl:977 #, fuzzy msgid "Offline Messages:" msgstr "Mensagens diferidas:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 #, fuzzy msgid "Remove All Offline Messages" msgstr "Mensagens diferidas" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 #, fuzzy msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Módulo vCard de ejabberd" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 #, fuzzy msgid "ejabberd Publish-Subscribe module" msgstr "Módulo pub/sub de ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 #, fuzzy msgid "Node ID" msgstr "Nodo" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "É necessário um cliente com suporte de x:data para poder registar a alcunha" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Escolha um nome de utilizador e palavra-chave para se registar neste servidor" @@ -1542,7 +1569,7 @@ msgstr "Configuração das Listas de Controlo de Acesso do ejabberd" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1553,7 +1580,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "Nome do utilizador de IRC" @@ -1566,196 +1593,203 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Nunca" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Lista de contactos" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Palavra-chave:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Palavra-chave:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Subscrição" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Remover" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Lista de contactos de " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 #, fuzzy msgid "Add Jabber ID" msgstr "Adicionar Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Lista de contactos" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 #, fuzzy msgid "Shared Roster Groups" msgstr "Lista de contactos partilhada" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 #, fuzzy msgid "Name:" msgstr "Nome" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 #, fuzzy msgid "Description:" msgstr "Subscrição" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 #, fuzzy msgid "Group " msgstr "Grupos" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Servidor Jabber em Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Data de nascimento" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Cidade" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "País" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 #, fuzzy msgid "Email" msgstr "email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Apelido" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 #, fuzzy msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "Preencha os campos para procurar utilizadores Jabber coincidentes" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Nome completo" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Segundo nome" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Nome da organização" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unidade da organização" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Procurar utilizadores em " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "É necessário um cliente com suporte de x:data para poder procurar" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Módulo vCard de ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 #, fuzzy msgid "Search Results for " msgstr "Procurar utilizadores em " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Preencha os campos para procurar utilizadores Jabber coincidentes" +#~ msgid "Delete" +#~ msgstr "Eliminar" + +#, fuzzy +#~ msgid "This room is not anonymous" +#~ msgstr "Tornar a sala anónima?" + #~ msgid "Access denied by service policy" #~ msgstr "Acesso negado pela política de serviço" @@ -1907,8 +1941,5 @@ msgstr "Preencha os campos para procurar utilizadores Jabber coincidentes" #~ msgid "ejabberd access rules configuration" #~ msgstr "Configuração das Regras de Acesso do ejabberd" -#~ msgid "ejabberd users" -#~ msgstr "Utilizadores do ejabberd" - #~ msgid "~p statistics" #~ msgstr "Estatísticas de ~p" diff --git a/priv/msgs/ru.po b/priv/msgs/ru.po index 77eacbc1524..df35e3a02ca 100644 --- a/priv/msgs/ru.po +++ b/priv/msgs/ru.po @@ -17,340 +17,341 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Вы обязаны использовать STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Не указан ресурс" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Заменено новым соединением" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "выгнали из комнаты" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Введите увиденный текст" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Ваши сообщения к ~s блокируются. Для снятия блокировки перейдите по ссылке ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Если вы не видите изображение капчи, перейдите по ссылке." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Ссылка на капчу" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Проверка капчи прошла успешно." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Не авторизован" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Web-интерфейс администрирования ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Администрирование" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Списки управления доступом" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Отправлено" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Неправильный формат" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Отправить" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Необработанный формат" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Удалить выделенные" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Правила доступа" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Конфигурация правила доступа ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Виртуальные хосты" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Пользователи" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Подключённые пользователи" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Статистика последнего подключения пользователей" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Период" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "За последний месяц" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "За последний год" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Вся статистика" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Показать обычную таблицу" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Показать интегральную таблицу" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Статистика" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Не Найдено" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Узел не найден" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Добавить" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Хост" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Зарегистрированные пользователи" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Пользователь" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Пароль" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Добавить пользователя" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Офлайновые сообщения" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Последнее подключение" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Никогда" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Подключён" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Зарегистрированные пользователи:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Подключённые пользователи:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Исходящие s2s-серверы:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Исходящие s2s-серверы:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Нет" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Сменить пароль" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Пользователь " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Подключённые ресурсы:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Пароль:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Удалить пользователя" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Нет данных" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Узлы" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Работающие узлы" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Остановленные узлы" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Узел " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "База данных" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Резервное копирование" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Прослушиваемые порты" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Обновить" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Перезапустить" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Остановить" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Модули" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Ошибка вызова RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Таблицы базы данных на " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Название" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Тип таблицы" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Элементы" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Память" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Ошибка" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Резервное копирование " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -361,492 +362,488 @@ msgstr "" "(например с помощью модуля ODBC), то его резервное копирование следует " "осуществлять отдельно." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Сохранить бинарную резервную копию:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Продолжить" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Восстановить из бинарной резервной копии немедленно:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Восстановить из бинарной резервной копии при следующем запуске (требует " "меньше памяти):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Сохранить текстовую резервную копию:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Восстановить из текстовой резервной копии немедленно:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Импорт пользовательских данных из файла формата PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Импорт пользовательских данных из буферного файла jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Импорт пользовательских данных из буферной директории jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Прослушиваемые порты на " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Модули на " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "статистика узла ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Время работы:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Процессорное время:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Транзакции завершенные:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Транзакции отмененные:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Транзакции перезапущенные:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Транзакции запротоколированные:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Обновление " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "План обновления" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Изменённые модули" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Сценарий обновления" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Низкоуровневый сценарий обновления" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Проверка сценария" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Порт" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Протокол" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Модуль" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Параметры" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Удалить" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Запустить" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Команды" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Пинг" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Понг" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Действительно удалить сообщение дня?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Тема" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Тело сообщения" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Тело объявления не должно быть пустым" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Объявления" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Разослать объявление всем пользователям" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Разослать объявление всем пользователям на всех виртуальных серверах" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Разослать объявление всем подключённым пользователям" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Разослать объявление всем подключённым пользователям на всех виртуальных " "серверах" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Установить сообщение дня и разослать его подключённым пользователям" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Установить сообщение дня на всех виртуальных серверах и разослать его " "подключённым пользователям" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Обновить сообщение дня (не рассылать)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Обновить сообщение дня на всех виртуальных серверах (не рассылать)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Удалить сообщение дня" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Удалить сообщение дня со всех виртуальных серверов" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Конфигурация" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Запуск модулей" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Остановка модулей" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Восстановление из резервной копии" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Копирование в текстовый файл" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Импорт из файла" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Импорт из директории" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Перезапустить службу" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Остановить службу" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Удалить пользователя" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Завершить сеанс пользователя" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Получить пароль пользователя" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Изменить пароль пользователя" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Получить время последнего подключения пользователя" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Получить статистику по пользователю" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Получить количество зарегистрированных пользователей" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Получить количество подключённых пользователей" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Управление пользователями" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Все пользователи" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Исходящие s2s-соединения" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Управление резервным копированием" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Импорт пользователей из спула jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "К ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "От ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Конфигурация таблиц базы данных на " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Выберите тип хранения таблиц" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "только диск" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "ОЗУ и диск" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "ОЗУ" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "не хранится локально" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Остановка модулей на " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Выберите модули, которые следует остановить" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Запуск модулей на " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Введите список вида {Module, [Options]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Список запускаемых модулей" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Резервное копирование в файл на " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Введите путь к резервному файлу" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Путь к файлу" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Восстановление из резервной копии на " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Копирование в текстовый файл на " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Введите путь к текстовому файлу" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Импорт пользователя из файла на " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Введите путь к файлу из спула jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Импорт пользователей из директории на " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Введите путь к директории спула jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Путь к директории" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "По истечение" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Конфигурация списков управления доступом" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Списки управления доступом" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Конфигурация доступа" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Правила доступа" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Проверка пароля" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Количество зарегистрированных пользователей" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Количество подключённых пользователей" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Время последнего подключения" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Размер списка контактов" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP адреса" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Ресурсы" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Администрирование " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Действие над пользователем" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Изменить параметры" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -956,483 +953,515 @@ msgstr "Кодировка сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Комнаты" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Регистрация псевдонима на " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Введите псевдоним, который Вы хотели бы зарегистрировать" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдоним" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Комнаты" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "вышел(а) из комнаты" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Зарегистрированные пользователи" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Конфигурация комнаты изменилась" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "вошёл(а) в комнату" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "вышел(а) из комнаты" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "запретили входить в комнату" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "выгнали из комнаты вследствие смены ранга" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "выгнали из комнаты потому что она стала только для членов" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "выгнали из комнаты из-за останова системы" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "изменил(а) имя на" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " установил(а) тему: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Комната создана" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Комната уничтожена" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Комната запущена" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Комната остановлена" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Понедельник" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Вторник" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Среда" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Четверг" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Пятница" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Суббота" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Воскресенье" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "января" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "февраля" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "марта" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "апреля" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "мая" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "июня" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "июля" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "августа" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "сентября" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "октября" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "ноября" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "декабря" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Конфигурация комнаты" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Участники комнаты" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Только модераторы и участники могут изменять тему в этой комнате" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Только модераторы могут изменять тему в этой комнате" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Эта комната не анонимная" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s недопустимый" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Псевдоним ~s в комнате отсутствует" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Недопустимый ранг: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Недопустимая роль: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Конфигурация комнаты ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Название комнаты" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Описание комнаты" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Сделать комнату постоянной" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Сделать комнату видимой всем" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Сделать список участников видимым всем" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Сделать комнату защищённой паролем" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Максимальное количество участников" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Не ограничено" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Сделать реальные Jabber ID участников видимыми" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "только модераторам" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "всем участникам" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Комната только для зарегистрированных участников" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Сделать комнату модерируемой" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Сделать пользователей участниками по умолчанию" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Разрешить пользователям изменять тему" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Разрешить приватные сообщения" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Разрешить посетителям посылать приватные сообщения" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "никто" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Разрешить iq-запросы к пользователям" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Разрешить пользователям посылать приглашения" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Разрешить посетителям вставлять текcт статуса в сообщения о присутствии" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Разрешить посетителям изменять псевдоним" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Разрешить посетителям запрашивать право голоса" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Минимальный интервал между запросами на право голоса" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Сделать комнату защищённой капчей" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Исключить показ капчи для списка Jabber ID" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Включить журналирование" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Чтобы сконфигурировать комнату, требуется x:data-совместимый клиент" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Число присутствующих" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "приватная, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Запрос на право голоса" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Подтвердите или отклоните право голоса." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "JID пользователя" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Предоставить голос?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s приглашает вас в комнату ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "пароль:" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Oчередь офлайновых сообщений ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Время" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "От кого" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Кому" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Пакет" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Офлайновые сообщения:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Удалить все офлайновые сообщения" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams модуль" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Публикация-Подписка" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Модуль ejabberd Публикации-Подписки" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Запрос подписчика PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Решите: предоставить ли подписку этому объекту." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID узла" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Адрес подписчика" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Разрешить этому Jabber ID подписаться на данный узел?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Доставлять вместе с уведомлениями o публикациях сами публикации" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Доставлять уведомления о событиях" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Уведомлять подписчиков об изменении конфигурации сборника" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Уведомлять подписчиков об удалении сборника" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Уведомлять подписчиков об удалении публикаций из сборника" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Сохранять публикации в хранилище" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Легко запоминаемое имя для узла" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Максимальное число сохраняемых публикаций" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Разрешить подписку" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Укажите механизм управления доступом" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Группы списка контактов, которым разрешена подписка" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Условия публикации" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "Очищать все записи автора публикации когда он отключается" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Укажите тип сообщения о событии" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Максимальный размер полезной нагрузки в байтах" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Когда посылать последний опубликованный элемент" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Доставлять уведомления только доступным пользователям" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Имя коллекции, в которую входит узел" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Чтобы зарегистрироваться, требуется x:data-совместимый клиент" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Выберите имя пользователя и пароль для регистрации на этом сервере" @@ -1468,7 +1497,7 @@ msgstr "Регистрация Jabber-аккаунта" msgid "Register a Jabber account" msgstr "Зарегистрировать Jabber-аккаунт" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Удалить Jabber-аккаунт" @@ -1482,7 +1511,7 @@ msgstr "" "(Jabber-идентификатор) будет в виде: \"пользователь@сервер\". Пожалуйста, " "внимательно читайте инструкции для правильного заполнения полей." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Имя пользователя:" @@ -1496,21 +1525,21 @@ msgstr "" msgid "Characters not allowed:" msgstr "Недопустимые символы:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Сервер:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "Не говорите никому свой пароль, даже администраторам сервера." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Позже Вы можете изменить пароль через Jabber-клиент." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1518,7 +1547,7 @@ msgstr "" "Некоторые Jabber-клиенты могут сохранять пароль на Вашем компьютере. " "Используйте эту функцию только в том случае, если считаете это безопасным." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1528,112 +1557,112 @@ msgstr "" "месте. В Jabber'е нет автоматизированного средства восстановления пароля в " "том случае, если Вы его забудете." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Проверка пароля:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Зарегистрировать" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Старый пароль:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Новый пароль:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Здесь Вы можете удалить Jabber-аккаунт с этого сервера." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Удалить" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Подписка" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Ожидание" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Группы" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Утвердить" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Удалить" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Ростер пользователя " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Добавить Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Ростер" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Группы общих контактов" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Название:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Описание:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Члены:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Видимые группы:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Группа " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "День рождения" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Город" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Страна" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Электронная почта" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Фамилия" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1641,46 +1670,52 @@ msgstr "" "Заполните форму для поиска пользователя Jabber (Если добавить * в конец " "поля, то происходит поиск подстроки)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Полное имя" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Отчество" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Название организации" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Отдел организации" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Поиск пользователей в " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Чтобы воспользоваться поиском, требуется x:data-совместимый клиент" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Поиск пользователей по vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard модуль" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Результаты поиска в " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Заполните форму для поиска пользователя Jabber" +#~ msgid "Delete" +#~ msgstr "Удалить" + +#~ msgid "This room is not anonymous" +#~ msgstr "Эта комната не анонимная" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "Маршрутизация этой строфы запрещена вашим активным списком приватности." diff --git a/priv/msgs/sk.po b/priv/msgs/sk.po index c9be6f294f6..39d9a21d0a1 100644 --- a/priv/msgs/sk.po +++ b/priv/msgs/sk.po @@ -12,339 +12,340 @@ msgstr "" "X-Additional-Translator: Juraj Michalek\n" "X-Additional-Translator: SkLUG\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Je vyžadované použitie STARTTLS " -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Nebol poskytnutý žiadny zdroj" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Nahradené novým spojením" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "bol(a) vyhodený(á) z miestnosti" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Zadajte zobrazený text" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Správa určená pre ~s bola zablokovaná. Oblokovať ju môžete na ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Pokiaľ nevidíte obrázok CAPTCHA, navštívte webovú stránku." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Webová stránka CAPTCHA" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Platná CAPTCHA." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Neautorizovaný" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administrácia" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Zoznamy prístupových oprávnení (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Odoslané" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Zlý formát" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Odoslať" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Surové dáta" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Zmazať vybrané" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Prístupové pravidlá" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s konfigurácia prístupového pravidla" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtuálne servery" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Používatelia" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Online užívatelia" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Posledná aktivita používateľa" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Čas:" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Posledný mesiac" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Posledný rok" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Všetky aktivity" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Zobraziť bežnú tabuľku" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Zobraziť kompletnú tabuľku" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Štatistiky" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Nebol nájdený" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Uzol nenájdený" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Pridať nový" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Server" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Registrovaní používatelia" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Užívateľ" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Heslo" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Pridať používateľa" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Offline správy" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Posledná aktivita" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Nikdy" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Registrovaní používatelia:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Online používatelia:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Odchádzajúce s2s spojenia:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Odchádzajúce s2s servery:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nič" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Zmeniť heslo" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Používateľ " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Pripojené zdroje:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Heslo:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Odstrániť užívateľa" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Žiadne dáta" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Uzly" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Bežiace uzly" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zastavené uzly" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Uzol" -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databáza" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Zálohovať" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Otvorené portov" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Aktualizovať" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Reštart" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Zastaviť" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduly" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Chyba RPC volania" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Databázové tabuľky na " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Meno" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Typ úložiska" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Prvky" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Pamäť" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Chyba" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Záloha " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -354,489 +355,485 @@ msgstr "" "Mnesia databázu. Ak používate ODBC modul, musíte zálohovať vašu SQL databázu " "separátne." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Uložiť binárnu zálohu:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Okamžite obnoviť binárnu zálohu:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Obnoviť binárnu zálohu pri nasledujúcom reštarte ejabberd (vyžaduje menej " "pamäte)" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Uložiť zálohu do textového súboru:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Okamžite obnoviť zálohu z textového súboru:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importovat dáta užívateľov zo súboru PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportovať dáta všetkých uživateľov na serveri do súborov PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportovať dáta uživateľov na hostitelovi do súborov PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importovať dáta užívateľov z jabberd14 spool súboru:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importovať dáta užívateľov z jabberd14 spool adresára:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Otvorené porty na " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduly na " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Štatistiky ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Čas procesoru" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transakcie potvrdená" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transakcie zrušená" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transakcie reštartovaná" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transakcie zaznamenaná" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Aktualizovať " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Aktualizovať plán" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Modifikované moduly" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Aktualizované skripty" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Nízkoúrovňový aktualizačný skript" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Kontrola skriptu" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Nastavenia" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Zmazať" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Štart" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Príkazy" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Skutočne zmazať správu dňa?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Predmet" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Telo správy" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Správa neobsahuje text" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Oznámenia" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Odoslať oznam všetkým používateľom" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Poslať oznámenie všetkým užívateľom na všetkých serveroch" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Odoslať zoznam všetkým online používateľom" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Odoslať oznam všetkým online používateľom na všetkých serveroch" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Nastaviť správu dňa a odoslať ju online používateľom" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Nastaviť správu dňa na všetkých serveroch a poslať ju online užívateľom" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Aktualizovať správu dňa (neodosielať)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Upraviť správu dňa na všetkých serveroch" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Zmazať správu dňa" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Zmazať správu dňa na všetkých serveroch" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Konfigurácia" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Spustiť moduly" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Zastaviť moduly" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Obnoviť" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Uložiť do textového súboru" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Import súboru" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Import adresára" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Reštartovať službu" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Vypnúť službu" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Vymazať užívateľa" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Ukončiť reláciu užívateľa" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Zobraziť heslo užívateľa" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Zmeniť heslo užívateľa" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Zobraziť čas posledného prihlásenia" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Zobraziť štatistiku užívateľa" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Zobraziť počet registrovaných užívateľov" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Zobraziť počet pripojených užívateľov" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Správa užívateľov" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Všetci užívatelia" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Odchádzajúce s2s spojenia" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Správa zálohovania" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importovať užívateľov z jabberd14 spool súborov" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Pre ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Od ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Konfigurácia databázových tabuliek " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Vyberte typ úložiska pre tabuľky" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Len kópia disku" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Kópia RAM a disku" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Kópia RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Vzdialená kópia" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Zastaviť moduly na " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Vyberte moduly, ktoré majú byť zastavené" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Spustiť moduly na " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Vložte zoznam modulov {Modul, [Parametre]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Zoznam modulov, ktoré majú byť spustené" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Záloha do súboru na " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Zadajte cestu k súboru so zálohou" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Cesta k súboru" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Obnoviť zálohu zo súboru na " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Uložiť zálohu do textového súboru na " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Zadajte cestu k textovému súboru" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importovať užívateľa zo súboru na " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Zadajte cestu k spool súboru jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importovať užívateľov z adresára na " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Zadajte cestu k jabberd14 spool adresáru" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Cesta k adresáru" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Časový posun" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfigurácia zoznamu prístupových oprávnení (ACL)" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Zoznamy prístupových oprávnení (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Konfigurácia prístupu" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Prístupové pravidlá" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Overenie hesla" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Počet registrovaných užívateľov" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Počet online užívateľov" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Posledné prihlásenie" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Počet kontaktov v zozname" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP adresa" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Zdroje" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administrácia " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Operácia aplikovaná na užívateľa" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Editovať vlastnosti" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -946,483 +943,515 @@ msgstr "Kódovanie pre server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Diskusné miestnosti" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Na registráciu prezývky potrebujete klienta podporujúceho z x:data" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registrácia prezývky na " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Zadajte prezývku, ktorú chcete registrovať" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Prezývka" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Diskusné miestnosti" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "odišiel(a) z miestnosti" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Registrovaní používatelia" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Nastavenie diskusnej miestnosti bolo zmenené" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "vstúpil(a) do miestnosti" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "odišiel(a) z miestnosti" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "bol(a) zablokovaný(á)" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "bol vyhodený(á) kvôli zmene priradenia" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "bol vyhodený(á), pretože miestnosť bola vyhradená len pre členov" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "bol vyhodený(á) kvôli reštartu systému" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "sa premenoval(a) na" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr "zmenil(a) tému na: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Diskusná miestnosť je vytvorená" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Diskusná miestnosť je zrušená" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Diskusná miestnosť je obnovená" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Diskusná miestnosť je pozastavená" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Pondelok" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Utorok" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Streda" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Štvrtok" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Piatok" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Sobota" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Nedeľa" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Január" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Február" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Marec" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Apríl" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Máj" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Jún" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Júl" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "August" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "September" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Október" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "November" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "December" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Nastavenia miestnosti" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Ľudí v miestnosti" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Len moderátori a zúčastnený majú povolené meniť tému tejto miestnosti" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Len moderátori majú povolené meniť tému miestnosti" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Táto miestnosť nie je anonymná" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s je neplatné" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Prezývka ~s v miestnosti neexistuje" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Neplatné priradenie: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Neplatná rola: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Konfigurácia miestnosti ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Názov miestnosti" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Popis miestnosti" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Nastaviť miestnosť ako trvalú" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Nastaviť miestnosť ako verejne prehľadávateľnú" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Nastaviť zoznam zúčastnených ako verejný" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Chrániť miestnosť heslom" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Počet účastníkov" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Zobrazovať skutočné Jabber ID" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "moderátorom" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "všetkým" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Nastaviť miestnosť len pre členov" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Nastaviť miestnosť ako moderovanú" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Užívatelia sú implicitne členmi" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Povoliť užívateľom meniť tému" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Povoliť užívateľom odosielať súkromné správy" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Povoliť užívateľom odosielať súkromné správy" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "nikto" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Povoliť užívateľom dotazovať sa informácie o iných užívateľoch" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Povoliť používateľom posielanie pozvánok" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Návštevníci môžu posielať textové informácie v stavových správach" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Návštevníci môžu meniť prezývky" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Povoliť používateľom posielanie pozvánok" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimum interval between voice requests (in seconds)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Chrániť miestnosť systémom CAPTCHA" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Nepoužívať CAPTCHA pre nasledujúce Jabber ID" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Zapnúť zaznamenávanie histórie" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Na konfiguráciu miestnosti potrebujete klienta podporujúceho x:data" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Počet zúčastnených" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "súkromná, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Žiadosť o Voice" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Povolte alebo zamietnite žiadosť o Voice." -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Používateľ " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Prideltiť Voice tejto osobe?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s Vás pozýva do miestnosti ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "heslo je" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s Offline správy" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Čas" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Od" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Pre" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Offline správy" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Odstrániť všetky offline správy" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Žiadosť odberateľa PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Zvolte, či chcete povoliť toto odoberanie" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID uzlu" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Adresa odberateľa" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Dovoliť tomuto Jabber ID odoberať PubSub uzol?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Doručiť náklad s upozornením na udalosť" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Doručiť oznamy o udalosti" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Upozorniť prihlásených používateľov na zmenu nastavenia uzlu" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Upozorniť prihlásených používateľov na zmazanie uzlu" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Upozorniť prihlásených používateľov na odstránenie položiek z uzlu" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Uložiť položky natrvalo do úložiska" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Prístupný názov pre uzol" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Maximálny počet položiek, ktoré je možné natrvalo uložiť" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Povoliť prihlasovanie" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Uveďte model prístupu" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Skupiny kontaktov, ktoré môžu odoberať" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Špecifikovať model publikovania" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Odstrániť všetky relevantné položky, keď užívateľ prejde do módu offline" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Uveďte typ pre správu o udalosti" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Maximálny náklad v bajtoch" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Kedy odoslať posledne publikovanú položku" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Doručovať upozornenia len aktuálne prihláseným používateľom" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Kolekcie asociované s uzlom" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Na registráciu prezývky potrebujete klienta podporujúceho z x:data" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Zvolte meno užívateľa a heslo pre registráciu na tomto servere" @@ -1458,7 +1487,7 @@ msgstr "Registrácia jabber účtu" msgid "Register a Jabber account" msgstr "Zaregistrovať Jabber účet" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Zrušiť Jabber účet" @@ -1472,7 +1501,7 @@ msgstr "" "(Jabber IDentifikátor) bude vo formáte: užívateľ@server. Pozorne sledujte " "inštrukcie, aby ste údaje vypnili správne." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "IRC prezývka" @@ -1486,22 +1515,22 @@ msgstr "" msgid "Characters not allowed:" msgstr "Nepovolené znaky:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Server ~b" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "Nevyzrádzajte heslo nikomu, ani administrátorom tohoto Jabber servera." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Neskôr si heslo môžete zmeniť pomocou Jabber klienta." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1509,7 +1538,7 @@ msgstr "" "Niektorí Jabber klenti môžu ukladať heslá v počítači. Používajte túto " "funkciu len ak veríte, že sú tam v bezpečí. " -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1518,113 +1547,113 @@ msgstr "" "Zapamätajte si heslo alebo si ho zapíšte na papier. Jabber neposkytuje " "automatickú funkciu ako zistiť zabudnuté heslo. " -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Overenie hesla" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Zoznam kontaktov" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Staré heslo:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Nové heslo:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Na tejto stránke si môžete zrušiť Jabber účet registrovaný na tomto serveri." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Zrušiť účet" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Prihlásenie" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Čakajúce" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Skupiny" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Overiť" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Odstrániť" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Zoznam kontaktov " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Pridať Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Zoznam kontaktov" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Skupiny pre zdieľaný zoznam kontaktov" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Meno:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Popis:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Členovia:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Zobrazené skupiny:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Skupina " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Dátum narodenia" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Mesto" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Krajina" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-mail" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Priezvisko" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1632,46 +1661,52 @@ msgstr "" "Pre vyhľadanie Jabber používateľa vyplňte formulár (pridajte znak * na " "koniec, pre vyhľadanie podreťazca)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Celé meno: " -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Prostredné meno: " -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Meno organizácie: " -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organizačná jednotka: " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Hľadať užívateľov v " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Na vyhľadávanie potrebujete klienta podporujúceho x:data" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Hľadať užívateľov vo vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modul" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Hľadať výsledky pre " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Vyplnte políčka pre vyhľadávanie Jabber užívateľa" +#~ msgid "Delete" +#~ msgstr "Zmazať" + +#~ msgid "This room is not anonymous" +#~ msgstr "Táto miestnosť nie je anonymná" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Aktívny list súkromia zbránil v smerovaní tejto stanzy." diff --git a/priv/msgs/sv.po b/priv/msgs/sv.po index 85f8f256ecb..a42582ddf8a 100644 --- a/priv/msgs/sv.po +++ b/priv/msgs/sv.po @@ -11,340 +11,341 @@ msgstr "" "X-Additional-Translator: Magnus Henoch\n" "X-Additional-Translator: Jonas Ådahl\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Du måste använda STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Ingen resurs angiven" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Ersatt av ny anslutning" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "har blivit kickad" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Skriv in sökväg till textfil" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Dina meddelanden till ~s är blockerade. För att avblockera dem, gå till ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Din CAPTCHA är godkänd." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Ej auktoriserad" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Administration" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "ACL" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Skicka in" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Dåligt format" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Skicka" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Ra" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Tabort valda" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Åtkomstregler" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Åtkomstregelkonfiguration för ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Virtuella servrar" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Användare" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Anslutna användare" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Användarens senaste aktivitet" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Period: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Senaste månaden" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Senaste året" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "All aktivitet" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Visa normal tabell" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Visa kumulativ tabell" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistik" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Noden finns inte" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Noden finns inte" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Lägg till ny" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Server" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Registrerade användare" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Användarnamn" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Lösenord" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Lägg till användare" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Offline meddelanden" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Senast aktivitet" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Aldrig" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Ansluten" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Registrerade användare" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Inloggade användare" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Utgående s2s anslutning" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Utgående s2s server" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Inga" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Ändra lösenord" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Användare " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Anslutna resurser:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Lösenord:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Ta bort användare" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Ingen data" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Noder" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Körande noder" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Stannade noder" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nod " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databas" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Säkerhetskopiera" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Lyssnarport" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Uppdatera" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Omstart" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Stoppa" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduler" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "RPC Uppringningserror" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Databas tabell pa" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Namn" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Lagringstyp" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elements" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Minne" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Fel" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Backup av" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -354,486 +355,482 @@ msgstr "" "databas. Om du använder ODBC modul så måste du ta backup på SQLs databas " "enskilt" -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Lagra den binära backupen" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "återställ den binära backupen omedelbart" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "återställ den binära backupen efter nästa ejabberd omstart" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Lagra textbackup" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "återställ textbackup omedelbart" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importera användardata från en PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportera data av alla användare i servern till en PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Exportera data av användare i en host till PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Importera användare från jabberd14 Spool filer" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Importera användare från jabberd14 Spool directory:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Lyssnande portar på " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Moduler på" -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Statistik på ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Tid upp" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "CPU tid" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transaktioner kommittade" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transaktioner borttagna" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transaktioner omstartade" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transaktioner loggade " -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Uppdatera" -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Uppdateringsplan" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Uppdaterade moduler" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Uppdatera skript" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Uppdaterade laglevel skript" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Skript kollat" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Parametrar" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Ta bort" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Starta" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Kommandon" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Verkligen ta bort dagens meddelanden?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Ämne" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Meddelande kropp" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Ingen kropp behövs för dessa meddelanden" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Meddelanden" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Sänd meddelanden till alla användare" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Sänd meddelanden till alla användare på alla värdar" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Sänd meddelanden till alla inloggade användare" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Sänd meddelanden till alla inloggade användare på alla värdar" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Sätt dagens status meddelande och skicka till alla användare" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Sätt dagens status meddelande pa alla värdar och skicka till alla användare" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Uppdatera dagens status meddelande (skicka inte)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Uppdatera dagens status meddelande på alla värdar (skicka inte)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Ta bort dagens meddelande" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Ta bort dagens meddelande på alla värdar" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Konfiguration" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Starta moduler" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Stanna moduler" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Återställ" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Dumpa till textfil" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Importera fil" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Importera katalog" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Starta om servicen" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Stäng ner servicen" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Ta bort användare" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Avsluta användarsession" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Hämta användarlösenord" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Andra användarlösenord" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Hämta användarens senast inloggade tid" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Hämta användarstatistik" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Hämta antal registrerade användare" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Hämta antal inloggade användare" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Användarmanagement" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Alla användare" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Utgaende s2s anslutning" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Hantera säkerhetskopior" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Importera användare från jabberd14 Spool filer" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Till ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Från ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Databastabellers konfiguration" -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Välj lagringstyp för tabeller" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Endast diskkopia" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM- och diskkopia" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM-kopia" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Sparas inte lokalt" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Stoppa moduler på " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Välj vilka moduler som skall stoppas" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Starta moduler på " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Skriv in en lista av {Module, [Options]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Lista av moduler som skall startas" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Säkerhetskopiera till fil på " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Skriv in sökväg till fil för säkerhetskopia" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Sökväg till fil" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Återställ säkerhetskopia från fil på " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Dumpa säkerhetskopia till textfil på " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Skriv in sökväg till textfil" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Importera användare från fil på " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Skriv in sökväg till spoolfil från jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Importera användare från katalog på " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Skriv in sökväg till spoolkatalog från jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Sökväg till katalog" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Tidsförsening" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Konfiguera ACL" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "ACL" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Åtkomstkonfiguration" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Åtkomstregler" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Lösenordsverifikation" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Antal registrerade användare" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Antal inloggade användare" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Senaste login" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Roster storlek" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP adresser" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Resurser" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Administration av " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Handling mot användare" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Redigera egenskaper" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -942,173 +939,197 @@ msgstr "Encoding för server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Chattrum" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "Du behöver en klient som stödjer x:data för att registrera smeknamn" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Registrera smeknamn på " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Skriv in smeknamnet du vill registrera" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Smeknamn" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Chattrum" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "lämnar rummet" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Registrerade användare" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Chattrum konfiguration modifierad" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "joinar rummet" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "lämnar rummet" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "har blivit bannad" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "har blivit kickad p.g.a en ändring av tillhörighet" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "har blivit kickad p.g.a att rummet har ändrats till endast användare" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "har blivit kickad p.g.a en systemnerstängning" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "är känd som" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " har satt ämnet till: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 #, fuzzy msgid "Chatroom is created" msgstr "Chattrum" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 #, fuzzy msgid "Chatroom is destroyed" msgstr "Chattrum" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 #, fuzzy msgid "Chatroom is started" msgstr "Chattrum" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 #, fuzzy msgid "Chatroom is stopped" msgstr "Chattrum" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Måndag" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Tisdag" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Onsdag" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Torsdag" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Fredag" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Lördag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Söndag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Januari" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Februari" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Mars" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "April" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Maj" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Augusti" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "September" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "November" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "December" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Rumkonfiguration" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1116,324 +1137,332 @@ msgstr "" "Endast moderatorer och deltagare har tillåtelse att ändra ämnet i det här " "rummet" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Endast moderatorer får ändra ämnet i det här rummet" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Detta rum är inte anonymt" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Otillåtet Jabber ID ~s" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Smeknamnet ~s existerar inte i det här rummet" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Ogiltlig rang: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Ogiltlig roll: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Konfiguration för ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Rumstitel" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 #, fuzzy msgid "Room description" msgstr "Beskrivning:" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Gör rummet permanent" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Gör rummet publikt sökbart" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Gör deltagarlistan publik" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Gör losenorden i rummet publika" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Maximalt antal av användare" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Ingen gräns" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Nuvarande äkta Jabber IDs till" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "endast moderatorer" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "Vemsomhelst" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Gör om rummet till endast medlemmar" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Gör rummet modererat" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Gör om användare till deltagare" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Tillåt användare att byta ämne" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Tillåt användare att skicka privata meddelanden" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Tillåt användare att skicka privata meddelanden" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Tillåt användare att söka efter andra användare" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Tillåt användare att skicka inbjudningar" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "Tillåt gäster att skicka statustext som uppdatering" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Tillåt gäster att kunna ändra smeknamn" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Tillåt användare att skicka inbjudningar" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Gör losenorden i rummet publika" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Möjliggör login" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "Du behöver en klient som stödjer x:data för att konfiguera detta rum" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Användare " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s bjöd in dig till rummet ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "Lösenordet är" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s's offline meddelandekö" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Tid" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Från" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Till" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Offline meddelanden:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 #, fuzzy msgid "Remove All Offline Messages" msgstr "Offline meddelanden" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestrem modul" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Publikprenumeration" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd publikprenumerations modul" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Pubsub prenumerationsforfrågan" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Välj om du vill godkänna hela denna prenumertion." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Node ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Prenumerationsadress" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Tillåt denna Jabber ID att prenumerera på denna pubsub node" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Skicka innehåll tillsammans med notifikationer" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Skicka eventnotifikation" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Meddela prenumeranter när nodens konfiguration ändras" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Meddela prenumeranter när noden tas bort" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Meddela prenumeranter när dataposter tas bort från noden" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Spara dataposter permanent" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Ett vänligt namn for noden" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Högsta antal dataposter som sparas" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Tillåta prenumerationer?" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Specificera accessmodellen" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Rostergrupper tillåts att prenumerera" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Ange publiceringsmodell" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 #, fuzzy msgid "Specify the event message type" msgstr "Specificera accessmodellen" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Högsta innehållsstorlek i bytes" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "När att skicka senast publicerade ämne" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Skicka notifikationer bara till uppkopplade användare" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Du behöver en klient som stödjer x:data för att registrera smeknamn" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Välj ett användarnamn och lösenord för att registrera mot denna server" @@ -1469,7 +1498,7 @@ msgstr "" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1480,7 +1509,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "IRC-användarnamn" @@ -1493,144 +1522,144 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Server ~b" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Lösenordsverifikation" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Kontaktlista" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Lösenord:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Lösenord:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Prenumeration" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Ännu inte godkända" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Grupper" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Validera" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Ta bort" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Kontaktlista för " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Lägg till Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Kontaktlista" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Delade Rostergrupper" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Namn:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Beskrivning:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Medlemmar:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Visade grupper:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Grupp " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Födelsedag" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Stad" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Land" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Efternamn" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1638,46 +1667,52 @@ msgstr "" "Fyll i formuläret för att söka efter en användare (lägg till * på slutet av " "fältet för att hitta alla som börjar så)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Fullständigt namn" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Mellannamn" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Organisationsnamn" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Organisationsenhet" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Sök efter användare på " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Du behöver en klient som stödjer x:data, för att kunna söka" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard användare sök" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard-modul" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Sökresultat för" -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Fyll i fält för att söka efter jabberanvändare" +#~ msgid "Delete" +#~ msgstr "Ta bort" + +#~ msgid "This room is not anonymous" +#~ msgstr "Detta rum är inte anonymt" + #~ msgid "Access denied by service policy" #~ msgstr "Åtkomst nekad enligt lokal policy" diff --git a/priv/msgs/th.po b/priv/msgs/th.po index 401c98715a6..6f2f5db865f 100644 --- a/priv/msgs/th.po +++ b/priv/msgs/th.po @@ -7,342 +7,343 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Thai (ภาษาไทย)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "ต้องใช้ STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "ไม่ได้ระบุข้อมูล" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "แทนที่ด้วยการเชื่อมต่อใหม่" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "ถูกไล่ออก" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 #, fuzzy msgid "Enter the text you see" msgstr "ป้อนพาธของไฟล์ข้อความ" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 #, fuzzy msgid "ejabberd Web Admin" msgstr "เว็บอินเทอร์เฟซของ ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "การดูแล" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "รายการควบคุมการเข้าถึง" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "ส่งแล้ว" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "รูปแบบที่ไม่ถูกต้อง" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "ส่ง" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "ข้อมูลดิบ" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "ลบข้อความที่เลือก" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "กฎการเข้าถึง" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s การกำหนดค่ากฎการเข้าถึง" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "โฮสต์เสมือน" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "ผู้ใช้" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "ผู้ใช้ออนไลน์" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "กิจกรรมล่าสุดของผู้ใช้" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "ระยะเวลา:" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "เดือนที่แล้ว" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "ปีที่แล้ว" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "กิจกรรมทั้งหมด" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "แสดงตารางทั่วไป" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "แสดงตารางรวม" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "สถิติ" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 #, fuzzy msgid "Not Found" msgstr "ไม่พบโหนด" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "ไม่พบโหนด" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "เพิ่มผู้ใช้ใหม่" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "โฮสต์" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "ผู้ใช้ที่ลงทะเบียน" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "ผู้ใช้" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "รหัสผ่าน" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "เพิ่มผู้ใช้" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "ข้อความออฟไลน์" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "กิจกรรมล่าสุด" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "ไม่เคย" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "ออนไลน์" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "ผู้ใช้ที่ลงทะเบียน:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "ผู้ใช้ออนไลน์:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "การเชื่อมต่อ s2s ขาออก:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "เซิร์ฟเวอร์ s2s ขาออก:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "ไม่มี" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "เปลี่ยนรหัสผ่าน" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "ผู้ใช้" -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "ทรัพยากรที่เชื่อมต่อ:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "รหัสผ่าน:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "ลบผู้ใช้" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "ไม่มีข้อมูล" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "โหนด" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "โหนดที่ทำงาน" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "โหนดที่หยุด" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "โหนด " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "ฐานข้อมูล" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "การสำรองข้อมูล " -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "พอร์ทฟัง" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "อัพเดต" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "เริ่มต้นใหม่" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "หยุด" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "โมดูล" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "ข้อผิดพลาดจากการเรียกใช้ RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "ตารางฐานข้อมูลที่" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "ชื่อ" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "ชนิดที่เก็บข้อมูล" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "หน่วยความจำ" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "การสำรองข้อมูล" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 #, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " @@ -352,489 +353,485 @@ msgstr "" "โปรดทราบว่าตัวเลือกเหล่านี้จะสำรองข้อมูลในฐานข้อมูล builtin Mnesia เท่านั้น หากคุณใช้โมดูล " "ODBC คุณต้องสำรองข้อมูลของฐานข้อมูล SQL แยกต่างหากด้วย" -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "จัดเก็บข้อมูลสำรองแบบไบนารี:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "ตกลง" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "คืนค่าข้อมูลสำรองแบบไบนารีโดยทันที:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "คืนค่าข้อมูลสำรองแบบไบนารีหลังจากที่ ejabberd ถัดไปเริ่มการทำงานใหม่ (ใช้หน่วยความจำน้อยลง):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "จัดเก็บข้อมูลสำรองที่เป็นข้อความธรรมดา:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "คืนค่าข้อมูลสำรองที่เป็นข้อความธรรมดาโดยทันที:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "อิมพอร์ตผู้ใช้จากไฟล์เก็บพักข้อมูล jabberd14" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "อิมพอร์ตผู้ใช้จากไฟล์เก็บพักข้อมูล jabberd14" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "พอร์ทฟังที่" -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "โมดูลที่ " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "สถิติของ ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "เวลาการทำงานต่อเนื่อง:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "เวลาการทำงานของ CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "ทรานแซกชันที่ได้รับมอบหมาย:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "ทรานแซกชันที่ถูกยกเลิก:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "ทรานแซกชันที่เริ่มทำงานใหม่อีกครั้ง:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "ทรานแซกชันที่บันทึก:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "อัพเดต " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "แผนการอัพเดต" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 #, fuzzy msgid "Modified modules" msgstr "โมดูลที่อัพเดต" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "อัพเดตสคริปต์" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "อัพเดตสคริปต์ระดับต่ำ" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "ตรวจสอบคริปต์" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "พอร์ท" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 #, fuzzy msgid "Protocol" msgstr "พอร์ท" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "โมดูล" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "ตัวเลือก" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "ลบ" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "เริ่ม" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "คำสั่ง" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "แน่ใจว่าต้องการลบข้อความของวันหรือไม่" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "หัวเรื่อง" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "เนื้อหาของข้อความ" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "ไม่ได้ป้อนเนื้อหาสำหรับข้อความที่ประกาศ" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "ประกาศ" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "ส่งประกาศถึงผู้ใช้ทั้งหมด" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "ส่งประกาศถึงผู้ใช้ทั้งหมดบนโฮสต์ทั้งหมด" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "ส่งประกาศถึงผู้ใช้ออนไลน์ทั้งหมด" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "ส่งประกาศถึงผู้ใช้ออนไลน์ทั้งหมดบนโฮสต์ทั้งหมด" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "ตั้งค่าข้อความของวันและส่งถึงผู้ใช้ออนไลน์" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "ตั้งค่าข้อความของวันบนโฮสต์ทั้งหมดและส่งถึงผู้ใช้ออนไลน์" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "อัพเดตข้อความของวัน (ไม่ต้องส่ง)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "อัพเดตข้อความของวันบนโฮสต์ทั้งหมด (ไม่ต้องส่ง) " -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "ลบข้อความของวัน" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "ลบข้อความของวันบนโฮสต์ทั้งหมด" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "การกำหนดค่า" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "เริ่มโมดูล" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "หยุดโมดูล" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "การคืนค่า" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "ถ่ายโอนข้อมูลไปยังไฟล์ข้อความ" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "อิมพอร์ตไฟล์" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "อิมพอร์ตไดเร็กทอรี" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "เริ่มต้นการบริการใหม่อีกครั้ง" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "ปิดการบริการ" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "ลบผู้ใช้" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "สิ้นสุดเซสชันของผู้ใช้" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "ขอรับรหัสผ่านของผู้ใช้" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "เปลี่ยนรหัสผ่านของผู้ใช้" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "แสดงเวลาเข้าสู่ระบบครั้งล่าสุดของผู้ใช้" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "แสดงสถิติของผู้ใช้" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "แสดงจำนวนผู้ใช้ที่ลงทะเบียน" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "แสดงจำนวนผู้ใช้ออนไลน์" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "การจัดการผู้ใช้" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "ผู้ใช้ทั้งหมด" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "การเชื่อมต่อ s2s ขาออก" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "การจัดการข้อมูลสำรอง" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "อิมพอร์ตผู้ใช้จากไฟล์เก็บพักข้อมูล jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "ถึง ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "จาก ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "การกำหนดค่าตารางฐานข้อมูลที่" -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "เลือกชนิดการจัดเก็บของตาราง" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "คัดลอกเฉพาะดิสก์" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "คัดลอก RAM และดิสก์" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "คัดลอก RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "คัดลอกระยะไกล" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "หยุดโมดูลที่" -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "เลือกโมดูลเพื่อหยุดการทำงาน" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "เริ่มโมดูลที่" -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "ป้อนรายการของ {โมดูล, [ตัวเลือก]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "รายการของโมดูลที่จะเริ่มการทำงาน" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "สำรองไฟล์ข้อมูลที่" -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "ป้อนพาธเพื่อสำรองไฟล์ข้อมูล" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "พาธของไฟล์ข้อมูล" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "คืนค่าการสำรองข้อมูลจากไฟล์ที่" -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "ถ่ายโอนการสำรองข้อมูลไปยังไฟล์ข้อความที่" -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "ป้อนพาธของไฟล์ข้อความ" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "อิมพอร์ตผู้ใช้จากไฟล์ที่" -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "ป้อนพาธไปยังไฟล์เก็บพักข้อมูล jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "อิมพอร์ตผู้ใช้จาก Dir ที่" -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "ป้อนพาธไปยัง jabberd14 spool dir" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "พาธไปยัง Dir" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "การหน่วงเวลา" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "การกำหนดค่ารายการควบคุมการเข้าถึง" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "รายการควบคุมการเข้าถึง" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "การกำหนดค่าการเข้าถึง" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "กฎการเข้าถึง" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "การตรวจสอบรหัสผ่าน" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "จำนวนผู้ใช้ที่ลงทะเบียน" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "จำนวนผู้ใช้ออนไลน์" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "การเข้าสู่ระบบครั้งล่าสุด" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "ขนาดของบัญชีรายชื่อ" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "ที่อยู่ IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "ทรัพยากร" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "การดูแล " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "การดำเนินการกับผู้ใช้" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "แก้ไขคุณสมบัติ" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -946,503 +943,535 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "ห้องสนทนา" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อลงทะเบียนชื่อเล่น" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "การลงทะเบียนชื่อเล่นที่ " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "ป้อนชื่อเล่นที่คุณต้องการลงทะเบียน" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "ชื่อเล่น" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC module" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "ห้องสนทนา" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "ออกจากห้อง" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "ผู้ใช้ที่ลงทะเบียน" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "มีการปรับเปลี่ยนการกำหนดค่าของห้องสนทนา" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "เข้าห้องสนทนานี้" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "ออกจากห้อง" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "ถูกสั่งห้าม" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "ซึ่งรู้จักกันในชื่อ" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " ตั้งหัวข้อว่า: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 #, fuzzy msgid "Chatroom is created" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 #, fuzzy msgid "Chatroom is destroyed" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 #, fuzzy msgid "Chatroom is started" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 #, fuzzy msgid "Chatroom is stopped" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "วันจันทร์" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "วันอังคาร" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "วันพุธ" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "วันพฤหัสบดี" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "วันศุกร์" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "วันเสาร์" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "วันอาทิตย์" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "มกราคม" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "กุมภาพันธ์" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "มีนาคม" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "เมษายน" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "พฤษภาคม" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "มิถุนายน" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "กรกฎาคม" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "สิงหาคม" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "กันยายน" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "ตุลาคม" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "พฤศจิกายน" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "ธันวาคม" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "การกำหนดค่าห้องสนทนา" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 #, fuzzy msgid "Room Occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "ผู้ดูแลการสนทนาและผู้เข้าร่วมเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "ห้องนี้ไม่ปิดบังชื่อ" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s ไม่ถูกต้อง" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "ไม่มีชื่อเล่น ~s อยู่ในห้องนี้" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "การเข้าร่วมที่ไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "บทบาทไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 #, fuzzy msgid "Configuration of room ~s" msgstr "การกำหนดค่าสำหรับ " -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "ชื่อห้อง" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 #, fuzzy msgid "Room description" msgstr "รายละเอียด:" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "สร้างเป็นห้องถาวร" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "สร้างเป็นห้องที่บุคคลทั่วไปสามารถค้นหาได้" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "สร้างรายการผู้เข้าร่วมสำหรับใช้งานโดยบุคคลทั่วไป" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "สร้างห้องที่มีการป้องกันด้วยรหัสผ่าน" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "จำนวนผู้ครอบครองห้องสูงสุด" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "ไม่จำกัด" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "แสดง Jabber IDs ที่ถูกต้องแก่" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "สำหรับผู้ดูแลการสนทนาเท่านั้น" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "ทุกคน" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "สร้างห้องสำหรับสมาชิกเท่านั้น" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 #, fuzzy msgid "Make room moderated" msgstr "สร้างเป็นห้องถาวร" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "ผู้ใช้เริ่มต้นเป็นผู้เข้าร่วม" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 #, fuzzy msgid "Allow users to change the subject" msgstr "อนุญาตให้ผู้ใช้เปลี่ยนหัวข้อได้" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "อนุญาตให้ผู้ใช้ถามคำถามกับผู้ใช้คนอื่นๆ ได้" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 #, fuzzy msgid "Allow visitors to change nickname" msgstr "อนุญาตให้ผู้ใช้เปลี่ยนหัวข้อได้" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "สร้างห้องที่มีการป้องกันด้วยรหัสผ่าน" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "เปิดใช้งานการบันทึก" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดค่าห้องสนทนา " -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "ส่วนตัว, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "ผู้ใช้" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s เชิญคุณเข้าร่วมสนทนาในห้อง ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "รหัสผ่านคือ" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s's ลำดับข้อความออฟไลน์" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "เวลา" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "จาก" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "ถึง" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "แพ็กเก็ต" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "ข้อความออฟไลน์:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 #, fuzzy msgid "Remove All Offline Messages" msgstr "ข้อความออฟไลน์" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "เผยแพร่-สมัครเข้าใช้งาน" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe module" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "คำร้องขอของผู้สมัครเข้าใช้งาน PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "เลือกว่าจะอนุมัติการสมัครเข้าใช้งานของเอนทิตี้นี้หรือไม่" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID โหนด" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "ที่อยู่ของผู้สมัคร" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "อนุญาตให้ Jabber ID นี้เข้าร่วมเป็นสมาชิกของโหนด pubsub หรือไม่" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "ส่งส่วนของข้อมูล (payload) พร้อมกับการแจ้งเตือนเหตุการณ์" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "ส่งการแจ้งเตือนเหตุการณ์" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "แจ้งเตือนผู้สมัครสมาชิกเมื่อการกำหนดค่าโหนดเปลี่ยนแปลง" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "แจ้งเตือนผู้สมัครสมาชิกเมื่อโหนดถูกลบ" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "แจ้งเตือนผู้สมัครสมาชิกเมื่อรายการถูกลบออกจากโหนด" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "ยืนยันรายการที่จะจัดเก็บ" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "จำนวนสูงสุดของรายการที่ยืนยัน" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "อนุญาตให้เข้าร่วมเป็นสมาชิกหรือไม่" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "ระบุโมเดลการเข้าถึง" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "ระบุโมเดลผู้เผยแพร่" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 #, fuzzy msgid "Specify the event message type" msgstr "ระบุโมเดลการเข้าถึง" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "ขนาดสูงสุดของส่วนของข้อมูล (payload) มีหน่วยเป็นไบต์" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "เวลาที่ส่งรายการที่เผยแพร่ครั้งล่าสุด" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "ส่งการแจ้งเตือนถึงผู้ใช้ที่สามารถติดต่อได้เท่านั้น" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อลงทะเบียนชื่อเล่น" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "เลือกชื่อผู้ใช้และรหัสผ่านเพื่อลงทะเบียนกับเซิร์ฟเวอร์นี้" @@ -1478,7 +1507,7 @@ msgstr "" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1489,7 +1518,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "ชื่อผู้ใช้ IRC" @@ -1502,144 +1531,144 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "ไม่เคย" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "การตรวจสอบรหัสผ่าน" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "บัญชีรายชื่อ" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "รหัสผ่าน:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "รหัสผ่าน:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "การสมัครสมาชิก" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "ค้างอยู่" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "กลุ่ม" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "ตรวจสอบ" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "ลบ" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "บัญชีรายชื่อของ " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "เพิ่ม Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "บัญชีรายชื่อ" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "กลุ่มบัญชีรายชื่อที่ใช้งานร่วมกัน" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "ชื่อ:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "รายละเอียด:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "สมาชิก:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "กลุ่มที่แสดง:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "กลุ่ม" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "วันเกิด" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "เมือง" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "ประเทศ" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "อีเมล" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "นามสกุล" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1647,46 +1676,52 @@ msgstr "" "กรอกข้อมูลในแบบฟอร์มเพื่อค้นหาผู้ใช้ Jabber ที่ตรงกัน (ใส่เครื่องหมาย * " "ที่ท้ายสุดของฟิลด์เพื่อจับคู่กับสตริงย่อย)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "ชื่อเต็ม" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "ชื่อกลาง" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "ชื่อองค์กร" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "หน่วยขององค์กร" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "ค้นหาผู้ใช้ใน " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อค้นหา" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "ค้นหาผู้ใช้ vCard " -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard module" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "ผลการค้นหาสำหรับ " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "กรอกข้อมูลลงในฟิลด์เพื่อค้นหาผู้ใช้ Jabber ที่ตรงกัน" +#~ msgid "Delete" +#~ msgstr "ลบ" + +#~ msgid "This room is not anonymous" +#~ msgstr "ห้องนี้ไม่ปิดบังชื่อ" + #~ msgid "Access denied by service policy" #~ msgstr "การเข้าถึงถูกปฏิเสธโดยนโยบายการบริการ" diff --git a/priv/msgs/tr.po b/priv/msgs/tr.po index bbf4240f16c..84a638baa6f 100644 --- a/priv/msgs/tr.po +++ b/priv/msgs/tr.po @@ -13,342 +13,343 @@ msgstr "" "X-Language: Turkish (türkçe)\n" "X-Generator: KBabel 1.11.4\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "STARTTLS kullanımı gereklidir" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Hiç kaynak sağlanmadı" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Eski bağlantı yenisi ile değiştirildi" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "odadan atıldı" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Gördüğünüz metni giriniz" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "~s kullanıcısına mesajlarınız engelleniyor. Durumu düzeltmek için ~s " "adresini ziyaret ediniz." -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "Eğer burada CAPTCHA resmini göremiyorsanız, web sayfasını ziyaret edin." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "CAPTCHA web sayfası" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "İnsan doğrulaması (captcha) geçerli." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Yetkisiz" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd Web Yöneticisi" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Yönetim" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Erişim Kontrol Listeleri (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Gönderilenler" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Kötü biçem" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Gönder" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Ham" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Seçilenleri Sil" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Erişim Kuralları" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s erişim kuralları ayarları" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Sanal Sunucuları" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Kullanıcılar" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Bağlı Kullanıcılar" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Kullanıcıların Son Aktiviteleri" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Periyot:" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Geçen ay" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Geçen yıl" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Tüm aktivite" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Sıradan Tabloyu Göster" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Önemli Tabloyu Göster" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "İstatistikler" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "Bulunamadı" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Düğüm bulunamadı" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Yeni Ekle" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Sunucu" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Kayıtlı Kullanıcılar" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Kullanıcı" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Parola" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Kullanıcı Ekle" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Çevirim-dışı Mesajlar" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Son Aktivite" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Asla" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Bağlı" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Kayıtlı Kullanıcılar:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Bağlı Kullanıcılar:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Giden s2s Bağlantıları:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Giden s2s Sunucuları" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Hiçbiri" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Parola Değiştir" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Kullanıcı " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Bağlı Kaynaklar:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Parola:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Kullanıcıyı Kaldır" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Veri Yok" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Düğümler" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Çalışan Düğümler" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Durdurulmuş Düğümler" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Düğüm " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Veritabanı" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Yedekle" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Dinlenen Kapılar (Portlar)" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "GÜncelle" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Tekrar Başlat" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Durdur" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modüller" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "RPC Çağrı Hatası" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Veritabanı Tabloları : " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "İsim" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Depolama Tipi" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Elementler" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Bellek" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Hata" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Yedek : " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -358,491 +359,487 @@ msgstr "" "edin. Eğer ODBC modülünü kullanıyorsanız, SQL veritabanınızı da ayrıca " "yedeklemeniz gerekiyor." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "İkili yedeği sakla:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Tamam" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Hemen ikili yedekten geri al:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "ejabberd'nin bir sonraki tekrar başlatılışında ikili yedekten geri al (daha " "az bellek gerektirir)" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Düz metin yedeği sakla:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Hemen düz metin yedekten geri al" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Kullanıcıları bir PIEFXIS dosyasından (XEP-0227) içe aktar:" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Sunucudaki tüm kullanıcıların verisini PIEFXIS dosyalarına (XEP-0227) dışa " "aktar:" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Bir sunucudaki kullanıcıların verisini PIEFXIS dosyalarına (XEP-0227) dışa " "aktar:" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Jabberd 1.4 Spool Dosyalarından Kullanıcıları İçe Aktar:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Jabberd 1.4 Spool Dizininden Kullanıcıları İçe Aktar:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Dinlenen Kapılar (Portlar) : " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Modüller : " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "~p istatistikleri" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Hizmet Süresi:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "İşlemci Zamanı:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Tamamlanan Hareketler (Transactions Committed):" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "İptal Edilen Hareketler (Transactions):" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Tekrar Başlatılan Hareketler (Transactions):" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Kaydı Tutulan Hareketler (Transactions):" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Güncelle " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Planı güncelle" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Değişen modüller" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Betiği Güncelle" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Düşük seviye güncelleme betiği" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Betik kontrolü" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Kapı (Port)" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Protokol" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Modül" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Seçenekler" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Sil" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Başlat" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Komutlar" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Günün mesajını silmek istediğinize emin misiniz?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Konu" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Mesajın gövdesi" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Duyuru mesajının gövdesi yok" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Duyurular" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Duyuruyu tüm kullanıcılara yolla" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Tüm sunuculardaki tüm kullanıcılara duyuru yolla" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Duyuruyu tüm bağlı kullanıcılara yolla" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Duyuruyu tüm sunuculardaki tüm bağlı kullanıcılara yolla" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Günün mesajını belirle" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Tüm sunucularda günün mesajını belirle ve bağlı tüm kullanıcılara gönder" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Günün mesajını güncelle (gönderme)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Tüm sunuculardaki günün mesajını güncelle (gönderme)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Günün mesajını sil" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Tüm sunuculardaki günün mesajını sil" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Ayarlar" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Modülleri Başlat" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Modülleri Durdur" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Yedekten Geri Al" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Metin Dosyasına Döküm Al" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Dosyayı İçe Aktar" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Dizini İçe Aktar" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Servisi Tekrar Başlat" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Servisi Kapat" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Kullanıcıyı Sil" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Kullanıcı Oturumunu Kapat" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Kullanıcı Parolasını Al" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Kullanıcı Parolasını Değiştir" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Kullanıcı Son Giriş Zamanınlarını Al" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Kullanıcı İstatistiklerini Al" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Kayıtlı Kullanıcı Sayısını Al" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Bağlı Kullanıcı Sayısını Al" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Kullanıcı Yönetimi" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Tüm Kullanıcılar" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Giden s2s Bağlantıları" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Yedek Yönetimi" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Jabberd 1.4 Spool Dosyalarından Kullanıcıları İçeri Aktar" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Kime ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Kimden ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Veritabanı Tablo Ayarları : " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Tabloların veri depolama tipini seçiniz" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Sadece disk kopyala" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "RAM ve disk kopyala" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "RAM kopyala" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Uzak kopyala" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Modülleri Durdur : " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Durdurulacak modülleri seçiniz" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Modülleri Başlat : " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "{Module, [Options]} listesi giriniz" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Başlatılacak modüllerin listesi" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Dosyaya Yedekle : " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Yedek dosyasının yolunu giriniz" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Dosyanın Yolu" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Dosyadaki Yedekten Geri Al : " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Metin Dosyasına Döküm Alarak Yedekle : " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Metin dosyasının yolunu giriniz" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Dosyadan Kullanıcıları İçe Aktar : " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "jabberd14 spool dosyası için yol giriniz" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Dizinden Kullanıcıları İçe Aktar : " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "jabberd14 spool dosyası için yol giriniz" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Dizinin Yolu" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Zaman gecikmesi" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Erişim Kontrol Listelerinin Ayarlanması (ACL)" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Erişim kontrol listeleri (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Erişim Ayarları" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Erişim kuralları" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Parola Doğrulaması" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Kayıtlı kullanıcı sayısı" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Bağlı kullanıcı sayısı" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Son giriş" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "İsim listesi boyutu" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP adresleri" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Kaynaklar" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Yönetim : " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Kullanıcıya uygulanacak eylem" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Özellikleri Düzenle" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -954,170 +951,194 @@ msgstr "Sunucu için kodlama ~b" msgid "Server ~b" msgstr "Sunucu ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Sohbet Odaları" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Takma isminizi kaydettirmek için x:data destekleyen bir istemciye " "gereksinimiz var" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Takma İsim Kaydı : " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Kaydettirmek istediğiniz takma ismi giriniz" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Takma isim" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC modülü" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Sohbet Odaları" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "odadan ayrıldı" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Kayıtlı Kullanıcılar" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Sohbet odası ayarı değiştirildi" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "odaya katıldı" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "odadan ayrıldı" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "odaya girmesi yasaklandı" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "ilişki değişikliğinden dolayı atıldı" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "oda üyelere-özel hale getirildiğinden dolayı atıldı" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "sistem kapandığından dolayı atıldı" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "isim değiştirdi :" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " konuyu değiştirdi: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Sohbet odası oluşturuldu" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Sohbet odası kaldırıldı" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Sohbet odası başlatıldı" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Sohbet odası durduruldu" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Pazartesi" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Salı" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Çarşamba" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Perşembe" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Cuma" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Cumartesi" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Pazar" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Ocak" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Şubat" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Mart" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Nisan" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Mayıs" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Haziran" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Temmuz" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Ağustos" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Eylül" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Ekim" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Kasım" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Aralık" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Oda Ayarları" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Oda Sakini Sayısı" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1125,320 +1146,328 @@ msgstr "" "Sadece moderatörlerin ve katılımcıların bu odanın konusunu değiştirmesine " "izin veriliyor" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Sadece moderatörlerin bu odanın konusunu değiştirmesine izin veriliyor" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Bu oda anonim değil" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s geçersiz" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "~s takma ismi odada yok" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Geçersiz ilişki: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Geçersiz rol: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "~s odasının ayarları" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Oda başlığı" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Oda tanımı" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Odayı kalıcı hale getir" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Odayı herkes tarafından aranabilir hale getir" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Katılımcı listesini herkese açık hale getir" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Odayı parola korumalı hale getir" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Odada En Fazla Bulunabilecek Kişi Sayısı" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Sınırsız" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Gerçek Jabber ID'lerini göster :" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "sadece moderatörler" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "herkes" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Odayı sadece üyelere açık hale getir" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Odayı moderasyonlu hale getir" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Kullanıcılar öntanımlı olarak katılımcı olsun" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Kullanıcıların konu değiştirmesine izin ver" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Kullanıcıların özel mesaj göndermelerine izin ver" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "Ziyaretçilerin özel mesaj göndermelerine izin ver" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "hiç kimse" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Kullanıcıların diğer kullanıcıları sorgulamalarına izin ver" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Kullanıcıların davetiye göndermelerine izin ver" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Ziyaretçilerin varlık (presence) güncellemelerinde durum metni " "göndermelerine izin ver" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Ziyaretçilerin takma isim değiştirmelerine izin ver" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "Ziyaretçilerin ses isteğine göndermelerine izin ver" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ses istekleri arasında olabilecek en az aralık (saniye olarak)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Odayı insan doğrulaması (captcha) korumalı hale getir" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA doğrulamasını şu Jabber ID'ler için yapma" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Kayıt tutma özelliğini aç" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "Odayı ayarlamak için x:data becerisine sahip bir istemciye gereksinimiz var" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Oda sakini sayısı" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "özel" -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "Ses isteği" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "Ses isteğini kabul edin ya da reddedin" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "Kullanıcı JID" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "Bu kişiye ses verelim mi?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s sizi ~s odasına davet ediyor" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "parola :" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s Kullanıcısının Mesaj Kuyruğu" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Zaman" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Kimden" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Kime" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Çevirim-dışı Mesajlar:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Tüm Çevirim-dışı Mesajları Kaldır" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modülü" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Yayınla-Üye Ol" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modülü" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub üye isteği" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Bu varlığın üyeliğini onaylayıp onaylamamayı seçiniz." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "Düğüm ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Üye Olanın Adresi" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Bu Jabber ID bu pubsub düğümüne üye olmasına izin verilsin mi?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Yükleri (payload) olay uyarıları ile beraber gönder" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Olay uyarıları gönderilsin" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Düğüm ayarları değiştiğinde üyeleri uyar" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Bir düğüm silindiğinde üyeleri uyar" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Düğümden öğeler kaldırıldığında üyeleri uyar" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Öğeleri depoda kalıcı hale getir" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Düğüm için dostane bir isim" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Kalıcı hale getirilecek en fazla öğe sayısı" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Üyeliklere izin verilsin mi" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Erişim modelini belirtiniz" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Üye olunmasına izin verilen kontak listesi grupları" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Yayıncı modelini belirtiniz" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "İlgili yayıncı çevirimdışı olunca tüm onunla ilgili olanları sil" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Olay mesaj tipini belirtiniz" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "En fazla yük (payload) boyutu (bayt olarak)" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Son yayınlanan öğe ne zaman gönderilsin" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Uyarıları sadece durumu uygun kullanıcılara ulaştır" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Bir düğüm ile bağlantılı koleksiyonlar" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Takma isminizi kaydettirmek için x:data ve CAPTCHA destekleyen bir istemciye " "gereksinimiz var" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Bu sunucuya kayıt olmak için bir kullanıcı ismi ve parola seçiniz" @@ -1474,7 +1503,7 @@ msgstr "Jabber Hesap Kaydı" msgid "Register a Jabber account" msgstr "Bir Jabber hesabı kaydet" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Bir Jabber hesabı kaydı sil" @@ -1489,7 +1518,7 @@ msgstr "" "kullanici_adi@sunucu. Lütfen alanları doğru doldurabilmek için yönergeleri " "dikkatle okuyunuz." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Kullanıcı adı:" @@ -1502,22 +1531,22 @@ msgstr "" msgid "Characters not allowed:" msgstr "İzin verilmeyen karakterler:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Sunucu:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "Parolanızı kimseye söylemeyin, Jabber sunucusunun yöneticilerine bile." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" "Parolanızı daha sonra bir Jabber istemci kullanarak değiştirebilirsiniz." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1525,7 +1554,7 @@ msgstr "" "Bazı Jabber istemcileri parolanızı bilgisayarınızda saklayabilir. Bu " "özelliği ancak bilgisayarın güvenli olduğuna güveniyorsanız kullanın." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1535,114 +1564,114 @@ msgstr "" "Jabber'da parolanızı unutursanız, otomatik kurtarmak için bir yöntem " "bulunmuyor." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Parola Doğrulaması:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Kayıt Ol" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Eski Parola:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Yeni Parola:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" "Bu sayfa bu Jabber sunucusundan bir Jabber hesabının kaydını silmeye olanak " "tanıyor." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Kaydı Sil" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Üyelik" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Sıra Bekleyen" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Gruplar" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Geçerli" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Kaldır" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Kontak Listesi : " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Jabber ID'si Ekle" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Kontak Listesi" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Paylaşımlı Kontak Listesi Grupları" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "İsim:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Tanım:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Üyeler:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Gösterilen Gruplar:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Group " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Sunucusu" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Doğumgünü" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "İl" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Ülke" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "E-posta" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Soyisim" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1650,47 +1679,53 @@ msgstr "" "Eşleşen jabber kullanıcılarını aramak için formu doldurunuz (Alt dizgi " "eşlemek için alanın sonuna * ekleyin)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Tam İsim" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Ortanca İsim" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Kurum İsmi" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Kurumun İlgili Birimi" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Kullanıcılarda arama yap : " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "" "Arama yapabilmek için x:data becerisine sahip bir istemciye gereksinimiz var" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard Kullanıcı Araması" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard modülü" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Arama sonuçları : " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Eşleşen jabber kullanıcılarını aramak için alanları doldurunuz" +#~ msgid "Delete" +#~ msgstr "Sil" + +#~ msgid "This room is not anonymous" +#~ msgstr "Bu oda anonim değil" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "Etkin mahremiyet listeniz bu bölümün yönlendirilmesini engelledi." diff --git a/priv/msgs/uk.po b/priv/msgs/uk.po index 5bf367f7ab5..d9f8b91395f 100644 --- a/priv/msgs/uk.po +++ b/priv/msgs/uk.po @@ -14,339 +14,340 @@ msgstr "" "X-Additional-Translator: Stoune\n" "X-Additional-Translator: Sergei Golovan\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Ви мусите використовувати STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Не вказаний ресурс" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Замінено новим з'єднанням" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "вигнали з кімнати" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "Введіть текст, що ви бачите" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Якщо ви не бачите зображення капчі, перейдіть за за цією адресою." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "Адреса капчі" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "Перевірку капчею закінчено успішно" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "Не авторизовано" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Веб-інтерфейс Адміністрування ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Адміністрування" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Списки керування доступом" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Відправлено" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Неправильний формат" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Відправити" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "необроблений формат" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Видалити виділені" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Правила доступу" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Конфігурація правила доступу ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "віртуальні хости" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Користувачі" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Підключені користувачі" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Статистика останнього підключення користувачів" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Період" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "За останній місяць" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "За останній рік" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Вся статистика" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Показати звичайну таблицю" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Показати інтегральну таблицю" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Статистика" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "не знайдено" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Вузол не знайдено" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Додати" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Хост" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Зареєстровані користувачі" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Користувач" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Пароль" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Додати користувача" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Офлайнові повідомлення" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Останнє підключення" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Ніколи" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Підключений" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Зареєстровані користувачі:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Підключені користувачі:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Вихідні s2s-з'єднання:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Вихідні s2s-сервери:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Немає" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Змінити пароль" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Користувач " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Підключені ресурси:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Пароль:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Видалити користувача" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Немає даних" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Вузли" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Працюючі вузли" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Зупинені вузли" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Вузол " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "База даних" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Резервне копіювання" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Відкриті порти" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Обновити" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Перезапустити" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Зупинити" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Модулі" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Помилка виклику RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Таблиці бази даних на " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Назва" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Тип таблиці" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "Елементи" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Пам'ять" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "Помилка" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Резервне копіювання " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -357,490 +358,486 @@ msgstr "" "(наприклад за допомогою модуля ODBC), то його резервне копіювання потрібно " "робити окремо." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Зберегти бінарну резервну копію:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "Продовжити" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Відновити з бінарної резервної копії негайно:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Відновити з бінарної резервної копії при наступному запуску (потребує менше " "пам'яті):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Зберегти текстову резервну копію:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Відновити з текстової резервної копії негайно:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Імпорт даних користовучів з файлу PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "Експорт даних всіх користувачів сервера до файлу PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Експорт даних користувачів домена до файлу PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "Імпорт користувачів з файла спула jabberd14:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "Імпорт користувачів з діректорії спула jabberd14:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Відкриті порти на " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Модулі на " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Статистика вузла ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Час роботи:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Процесорний час:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Транзакції завершені:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Транзакції відмінені:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Транзакції перезапущені:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Транзакції запротокольовані:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Поновлення " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "План поновлення" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "Змінені модулі" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Сценарій поновлення" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Низькорівневий сценарій поновлення" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Перевірка сценарію" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Порт" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "Протокол" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Модуль" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Параметри" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Видалити" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Запустити" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Команди" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Пінг" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Понг" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Насправді видалити повідомлення дня?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Тема" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Тіло повідомлення" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Тіло оголошення має бути непустим" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Сповіщення" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Надіслати сповіщення всім користувачам" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Надіслати сповіщення до усіх користувачів на усіх хостах" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Надіслати сповіщення всім підключеним користувачам" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Надіслати сповіщення всім підключеним користувачам на всіх віртуальних " "серверах" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Встановити повідомлення дня та надіслати його підключеним користувачам" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Встановити повідомлення дня на всіх хостах та надійслати його підключеним " "користувачам" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Оновити повідомлення дня (не надсилати)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Оновити повідомлення дня на всіх хостах (не надсилати)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Видалити повідомлення дня" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Видалити повідомлення дня на усіх хостах" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Конфігурація" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Запуск модулів" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Зупинка модулів" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Відновлення з резервної копії" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Копіювання в текстовий файл" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Імпорт з файла" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Імпорт з директорії" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Перезапустити Сервіс" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Вимкнути Сервіс" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Видалити Користувача" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Закінчити Сеанс Користувача" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Отримати Пароль Користувача" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Змінити Пароль Користувача" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Отримати Час Останнього Підключення Користувача" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Отримати Статистику по Користувачу" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Отримати Кількість Зареєстрованих Користувачів" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Отримати Кількість Підключених Користувачів" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Управління Користувачами" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Всі користувачі" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Вихідні s2s-з'єднання" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Керування резервним копіюванням" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Імпорт користувачів зі спулу jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "До ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Від ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Конфігурація таблиць бази даних на " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Оберіть тип збереження таблиць" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Тільки диск" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "ОЗП та диск" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "ОЗП" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "не зберігаеться локально" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Зупинка модулів на " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Виберіть модулі, які необхідно зупинити" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Запуск модулів на " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Введіть перелік такого виду {Module, [Options]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Список завантажуваних модулів" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Резервне копіювання в файл на " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Введіть шлях до резервного файла" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Шлях до файла" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Відновлення з резервної копії на " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Копіювання в текстовий файл на " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Введіть шлях до текстового файла" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Імпортування користувача з файла на " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Введіть шлях до файла зі спула jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Імпортування користувача з директорії на " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Введіть шлях до директорії спула jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Шлях до директорії" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Час затримки" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Конфігурація списків керування доступом" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Списки керування доступом" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Конфігурація доступу" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Правила доступу" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Перевірка Пароля" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Кількість зареєстрованих користувачів" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Кількість підключених користувачів" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Останнє підключення" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Кількість контактів" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP адреси" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Ресурси" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Адміністрування " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Дія над користувачем" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Змінити параметри" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -952,493 +949,525 @@ msgstr "Кодування для сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Кімнати" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:" "data" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Реєстрація псевдоніма на " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Введіть псевдонім, який ви хочете зареєструвати" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдонім" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Кімнати" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "вийшов(ла) з кімнати" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Зареєстровані користувачі" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Конфігурація кімнати змінилась" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "увійшов(ла) в кімнату" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "вийшов(ла) з кімнати" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "заборонили вхід в кімнату" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "вигнано з кімнати внаслідок зміни рангу" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "вигнано з кімнати тому, що вона стала тільки для учасників" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "вигнано з кімнати внаслідок зупинки системи" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "змінив(ла) псевдонім на" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " встановив(ла) тему: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "Створено кімнату" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "Знищено кімнату" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "Запущено кімнату" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "Зупинено кімнату" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Понеділок" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Вівторок" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Середа" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Четвер" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "П'ятниця" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Субота" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Неділя" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "січня" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "лютого" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "березня" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "квітня" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "травня" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "червня" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "липня" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "серпня" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "вересня" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "грудня" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "листопада" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "грудня" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Конфігурація кімнати" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "Учасники кімнати" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Тільки модератори та учасники можуть змінювати тему в цій кімнаті" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Ця кімната не анонімна" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s недопустимий" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Псевдонім ~s в кімнаті відсутній" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Недопустимий ранг: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Недопустима роль: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "Конфігурація кімнати ~s" -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Назва кімнати" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "Опис кімнати" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Зробити кімнату постійною" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Зробити кімнату видимою всім" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Зробити список учасників видимим всім" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Зробити кімнату захищеною паролем" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Максимальна кількість учасників" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Без обмежень" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Зробити реальні Jabber ID учасників видимими" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "тільки модераторам" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "всім учасникам" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Кімната тільки для зареєтрованых учасників" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Зробити кімнату модерованою" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Зробити користувачів учасниками за замовчуванням" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "Дозволити користувачам змінювати тему" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Дозволити приватні повідомлення" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Дозволити приватні повідомлення" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Дозволити iq-запити до користувачів" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Дозволити користувачам надсилати запрошення" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Дозволити відвідувачам відсилати текст статусу в оновленнях присутності" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Дозволити відвідувачам змінювати псевдонім" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Дозволити користувачам надсилати запрошення" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "Зробити кімнату захищеною капчею" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Пропускати ці Jabber ID без CAPTCHA-запиту" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Включити журнал роботи" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "Для конфігурування кімнати потрібно використовувати клієнт з підтримкою x:" "data" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Кількість присутніх" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "приватна, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Користувач " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s запрошує вас до кімнати ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "пароль:" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "Черга офлайнових повідомлень ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Час" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Від кого" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Кому" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Пакет" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Офлайнові повідомлення:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "Видалити всі офлайнові повідомлення" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams модуль" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Публікація-Підписка" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Модуль ejabberd Публікації-Підписки" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Запит на підписку PubSub" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Вирішіть, чи задовольнити запит цього об'єкту на підписку" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID вузла" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Адреса абонента" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Чи дозволити цьому Jabber ID підписатись новини наданого вузла" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Доставляти разом з повідомленнями про публікації самі публікації" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Доставляти сповіщення про події" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Повідомляти абонентів про зміни в конфігурації збірника" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Повідомляти абонентів про видалення збірника" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Повідомляти абонентів про видалення публікацій із збірника" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Зберегати публікації до сховища" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "Псевдонім для вузла" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Максимальне число збережених публікацій" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Дозволяти підписку" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Визначити модель доступу" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Дозволені для підписки групи ростера" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Умови публікації" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Видалити всі елементи, коли особа, що їх опублікувала, вимикається від мережі" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "Вкажіть тип повідомлень зі сповіщеннями про події" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Максимальний розмір корисного навантаження в байтах" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Коли надсилати останній опублікований елемент" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Доставляти повідомленнями тільки доступним користувачам" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "Колекція, до якої входить вузол" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:" "data" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Виберіть назву користувача та пароль для реєстрації на цьому сервері" @@ -1474,7 +1503,7 @@ msgstr "Реєстрація Jabber-акаунту" msgid "Register a Jabber account" msgstr "Зареєструвати Jabber-акаунт" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "Видалити Jabber-акаунт" @@ -1488,7 +1517,7 @@ msgstr "" "(ідентифікатор Jabber) матиме вигляд \"користувач@сервер\". Щоб вірно " "заповнити поля нижче, будь ласка, уважно читайте інструкції до них." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "Ім'я користувача:" @@ -1502,21 +1531,21 @@ msgstr "" msgid "Characters not allowed:" msgstr "Заборонені символи:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "Сервер:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "Нікому не кажіть свій пароль, навіть адміністраторам сервера." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "Пізніше можна змінити пароль через Jabber-клієнт." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1524,7 +1553,7 @@ msgstr "" "Деякі Jabber-клієнти можуть зберігати пароль на вашому комп'ютері. " "Користуйтесь цією функцією тільки у тому випадку, якщо вважаєте її безпечною." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1534,112 +1563,112 @@ msgstr "" "безпечному місці. У Jabber'і немає автоматизованих засобів відновлення " "пароля на той випадок, якщо ви його забудете." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "Перевірка Пароля:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "Реєстрація" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "Старий пароль:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "Новий Пароль:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "Ця сторінка дозволяє видалити свій акаунт з Jabber-сервера." -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "Видалити" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Підписка" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Очікування" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Групи" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Затвердити" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Видалити" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Ростер користувача " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Додати Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Ростер" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Спільні групи контактів" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Назва:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Опис:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Члени:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Видимі групи:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Група " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "День народження" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Місто" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Країна" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Електронна пошта" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Прізвище" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1647,46 +1676,52 @@ msgstr "" "Заповніть поля для пошуку користувача Jabber (Додайте * в кінець поля для " "пошуку підрядка)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Повне ім'я" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "По-батькові" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Назва організації" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Відділ організації" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Пошук користувачів в " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Для пошуку необхідний клієнт із підтримкою x:data" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Пошук користувачів по vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard модуль" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Результати пошуку в " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Заповніть поля для пошуку користувача Jabber" +#~ msgid "Delete" +#~ msgstr "Видалити" + +#~ msgid "This room is not anonymous" +#~ msgstr "Ця кімната не анонімна" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "" #~ "Маршрутизація цієї строфи була відмінена активним списком приватності." diff --git a/priv/msgs/vi.po b/priv/msgs/vi.po index c989ca09e65..dad52d6484d 100644 --- a/priv/msgs/vi.po +++ b/priv/msgs/vi.po @@ -7,342 +7,343 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Vietnamese (tiếng việt)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "Yêu cầu sử dụng STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Không có nguồn lực cung cấp" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Được thay thế bởi kết nối mới" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "đã bị đẩy ra khỏi" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 #, fuzzy msgid "Enter the text you see" msgstr "Nhập đường dẫn đến tập tin văn bản" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 #, fuzzy msgid "ejabberd Web Admin" msgstr "Giao diện Web ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Quản trị" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Danh Sách Kiểm Soát Truy Cập" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Đã gửi" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Định dạng hỏng" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Gửi" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Thô" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Tùy chọn Xóa được Chọn" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Quy Tắc Truy Cập" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s cấu hình quy tắc truy cập" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Máy Chủ Ảo" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Người sử dụng" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Người Sử Dụng Trực Tuyến" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Hoạt Động Cuối Cùng Của Người Sử Dụng" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Giai đoạn: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Tháng trước" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Năm trước" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Tất cả hoạt động" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Hiển Thị Bảng Thường" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Hiển Thị Bảng Đầy Đủ" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Số liệu thống kê" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 #, fuzzy msgid "Not Found" msgstr "Nút không tìm thấy" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nút không tìm thấy" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Thêm Mới" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Máy chủ" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Người Sử Dụng Đã Đăng Ký" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Người sử dụng" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Mật Khẩu" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Thêm Người Sử Dụng" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Thư Ngoại Tuyến" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Hoạt Động Cuối Cùng" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Không bao giờ" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Trực tuyến" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Người Sử Dụng Đã Đăng Ký:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Người Sử Dụng Trực Tuyến:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Kết Nối Bên Ngoài s2s:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Máy chủ Bên Ngoài s2s:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Không có" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Thay Đổi Mật Khẩu" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Người sử dụng " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Tài Nguyên Được Kết Nối:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Mật Khẩu:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Gỡ Bỏ Người Sử Dụng" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Không Dữ Liệu" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nút" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nút Hoạt Động" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nút Dừng" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nút " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Cơ sở dữ liệu" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sao lưu dự phòng" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Cổng Kết Nối" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Cập Nhật" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Khởi động lại" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Dừng" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Môđun" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Lỗi Gọi RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Bảng Cơ Sở Dữ Liệu tại" -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Tên" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Loại Lưu Trữ" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Bộ Nhớ" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Sao lưu dự phòng về" -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 #, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " @@ -353,493 +354,489 @@ msgstr "" "Mnesia. Nếu bạn đang sử dụng môđun ODBC, bạn cũng cần sao lưu cơ sở dữ liệu " "SQL của bạn riêng biệt." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Lưu dữ liệu sao lưu dạng nhị phân:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Khôi phục bản sao lưu dự phòng dạng nhị phận ngay lập tức:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Khôi phục bản sao lưu dự phòng dạng nhị phân sau lần khởi động ejabberd kế " "tiếp (yêu cầu ít bộ nhớ hơn):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Khôi phục bản sao lưu dự phòng thuần văn bản" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Khôi phục bản sao lưu dự phòng thuần văn bản ngay lập tức:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "Nhập Người Sử Dụng Từ Các Tập Tin Spool jabberd14" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Nhập Người Sử Dụng Từ Các Tập Tin Spool jabberd14" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Cổng Liên Lạc tại" -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Môđun tại " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Thống kê về ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Thời gian tải lên:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Thời Gian CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Giao Dịch Được Cam Kết:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Giao Dịch Hủy Bỏ:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Giao Dịch Khởi Động Lại:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Giao Dịch Được Ghi Nhận:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Cập Nhật " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Kế hoạch cập nhật" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 #, fuzzy msgid "Modified modules" msgstr "Môđun cập nhật" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Cập nhận lệnh" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Lệnh cập nhật mức độ thấp" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Lệnh kiểm tra" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Cổng" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 #, fuzzy msgid "Protocol" msgstr "Cổng" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Môđun" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Tùy chọn" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Xóa" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Khởi động" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Lệnh" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Có thực sự xóa thư trong ngày này không?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Tiêu đề" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Thân thư" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "Không có nội dung trong thư thông báo" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Thông báo" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Gửi thông báo đến tất cả người sử dụng" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Gửi thông báo đến tất cả người sử dụng trên tất cả các máy chủ" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Gửi thông báo đến tất cả người sử dụng trực tuyến" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "" "Gửi thông báo đến tất cả người sử dụng trực tuyến trên tất cả các máy chủ" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Tạo lập thư trong ngày và gửi đến những người sử dụng trực tuyến" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Tạo lập thư trong ngày trên tất cả các máy chủ và gửi đến những người sử " "dụng trực tuyến" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Cập nhật thư trong ngày (không gửi)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Cập nhật thư trong ngày trên tất cả các máy chủ (không gửi)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Xóa thư trong ngày" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Xóa thư trong ngày trên tất cả các máy chủ" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Cấu hình" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Môđun Khởi Động" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Môđun Dừng" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Khôi phục" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Kết xuất ra Tập Tin Văn Bản" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Nhập Tập Tin" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Nhập Thư Mục" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Khởi Động Lại Dịch Vụ" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Tắt Dịch Vụ" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Xóa Người Sử Dụng" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Kết Thúc Phiên Giao Dịch Người Sử Dụng" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Nhận Mật Khẩu Người Sử Dụng" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Thay Đổi Mật Khẩu Người Sử Dụng" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Nhận Thời Gian Đăng Nhập Cuối Cùng Của Người Sử Dụng" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Nhận Thông Tin Thống Kê Người Sử Dụng" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Nhận Số Người Sử Dụng Đã Đăng Ký" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Nhận Số Người Sử Dụng Trực Tuyến" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Quản Lý Người Sử Dụng" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Tất Cả Người Sử Dụng" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Kết Nối Bên Ngoài s2s" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Quản lý Sao Lưu Dự Phòng" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Nhập Người Sử Dụng Từ Các Tập Tin Spool jabberd14" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Gửi đến ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Nhận từ ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Cấu Hình Bảng Cơ Sở Dữ Liệu tại" -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Chọn loại bảng lưu trữ" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Chỉ sao chép vào đĩa" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Sao chép vào RAM và đĩa" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Sao chép vào RAM" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Sao chép từ xa" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Môđun Dừng tại" -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Chọn môđun để dừng" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Môđun Khởi Động tại " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Nhập danh sách {Môđun, [Các Tùy Chọn]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Danh sách các môđun khởi động" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Sao lưu dự phòng ra Tập Tin tại" -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Nhập đường dẫn đến tập tin sao lưu dự phòng" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Đường dẫn đến Tập Tin" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Phục hồi Sao Lưu từ Tập Tin tại " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Kết Xuất Sao Lưu ra Tập Tin Văn Bản tại" -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Nhập đường dẫn đến tập tin văn bản" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Nhập Người Sử Dụng từ Tập Tin tại" -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Nhập đường dẫn đến tập tin spool jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Nhập Người Sử Dụng từ Thư Mục tại" -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Nhập đường dẫn đến thư mục spool jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Đường Dẫn đến Thư Mục" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Thời gian trì hoãn" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Cấu Hình Danh Sách Kiểm Soát Truy Cập" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Danh sách kiểm soát truy cập" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Cấu Hình Truy Cập" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Quy tắc Truy Cập" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Kiểm Tra Mật Khẩu" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Số người sử dụng đã đăng ký" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Số người sử dụng trực tuyến" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Đăng nhập lần cuối" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Kích thước bảng phân công" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Địa chỉ IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Nguồn tài nguyên" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Quản trị về " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Hành động đối với người sử dụng" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Chỉnh Sửa Thuộc Tính" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -957,176 +954,200 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Phòng trò chuyện" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để đăng ký " "bí danh" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Đăng Ký Bí Danh tại" -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Nhập bí danh bạn muốn đăng ký" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Bí danh" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Môdun ejabberd MUC Bản quyền" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Phòng trò chuyện" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "rời khỏi phòng này" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Người Sử Dụng Đã Đăng Ký" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Cấu hình phòng trò chuyện được chỉnh sửa" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "tham gia phòng này" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "rời khỏi phòng này" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "đã bị cấm" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "bây giờ được biết như" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " đã đặt chủ đề thành: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 #, fuzzy msgid "Chatroom is created" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 #, fuzzy msgid "Chatroom is destroyed" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 #, fuzzy msgid "Chatroom is started" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 #, fuzzy msgid "Chatroom is stopped" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "Thứ Hai" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "Thứ Ba" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "Thứ Tư" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "Thứ Năm" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "Thứ Sáu" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "Thứ Bảy" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "Chủ Nhật" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "Tháng Một" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "Tháng Hai" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "Tháng Ba" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "Tháng Tư" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "Tháng Năm" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "Tháng Sáu" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "Tháng Bảy" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "Tháng Tám" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "Tháng Chín" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "Tháng Mười" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "Tháng Mười Một" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "Tháng Mười Hai" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Cấu Hình Phòng" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 #, fuzzy msgid "Room Occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " @@ -1135,333 +1156,341 @@ msgstr "" "Chỉ có những người điều phối và những người tham gia được phép thay đổi chủ " "đề trong phòng này" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Phòng này không nặc danh" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s không hợp lệ" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Bí danh ~s không tồn tại trong phòng này" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Tư cách không hợp lệ: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Vai trò không hợp lệ: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 #, fuzzy msgid "Configuration of room ~s" msgstr "Cấu hình cho " -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Tên phòng" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 #, fuzzy msgid "Room description" msgstr "Miêu tả:" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Tạo phòng bền vững" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Tạo phòng có thể tìm kiếm công khai" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Tạo danh sách người tham dự công khai" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Tạo phòng được bảo vệ bằng mật khẩu" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Số Lượng Người Tham Dự Tối Đa" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Không giới hạn" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Jabber ID thực tế hiện hành đến" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "nhà điều phối duy nhất" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "bất kỳ ai" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Tạo phòng chỉ cho phép tư cách thành viên tham gia" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 #, fuzzy msgid "Make room moderated" msgstr "Tạo phòng bền vững" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Người sử dụng mặc định là người tham dự" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 #, fuzzy msgid "Allow users to change the subject" msgstr "Cho phép người sử dụng thay đổi chủ đề" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Cho phép người sử dụng hỏi người sử dụng khác" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Cho phép người sử dụng gửi lời mời" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Cho phép người sử dụng thay đổi chủ đề" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Cho phép người sử dụng gửi lời mời" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Tạo phòng được bảo vệ bằng mật khẩu" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Cho phép ghi nhật ký" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định " "cấu hình phòng họp" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "riêng," -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Người sử dụng " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s mời bạn vào phòng ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "mật khẩu là" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s's Danh Sách Chờ Thư Ngoại Tuyến" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Thời Gian" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Từ" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Đến" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Gói thông tin" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Thư Ngoại Tuyến:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 #, fuzzy msgid "Remove All Offline Messages" msgstr "Thư Ngoại Tuyến" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Môdun SOCKS5 Bytestreams Bản quyền" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Xuất Bản-Đăng Ký" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Môdun ejabberd Xuất Bản-Đăng Ký Bản quyền" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Yêu cầu người đăng ký môđun Xuất Bản Đăng Ký" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Chọn có nên chấp nhận sự đăng ký của đối tượng này không" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID Nút" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Địa Chỉ Người Đăng Ký" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Cho phép Jabber ID đăng ký nút môđun xuất bản đăng ký này không?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Đưa ra thông tin dung lượng với các thông báo sự kiện" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Đưa ra các thông báo sự kiện" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Thông báo cho người đăng ký khi nào cấu hình nút thay đổi" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Thông báo cho người đăng ký khi nào nút bị xóa bỏ" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Thông báo cho người đăng ký khi nào các mục chọn bị gỡ bỏ khỏi nút" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Những mục cần để lưu trữ" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Số mục tối đa để lưu trữ" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Xác định nên cho phép đăng ký không" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Xác định mô hình truy cập" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Xác định mô hình nhà xuất bản" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 #, fuzzy msgid "Specify the event message type" msgstr "Xác định mô hình truy cập" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Kích thước dung lượng byte tối đa" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Khi cần gửi mục được xuất bản cuối cùng" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Chỉ gửi thông báo đến những người sử dụng hiện có" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để đăng ký " "bí danh" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "Chọn một tên truy cập và mật khẩu để đăng ký với máy chủ này" @@ -1497,7 +1526,7 @@ msgstr "" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1508,7 +1537,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "Tên truy cập IRC" @@ -1521,144 +1550,144 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Không bao giờ" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Kiểm Tra Mật Khẩu" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Bảng phân công" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Mật Khẩu:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Mật Khẩu:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Đăng ký" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Chờ" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Nhóm" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Xác nhận hợp lệ" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Gỡ bỏ" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Bảng phân công của " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Thêm Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Bảng phân công" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Nhóm Phân Công Chia Sẻ" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Tên:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Miêu tả:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Thành viên:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Nhóm được hiển thị:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Nhóm " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server Bản quyền" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Ngày sinh" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Thành phố" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Quốc gia" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Email" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "Họ" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1666,49 +1695,55 @@ msgstr "" "Điền vào mẫu này để tìm kiếm bất kỳ thông tin nào khớp với Người sử dụng " "Jabber (Thêm dấu * vào cuối ô để thông tin khớp với chuỗi bên trong)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "Tên Đầy Đủ" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "Họ Đệm" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Tên Tổ Chức" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Bộ Phận" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Tìm kiếm người sử dụng trong" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để tìm kiếm" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Tìm Kiếm Người Sử Dụng vCard" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Môdun ejabberd vCard Bản quyền" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Kết Quả Tìm Kiếm cho " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Điền vào các ô để tìm kiếm bất kỳ các thông tin nào khớp với Người sử dụng " "Jabber" +#~ msgid "Delete" +#~ msgstr "Xóa" + +#~ msgid "This room is not anonymous" +#~ msgstr "Phòng này không nặc danh" + #~ msgid "Access denied by service policy" #~ msgstr "Sự truy cập bị chặn theo chính sách phục vụ" diff --git a/priv/msgs/wa.po b/priv/msgs/wa.po index 9c3857cd85c..7f424fd4cbb 100644 --- a/priv/msgs/wa.po +++ b/priv/msgs/wa.po @@ -7,341 +7,342 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Walon (Walloon)\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "L' eployaedje di STARTTL est oblidjî" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "Nole rissoûce di dnêye" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "Replaecî pa on novea raloyaedje" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "a stî pité evoye" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 #, fuzzy msgid "Enter the text you see" msgstr "Dinez l' tchimin viè l' fitchî tecse" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Manaedjeu waibe ejabberd" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "Manaedjaedje" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Droets (ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "Candjmints evoyîs" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "Mwais fôrmat" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "Evoyî" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "Dinêyes brutes" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "Disfacer les elemints tchoezis" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "Rîles d' accès" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "Apontiaedje des rîles d' accès a ~s" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "Forveyous sierveus" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "Uzeus" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Uzeus raloyîs" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "Dierinne activité des uzeus" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "Termene:" -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "Dierin moes" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "Dierinne anêye" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "Dispoy todi" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "Mostrer crexhince" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "Mostrer totå" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "Sitatistikes" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 #, fuzzy msgid "Not Found" msgstr "Nuk nén trové" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "Nuk nén trové" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Radjouter" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "Sierveu" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "Uzeus edjistrés" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "Uzeu" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "Sicret" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "Radjouter èn uzeu" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "Messaedjes ki ratindèt" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "Dierinne activité" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "Måy" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "Raloyî" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "Uzeus edjistrés:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Uzeus raloyîs:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "Raloyaedjes s2s e rexhowe:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "Sierveus s2s e rexhowe:" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Nole" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Candjî l' sicret" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "Uzeu " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "Raloyî avou les rsoûces:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "Sicret:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "Disfacer l' uzeu" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "Nole dinêye disponibe" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "Nuks" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nuks en alaedje" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nuks essoctés" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "Nuk " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Båze di dnêyes" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Copeye di såvrité" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "Pôrts drovous" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "Mete a djoû" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "Renonder" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "Arester" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "Aroke di houcaedje RPC" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "Tåves del båze di dnêyes so " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "No" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "Sôre di wårdaedje" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "Memwere" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "Copeye di såvrité po " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 #, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " @@ -353,491 +354,487 @@ msgstr "" "båze di dnêyes avou l' module ODBC, vos dvoz fé ene copeye di såvrité del " "båze SQL da vosse sepårumint." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "Copeye di såvrité binaire:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "'l est bon" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "Rapexhî do côp foû d' ene copeye di såvrité binaire:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Rapexhî l' copeye di såvrité binaire après l' renondaedje ki vént " "d' ejabberd (çoula prind moens d' memwere del fé insi):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "Copeye di såvrité tecse:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "Rapexhî do côp foû d' ene copeye di såvrité tecse:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "Sititchî des uzeus Jabberd 1.4" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Sititchî des uzeus Jabberd 1.4" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "Pôrts drovous so " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "Modules so " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "Sitatistikes di ~p" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "Tins dispoy l' enondaedje:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "Tins CPU:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "Transaccions evoyeyes:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "Transaccions arestêyes:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "Transaccions renondêyes:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "Transaccions wårdêyes e djournå:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "Metaedje a djoû " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "Plan d' metaedje a djoû" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 #, fuzzy msgid "Modified modules" msgstr "Modules metous a djoû" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "Sicripe di metaedje a djoû" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "Sicripe di metaedje a djoû d' bas livea" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "Acertinaedje do scripe" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "Pôrt" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 #, fuzzy msgid "Protocol" msgstr "Pôrt" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "Tchuzes" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "Disfacer" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Enonder" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "Comandes" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "Voloz vs vormint disfacer l' messaedje do djoû?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "Sudjet" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "Coir do messaedje" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "I n' a nou coir do messaedje po ciste anonce la" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "Anonces" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "Evoyî l' anonce a tos les uzeus" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "Evoyî l' anonce a tos les uzeus so tos les lodjoes" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "Evoyî l' anonce a tos les uzeus raloyîs" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "Evoyî l' anonce a tos les uzeus raloyîs so tos les lodjoes" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "Defini l' messaedje do djoû et l' evoyî åzès uzeus raloyîs" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "" "Defini l' messaedje do djoû so tos les lodjoes et l' evoyî åzès uzeus raloyîs" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "Mete a djoû l' messaedje do djoû (nén l' evoyî)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "Mete a djoû l' messaedje do djoû so tos les lodjoes (nén l' evoyî)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "Disfacer l' messaedje do djoû" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "Disfacer l' messaedje do djoû so tos les lodjoes" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "Apontiaedjes" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Enonder des modules" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "Arester des modules" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Rapexhî" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "Schaper en on fitchî tecse" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "Sititchî d' on fitchî" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "Sititchî d' on ridant" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "Renonder siervice" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "Arester siervice" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "Disfacer èn uzeu" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "Fini l' session d' l' uzeu" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "Riçure sicret d' l' uzeu" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "Candjî l' sicret d' l' uzeu" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "Riçure li date/eure do dierin elodjaedje di l' uzeu" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "Riçure les statistikes di l' uzeu" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "Riçure li nombe d' uzeus edjîstrés" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "Riçure li nombe d' uzeus raloyîs" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Manaedjaedje des uzeus" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "Tos les uzeus" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "Raloyaedjes s2s e rexhowe" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "Manaedjaedje des copeyes di såvrité" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "Sititchî des uzeus Jabberd 1.4" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "Viè ~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "Dispoy ~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "Apontiaedje des tåves del båze di dnêyes so " -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "Tchoezi l' sôre di wårdaedje po les tåves" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "Copeye seulmint sol deure plake" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "Copeye e memwere (RAM) et sol deure plake" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "Copeye e memwere (RAM)" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "Copeye å lon" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "Arester les modules so " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "Tchoezixhoz les modules a-z arester" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "Renonder les modules so " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "Dinez ene djivêye del cogne {Module, [Tchuzes]}" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "Djivêye di modules a-z enonder" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "Fé ene copeye di såvrité dins on fitchî so " -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "Dinez l' tchimin viè l' fitchî copeye di såvrité" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "Tchimin viè l' fitchî" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "Rapexhî dispoy li fitchî copeye di såvrité so " -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "Copeye di såvritè viè on fitchî tecse so " -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "Dinez l' tchimin viè l' fitchî tecse" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "Sititchî uzeu d' on fitchî so " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "Dinez l' tchimin viè l' fitchî di spool jabberd14" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "Sitichî des uzeus d' on ridant so " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "Dinez l' tchimin viè l' ridant di spool jabberd14" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "Tchimin viè l' ridant" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "Tårdjaedje" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "Apontiaedje des droets (ACL)" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "Droets (ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "Apontiaedje des accès" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "Rîles d' accès" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "Acertinaedje do scret" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "Nombe d' uzeus edjîstrés" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "Nombe d' uzeus raloyîs" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "Dierin elodjaedje" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "Grandeu del djivêye des soçons" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "Adresses IP" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "Rissoûces" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "Manaedjaedje di " -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "Accion so l' uzeu" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "Candjî les prôpietés" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -955,176 +952,200 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "Såles di berdelaedje" -#: mod_muc.erl:914 +#: mod_muc.erl:997 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "Edjîstraedje di metou no amon " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "Dinez l' metou no ki vos vloz edjîstrer" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Metou no" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "Module MUC (såles di berdelaedje) po ejabberd" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "Såles di berdelaedje" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "cwite li såle" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "Uzeus edjistrés" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "L' apontiaedje del såle di berdelaedje a candjî" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "arive sol såle" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "cwite li såle" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "a stî bani" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "a stî pité evoye cåze d' on candjmint d' afiyaedje" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "" "a stî pité evoye cåze ki l' såle a stî ristrindowe åzès mimbes seulmint" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "a stî pité evoye cåze d' èn arestaedje do sistinme" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "est asteure kinoxhou come" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr " a candjî l' tite a: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 #, fuzzy msgid "Chatroom is created" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 #, fuzzy msgid "Chatroom is destroyed" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 #, fuzzy msgid "Chatroom is started" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 #, fuzzy msgid "Chatroom is stopped" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "londi" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "mårdi" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "mierkidi" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "djudi" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "vénrdi" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "semdi" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "dimegne" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "djanvî" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "fevrî" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "måss" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "avri" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "may" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "djun" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "djulete" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "awousse" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "setimbe" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "octôbe" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "nôvimbe" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "decimbe" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "Apontiaedje del såle" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 #, fuzzy msgid "Room Occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " @@ -1133,330 +1154,338 @@ msgstr "" "Seulmint les moderateus et les pårticipants polèt candjî l' sudjet dins " "cisse såle ci" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "Cisse såle ci n' est nén anonime" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Li Jabber ID ~s n' est nén valide" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "Li metou no ~s n' egzistêye nén dins l' såle" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "Afiyaedje nén valide: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "Role nén valide: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 #, fuzzy msgid "Configuration of room ~s" msgstr "Apontiaedje po " -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "Tite del såle" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 #, fuzzy msgid "Room description" msgstr "Discrijhaedje:" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "Rinde li såle permaninte" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "Rinde li såle di berdelaedje cweråve publicmint" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "Rinde publike li djivêye des pårticipants" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "Rinde li såle di berdelaedje protedjeye pa scret" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "Nombe macsimom di prezints" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "Pont d' limite" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "Mostrer les vraiys Jabber IDs a" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "les moderateus seulmint" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "tot l' minme kî" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "Rinde li såle di berdelaedje ristrindowe ås mimbes seulmint" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "Rinde li såle di berdelaedje moderêye" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "Les uzeus sont des pårticipants come prémetowe dujhance" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 #, fuzzy msgid "Allow users to change the subject" msgstr "Les uzeus polèt candjî l' tite" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "Les uzeus polèt evoyî des messaedjes privés" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Les uzeus polèt evoyî des messaedjes privés" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "Les uzeus polèt cweri ls ôtes uzeus" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "Les uzeus polèt evoyî priyaedjes" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permete ki les viziteus evoyexhe des tecse d' estat dins leus messaedjes di " "prezince" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "Permete ki les viziteus candjexhe leus metous nos" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Les uzeus polèt evoyî priyaedjes" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Rinde li såle di berdelaedje protedjeye pa scret" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "Mete en alaedje li djournå" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "I vs fåt on cliyint ki sopoite x:data por vos poleur apontyî l' såle" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 #, fuzzy msgid "User JID" msgstr "Uzeu " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s vos preye sol såle ~s" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "li scret est" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "messaedjes ki ratindèt el cawêye po ~s" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "Date" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "Di" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "Po" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Messaedjes ki ratindèt:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 #, fuzzy msgid "Remove All Offline Messages" msgstr "Messaedjes ki ratindèt" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Module SOCKS5 Bytestreams po ejabberd" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "Eplaidaedje-abounmint" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "Module d' eplaidaedje-abounmint po ejabberd" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "Dimande d' eplaidaedje-abounmint d' èn abouné" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "Tchoezi s' i fåt aprover ou nén l' abounmint di ciste intité." -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "ID d' nuk" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "Adresse di l' abouné" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" "Permete ki ci Jabber ID ci si poye abouner a ç' nuk eplaidaedje-abounmint ci?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "Evoyî l' contnou avou les notifiaedjes d' evenmints" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "Evoyî des notifiaedjes d' evenmints" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "Notifyî åzès abounés cwand l' apontiaedje do nuk candje" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "Notifyî åzès abounés cwand l' nuk est disfacé" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "Notifyî åzès abounés cwand des cayets sont oisté foû do nuk" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "Cayets permanints a wårder" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "On no uzeu-ahessåve pol nuk" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "Nombe macsimoms di cayets permanints" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "Si on permete les abounmints" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "Sipecifyî l' modele d' accès" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "Pårtaedjîs groupes di soçons k' on s' î pout abouner" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "Dinez l' modele d' eplaideu" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 #, fuzzy msgid "Specify the event message type" msgstr "Sipecifyî l' modele d' accès" -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "Contnou macsimom en octets" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "Cwand evoyî l' dierin cayet eplaidî" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "Seulmint evoyî des notifiaedje åzès uzeus disponibes" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:240 +#: mod_register.erl:250 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "" "Tchoezixhoz on no d' uzeu eyet on scret po vs edjîstrer so ç' sierveu ci" @@ -1493,7 +1522,7 @@ msgstr "" msgid "Register a Jabber account" msgstr "" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "" @@ -1504,7 +1533,7 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" msgstr "No d' uzeu IRC" @@ -1517,144 +1546,144 @@ msgstr "" msgid "Characters not allowed:" msgstr "" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" msgstr "Måy" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "" -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." msgstr "" -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy msgid "Password Verification:" msgstr "Acertinaedje do scret" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 #, fuzzy msgid "Register" msgstr "Djivêye des soçons" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" msgstr "Sicret:" -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 #, fuzzy msgid "New Password:" msgstr "Sicret:" -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "Abounmimnt" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "Ratindant" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "Groupes" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "Valider" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "Oister" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "Djivêye des soçons da " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "Radjouter èn ID Jabber" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "Djivêye des soçons" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "Pårtaedjîs groupes ezès djivêyes di soçons" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "Pitit no:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "Discrijhaedje:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "Mimbes:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "Groupes håynés:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "Groupe " -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Sierveu Jabber Erlang" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "Date d' askepiaedje" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "Veye" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "Payis" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "Emile" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "No d' famile" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" @@ -1662,46 +1691,52 @@ msgstr "" "Rimplixhoz les tchamps do formulaire po cweri èn uzeu Jabber (radjouter «*» " "al fén do tchamp po cweri tot l' minme kéne fén d' tchinne" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "No etir" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "No do mitan" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "No d' l' organizåcion" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "Unité d' l' organizåcion" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "Cweri des uzeus dins " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po fé on cweraedje" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "Calpin des uzeus" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "Module vCard ejabberd" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "Rizultats do cweraedje po " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "Rimplixhoz les tchamps po cweri èn uzeu Jabber" +#~ msgid "Delete" +#~ msgstr "Disfacer" + +#~ msgid "This room is not anonymous" +#~ msgstr "Cisse såle ci n' est nén anonime" + #~ msgid "Access denied by service policy" #~ msgstr "L' accès a stî rfuzé pal politike do siervice" diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index 8554049579b..0438b2e4d92 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -9,339 +9,340 @@ msgstr "" "X-Additional-Translator: Zhan Caibao - zhancaibao AT gmail DOT com\n" "X-Additional-Translator: Mike Wang\n" -#: ejabberd_c2s.erl:526 ejabberd_c2s.erl:873 +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" msgstr "要求使用 STARTTLS" -#: ejabberd_c2s.erl:624 +#: ejabberd_c2s.erl:626 msgid "No resource provided" msgstr "无资源提供" -#: ejabberd_c2s.erl:1397 +#: ejabberd_c2s.erl:1401 msgid "Replaced by new connection" msgstr "被新的连接替换" -#: ejabberd_c2s.erl:1401 mod_configure.erl:1855 mod_muc_log.erl:469 -#: mod_muc_log.erl:472 +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 msgid "has been kicked" msgstr "已被踢出" -#: ejabberd_c2s.erl:2504 +#: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:125 ejabberd_captcha.erl:248 ejabberd_captcha.erl:293 +#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" msgstr "请输入您所看到的文本" -#: ejabberd_captcha.erl:150 +#: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "您发送给 ~s 的消息已被阻止. 要解除阻止, 请访问 ~s" -#: ejabberd_captcha.erl:195 +#: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "如果您在这里没有看到验证码图片, 请访问网页." -#: ejabberd_captcha.erl:230 +#: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" msgstr "验证码网页" -#: ejabberd_captcha.erl:396 +#: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." msgstr "验证码有效." -#: ejabberd_web_admin.erl:201 ejabberd_web_admin.erl:213 -#: ejabberd_web_admin.erl:233 ejabberd_web_admin.erl:245 +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" msgstr "未认证的" -#: ejabberd_web_admin.erl:302 ejabberd_web_admin.erl:334 +#: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "ejabberd 网页管理" -#: ejabberd_web_admin.erl:592 ejabberd_web_admin.erl:603 +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 msgid "Administration" msgstr "管理" -#: ejabberd_web_admin.erl:660 ejabberd_web_admin.erl:696 mod_configure.erl:197 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 msgid "Access Control Lists" msgstr "访问控制列表(ACL)" -#: ejabberd_web_admin.erl:664 ejabberd_web_admin.erl:700 -#: ejabberd_web_admin.erl:768 ejabberd_web_admin.erl:801 -#: ejabberd_web_admin.erl:842 ejabberd_web_admin.erl:1319 -#: ejabberd_web_admin.erl:1600 ejabberd_web_admin.erl:1760 -#: ejabberd_web_admin.erl:1794 ejabberd_web_admin.erl:1874 -#: ejabberd_web_admin.erl:2046 ejabberd_web_admin.erl:2075 -#: ejabberd_web_admin.erl:2172 mod_offline.erl:777 mod_roster.erl:1490 -#: mod_shared_roster.erl:1169 mod_shared_roster.erl:1264 +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 msgid "Submitted" msgstr "已提交" -#: ejabberd_web_admin.erl:665 ejabberd_web_admin.erl:701 -#: ejabberd_web_admin.erl:769 ejabberd_web_admin.erl:802 -#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:1320 -#: ejabberd_web_admin.erl:1601 ejabberd_web_admin.erl:1761 -#: ejabberd_web_admin.erl:2047 ejabberd_web_admin.erl:2076 mod_roster.erl:1491 -#: mod_shared_roster.erl:1170 mod_shared_roster.erl:1265 +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" msgstr "格式错误" -#: ejabberd_web_admin.erl:676 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:850 -#: ejabberd_web_admin.erl:1863 mod_shared_roster.erl:1272 +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 msgid "Submit" msgstr "提交" -#: ejabberd_web_admin.erl:705 ejabberd_web_admin.erl:806 +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 msgid "Raw" msgstr "原始格式" -#: ejabberd_web_admin.erl:710 ejabberd_web_admin.erl:812 mod_offline.erl:799 -#: mod_shared_roster.erl:1178 +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 msgid "Delete Selected" msgstr "删除已选内容" -#: ejabberd_web_admin.erl:764 ejabberd_web_admin.erl:797 mod_configure.erl:199 -#: mod_configure.erl:534 +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 msgid "Access Rules" msgstr "访问规则" -#: ejabberd_web_admin.erl:838 +#: ejabberd_web_admin.erl:849 msgid "~s access rule configuration" msgstr "~s 访问规则配置" -#: ejabberd_web_admin.erl:856 +#: ejabberd_web_admin.erl:867 msgid "Virtual Hosts" msgstr "虚拟主机" -#: ejabberd_web_admin.erl:865 ejabberd_web_admin.erl:873 +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 msgid "Users" msgstr "用户" -#: ejabberd_web_admin.erl:880 ejabberd_web_admin.erl:1265 -#: mod_configure.erl:525 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "在线用户" -#: ejabberd_web_admin.erl:896 +#: ejabberd_web_admin.erl:907 msgid "Users Last Activity" msgstr "用户上次活动" -#: ejabberd_web_admin.erl:900 +#: ejabberd_web_admin.erl:911 msgid "Period: " msgstr "持续时间: " -#: ejabberd_web_admin.erl:913 +#: ejabberd_web_admin.erl:924 msgid "Last month" msgstr "上个月" -#: ejabberd_web_admin.erl:914 +#: ejabberd_web_admin.erl:925 msgid "Last year" msgstr "上一年" -#: ejabberd_web_admin.erl:916 +#: ejabberd_web_admin.erl:927 msgid "All activity" msgstr "所有活动" -#: ejabberd_web_admin.erl:919 +#: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" msgstr "显示普通列表" -#: ejabberd_web_admin.erl:922 +#: ejabberd_web_admin.erl:933 msgid "Show Integral Table" msgstr "显示完整列表" -#: ejabberd_web_admin.erl:929 ejabberd_web_admin.erl:1771 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:246 msgid "Statistics" msgstr "统计" -#: ejabberd_web_admin.erl:939 +#: ejabberd_web_admin.erl:950 msgid "Not Found" msgstr "没有找到" -#: ejabberd_web_admin.erl:952 +#: ejabberd_web_admin.erl:963 msgid "Node not found" msgstr "没有找到节点" -#: ejabberd_web_admin.erl:1174 ejabberd_web_admin.erl:2419 -#: mod_shared_roster.erl:1164 +#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "添加新用户" -#: ejabberd_web_admin.erl:1263 +#: ejabberd_web_admin.erl:1273 msgid "Host" msgstr "主机" -#: ejabberd_web_admin.erl:1264 +#: ejabberd_web_admin.erl:1274 msgid "Registered Users" msgstr "注册用户" -#: ejabberd_web_admin.erl:1328 ejabberd_web_admin.erl:1383 -#: mod_register.erl:252 mod_vcard.erl:486 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 +#: mod_register.erl:262 mod_vcard.erl:490 msgid "User" msgstr "用户" -#: ejabberd_web_admin.erl:1333 mod_configure.erl:1399 mod_configure.erl:1486 -#: mod_configure.erl:1890 mod_configure.erl:2125 mod_muc_room.erl:3347 -#: mod_register.erl:262 +#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 +#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 +#: mod_register.erl:272 msgid "Password" msgstr "密码" -#: ejabberd_web_admin.erl:1342 mod_configure.erl:178 mod_configure.erl:540 -#: mod_configure.erl:1387 +#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: mod_configure.erl:1386 msgid "Add User" msgstr "添加用户" -#: ejabberd_web_admin.erl:1384 +#: ejabberd_web_admin.erl:1394 msgid "Offline Messages" msgstr "离线消息" -#: ejabberd_web_admin.erl:1385 ejabberd_web_admin.erl:1611 +#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 msgid "Last Activity" msgstr "上次活动" -#: ejabberd_web_admin.erl:1403 ejabberd_web_admin.erl:1583 -#: mod_configure.erl:1918 +#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 +#: mod_configure.erl:1917 msgid "Never" msgstr "从未" -#: ejabberd_web_admin.erl:1421 ejabberd_web_admin.erl:1594 -#: mod_configure.erl:1928 +#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 +#: mod_configure.erl:1927 msgid "Online" msgstr "在线" -#: ejabberd_web_admin.erl:1477 ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 msgid "Registered Users:" msgstr "注册用户:" -#: ejabberd_web_admin.erl:1480 ejabberd_web_admin.erl:1499 -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "在线用户:" -#: ejabberd_web_admin.erl:1483 +#: ejabberd_web_admin.erl:1493 msgid "Outgoing s2s Connections:" msgstr "出站 s2s 连接:" -#: ejabberd_web_admin.erl:1486 +#: ejabberd_web_admin.erl:1496 msgid "Outgoing s2s Servers:" msgstr "出站 s2s 服务器" -#: ejabberd_web_admin.erl:1522 ejabberd_web_admin.erl:1718 -#: ejabberd_web_admin.erl:1728 ejabberd_web_admin.erl:2140 mod_roster.erl:1426 +#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "无" -#: ejabberd_web_admin.erl:1575 mod_register_web.erl:188 -#: mod_register_web.erl:346 mod_register_web.erl:354 mod_register_web.erl:378 +#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "更改密码" -#: ejabberd_web_admin.erl:1596 +#: ejabberd_web_admin.erl:1610 #, fuzzy msgid "User ~s" msgstr "用户 " -#: ejabberd_web_admin.erl:1607 +#: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" msgstr "已连接资源:" -#: ejabberd_web_admin.erl:1609 mod_register_web.erl:238 -#: mod_register_web.erl:474 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "密码:" -#: ejabberd_web_admin.erl:1616 mod_configure.erl:2119 +#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 msgid "Remove User" msgstr "删除用户" -#: ejabberd_web_admin.erl:1664 +#: ejabberd_web_admin.erl:1678 msgid "No Data" msgstr "没有数据" -#: ejabberd_web_admin.erl:1737 +#: ejabberd_web_admin.erl:1751 msgid "Nodes" msgstr "节点" -#: ejabberd_web_admin.erl:1738 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 msgid "Running Nodes" msgstr "运行中的节点" -#: ejabberd_web_admin.erl:1739 mod_configure.erl:530 +#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "已经停止的节点" -#: ejabberd_web_admin.erl:1757 ejabberd_web_admin.erl:1782 +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 #, fuzzy msgid "Node ~p" msgstr "节点 " -#: ejabberd_web_admin.erl:1766 mod_configure.erl:151 mod_configure.erl:612 +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "数据库" -#: ejabberd_web_admin.erl:1767 mod_configure.erl:160 mod_configure.erl:649 +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "备份" -#: ejabberd_web_admin.erl:1769 +#: ejabberd_web_admin.erl:1783 msgid "Listened Ports" msgstr "被监听的端口" -#: ejabberd_web_admin.erl:1772 ejabberd_web_admin.erl:2187 -#: ejabberd_web_admin.erl:2395 +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 msgid "Update" msgstr "更新" -#: ejabberd_web_admin.erl:1776 ejabberd_web_admin.erl:2539 +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 msgid "Restart" msgstr "重启" -#: ejabberd_web_admin.erl:1778 ejabberd_web_admin.erl:2543 +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 msgid "Stop" msgstr "停止" -#: ejabberd_web_admin.erl:1785 mod_configure.erl:614 mod_configure.erl:627 +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "模块" -#: ejabberd_web_admin.erl:1790 +#: ejabberd_web_admin.erl:1804 msgid "RPC Call Error" msgstr "RPC 调用错误" -#: ejabberd_web_admin.erl:1841 +#: ejabberd_web_admin.erl:1855 #, fuzzy msgid "Database Tables at ~p" msgstr "数据库列表位于 " -#: ejabberd_web_admin.erl:1851 mod_vcard.erl:486 mod_vcard.erl:612 +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "姓名" -#: ejabberd_web_admin.erl:1852 +#: ejabberd_web_admin.erl:1866 msgid "Storage Type" msgstr "存储类型" -#: ejabberd_web_admin.erl:1853 +#: ejabberd_web_admin.erl:1867 msgid "Elements" msgstr "元素" -#: ejabberd_web_admin.erl:1854 +#: ejabberd_web_admin.erl:1868 msgid "Memory" msgstr "内存" -#: ejabberd_web_admin.erl:1876 ejabberd_web_admin.erl:2049 +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 msgid "Error" msgstr "错误" -#: ejabberd_web_admin.erl:1879 +#: ejabberd_web_admin.erl:1893 #, fuzzy msgid "Backup of ~p" msgstr "备份来源 " -#: ejabberd_web_admin.erl:1885 +#: ejabberd_web_admin.erl:1897 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -350,484 +351,480 @@ msgstr "" "注意:这些选项仅将备份内置的 Mnesia 数据库. 如果您正在使用 ODBC 模块, 您还需" "要分别备份您的数据库." -#: ejabberd_web_admin.erl:1895 +#: ejabberd_web_admin.erl:1907 msgid "Store binary backup:" msgstr "存储为二进制备份:" -#: ejabberd_web_admin.erl:1902 ejabberd_web_admin.erl:1912 -#: ejabberd_web_admin.erl:1923 ejabberd_web_admin.erl:1932 -#: ejabberd_web_admin.erl:1942 ejabberd_web_admin.erl:1955 -#: ejabberd_web_admin.erl:1967 ejabberd_web_admin.erl:1983 -#: ejabberd_web_admin.erl:1999 ejabberd_web_admin.erl:2010 -#: ejabberd_web_admin.erl:2020 +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 msgid "OK" msgstr "确定" -#: ejabberd_web_admin.erl:1905 +#: ejabberd_web_admin.erl:1917 msgid "Restore binary backup immediately:" msgstr "立即恢复二进制备份:" -#: ejabberd_web_admin.erl:1915 +#: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "在下次 ejabberd 重启后恢复二进制备份(需要的内存更少):" -#: ejabberd_web_admin.erl:1925 +#: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" msgstr "存储为普通文本备份:" -#: ejabberd_web_admin.erl:1935 +#: ejabberd_web_admin.erl:1947 msgid "Restore plain text backup immediately:" msgstr "立即恢复普通文本备份:" -#: ejabberd_web_admin.erl:1945 +#: ejabberd_web_admin.erl:1957 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "从 PIEFXIS 文件 (XEP-0227) 导入用户数据:" -#: ejabberd_web_admin.erl:1958 +#: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "将服务器上所有用户的数据导出到 PIEFXIS 文件 (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "将某主机的用户数据导出到 PIEFXIS 文件 (XEP-0227):" -#: ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2002 +#: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" msgstr "从 jabberd14 Spool 文件导入用户数据:" -#: ejabberd_web_admin.erl:2013 +#: ejabberd_web_admin.erl:2025 msgid "Import users data from jabberd14 spool directory:" msgstr "从 jabberd14 Spool 目录导入用户数据:" -#: ejabberd_web_admin.erl:2041 +#: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " msgstr "监听的端口位于 " -#: ejabberd_web_admin.erl:2070 +#: ejabberd_web_admin.erl:2082 #, fuzzy msgid "Modules at ~p" msgstr "模块位于 " -#: ejabberd_web_admin.erl:2101 +#: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" msgstr "~p 的统计" -#: ejabberd_web_admin.erl:2105 +#: ejabberd_web_admin.erl:2117 msgid "Uptime:" msgstr "正常运行时间:" -#: ejabberd_web_admin.erl:2109 +#: ejabberd_web_admin.erl:2121 msgid "CPU Time:" msgstr "CPU 时间:" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "提交的事务:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2133 msgid "Transactions Aborted:" msgstr "取消的事务:" -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:2137 msgid "Transactions Restarted:" msgstr "重启的事务:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2141 msgid "Transactions Logged:" msgstr "记入日志的事务:" -#: ejabberd_web_admin.erl:2169 +#: ejabberd_web_admin.erl:2181 #, fuzzy msgid "Update ~p" msgstr "更新 " -#: ejabberd_web_admin.erl:2180 +#: ejabberd_web_admin.erl:2192 msgid "Update plan" msgstr "更新计划" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2193 msgid "Modified modules" msgstr "被修改模块" -#: ejabberd_web_admin.erl:2182 +#: ejabberd_web_admin.erl:2194 msgid "Update script" msgstr "更新脚本" -#: ejabberd_web_admin.erl:2183 +#: ejabberd_web_admin.erl:2195 msgid "Low level update script" msgstr "低级别更新脚本" -#: ejabberd_web_admin.erl:2184 +#: ejabberd_web_admin.erl:2196 msgid "Script check" msgstr "脚本检查" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2364 +#: ejabberd_web_admin.erl:2376 msgid "Port" msgstr "端口" -#: ejabberd_web_admin.erl:2365 +#: ejabberd_web_admin.erl:2377 msgid "Protocol" msgstr "协议" -#: ejabberd_web_admin.erl:2366 ejabberd_web_admin.erl:2521 +#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 msgid "Module" msgstr "模块" -#: ejabberd_web_admin.erl:2367 ejabberd_web_admin.erl:2522 +#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 msgid "Options" msgstr "选项" -#: ejabberd_web_admin.erl:2399 -msgid "Delete" -msgstr "删除" - -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "开始" -#: mod_adhoc.erl:112 mod_adhoc.erl:146 mod_adhoc.erl:166 mod_adhoc.erl:189 +#: mod_adhoc.erl:114 mod_adhoc.erl:148 mod_adhoc.erl:168 mod_adhoc.erl:191 msgid "Commands" msgstr "命令" -#: mod_adhoc.erl:174 mod_adhoc.erl:263 +#: mod_adhoc.erl:176 mod_adhoc.erl:265 msgid "Ping" msgstr "Ping" -#: mod_adhoc.erl:277 +#: mod_adhoc.erl:279 msgid "Pong" msgstr "Pong" -#: mod_announce.erl:532 +#: mod_announce.erl:523 msgid "Really delete message of the day?" msgstr "确实要删除每日消息吗?" -#: mod_announce.erl:545 mod_configure.erl:1239 mod_configure.erl:1299 +#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" msgstr "标题" -#: mod_announce.erl:553 mod_configure.erl:1245 mod_configure.erl:1305 +#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 msgid "Message body" msgstr "消息主体" -#: mod_announce.erl:636 +#: mod_announce.erl:627 msgid "No body provided for announce message" msgstr "通知消息无正文内容" -#: mod_announce.erl:671 +#: mod_announce.erl:662 msgid "Announcements" msgstr "通知" -#: mod_announce.erl:673 +#: mod_announce.erl:664 msgid "Send announcement to all users" msgstr "发送通知给所有用户" -#: mod_announce.erl:675 +#: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "发送通知给所有主机上的所有用户" -#: mod_announce.erl:677 +#: mod_announce.erl:668 msgid "Send announcement to all online users" msgstr "发送通知给所有在线用户" -#: mod_announce.erl:679 mod_configure.erl:1232 mod_configure.erl:1292 +#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" msgstr "发送通知给所有主机的在线用户" -#: mod_announce.erl:681 +#: mod_announce.erl:672 msgid "Set message of the day and send to online users" msgstr "设定每日消息并发送给所有在线用户" -#: mod_announce.erl:683 +#: mod_announce.erl:674 msgid "Set message of the day on all hosts and send to online users" msgstr "设置所有主机上的每日消息并发送给在线用户" -#: mod_announce.erl:685 +#: mod_announce.erl:676 msgid "Update message of the day (don't send)" msgstr "更新每日消息(不发送)" -#: mod_announce.erl:687 +#: mod_announce.erl:678 msgid "Update message of the day on all hosts (don't send)" msgstr "更新所有主机上的每日消息(不发送)" -#: mod_announce.erl:689 +#: mod_announce.erl:680 msgid "Delete message of the day" msgstr "删除每日消息" -#: mod_announce.erl:691 +#: mod_announce.erl:682 msgid "Delete message of the day on all hosts" msgstr "删除所有主机上的每日消息" -#: mod_configure.erl:141 mod_configure.erl:297 mod_configure.erl:319 -#: mod_configure.erl:523 +#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 +#: mod_configure.erl:522 msgid "Configuration" msgstr "配置" -#: mod_configure.erl:154 mod_configure.erl:637 +#: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "启动模块" -#: mod_configure.erl:157 mod_configure.erl:639 +#: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" msgstr "停止模块" -#: mod_configure.erl:163 mod_configure.erl:651 +#: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "恢复" -#: mod_configure.erl:166 mod_configure.erl:653 +#: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" msgstr "转储到文本文件" -#: mod_configure.erl:169 mod_configure.erl:664 +#: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" msgstr "导入文件" -#: mod_configure.erl:172 mod_configure.erl:666 +#: mod_configure.erl:171 mod_configure.erl:665 msgid "Import Directory" msgstr "导入目录" -#: mod_configure.erl:174 mod_configure.erl:620 mod_configure.erl:1206 +#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 msgid "Restart Service" msgstr "重启服务" -#: mod_configure.erl:176 mod_configure.erl:622 mod_configure.erl:1266 +#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 msgid "Shut Down Service" msgstr "关闭服务" -#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1420 +#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 msgid "Delete User" msgstr "删除用户" -#: mod_configure.erl:182 mod_configure.erl:543 mod_configure.erl:1438 +#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 msgid "End User Session" msgstr "结束用户会话" -#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1456 -#: mod_configure.erl:1474 +#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 +#: mod_configure.erl:1473 msgid "Get User Password" msgstr "获取用户密码" -#: mod_configure.erl:186 mod_configure.erl:547 +#: mod_configure.erl:185 mod_configure.erl:546 msgid "Change User Password" msgstr "更改用户密码" -#: mod_configure.erl:188 mod_configure.erl:549 mod_configure.erl:1501 +#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 msgid "Get User Last Login Time" msgstr "获取用户上次登陆时间" -#: mod_configure.erl:190 mod_configure.erl:551 mod_configure.erl:1518 +#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 msgid "Get User Statistics" msgstr "获取用户统计" -#: mod_configure.erl:192 mod_configure.erl:553 +#: mod_configure.erl:191 mod_configure.erl:552 msgid "Get Number of Registered Users" msgstr "获取注册用户数" -#: mod_configure.erl:195 mod_configure.erl:555 +#: mod_configure.erl:194 mod_configure.erl:554 msgid "Get Number of Online Users" msgstr "获取在线用户数" -#: mod_configure.erl:321 mod_configure.erl:524 +#: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "用户管理" -#: mod_configure.erl:526 +#: mod_configure.erl:525 msgid "All Users" msgstr "所有用户" -#: mod_configure.erl:527 +#: mod_configure.erl:526 msgid "Outgoing s2s Connections" msgstr "出站 s2s 连接" -#: mod_configure.erl:616 +#: mod_configure.erl:615 msgid "Backup Management" msgstr "备份管理" -#: mod_configure.erl:618 +#: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" msgstr "从 jabberd14 Spool 文件导入用户" -#: mod_configure.erl:763 +#: mod_configure.erl:762 msgid "To ~s" msgstr "发送给~s" -#: mod_configure.erl:783 +#: mod_configure.erl:782 msgid "From ~s" msgstr "来自~s" -#: mod_configure.erl:1003 +#: mod_configure.erl:1002 msgid "Database Tables Configuration at " msgstr "数据库表格配置位于" -#: mod_configure.erl:1009 +#: mod_configure.erl:1008 msgid "Choose storage type of tables" msgstr "请选择表格的存储类型" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "仅磁盘复制" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM and disc copy" msgstr "内存与磁盘复制" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "RAM copy" msgstr "内存(RAM)复制" -#: mod_configure.erl:1018 mod_configure.erl:1020 +#: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Remote copy" msgstr "远程复制" -#: mod_configure.erl:1046 +#: mod_configure.erl:1045 msgid "Stop Modules at " msgstr "要停止的模块位于 " -#: mod_configure.erl:1052 +#: mod_configure.erl:1051 msgid "Choose modules to stop" msgstr "请选择要停止的模块" -#: mod_configure.erl:1073 +#: mod_configure.erl:1072 msgid "Start Modules at " msgstr "要启动的模块位于 " -#: mod_configure.erl:1079 +#: mod_configure.erl:1078 msgid "Enter list of {Module, [Options]}" msgstr "请输入{模块, [选项]}列表" -#: mod_configure.erl:1081 +#: mod_configure.erl:1080 msgid "List of modules to start" msgstr "要启动的模块列表" -#: mod_configure.erl:1095 +#: mod_configure.erl:1094 msgid "Backup to File at " msgstr "备份文件位于" -#: mod_configure.erl:1100 mod_configure.erl:1121 +#: mod_configure.erl:1099 mod_configure.erl:1120 msgid "Enter path to backup file" msgstr "请输入备份文件的路径" -#: mod_configure.erl:1101 mod_configure.erl:1122 mod_configure.erl:1143 -#: mod_configure.erl:1164 +#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 +#: mod_configure.erl:1163 msgid "Path to File" msgstr "文件路径" -#: mod_configure.erl:1116 +#: mod_configure.erl:1115 msgid "Restore Backup from File at " msgstr "要恢复的备份文件位于" -#: mod_configure.erl:1137 +#: mod_configure.erl:1136 msgid "Dump Backup to Text File at " msgstr "转储备份到文本文件于" -#: mod_configure.erl:1142 +#: mod_configure.erl:1141 msgid "Enter path to text file" msgstr "请输入文本文件的路径" -#: mod_configure.erl:1157 +#: mod_configure.erl:1156 msgid "Import User from File at " msgstr "导入用户的文件位于 " -#: mod_configure.erl:1163 +#: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" msgstr "请输入 jabberd14 spool 文件的路径" -#: mod_configure.erl:1178 +#: mod_configure.erl:1177 msgid "Import Users from Dir at " msgstr "导入用户的目录位于 " -#: mod_configure.erl:1184 +#: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" msgstr "请输入 jabberd14 spool 目录的路径" -#: mod_configure.erl:1185 +#: mod_configure.erl:1184 msgid "Path to Dir" msgstr "目录的路径" -#: mod_configure.erl:1210 mod_configure.erl:1270 +#: mod_configure.erl:1209 mod_configure.erl:1269 msgid "Time delay" msgstr "时间延迟" -#: mod_configure.erl:1317 +#: mod_configure.erl:1316 msgid "Access Control List Configuration" msgstr "访问控制列表(ACL)配置" -#: mod_configure.erl:1322 +#: mod_configure.erl:1321 msgid "Access control lists" msgstr "访问控制列表(ACL)" -#: mod_configure.erl:1353 +#: mod_configure.erl:1352 msgid "Access Configuration" msgstr "访问配置" -#: mod_configure.erl:1357 +#: mod_configure.erl:1356 msgid "Access rules" msgstr "访问规则" -#: mod_configure.erl:1391 mod_configure.erl:1424 mod_configure.erl:1442 -#: mod_configure.erl:1460 mod_configure.erl:1478 mod_configure.erl:1505 -#: mod_configure.erl:1522 mod_configure.erl:1888 mod_configure.erl:1936 -#: mod_configure.erl:1963 mod_roster.erl:1431 mod_vcard.erl:609 -#: mod_vcard_ldap.erl:603 +#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 +#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 +#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" -#: mod_configure.erl:1408 +#: mod_configure.erl:1407 msgid "Password Verification" msgstr "确认密码" -#: mod_configure.erl:1541 +#: mod_configure.erl:1540 msgid "Number of registered users" msgstr "注册用户数" -#: mod_configure.erl:1560 +#: mod_configure.erl:1559 msgid "Number of online users" msgstr "在线用户数" -#: mod_configure.erl:1938 +#: mod_configure.erl:1937 msgid "Last login" msgstr "上次登陆" -#: mod_configure.erl:1965 +#: mod_configure.erl:1964 msgid "Roster size" msgstr "花名册大小" -#: mod_configure.erl:1967 +#: mod_configure.erl:1966 msgid "IP addresses" msgstr "IP 地址" -#: mod_configure.erl:1969 +#: mod_configure.erl:1968 msgid "Resources" msgstr "资源" -#: mod_configure.erl:2097 +#: mod_configure.erl:2096 msgid "Administration of " msgstr "管理" -#: mod_configure.erl:2102 +#: mod_configure.erl:2101 msgid "Action on user" msgstr "对用户的动作" -#: mod_configure.erl:2110 +#: mod_configure.erl:2109 msgid "Edit Properties" msgstr "编辑属性" -#: mod_fail2ban.erl:90 +#: mod_fail2ban.erl:95 msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" -#: mod_ip_blacklist.erl:122 +#: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" @@ -933,483 +930,515 @@ msgstr "服务器 ~b 的编码" msgid "Server ~b" msgstr "服务器 ~b" -#: mod_muc.erl:721 +#: mod_muc.erl:797 mod_muc_admin.erl:320 msgid "Chatrooms" msgstr "聊天室" -#: mod_muc.erl:914 +#: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "您需要一个支持 x:data 的客户端来注册昵称" -#: mod_muc.erl:924 +#: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "昵称注册于 " -#: mod_muc.erl:930 +#: mod_muc.erl:1013 msgid "Enter nickname you want to register" msgstr "请输入您想要注册的昵称" -#: mod_muc.erl:931 mod_muc_room.erl:4188 mod_roster.erl:1432 mod_vcard.erl:486 -#: mod_vcard.erl:617 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "昵称" -#: mod_muc.erl:1094 +#: mod_muc.erl:1177 msgid "ejabberd MUC module" msgstr "ejabberd MUC 模块" -#: mod_muc_log.erl:440 mod_muc_log.erl:449 +#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 +#: mod_muc_admin.erl:319 +msgid "Multi-User Chat" +msgstr "" + +#: mod_muc_admin.erl:248 +#, fuzzy +msgid "Total rooms" +msgstr "聊天室" + +#: mod_muc_admin.erl:249 +#, fuzzy +msgid "Permanent rooms" +msgstr "离开房间" + +#: mod_muc_admin.erl:250 +#, fuzzy +msgid "Registered nicknames" +msgstr "注册用户" + +#: mod_muc_admin.erl:253 +msgid "List of rooms" +msgstr "" + +#: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "聊天室配置已修改" -#: mod_muc_log.erl:452 +#: mod_muc_log.erl:457 msgid "joins the room" msgstr "加入房间" -#: mod_muc_log.erl:455 mod_muc_log.erl:458 +#: mod_muc_log.erl:460 mod_muc_log.erl:463 msgid "leaves the room" msgstr "离开房间" -#: mod_muc_log.erl:462 mod_muc_log.erl:465 +#: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" msgstr "已被禁止" -#: mod_muc_log.erl:477 +#: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" msgstr "因联属关系改变而被踢出" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" msgstr "因该房间改为只对会员开放而被踢出" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" msgstr "因系统关机而被踢出" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:497 msgid "is now known as" msgstr "现在称呼为" -#: mod_muc_log.erl:495 mod_muc_log.erl:834 mod_muc_room.erl:2491 +#: mod_muc_log.erl:500 mod_muc_log.erl:839 msgid " has set the subject to: " msgstr "已将标题设置为: " -#: mod_muc_log.erl:535 +#: mod_muc_log.erl:540 msgid "Chatroom is created" msgstr "聊天室已被创建" -#: mod_muc_log.erl:537 +#: mod_muc_log.erl:542 msgid "Chatroom is destroyed" msgstr "聊天室已被销毁" -#: mod_muc_log.erl:539 +#: mod_muc_log.erl:544 msgid "Chatroom is started" msgstr "聊天室已被启动" -#: mod_muc_log.erl:541 +#: mod_muc_log.erl:546 msgid "Chatroom is stopped" msgstr "聊天室已被停用" -#: mod_muc_log.erl:545 +#: mod_muc_log.erl:550 msgid "Monday" msgstr "星期一" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:551 msgid "Tuesday" msgstr "星期二" -#: mod_muc_log.erl:547 +#: mod_muc_log.erl:552 msgid "Wednesday" msgstr "星期三" -#: mod_muc_log.erl:548 +#: mod_muc_log.erl:553 msgid "Thursday" msgstr "星期四" -#: mod_muc_log.erl:549 +#: mod_muc_log.erl:554 msgid "Friday" msgstr "星期五" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:555 msgid "Saturday" msgstr "星期六" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:556 msgid "Sunday" msgstr "星期天" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:560 msgid "January" msgstr "一月" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:561 msgid "February" msgstr "二月" -#: mod_muc_log.erl:557 +#: mod_muc_log.erl:562 msgid "March" msgstr "三月" -#: mod_muc_log.erl:558 +#: mod_muc_log.erl:563 msgid "April" msgstr "四月" -#: mod_muc_log.erl:559 +#: mod_muc_log.erl:564 msgid "May" msgstr "五月" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:565 msgid "June" msgstr "六月" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:566 msgid "July" msgstr "七月" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:567 msgid "August" msgstr "八月" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:568 msgid "September" msgstr "九月" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:569 msgid "October" msgstr "十月" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:570 msgid "November" msgstr "十一月" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:571 msgid "December" msgstr "十二月" -#: mod_muc_log.erl:954 +#: mod_muc_log.erl:959 msgid "Room Configuration" msgstr "房间配置" -#: mod_muc_log.erl:974 +#: mod_muc_log.erl:979 msgid "Room Occupants" msgstr "房间人数" -#: mod_muc_room.erl:973 +#: mod_muc_room.erl:997 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "只有主持人和参与人可以在此房间里更改主题" -#: mod_muc_room.erl:978 +#: mod_muc_room.erl:1002 msgid "Only moderators are allowed to change the subject in this room" msgstr "只有主持人可以在此房间里更改主题" -#: mod_muc_room.erl:1868 -msgid "This room is not anonymous" -msgstr "此房间不是匿名房间" - -#: mod_muc_room.erl:2722 +#: mod_muc_room.erl:2751 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s 无效" -#: mod_muc_room.erl:2736 +#: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" msgstr "昵称 ~s 不在该房间" -#: mod_muc_room.erl:2759 mod_muc_room.erl:3139 +#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" msgstr "无效加入: ~s" -#: mod_muc_room.erl:2810 +#: mod_muc_room.erl:2839 msgid "Invalid role: ~s" msgstr "无效角色: ~s" -#: mod_muc_room.erl:3312 +#: mod_muc_room.erl:3341 msgid "Configuration of room ~s" msgstr "房间 ~s 的配置 " -#: mod_muc_room.erl:3323 +#: mod_muc_room.erl:3352 msgid "Room title" msgstr "房间标题" -#: mod_muc_room.erl:3325 mod_muc_room.erl:4025 +#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 msgid "Room description" msgstr "房间描述" -#: mod_muc_room.erl:3333 +#: mod_muc_room.erl:3362 msgid "Make room persistent" msgstr "永久保存该房间" -#: mod_muc_room.erl:3339 +#: mod_muc_room.erl:3368 msgid "Make room public searchable" msgstr "使房间可被公开搜索" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3371 msgid "Make participants list public" msgstr "公开参与人列表" -#: mod_muc_room.erl:3344 +#: mod_muc_room.erl:3373 msgid "Make room password protected" msgstr "进入此房间需要密码" -#: mod_muc_room.erl:3358 +#: mod_muc_room.erl:3387 msgid "Maximum Number of Occupants" msgstr "允许的与会人最大数" -#: mod_muc_room.erl:3370 +#: mod_muc_room.erl:3399 msgid "No limit" msgstr "不限" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3429 msgid "Present real Jabber IDs to" msgstr "将真实 Jabber ID 显示给" -#: mod_muc_room.erl:3414 mod_muc_room.erl:3477 +#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 msgid "moderators only" msgstr "仅主持人" -#: mod_muc_room.erl:3424 mod_muc_room.erl:3487 +#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 msgid "anyone" msgstr "任何人" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3459 msgid "Make room members-only" msgstr "设置房间只接收会员" -#: mod_muc_room.erl:3433 +#: mod_muc_room.erl:3462 msgid "Make room moderated" msgstr "设置房间只接收主持人" -#: mod_muc_room.erl:3436 +#: mod_muc_room.erl:3465 msgid "Default users as participants" msgstr "用户默认被视为参与人" -#: mod_muc_room.erl:3439 +#: mod_muc_room.erl:3468 msgid "Allow users to change the subject" msgstr "允许用户更改主题" -#: mod_muc_room.erl:3442 +#: mod_muc_room.erl:3471 msgid "Allow users to send private messages" msgstr "允许用户发送私聊消息" -#: mod_muc_room.erl:3450 +#: mod_muc_room.erl:3479 msgid "Allow visitors to send private messages to" msgstr "允许访客发送私聊消息至" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3497 msgid "nobody" msgstr "没有人" -#: mod_muc_room.erl:3493 +#: mod_muc_room.erl:3522 msgid "Allow users to query other users" msgstr "允许用户查询其它用户" -#: mod_muc_room.erl:3496 +#: mod_muc_room.erl:3525 msgid "Allow users to send invites" msgstr "允许用户发送邀请" -#: mod_muc_room.erl:3499 +#: mod_muc_room.erl:3528 msgid "Allow visitors to send status text in presence updates" msgstr "更新在线状态时允许用户发送状态文本" -#: mod_muc_room.erl:3503 +#: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" msgstr "允许用户更改昵称" -#: mod_muc_room.erl:3506 +#: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" msgstr "允许访客发送声音请求" -#: mod_muc_room.erl:3509 +#: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" msgstr "声音请求的最小间隔(以秒为单位)" -#: mod_muc_room.erl:3516 +#: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" msgstr "保护房间验证码" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3552 +msgid "Enable message archiving" +msgstr "" + +#: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "从验证码挑战中排除 Jabber ID" -#: mod_muc_room.erl:3531 +#: mod_muc_room.erl:3567 msgid "Enable logging" msgstr "启用服务器端聊天记录" -#: mod_muc_room.erl:3541 +#: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" msgstr "您需要一个兼容 x:data 的客户端来配置房间" -#: mod_muc_room.erl:4027 +#: mod_muc_room.erl:4103 msgid "Number of occupants" msgstr "驻留人数" -#: mod_muc_room.erl:4097 +#: mod_muc_room.erl:4173 msgid "private, " msgstr "保密, " -#: mod_muc_room.erl:4161 +#: mod_muc_room.erl:4237 msgid "Voice request" msgstr "声音请求" -#: mod_muc_room.erl:4166 +#: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." msgstr "接受或拒绝声音请求" -#: mod_muc_room.erl:4186 +#: mod_muc_room.erl:4262 msgid "User JID" msgstr "用户 JID" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4266 msgid "Grant voice to this person?" msgstr "为此人授权声音?" -#: mod_muc_room.erl:4333 +#: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" msgstr "~s 邀请你到 ~s 房间" -#: mod_muc_room.erl:4345 +#: mod_muc_room.erl:4421 msgid "the password is" msgstr "密码是" -#: mod_offline.erl:773 +#: mod_multicast.erl:273 +msgid "Multicast" +msgstr "" + +#: mod_multicast.erl:288 +msgid "ejabberd Multicast service" +msgstr "" + +#: mod_offline.erl:783 msgid "~s's Offline Messages Queue" msgstr "~s 的离线消息队列" -#: mod_offline.erl:786 +#: mod_offline.erl:796 msgid "Time" msgstr "时间" -#: mod_offline.erl:787 +#: mod_offline.erl:797 msgid "From" msgstr "从" -#: mod_offline.erl:788 +#: mod_offline.erl:798 msgid "To" msgstr "到" -#: mod_offline.erl:789 +#: mod_offline.erl:799 msgid "Packet" msgstr "数据包" -#: mod_offline.erl:967 +#: mod_offline.erl:977 msgid "Offline Messages:" msgstr "离线消息:" -#: mod_offline.erl:971 +#: mod_offline.erl:981 msgid "Remove All Offline Messages" msgstr "移除所有离线消息" -#: mod_proxy65_service.erl:249 +#: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 字节流模块" -#: mod_pubsub.erl:1815 mod_pubsub_odbc.erl:1431 +#: mod_pubsub.erl:1103 msgid "Publish-Subscribe" msgstr "发行-订阅" -#: mod_pubsub.erl:1991 mod_pubsub_odbc.erl:1609 +#: mod_pubsub.erl:1223 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd 发行-订阅模块" -#: mod_pubsub.erl:2330 mod_pubsub_odbc.erl:1953 +#: mod_pubsub.erl:1538 msgid "PubSub subscriber request" msgstr "PubSub 订阅人请求" -#: mod_pubsub.erl:2336 mod_pubsub_odbc.erl:1959 +#: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." msgstr "选择是否允许该实体的订阅" -#: mod_pubsub.erl:2355 mod_pubsub_odbc.erl:1978 +#: mod_pubsub.erl:1560 msgid "Node ID" msgstr "节点 ID" -#: mod_pubsub.erl:2368 mod_pubsub_odbc.erl:1991 +#: mod_pubsub.erl:1572 msgid "Subscriber Address" msgstr "订阅人地址" -#: mod_pubsub.erl:2382 mod_pubsub_odbc.erl:2005 +#: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "允许该 Jabber ID 订阅该 pubsub 节点?" -#: mod_pubsub.erl:4767 mod_pubsub_odbc.erl:4375 +#: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" msgstr "用事件通告传输有效负载" -#: mod_pubsub.erl:4769 mod_pubsub_odbc.erl:4377 +#: mod_pubsub.erl:3704 msgid "Deliver event notifications" msgstr "传递事件通知" -#: mod_pubsub.erl:4771 mod_pubsub_odbc.erl:4379 +#: mod_pubsub.erl:3706 msgid "Notify subscribers when the node configuration changes" msgstr "当节点设置改变时通知订阅人" -#: mod_pubsub.erl:4774 mod_pubsub_odbc.erl:4382 +#: mod_pubsub.erl:3708 msgid "Notify subscribers when the node is deleted" msgstr "当节点被删除时通知订阅人" -#: mod_pubsub.erl:4777 mod_pubsub_odbc.erl:4385 +#: mod_pubsub.erl:3710 msgid "Notify subscribers when items are removed from the node" msgstr "当从节点删除内容条目时通知订阅人" -#: mod_pubsub.erl:4780 mod_pubsub_odbc.erl:4388 +#: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "持久化内容条目" -#: mod_pubsub.erl:4782 mod_pubsub_odbc.erl:4390 +#: mod_pubsub.erl:3714 msgid "A friendly name for the node" msgstr "该节点的友好名称" -#: mod_pubsub.erl:4784 mod_pubsub_odbc.erl:4392 +#: mod_pubsub.erl:3716 msgid "Max # of items to persist" msgstr "允许持久化的最大内容条目数" -#: mod_pubsub.erl:4786 mod_pubsub_odbc.erl:4394 +#: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" msgstr "是否允许订阅" -#: mod_pubsub.erl:4788 mod_pubsub_odbc.erl:4396 +#: mod_pubsub.erl:3720 msgid "Specify the access model" msgstr "指定访问范例" -#: mod_pubsub.erl:4791 mod_pubsub_odbc.erl:4399 +#: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "允许订阅的花名册组" -#: mod_pubsub.erl:4793 mod_pubsub_odbc.erl:4401 +#: mod_pubsub.erl:3724 msgid "Specify the publisher model" msgstr "指定发布人范例" -#: mod_pubsub.erl:4795 mod_pubsub_odbc.erl:4403 +#: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" msgstr "相关发布人离线后清除所有选项" -#: mod_pubsub.erl:4798 mod_pubsub_odbc.erl:4406 +#: mod_pubsub.erl:3728 msgid "Specify the event message type" msgstr "指定事件消息类型" # bytes was translated as 'bits'. It's corrected now. -#: mod_pubsub.erl:4800 mod_pubsub_odbc.erl:4408 +#: mod_pubsub.erl:3730 msgid "Max payload size in bytes" msgstr "最大有效负载字节数" -#: mod_pubsub.erl:4802 mod_pubsub_odbc.erl:4410 +#: mod_pubsub.erl:3732 msgid "When to send the last published item" msgstr "何时发送最新发布的内容条目" -#: mod_pubsub.erl:4805 mod_pubsub_odbc.erl:4413 +#: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" msgstr "仅将通知发送给可发送的用户" -#: mod_pubsub.erl:4808 mod_pubsub_odbc.erl:4416 +#: mod_pubsub.erl:3736 msgid "The collections with which a node is affiliated" msgstr "加入结点的集合" -#: mod_register.erl:240 +#: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "您需要一个支持 x:data 和验证码的客户端进行注册" -#: mod_register.erl:246 mod_register.erl:307 +#: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" msgstr "请选择在此服务器上注册所需的用户名和密码" @@ -1445,7 +1474,7 @@ msgstr "Jabber 帐户注册" msgid "Register a Jabber account" msgstr "注册 Jabber 帐户" -#: mod_register_web.erl:191 mod_register_web.erl:452 mod_register_web.erl:460 +#: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" msgstr "注销 Jabber 帐户" @@ -1458,7 +1487,7 @@ msgstr "" "本页面允许在此服务器上创建 Jabber 帐户. 你的 JID (Jabber ID) 的形式如下: 用户" "名@服务器. 请仔细阅读说明并正确填写相应字段." -#: mod_register_web.erl:224 mod_register_web.erl:359 mod_register_web.erl:468 +#: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "用户名:" @@ -1470,21 +1499,21 @@ msgstr "此处不区分大小写: macbeth 与 MacBeth 和 Macbeth 是一样的." msgid "Characters not allowed:" msgstr "禁用字符:" -#: mod_register_web.erl:236 mod_register_web.erl:363 mod_register_web.erl:472 +#: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 msgid "Server:" msgstr "服务器:" -#: mod_register_web.erl:244 +#: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "不要将密码告诉任何人, 就算是 Jabber 服务器的管理员也不可以." -#: mod_register_web.erl:248 +#: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." msgstr "你可以稍后用 Jabber 客户端修改你的密码." -#: mod_register_web.erl:251 +#: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in your computer. Use that " "feature only if you trust your computer is safe." @@ -1492,7 +1521,7 @@ msgstr "" "某些 Jabber 客户端可以在你的计算机里存储密码. 请仅在你确认你的计算机安全的情" "况下使用该功能." -#: mod_register_web.erl:255 +#: mod_register_web.erl:256 msgid "" "Memorize your password, or write it in a paper placed in a safe place. In " "Jabber there isn't an automated way to recover your password if you forget " @@ -1501,157 +1530,163 @@ msgstr "" "记住你的密码, 或将其记到纸上并放于安全位置. 如果你忘记了密码, Jabber 也没有自" "动恢复密码的方式." -#: mod_register_web.erl:261 mod_register_web.erl:373 +#: mod_register_web.erl:262 mod_register_web.erl:374 msgid "Password Verification:" msgstr "密码确认:" -#: mod_register_web.erl:268 +#: mod_register_web.erl:269 msgid "Register" msgstr "注册" -#: mod_register_web.erl:365 +#: mod_register_web.erl:366 msgid "Old Password:" msgstr "旧密码: " -#: mod_register_web.erl:369 +#: mod_register_web.erl:370 msgid "New Password:" msgstr "新密码: " -#: mod_register_web.erl:462 +#: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." msgstr "此页面允许在此 Jabber 服务器上注销 Jabber 帐户" -#: mod_register_web.erl:479 +#: mod_register_web.erl:480 msgid "Unregister" msgstr "取消注册" -#: mod_roster.erl:1433 +#: mod_roster.erl:1437 msgid "Subscription" msgstr "订阅" -#: mod_roster.erl:1434 +#: mod_roster.erl:1438 msgid "Pending" msgstr "挂起" -#: mod_roster.erl:1435 +#: mod_roster.erl:1439 msgid "Groups" msgstr "组" -#: mod_roster.erl:1473 +#: mod_roster.erl:1477 msgid "Validate" msgstr "确认" -#: mod_roster.erl:1482 +#: mod_roster.erl:1486 msgid "Remove" msgstr "移除" -#: mod_roster.erl:1487 +#: mod_roster.erl:1491 msgid "Roster of " msgstr "花名册属于 " -#: mod_roster.erl:1501 +#: mod_roster.erl:1505 msgid "Add Jabber ID" msgstr "添加 Jabber ID" -#: mod_roster.erl:1619 +#: mod_roster.erl:1623 msgid "Roster" msgstr "花名册" -#: mod_shared_roster.erl:1123 mod_shared_roster.erl:1165 -#: mod_shared_roster.erl:1259 +#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 +#: mod_shared_roster.erl:1261 msgid "Shared Roster Groups" msgstr "共享的花名册组群" -#: mod_shared_roster.erl:1235 +#: mod_shared_roster.erl:1237 msgid "Name:" msgstr "姓名:" -#: mod_shared_roster.erl:1239 +#: mod_shared_roster.erl:1241 msgid "Description:" msgstr "描述:" -#: mod_shared_roster.erl:1246 +#: mod_shared_roster.erl:1248 msgid "Members:" msgstr "会员:" -#: mod_shared_roster.erl:1253 +#: mod_shared_roster.erl:1255 msgid "Displayed Groups:" msgstr "已显示的组:" -#: mod_shared_roster.erl:1262 +#: mod_shared_roster.erl:1264 msgid "Group " msgstr "组" -#: mod_vcard.erl:164 mod_vcard_ldap.erl:222 +#: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber 服务器" -#: mod_vcard.erl:486 mod_vcard.erl:618 +#: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" msgstr "出生日期" -#: mod_vcard.erl:486 mod_vcard.erl:620 +#: mod_vcard.erl:490 mod_vcard.erl:624 msgid "City" msgstr "城市" -#: mod_vcard.erl:486 mod_vcard.erl:619 +#: mod_vcard.erl:490 mod_vcard.erl:623 msgid "Country" msgstr "国家" -#: mod_vcard.erl:486 mod_vcard.erl:621 +#: mod_vcard.erl:490 mod_vcard.erl:625 msgid "Email" msgstr "电子邮件" -#: mod_vcard.erl:486 mod_vcard.erl:615 +#: mod_vcard.erl:490 mod_vcard.erl:619 msgid "Family Name" msgstr "姓氏" -#: mod_vcard.erl:486 +#: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "填充表单以搜索任何匹配的 Jabber 用户(在字段末添加*来匹配子串)" -#: mod_vcard.erl:486 mod_vcard.erl:611 +#: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" msgstr "全名" -#: mod_vcard.erl:486 mod_vcard.erl:613 +#: mod_vcard.erl:490 mod_vcard.erl:617 msgid "Middle Name" msgstr "中间名" -#: mod_vcard.erl:486 mod_vcard.erl:622 +#: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "组织名称" -#: mod_vcard.erl:486 mod_vcard.erl:624 +#: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" msgstr "组织单位" -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " msgstr "搜索用户于 " -#: mod_vcard.erl:486 mod_vcard_ldap.erl:499 +#: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" msgstr "您需要一个兼容 x:data 的客户端来搜索" -#: mod_vcard.erl:515 mod_vcard_ldap.erl:528 +#: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" msgstr "vCard 用户搜索" -#: mod_vcard.erl:576 mod_vcard_ldap.erl:583 +#: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" msgstr "ejabberd vCard 模块" -#: mod_vcard.erl:605 mod_vcard_ldap.erl:599 +#: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " msgstr "搜索结果属于关键词 " -#: mod_vcard_ldap.erl:499 +#: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "填充字段以搜索任何匹配的 Jabber 用户" +#~ msgid "Delete" +#~ msgstr "删除" + +#~ msgid "This room is not anonymous" +#~ msgstr "此房间不是匿名房间" + #~ msgid "Your active privacy list has denied the routing of this stanza." #~ msgstr "你的活跃私聊列表拒绝了在此房间进行路由分发." From 9195fc55733a838415eb109979e4b4707a4bc17e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 7 Sep 2015 15:21:42 +0300 Subject: [PATCH 231/695] Update Russian PO file --- priv/msgs/ru.po | 626 +++++++++++++++++++++--------------------------- 1 file changed, 268 insertions(+), 358 deletions(-) diff --git a/priv/msgs/ru.po b/priv/msgs/ru.po index df35e3a02ca..5f7fff6d802 100644 --- a/priv/msgs/ru.po +++ b/priv/msgs/ru.po @@ -3,40 +3,19 @@ msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2012-04-15 13:38+0900\n" +"PO-Revision-Date: 2015-09-07 15:04+0300\n" "Last-Translator: Evgeniy Khramtsov \n" "Language-Team: Russian \n" -"Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" "X-Language: Russian (русский)\n" "X-Additional-Translator: Konstantin Khomoutov\n" "X-Additional-Translator: Sergei Golovan\n" "X-Generator: Lokalize 1.0\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 -msgid "Use of STARTTLS required" -msgstr "Вы обязаны использовать STARTTLS" - -#: ejabberd_c2s.erl:626 -msgid "No resource provided" -msgstr "Не указан ресурс" - -#: ejabberd_c2s.erl:1401 -msgid "Replaced by new connection" -msgstr "Заменено новым соединением" - -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 -msgid "has been kicked" -msgstr "выгнали из комнаты" - -#: ejabberd_c2s.erl:2490 -msgid "Too many unacked stanzas" -msgstr "" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -59,122 +38,10 @@ msgstr "Ссылка на капчу" msgid "The CAPTCHA is valid." msgstr "Проверка капчи прошла успешно." -#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 -#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 -msgid "Unauthorized" -msgstr "Не авторизован" - #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Web-интерфейс администрирования ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 -msgid "Administration" -msgstr "Администрирование" - -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 -#: mod_configure.erl:532 -msgid "Access Control Lists" -msgstr "Списки управления доступом" - -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 -msgid "Submitted" -msgstr "Отправлено" - -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 -msgid "Bad format" -msgstr "Неправильный формат" - -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 -msgid "Submit" -msgstr "Отправить" - -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 -msgid "Raw" -msgstr "Необработанный формат" - -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 -msgid "Delete Selected" -msgstr "Удалить выделенные" - -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 -#: mod_configure.erl:533 -msgid "Access Rules" -msgstr "Правила доступа" - -#: ejabberd_web_admin.erl:849 -msgid "~s access rule configuration" -msgstr "Конфигурация правила доступа ~s" - -#: ejabberd_web_admin.erl:867 -msgid "Virtual Hosts" -msgstr "Виртуальные хосты" - -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 -msgid "Users" -msgstr "Пользователи" - -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 -#: mod_configure.erl:524 -msgid "Online Users" -msgstr "Подключённые пользователи" - -#: ejabberd_web_admin.erl:907 -msgid "Users Last Activity" -msgstr "Статистика последнего подключения пользователей" - -#: ejabberd_web_admin.erl:911 -msgid "Period: " -msgstr "Период" - -#: ejabberd_web_admin.erl:924 -msgid "Last month" -msgstr "За последний месяц" - -#: ejabberd_web_admin.erl:925 -msgid "Last year" -msgstr "За последний год" - -#: ejabberd_web_admin.erl:927 -msgid "All activity" -msgstr "Вся статистика" - -#: ejabberd_web_admin.erl:930 -msgid "Show Ordinary Table" -msgstr "Показать обычную таблицу" - -#: ejabberd_web_admin.erl:933 -msgid "Show Integral Table" -msgstr "Показать интегральную таблицу" - -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 -msgid "Statistics" -msgstr "Статистика" - -#: ejabberd_web_admin.erl:950 -msgid "Not Found" -msgstr "Не Найдено" - -#: ejabberd_web_admin.erl:963 -msgid "Node not found" -msgstr "Узел не найден" - #: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Добавить" @@ -187,6 +54,20 @@ msgstr "Хост" msgid "Registered Users" msgstr "Зарегистрированные пользователи" +#: ejabberd_web_admin.erl:1275 mod_configure.erl:524 +msgid "Online Users" +msgstr "Подключённые пользователи" + +#: ejabberd_web_admin.erl:1329 ejabberd_web_admin.erl:1614 mod_offline.erl:787 +#: mod_roster.erl:1494 mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +msgid "Submitted" +msgstr "Отправлено" + +#: ejabberd_web_admin.erl:1330 ejabberd_web_admin.erl:1615 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +msgid "Bad format" +msgstr "Неправильный формат" + #: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 #: mod_register.erl:262 mod_vcard.erl:490 msgid "User" @@ -226,7 +107,6 @@ msgid "Registered Users:" msgstr "Зарегистрированные пользователи:" #: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Подключённые пользователи:" @@ -239,7 +119,7 @@ msgid "Outgoing s2s Servers:" msgstr "Исходящие s2s-серверы:" #: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1742 mod_roster.erl:1430 msgid "None" msgstr "Нет" @@ -249,9 +129,8 @@ msgid "Change Password" msgstr "Сменить пароль" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Пользователь " +msgstr "Пользователь ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -282,206 +161,6 @@ msgstr "Работающие узлы" msgid "Stopped Nodes" msgstr "Остановленные узлы" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy -msgid "Node ~p" -msgstr "Узел " - -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 -msgid "Database" -msgstr "База данных" - -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 -msgid "Backup" -msgstr "Резервное копирование" - -#: ejabberd_web_admin.erl:1783 -msgid "Listened Ports" -msgstr "Прослушиваемые порты" - -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 -msgid "Update" -msgstr "Обновить" - -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 -msgid "Restart" -msgstr "Перезапустить" - -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 -msgid "Stop" -msgstr "Остановить" - -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 -msgid "Modules" -msgstr "Модули" - -#: ejabberd_web_admin.erl:1804 -msgid "RPC Call Error" -msgstr "Ошибка вызова RPC" - -#: ejabberd_web_admin.erl:1855 -#, fuzzy -msgid "Database Tables at ~p" -msgstr "Таблицы базы данных на " - -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 -msgid "Name" -msgstr "Название" - -#: ejabberd_web_admin.erl:1866 -msgid "Storage Type" -msgstr "Тип таблицы" - -#: ejabberd_web_admin.erl:1867 -msgid "Elements" -msgstr "Элементы" - -#: ejabberd_web_admin.erl:1868 -msgid "Memory" -msgstr "Память" - -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 -msgid "Error" -msgstr "Ошибка" - -#: ejabberd_web_admin.erl:1893 -#, fuzzy -msgid "Backup of ~p" -msgstr "Резервное копирование " - -#: ejabberd_web_admin.erl:1897 -msgid "" -"Please note that these options will only backup the builtin Mnesia database. " -"If you are using the ODBC module, you also need to backup your SQL database " -"separately." -msgstr "" -"Заметьте, что здесь производится резервное копирование только встроенной " -"базы данных Mnesia. Если Вы также используете другое хранилище данных " -"(например с помощью модуля ODBC), то его резервное копирование следует " -"осуществлять отдельно." - -#: ejabberd_web_admin.erl:1907 -msgid "Store binary backup:" -msgstr "Сохранить бинарную резервную копию:" - -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 -msgid "OK" -msgstr "Продолжить" - -#: ejabberd_web_admin.erl:1917 -msgid "Restore binary backup immediately:" -msgstr "Восстановить из бинарной резервной копии немедленно:" - -#: ejabberd_web_admin.erl:1927 -msgid "" -"Restore binary backup after next ejabberd restart (requires less memory):" -msgstr "" -"Восстановить из бинарной резервной копии при следующем запуске (требует " -"меньше памяти):" - -#: ejabberd_web_admin.erl:1937 -msgid "Store plain text backup:" -msgstr "Сохранить текстовую резервную копию:" - -#: ejabberd_web_admin.erl:1947 -msgid "Restore plain text backup immediately:" -msgstr "Восстановить из текстовой резервной копии немедленно:" - -#: ejabberd_web_admin.erl:1957 -msgid "Import users data from a PIEFXIS file (XEP-0227):" -msgstr "Импорт пользовательских данных из файла формата PIEFXIS (XEP-0227):" - -#: ejabberd_web_admin.erl:1970 -msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" -msgstr "" -"Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-0227):" - -#: ejabberd_web_admin.erl:1982 -msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" -msgstr "" -"Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):" - -#: ejabberd_web_admin.erl:1998 -msgid "Export all tables as SQL queries to a file:" -msgstr "" - -#: ejabberd_web_admin.erl:2014 -msgid "Import user data from jabberd14 spool file:" -msgstr "Импорт пользовательских данных из буферного файла jabberd14:" - -#: ejabberd_web_admin.erl:2025 -msgid "Import users data from jabberd14 spool directory:" -msgstr "Импорт пользовательских данных из буферной директории jabberd14:" - -#: ejabberd_web_admin.erl:2053 -msgid "Listened Ports at " -msgstr "Прослушиваемые порты на " - -#: ejabberd_web_admin.erl:2082 -#, fuzzy -msgid "Modules at ~p" -msgstr "Модули на " - -#: ejabberd_web_admin.erl:2113 -msgid "Statistics of ~p" -msgstr "статистика узла ~p" - -#: ejabberd_web_admin.erl:2117 -msgid "Uptime:" -msgstr "Время работы:" - -#: ejabberd_web_admin.erl:2121 -msgid "CPU Time:" -msgstr "Процессорное время:" - -#: ejabberd_web_admin.erl:2129 -msgid "Transactions Committed:" -msgstr "Транзакции завершенные:" - -#: ejabberd_web_admin.erl:2133 -msgid "Transactions Aborted:" -msgstr "Транзакции отмененные:" - -#: ejabberd_web_admin.erl:2137 -msgid "Transactions Restarted:" -msgstr "Транзакции перезапущенные:" - -#: ejabberd_web_admin.erl:2141 -msgid "Transactions Logged:" -msgstr "Транзакции запротоколированные:" - -#: ejabberd_web_admin.erl:2181 -#, fuzzy -msgid "Update ~p" -msgstr "Обновление " - -#: ejabberd_web_admin.erl:2192 -msgid "Update plan" -msgstr "План обновления" - -#: ejabberd_web_admin.erl:2193 -msgid "Modified modules" -msgstr "Изменённые модули" - -#: ejabberd_web_admin.erl:2194 -msgid "Update script" -msgstr "Сценарий обновления" - -#: ejabberd_web_admin.erl:2195 -msgid "Low level update script" -msgstr "Низкоуровневый сценарий обновления" - -#: ejabberd_web_admin.erl:2196 -msgid "Script check" -msgstr "Проверка сценария" - #: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" @@ -502,6 +181,14 @@ msgstr "Модуль" msgid "Options" msgstr "Параметры" +#: ejabberd_web_admin.erl:2407 ejabberd_web_admin.erl:2551 +msgid "Restart" +msgstr "Перезапустить" + +#: ejabberd_web_admin.erl:2411 ejabberd_web_admin.erl:2555 +msgid "Stop" +msgstr "Остановить" + #: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Запустить" @@ -587,6 +274,10 @@ msgstr "Удалить сообщение дня со всех виртуаль msgid "Configuration" msgstr "Конфигурация" +#: mod_configure.erl:150 mod_configure.erl:611 +msgid "Database" +msgstr "База данных" + #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Запуск модулей" @@ -595,6 +286,10 @@ msgstr "Запуск модулей" msgid "Stop Modules" msgstr "Остановка модулей" +#: mod_configure.erl:159 mod_configure.erl:648 +msgid "Backup" +msgstr "Резервное копирование" + #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Восстановление из резервной копии" @@ -652,6 +347,14 @@ msgstr "Получить количество зарегистрированны msgid "Get Number of Online Users" msgstr "Получить количество подключённых пользователей" +#: mod_configure.erl:196 mod_configure.erl:532 +msgid "Access Control Lists" +msgstr "Списки управления доступом" + +#: mod_configure.erl:198 mod_configure.erl:533 +msgid "Access Rules" +msgstr "Правила доступа" + #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Управление пользователями" @@ -664,6 +367,10 @@ msgstr "Все пользователи" msgid "Outgoing s2s Connections" msgstr "Исходящие s2s-соединения" +#: mod_configure.erl:613 mod_configure.erl:626 +msgid "Modules" +msgstr "Модули" + #: mod_configure.erl:615 msgid "Backup Management" msgstr "Управление резервным копированием" @@ -809,6 +516,10 @@ msgstr "Количество зарегистрированных пользов msgid "Number of online users" msgstr "Количество подключённых пользователей" +#: mod_configure.erl:1854 mod_muc_log.erl:474 mod_muc_log.erl:477 +msgid "has been kicked" +msgstr "выгнали из комнаты" + #: mod_configure.erl:1937 msgid "Last login" msgstr "Время последнего подключения" @@ -842,10 +553,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Слишком много (~p) неудачных попыток аутентификации с этого IP-адреса (~s). " +"Адрес будет разблокирован в ~s UTC" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Этот IP адрес находится в чёрном списке ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -953,10 +666,6 @@ msgstr "Кодировка сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 -msgid "Chatrooms" -msgstr "Комнаты" - #: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент" @@ -981,26 +690,31 @@ msgstr "ejabberd MUC модуль" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Конференция" + +#: mod_muc_admin.erl:246 +msgid "Statistics" +msgstr "Статистика" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Комнаты" +msgstr "Все комнаты" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "вышел(а) из комнаты" +msgstr "Постоянные комнаты" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Зарегистрированные пользователи" +msgstr "Зарегистрированные псевдонимы" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Список комнат" + +#: mod_muc_admin.erl:320 +msgid "Chatrooms" +msgstr "Комнаты" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1156,7 +870,7 @@ msgstr "Jabber ID ~s недопустимый" msgid "Nickname ~s does not exist in the room" msgstr "Псевдоним ~s в комнате отсутствует" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2788 msgid "Invalid affiliation: ~s" msgstr "Недопустимый ранг: ~s" @@ -1271,7 +985,7 @@ msgstr "Сделать комнату защищённой капчей" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Включить хранение сообщений" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1319,11 +1033,11 @@ msgstr "пароль:" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Мультикаст" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd Multicast сервис" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" @@ -1345,6 +1059,10 @@ msgstr "Кому" msgid "Packet" msgstr "Пакет" +#: mod_offline.erl:809 mod_shared_roster.erl:1180 +msgid "Delete Selected" +msgstr "Удалить выделенные" + #: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Офлайновые сообщения:" @@ -1638,6 +1356,10 @@ msgstr "Видимые группы:" msgid "Group " msgstr "Группа " +#: mod_shared_roster.erl:1274 +msgid "Submit" +msgstr "Отправить" + #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" @@ -1678,6 +1400,10 @@ msgstr "Полное имя" msgid "Middle Name" msgstr "Отчество" +#: mod_vcard.erl:490 mod_vcard.erl:616 +msgid "Name" +msgstr "Название" + #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Название организации" @@ -1710,6 +1436,190 @@ msgstr "Результаты поиска в " msgid "Fill in fields to search for any matching Jabber User" msgstr "Заполните форму для поиска пользователя Jabber" +#~ msgid "Use of STARTTLS required" +#~ msgstr "Вы обязаны использовать STARTTLS" + +#~ msgid "No resource provided" +#~ msgstr "Не указан ресурс" + +#~ msgid "Replaced by new connection" +#~ msgstr "Заменено новым соединением" + +#~ msgid "Too many unacked stanzas" +#~ msgstr "Слишком много неподтверждённых пакетов" + +#~ msgid "Unauthorized" +#~ msgstr "Не авторизован" + +#~ msgid "Administration" +#~ msgstr "Администрирование" + +#~ msgid "Raw" +#~ msgstr "Необработанный формат" + +#~ msgid "~s access rule configuration" +#~ msgstr "Конфигурация правила доступа ~s" + +#~ msgid "Virtual Hosts" +#~ msgstr "Виртуальные хосты" + +#~ msgid "Users" +#~ msgstr "Пользователи" + +#~ msgid "Users Last Activity" +#~ msgstr "Статистика последнего подключения пользователей" + +#~ msgid "Period: " +#~ msgstr "Период" + +#~ msgid "Last month" +#~ msgstr "За последний месяц" + +#~ msgid "Last year" +#~ msgstr "За последний год" + +#~ msgid "All activity" +#~ msgstr "Вся статистика" + +#~ msgid "Show Ordinary Table" +#~ msgstr "Показать обычную таблицу" + +#~ msgid "Show Integral Table" +#~ msgstr "Показать интегральную таблицу" + +#~ msgid "Not Found" +#~ msgstr "Не Найдено" + +#~ msgid "Node not found" +#~ msgstr "Узел не найден" + +#~ msgid "Node ~p" +#~ msgstr "Узел ~p" + +#~ msgid "Listened Ports" +#~ msgstr "Прослушиваемые порты" + +#~ msgid "Update" +#~ msgstr "Обновить" + +#~ msgid "RPC Call Error" +#~ msgstr "Ошибка вызова RPC" + +#~ msgid "Database Tables at ~p" +#~ msgstr "Таблицы базы данных на ~p" + +#~ msgid "Storage Type" +#~ msgstr "Тип таблицы" + +#~ msgid "Elements" +#~ msgstr "Элементы" + +#~ msgid "Memory" +#~ msgstr "Память" + +#~ msgid "Error" +#~ msgstr "Ошибка" + +#~ msgid "Backup of ~p" +#~ msgstr "Резервное копирование ~p" + +#~ msgid "" +#~ "Please note that these options will only backup the builtin Mnesia " +#~ "database. If you are using the ODBC module, you also need to backup your " +#~ "SQL database separately." +#~ msgstr "" +#~ "Заметьте, что здесь производится резервное копирование только встроенной " +#~ "базы данных Mnesia. Если Вы также используете другое хранилище данных " +#~ "(например с помощью модуля ODBC), то его резервное копирование следует " +#~ "осуществлять отдельно." + +#~ msgid "Store binary backup:" +#~ msgstr "Сохранить бинарную резервную копию:" + +#~ msgid "OK" +#~ msgstr "Продолжить" + +#~ msgid "Restore binary backup immediately:" +#~ msgstr "Восстановить из бинарной резервной копии немедленно:" + +#~ msgid "" +#~ "Restore binary backup after next ejabberd restart (requires less memory):" +#~ msgstr "" +#~ "Восстановить из бинарной резервной копии при следующем запуске (требует " +#~ "меньше памяти):" + +#~ msgid "Store plain text backup:" +#~ msgstr "Сохранить текстовую резервную копию:" + +#~ msgid "Restore plain text backup immediately:" +#~ msgstr "Восстановить из текстовой резервной копии немедленно:" + +#~ msgid "Import users data from a PIEFXIS file (XEP-0227):" +#~ msgstr "Импорт пользовательских данных из файла формата PIEFXIS (XEP-0227):" + +#~ msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" +#~ msgstr "" +#~ "Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-" +#~ "0227):" + +#~ msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" +#~ msgstr "" +#~ "Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):" + +#~ msgid "Export all tables as SQL queries to a file:" +#~ msgstr "Экспортировать все таблицы в виде SQL запросов в файл:" + +#~ msgid "Import user data from jabberd14 spool file:" +#~ msgstr "Импорт пользовательских данных из буферного файла jabberd14:" + +#~ msgid "Import users data from jabberd14 spool directory:" +#~ msgstr "Импорт пользовательских данных из буферной директории jabberd14:" + +#~ msgid "Listened Ports at " +#~ msgstr "Прослушиваемые порты на " + +#~ msgid "Modules at ~p" +#~ msgstr "Модули на ~p" + +#~ msgid "Statistics of ~p" +#~ msgstr "статистика узла ~p" + +#~ msgid "Uptime:" +#~ msgstr "Время работы:" + +#~ msgid "CPU Time:" +#~ msgstr "Процессорное время:" + +#~ msgid "Transactions Committed:" +#~ msgstr "Транзакции завершенные:" + +#~ msgid "Transactions Aborted:" +#~ msgstr "Транзакции отмененные:" + +#~ msgid "Transactions Restarted:" +#~ msgstr "Транзакции перезапущенные:" + +#~ msgid "Transactions Logged:" +#~ msgstr "Транзакции запротоколированные:" + +#~ msgid "Update ~p" +#~ msgstr "Обновление ~p" + +#~ msgid "Update plan" +#~ msgstr "План обновления" + +#~ msgid "Modified modules" +#~ msgstr "Изменённые модули" + +#~ msgid "Update script" +#~ msgstr "Сценарий обновления" + +#~ msgid "Low level update script" +#~ msgstr "Низкоуровневый сценарий обновления" + +#~ msgid "Script check" +#~ msgstr "Проверка сценария" + #~ msgid "Delete" #~ msgstr "Удалить" From 64d1efa6f2fd21eea3244a429a7c6a92374d7af0 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Sep 2015 15:06:57 +0200 Subject: [PATCH 232/695] Update Catalan and Spanish translations --- priv/msgs/ca.po | 63 ++++++++++++++++++++++--------------------------- priv/msgs/es.po | 4 ++-- 2 files changed, 30 insertions(+), 37 deletions(-) diff --git a/priv/msgs/ca.po b/priv/msgs/ca.po index c2d1b477cb0..d9a377a7651 100644 --- a/priv/msgs/ca.po +++ b/priv/msgs/ca.po @@ -3,8 +3,8 @@ msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2012-04-22 00:19+0200\n" -"Last-Translator: JanKusanagi\n" +"PO-Revision-Date: 2015-09-07 14:13+0100\n" +"Last-Translator: Badlop \n" "Language-Team: American English \n" "Language: en_US\n" "MIME-Version: 1.0\n" @@ -13,7 +13,7 @@ msgstr "" "X-Language: Catalan (català)\n" "X-Additional-Translator: Vicent Alberola Canet\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Lokalize 1.4\n" +"X-Generator: Poedit 1.6.10\n" #: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" @@ -34,7 +34,7 @@ msgstr "Has sigut expulsat" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Massa missatges sense haver reconegut la seva recepció" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -247,9 +247,8 @@ msgid "Change Password" msgstr "Canviar Contrasenya" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Usuari " +msgstr "Usuari ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -281,9 +280,8 @@ msgid "Stopped Nodes" msgstr "Nodes parats" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Node " +msgstr "Node ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -320,9 +318,8 @@ msgid "RPC Call Error" msgstr "Error de cridada RPC" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Taules de la base de dades en " +msgstr "Taules de la base de dades en ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -345,9 +342,8 @@ msgid "Error" msgstr "Error" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Còpia de seguretat de " +msgstr "Còpia de seguretat de ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -406,7 +402,7 @@ msgstr "Exportar dades d'usuaris d'un host a arxius PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Exporta totes les taules a un fitxer SQL:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -421,9 +417,8 @@ msgid "Listened Ports at " msgstr "Ports a la escolta en " #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Mòduls en " +msgstr "Mòduls en ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -454,9 +449,8 @@ msgid "Transactions Logged:" msgstr "Transaccions registrades" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Actualitzar" +msgstr "Actualitzar ~p" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -836,10 +830,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Massa autenticacions (~p) han fallat des d'aquesta adreça IP (~s). L'adreça " +"serà desbloquejada en ~s UTC" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Esta adreça IP està a la llista negra en ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -956,20 +952,20 @@ msgstr "Sales de xat" #: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "" -"Necessites un client amb suport x:data per a poder registrar el Nickname" +"Necessites un client amb suport x:data per a poder registrar el sobrenom" #: mod_muc.erl:1007 msgid "Nickname Registration at " -msgstr "Registre del Nickname en " +msgstr "Registre del sobrenom en " #: mod_muc.erl:1013 msgid "Enter nickname you want to register" -msgstr "Introdueix el nickname que vols registrar" +msgstr "Introdueix el sobrenom que vols registrar" #: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" -msgstr "Nickname" +msgstr "Sobrenom" #: mod_muc.erl:1177 msgid "ejabberd MUC module" @@ -978,26 +974,23 @@ msgstr "mòdul ejabberd MUC" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Multi-Usuari Converses" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Sales de xat" +msgstr "Nombre total de sales" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "Deixar la sala" +msgstr "Sales permanents" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Usuaris registrats" +msgstr "Sobrenoms registrats" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Llista de sales" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1152,7 +1145,7 @@ msgstr "El Jabber ID ~s no és vàlid" #: mod_muc_room.erl:2765 msgid "Nickname ~s does not exist in the room" -msgstr "El Nickname ~s no existeix a la sala" +msgstr "El sobrenom ~s no existeix a la sala" #: mod_muc_room.erl:2788 mod_muc_room.erl:3168 msgid "Invalid affiliation: ~s" @@ -1254,7 +1247,7 @@ msgstr "" #: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" -msgstr "Permetre als visitants canviar el Nickname" +msgstr "Permetre als visitants canviar el sobrenom" #: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" @@ -1270,7 +1263,7 @@ msgstr "Crear una sala protegida per CAPTCHA" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Activar l'emmagatzematge de missatges" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1318,11 +1311,11 @@ msgstr "la contrasenya és" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "Servei de Multicast d'ejabberd" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 05da1d8314d..2d8c2b46183 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: es\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2015-07-24 12:41+0100\n" +"PO-Revision-Date: 2015-09-07 14:02+0100\n" "Last-Translator: Badlop \n" "Language-Team: \n" "Language: es\n" @@ -1264,7 +1264,7 @@ msgstr "Proteger la sala con CAPTCHA" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Activar el almacenamiento de mensajes" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" From 420cf68ecd354d212909cda0e7772af87b95313b Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 7 Sep 2015 17:35:58 +0200 Subject: [PATCH 233/695] Use our own includes + includes from all dependencies --- mix.exs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 99e00b0d883..b71d3cc08f8 100644 --- a/mix.exs +++ b/mix.exs @@ -21,8 +21,9 @@ defmodule Ejabberd.Mixfile do end defp erlc_options do - includes = Path.wildcard(Path.join("..", "/*/include")) - [:debug_info, {:d, :NO_EXT_LIB}] ++ Enum.map(includes, fn(path) -> {:i, path} end) + # Use our own includes + includes from all dependencies + includes = ["include"] + Path.wildcard(Path.join("..", "/*/include")) + [:debug_info] ++ Enum.map(includes, fn(path) -> {:i, path} end) end defp deps do From 7b230e7e441de3332ed9337beccaa30c4a21780a Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Sep 2015 17:46:05 +0200 Subject: [PATCH 234/695] Update Japanese translation (thanks to Tsukasa Hamano)(#729) --- priv/msgs/ja.po | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index 461aa024f31..e7cdabc8153 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -963,26 +963,23 @@ msgstr "ejabberd MUCモジュール" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "マルチユーザーチャット" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "チャットルーム" +msgstr "チャットルーム数" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "がチャットルームから退出しました" +msgstr "永続チャットルーム" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "登録ユーザー" +msgstr "登録ニックネーム" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "チャットルームの一覧" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1252,7 +1249,7 @@ msgstr "チャットルームを CAPTCHA で保護" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "メッセージアーカイブを有効化" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1301,11 +1298,11 @@ msgstr "パスワードは" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "マルチキャスト" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberdマルチキャストサービス" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" From 5a9f1b9bbab7ebd5c98722efd1d9b85ee74a0980 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Sep 2015 17:46:50 +0200 Subject: [PATCH 235/695] =?UTF-8?q?Update=20Brazilian=20Portuguese=20trans?= =?UTF-8?q?lation=20(thanks=20to=20Ot=C3=A1vio=20Fernandes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- priv/msgs/pt-br.po | 97 ++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index 1121c6e0bc6..b81711c85f9 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -30,7 +30,7 @@ msgstr "foi removido" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "número excessivo de instâncias sem confirmação" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -39,15 +39,15 @@ msgstr "Insira o texto que você vê" #: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -"Suas mensagens para ~s estão bloqueadas. Para desbloquea-las, visite: ~s" +"Suas mensagens para ~s estão bloqueadas. Para desbloqueá-las, visite: ~s" #: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." -msgstr "" +msgstr "Se você não conseguir ver o CAPTCHA aqui, visite a web page." #: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" -msgstr "" +msgstr "CAPTCHA web page" #: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." @@ -243,9 +243,8 @@ msgid "Change Password" msgstr "Mudar senha" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Usuário " +msgstr "Usuário ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -277,9 +276,8 @@ msgid "Stopped Nodes" msgstr "Nos parados" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Nó" +msgstr "Nó ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -316,9 +314,8 @@ msgid "RPC Call Error" msgstr "Erro de chamada RPC" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Tabelas de base de dados em " +msgstr "Tabelas do bancod de dados em ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -341,9 +338,8 @@ msgid "Error" msgstr "Erro" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Backup de " +msgstr "Backup de ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -376,8 +372,8 @@ msgstr "Restaurar backup binário imediatamente" msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" -"Restaurar backup binário após próximo reinicialização do ejabberd (requer " -"menos memória):" +"Restaurar backup binário após reinicialização do ejabberd (requer menos " +"memória):" #: ejabberd_web_admin.erl:1937 msgid "Store plain text backup:" @@ -404,7 +400,7 @@ msgstr "" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Exportar todas as tabelas como SQL para um arquivo:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -416,12 +412,11 @@ msgstr "Importar dados dos usuários de um diretório-fila jabberd14:" #: ejabberd_web_admin.erl:2053 msgid "Listened Ports at " -msgstr "Portas ouvintes em " +msgstr "Portas abertas em " #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Módulos em " +msgstr "Módulos em ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -452,9 +447,8 @@ msgid "Transactions Logged:" msgstr "Transações de log:" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Atualizar " +msgstr "Atualizar ~p" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -592,7 +586,7 @@ msgstr "Restaurar" #: mod_configure.erl:165 mod_configure.erl:652 msgid "Dump to Text File" -msgstr "Exportar para arquivo de texto" +msgstr "Exportar para arquivo texto" #: mod_configure.erl:168 mod_configure.erl:663 msgid "Import File" @@ -661,7 +655,7 @@ msgstr "Gestão de Backup" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" -msgstr "Importar usuários de arquivos jabberd14" +msgstr "Importar usuários de arquivos jabberd14 (spool files)" #: mod_configure.erl:762 msgid "To ~s" @@ -833,10 +827,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço " +"serádesbloqueado as ~s UTC" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Este endereço IP está bloqueado em ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -952,10 +948,9 @@ msgid "Chatrooms" msgstr "Salas de Chat" #: mod_muc.erl:997 -#, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" -"Você precisa de um cliente com suporte de x:data para poder registrar o nick" +"Você precisa de um cliente com suporte a x:data para registrar o seu apelido" #: mod_muc.erl:1007 msgid "Nickname Registration at " @@ -977,26 +972,23 @@ msgstr "Módulo de MUC para ejabberd" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Chat multi-usuário" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Salas de Chat" +msgstr "Salas no total" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "Sair da sala" +msgstr "Salas permanentes" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Usuários Registrados" +msgstr "Usuários registrados" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Lista de salas" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1232,9 +1224,8 @@ msgid "Allow users to send private messages" msgstr "Permitir a usuários enviarem mensagens privadas" #: mod_muc_room.erl:3479 -#, fuzzy msgid "Allow visitors to send private messages to" -msgstr "Permitir a usuários enviarem mensagens privadas" +msgstr "Permitir visitantes enviar mensagem privada para" #: mod_muc_room.erl:3497 msgid "nobody" @@ -1257,9 +1248,8 @@ msgid "Allow visitors to change nickname" msgstr "Permitir mudança de apelido aos visitantes" #: mod_muc_room.erl:3535 -#, fuzzy msgid "Allow visitors to send voice requests" -msgstr "Permitir a usuários envio de convites" +msgstr "Permitir aos visitantes o envio de convites" #: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" @@ -1271,7 +1261,7 @@ msgstr "Tornar protegida a senha da sala" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Habilitar arquivamento de mensagens" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1302,13 +1292,12 @@ msgid "Either approve or decline the voice request." msgstr "Você deve aprovar/desaprovar a requisição de voz." #: mod_muc_room.erl:4262 -#, fuzzy msgid "User JID" -msgstr "Usuário " +msgstr "Usuário JID" #: mod_muc_room.erl:4266 msgid "Grant voice to this person?" -msgstr "" +msgstr "Dar 'voice' a esta usuário?" #: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" @@ -1320,11 +1309,11 @@ msgstr "a senha é" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd Multicast service" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" @@ -1332,7 +1321,7 @@ msgstr "~s's Fila de Mensagens Offline" #: mod_offline.erl:796 msgid "Time" -msgstr "Fecha" +msgstr "Tempo" #: mod_offline.erl:797 msgid "From" @@ -1459,7 +1448,6 @@ msgid "The collections with which a node is affiliated" msgstr "As coleções com as quais o nó está relacionado" #: mod_register.erl:250 -#, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Você precisa de um cliente com suporte de x:data para poder registrar o nick" @@ -1516,9 +1504,8 @@ msgstr "" "campos." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 -#, fuzzy msgid "Username:" -msgstr "Nome de usuário no IRC" +msgstr "Usuário:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." @@ -1530,9 +1517,8 @@ msgid "Characters not allowed:" msgstr "Caracteres não aceitos:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 -#, fuzzy msgid "Server:" -msgstr "Servidor ~b" +msgstr "Servidor:" #: mod_register_web.erl:245 msgid "" @@ -1565,22 +1551,18 @@ msgstr "" "você a esquecer eventualmente." #: mod_register_web.erl:262 mod_register_web.erl:374 -#, fuzzy msgid "Password Verification:" msgstr "Verificação de Senha" #: mod_register_web.erl:269 -#, fuzzy msgid "Register" -msgstr "Lista de contatos" +msgstr "Registrar" #: mod_register_web.erl:366 -#, fuzzy msgid "Old Password:" msgstr "Senha Antiga:" #: mod_register_web.erl:370 -#, fuzzy msgid "New Password:" msgstr "Nova Senha:" @@ -1639,12 +1621,11 @@ msgstr "Descrição:" #: mod_shared_roster.erl:1248 msgid "Members:" -msgstr "Miembros:" +msgstr "Membros:" #: mod_shared_roster.erl:1255 -#, fuzzy msgid "Displayed Groups:" -msgstr "Grupos Indicados:" +msgstr "Grupos Exibidos:" #: mod_shared_roster.erl:1264 msgid "Group " @@ -1853,13 +1834,11 @@ msgstr "Preencha campos para buscar usuários Jabber que concordem" #~ msgid "The CAPTCHA verification has failed" #~ msgstr "A verificação do CAPTCHA falhou" -#, fuzzy #~ msgid "The password is too weak" #~ msgstr "Senha considerada fraca'" #~ msgid "Users are not allowed to register accounts so quickly" #~ msgstr "Usuários não estão autorizados a registrar contas imediatamente" -#, fuzzy #~ msgid "Captcha test failed" #~ msgstr "O CAPTCHA é inválido." From 73932fb5074448935f646c24534eea1881352fd2 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 7 Sep 2015 17:55:54 +0200 Subject: [PATCH 236/695] Fix typo --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index b71d3cc08f8..09a6cc62536 100644 --- a/mix.exs +++ b/mix.exs @@ -22,7 +22,7 @@ defmodule Ejabberd.Mixfile do defp erlc_options do # Use our own includes + includes from all dependencies - includes = ["include"] + Path.wildcard(Path.join("..", "/*/include")) + includes = ["include"] ++ Path.wildcard(Path.join("..", "/*/include")) [:debug_info] ++ Enum.map(includes, fn(path) -> {:i, path} end) end From 4d19ef55b63840de434eacf4c6c581044edeca66 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 8 Sep 2015 21:38:23 +0200 Subject: [PATCH 237/695] Update Esperanto and Dutch translations (thanks to Andreas van Cranenburgh) --- priv/msgs/eo.po | 53 ++++++++++++++++++++-------------------------- priv/msgs/nl.po | 56 ++++++++++++++++++++++--------------------------- 2 files changed, 48 insertions(+), 61 deletions(-) diff --git a/priv/msgs/eo.po b/priv/msgs/eo.po index ef64084c108..59fd981c36a 100644 --- a/priv/msgs/eo.po +++ b/priv/msgs/eo.po @@ -5,11 +5,12 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: Andreas van Cranenburgh \n" "Language-Team: \n" -"Language: \n" +"Language: eo\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Esperanto\n" +"X-Generator: Poedit 1.6.10\n" #: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" @@ -30,7 +31,7 @@ msgstr "estas forpelita" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Tro da neagnoskitaj stancoj" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -242,9 +243,8 @@ msgid "Change Password" msgstr "Ŝanĝu pasvorton" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Uzanto " +msgstr "Uzanto ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -276,9 +276,8 @@ msgid "Stopped Nodes" msgstr "Neaktivaj Nodoj" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Nodo " +msgstr "Nodo ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -315,9 +314,8 @@ msgid "RPC Call Error" msgstr "Eraro de RPC-alvoko" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Datumbaz-tabeloj je " +msgstr "Datumbaz-tabeloj je ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -340,9 +338,8 @@ msgid "Error" msgstr "Eraro" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Sekurkopio de " +msgstr "Sekurkopio de ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -399,7 +396,7 @@ msgstr "Eksportu datumoj de uzantoj en gastigo al PIEFXIS dosieroj (XEP-0227):" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Eksportu ĉiuj tabeloj kiel SQL-informmendo al dosierujo:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -414,9 +411,8 @@ msgid "Listened Ports at " msgstr "Atentataj pordoj je " #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Moduloj je " +msgstr "Moduloj je ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -447,9 +443,8 @@ msgid "Transactions Logged:" msgstr "Transakcioj protokolitaj" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Ĝisdatigu " +msgstr "Ĝisdatigu ~p-n" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -828,10 +823,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Tro da malsukcesaj aŭtentprovoj (~p) de ĉi tiu IP-adreso (~s). La adreso " +"estos malbarata je ~s UTC." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Ĉi tiu IP-adreso estas barata in ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -910,15 +907,14 @@ msgid "IRC settings" msgstr "IRC agordoj" #: mod_irc.erl:1039 -#, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " "settings." msgstr "" -"Enmetu uzantnomon kaj enkodigoj kiujn vi volas uzi por konektoj al IRC-" -"serviloj. Elektu \"Sekvonto\" por ekhavi pliajn kampojn. Elektu \"Kompletigu" -"\" por savi agordojn." +"Enmetu uzantnomon kaj enkodigojn kiujn vi volas uzi por konektoj al IRC-" +"serviloj. Elektu 'Sekvonto' por ekhavi pliajn kampojn. Elektu 'Kompletigu' " +"por savi agordojn." #: mod_irc.erl:1048 msgid "IRC username" @@ -968,26 +964,23 @@ msgstr "ejabberd MUC-modulo" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Grupbabilado" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" msgstr "Babilejoj" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "eliras la babilejo" +msgstr "Permanentaj babilejoj" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Registritaj uzantoj" +msgstr "Registritaj uzantnomoj" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Listo de babilejoj" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1258,7 +1251,7 @@ msgstr "Farigu babilejon protektata per CAPTCHA" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Ŝaltu mesaĝo-arkivo" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1306,11 +1299,11 @@ msgstr "la pasvorto estas" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd Multicast-servo" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" diff --git a/priv/msgs/nl.po b/priv/msgs/nl.po index 22f02d0d8bd..2e1881e3545 100644 --- a/priv/msgs/nl.po +++ b/priv/msgs/nl.po @@ -5,12 +5,13 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: Andreas van Cranenburgh \n" "Language-Team: \n" -"Language: \n" +"Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Dutch (nederlands)\n" "X-Additional-Translator: Sander Devrieze\n" +"X-Generator: Poedit 1.6.10\n" #: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" @@ -27,11 +28,11 @@ msgstr "Vervangen door een nieuwe verbinding" #: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 #: mod_muc_log.erl:477 msgid "has been kicked" -msgstr "werd gekicked" +msgstr "is weggestuurd" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Te veel niet-bevestigde stanzas" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -90,7 +91,7 @@ msgstr "Verzonden" #: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 #: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 msgid "Bad format" -msgstr "Slecht formaat" +msgstr "Verkeerd formaat" #: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 #: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 @@ -244,9 +245,8 @@ msgid "Change Password" msgstr "Wachtwoord wijzigen" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Gebruiker " +msgstr "Gebruiker ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -278,9 +278,8 @@ msgid "Stopped Nodes" msgstr "Gestopte nodes" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Node " +msgstr "Node ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -317,9 +316,8 @@ msgid "RPC Call Error" msgstr "RPC-oproepfout" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Databasetabellen van " +msgstr "Databasetabellen van ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -342,9 +340,8 @@ msgid "Error" msgstr "Fout" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Backup maken van " +msgstr "Backup maken van ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -405,7 +402,7 @@ msgstr "" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Exporteer alle tabellen als SQL-queries naar een bestand:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -420,9 +417,8 @@ msgid "Listened Ports at " msgstr "Openstaande poorten op " #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Modules op " +msgstr "Modules op ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -453,9 +449,8 @@ msgid "Transactions Logged:" msgstr "Gelogde transacties:" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Opwaarderen van " +msgstr "Opwaarderen van ~p" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -835,14 +830,16 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Te veel (~p) mislukte authenticatie-pogingen van dit IP-adres (~s). Dit " +"adres zal worden gedeblokkeerd om ~s UTC" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Dit IP-adres is geblokkeerd in ~s" #: mod_irc.erl:431 msgid "IRC Transport" -msgstr "IRC Transport" +msgstr "IRC-transport" #: mod_irc.erl:468 msgid "ejabberd IRC module" @@ -977,26 +974,23 @@ msgstr "ejabberd's MUC module" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Groepschat" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Groepsgesprekken" +msgstr "Aantal groepsgesprekken" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "verliet de chatruimte" +msgstr "Permanente groepsgesprekken" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Geregistreerde gebruikers" +msgstr "Geregistreerde gebruikersnamen" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Lijst van groepsgesprekken" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1012,7 +1006,7 @@ msgstr "verliet de chatruimte" #: mod_muc_log.erl:467 mod_muc_log.erl:470 msgid "has been banned" -msgstr "werd verbannen" +msgstr "is verbannen" #: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" @@ -1270,7 +1264,7 @@ msgstr "Chatruimte beveiligen met een geautomatiseerde Turing test" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Zet bericht-archivering aan" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1320,11 +1314,11 @@ msgstr "het wachtwoord is" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd Multicast service" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" From 8fd9670da23f1bea1838a851f8b2ecc6815868d2 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 10 Sep 2015 12:21:50 +0200 Subject: [PATCH 238/695] typo fix --- tools/leavecluster | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/leavecluster b/tools/leavecluster index edac8689eb2..b2dfea0c721 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -31,8 +31,6 @@ function error read foo echo "" } -echo ok -exit PA=/tmp/clustersetup_$$ CTL=$(which ejabberdctl) From a50f00f9e8360ed0d6e1c7791d2226f8663fd285 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 10 Sep 2015 20:11:02 +0200 Subject: [PATCH 239/695] Include ext_mod modules when checking accepted options (ejabberd-contrib#116) --- src/ejabberd_app.erl | 2 +- src/ejabberd_config.erl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 30f34aff4ca..319e494c223 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -53,6 +53,7 @@ start(normal, _Args) -> ejabberd_commands:init(), ejabberd_admin:start(), gen_mod:start(), + ext_mod:start(), ejabberd_config:start(), set_settings_from_config(), acl:start(), @@ -67,7 +68,6 @@ start(normal, _Args) -> %ejabberd_debug:eprof_start(), %ejabberd_debug:fprof_start(), maybe_add_nameservers(), - ext_mod:start(), ejabberd_auth:start(), start_modules(), ejabberd_listener:start_listeners(), diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 5b97710a8d0..971d6dbd653 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -740,6 +740,7 @@ get_option(Opt, F, Default) -> get_modules_with_options() -> {ok, Mods} = application:get_key(ejabberd, modules), + ExtMods = [Name || {Name, _Details} <- ext_mod:installed()], lists:foldl( fun(Mod, D) -> case catch Mod:opt_type('') of @@ -751,7 +752,7 @@ get_modules_with_options() -> {'EXIT', {undef, _}} -> D end - end, dict:new(), [?MODULE|Mods]). + end, dict:new(), [?MODULE|ExtMods++Mods]). validate_opts(#state{opts = Opts} = State) -> ModOpts = get_modules_with_options(), From df08253e9120c8d0f84f2936ca758cadb82b62d9 Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 10 Sep 2015 21:25:12 +0200 Subject: [PATCH 240/695] Update Hebrew translation (thanks to Isratine Citizen) --- priv/msgs/he.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 11e0bbe80bb..2007c0c17ca 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -1282,7 +1282,7 @@ msgstr "הפוך חדר אל מוגן CAPTCHA" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "אפשר אחסון הודעות" # זהויות #: mod_muc_room.erl:3558 @@ -1291,7 +1291,7 @@ msgstr "הוצא כתובות של Jabber מתוך אתגר CAPTCHA" #: mod_muc_room.erl:3567 msgid "Enable logging" -msgstr "אפשור רישום פעילות" +msgstr "אפשר רישום פעילות" #: mod_muc_room.erl:3577 msgid "You need an x:data capable client to configure room" From 8c1864eca15fa5f253fa979e1e11a2fd3ff53a87 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 11 Sep 2015 13:22:52 +0200 Subject: [PATCH 241/695] Update German translation (thanks to Nikolaus Polak) --- priv/msgs/de.po | 98 +++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/priv/msgs/de.po b/priv/msgs/de.po index 5dfe2eec923..56c55a798d6 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -5,7 +5,7 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: Nikolaus Polak \n" "Language-Team: \n" -"Language: \n" +"Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -16,6 +16,7 @@ msgstr "" "X-Additional-Translator: Patrick Dreker\n" "X-Additional-Translator: Torsten Werner\n" "X-Additional-Translator: Marina Hahn\n" +"X-Generator: Poedit 1.8.4\n" #: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" @@ -32,11 +33,11 @@ msgstr "Durch neue Verbindung ersetzt" #: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 #: mod_muc_log.erl:477 msgid "has been kicked" -msgstr "wurde gekickt" +msgstr "wurde entfernt" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Zu viele unbestätigte Stanzas" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -157,16 +158,16 @@ msgstr "Alle Aktivitäten" #: ejabberd_web_admin.erl:930 msgid "Show Ordinary Table" -msgstr "Normale Tabelle anzeigen" +msgstr "Gewöhnliche Tabelle anzeigen" #: ejabberd_web_admin.erl:933 msgid "Show Integral Table" -msgstr "Vollständige Tabelle anzeigen" +msgstr "Integrale Tabelle anzeigen" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 #: mod_muc_admin.erl:246 msgid "Statistics" -msgstr "Statistik" +msgstr "Statistiken" #: ejabberd_web_admin.erl:950 msgid "Not Found" @@ -178,7 +179,7 @@ msgstr "Knoten nicht gefunden" #: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" -msgstr "Neue hinzufügen" +msgstr "Neue(n) hinzufügen" #: ejabberd_web_admin.erl:1273 msgid "Host" @@ -250,9 +251,8 @@ msgid "Change Password" msgstr "Passwort ändern" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Benutzer " +msgstr "Benutzer ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -281,12 +281,11 @@ msgstr "Aktive Knoten" #: ejabberd_web_admin.erl:1753 mod_configure.erl:529 msgid "Stopped Nodes" -msgstr "Inaktive Knoten" +msgstr "Angehaltene Knoten" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Knoten " +msgstr "Knoten ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -323,9 +322,8 @@ msgid "RPC Call Error" msgstr "Fehler bei RPC-Aufruf" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Datenbanktabellen auf " +msgstr "Datenbanktabellen auf ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -348,9 +346,8 @@ msgid "Error" msgstr "Fehler" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Sicherung von " +msgstr "Sicherung von ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -410,7 +407,7 @@ msgstr "" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Alle Tabellen als SQL Abfragen in eine Datei exportieren:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -425,9 +422,8 @@ msgid "Listened Ports at " msgstr "Aktive Ports bei" #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Module bei " +msgstr "Module bei ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -458,9 +454,8 @@ msgid "Transactions Logged:" msgstr "Protokollierte Transaktionen:" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Aktualisierung " +msgstr "Aktualisierung ~p" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -532,7 +527,7 @@ msgstr "Nachrichtentext" #: mod_announce.erl:627 msgid "No body provided for announce message" -msgstr "Kein Text für die Ankündigung angegeben" +msgstr "Kein Text für die Ankündigungsnachricht angegeben" #: mod_announce.erl:662 msgid "Announcements" @@ -753,7 +748,7 @@ msgstr "Benutzer aus dieser Datei importieren " #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" -msgstr "Geben Sie den Pfad zur jabberd14-Spool-Datei ein" +msgstr "Geben sie den Pfad zur jabberd14-Spool-Datei ein" #: mod_configure.erl:1177 msgid "Import Users from Dir at " @@ -761,7 +756,7 @@ msgstr "Benutzer importieren aus dem Verzeichnis " #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" -msgstr "Geben Sie den Pfad zum jabberd14-Spool-Verzeichnis ein" +msgstr "Geben sie den Pfad zum jabberd14-Spool-Verzeichnis ein" #: mod_configure.erl:1184 msgid "Path to Dir" @@ -840,10 +835,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Zu viele (~p) fehlgeschlagene Anmeldeversuche von dieser IP Adresse (~s). " +"Die Adresse wird bis ~s UTC blockiert." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Diese IP Adresse ist blockiert in ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -868,8 +865,8 @@ msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -"Geben Sie Benutzernamen und Zeichenkodierung für die Verbindung zum IRC-" -"Server an" +"Geben sie den Benutzernamen, Zeichenkodierung, Ports und Passwörter, die sie " +"für die Verbindung zum IRC-Server verwenden wollen, an" #: mod_irc.erl:659 msgid "IRC Username" @@ -983,26 +980,23 @@ msgstr "ejabberd MUC-Modul" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Mehrbenutzer-Chat (MUC)" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Chaträume" +msgstr "Alle Chaträume" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "verlässt den Raum" +msgstr "permanente Chaträume" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Registrierte Benutzer" +msgstr "Registrierte Benutzernamen" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Liste von Chaträumen" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1022,15 +1016,15 @@ msgstr "wurde gebannt" #: mod_muc_log.erl:482 msgid "has been kicked because of an affiliation change" -msgstr "wurde wegen Änderung des Mitgliederstatus gekickt" +msgstr "wurde wegen Änderung des Mitgliederstatus entfernt" #: mod_muc_log.erl:487 msgid "has been kicked because the room has been changed to members-only" -msgstr "wurde gekickt weil der Raum auf Nur-Mitglieder umgestellt wurde" +msgstr "wurde entfernt weil der Raum auf Nur-Mitglieder umgestellt wurde" #: mod_muc_log.erl:492 msgid "has been kicked because of a system shutdown" -msgstr "wurde wegen Systemabschaltung gekickt" +msgstr "wurde wegen einer Systemabschaltung entfernt" #: mod_muc_log.erl:497 msgid "is now known as" @@ -1256,7 +1250,7 @@ msgstr "Erlaube Besuchern einen Text bei Statusänderung zu senden" #: mod_muc_room.erl:3532 msgid "Allow visitors to change nickname" -msgstr "Erlaube Besuchern ihren Spitznamen zu ändern" +msgstr "Erlaube Besuchern ihren Benutzernamen zu ändern" #: mod_muc_room.erl:3535 msgid "Allow visitors to send voice requests" @@ -1272,7 +1266,7 @@ msgstr "Raum mit Verifizierung (Captcha) versehen" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Nachrichtenarchivierung aktivieren" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1314,7 +1308,7 @@ msgstr "Sprachrechte dieser Person erteilen?" #: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" -msgstr "~s lädt Sie in den Raum ~s ein" +msgstr "~s lädt sie in den Raum ~s ein" #: mod_muc_room.erl:4421 msgid "the password is" @@ -1322,11 +1316,11 @@ msgstr "das Passwort lautet" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd Multicast Dienst" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" @@ -1374,7 +1368,7 @@ msgstr "PubSub-Abonnenten-Anfrage" #: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." -msgstr "Wähle Sie, ob dieses Abonnement akzeptiert werden soll." +msgstr "Wählen sie, ob dieses Abonnement akzeptiert werden soll." #: mod_pubsub.erl:1560 msgid "Node ID" @@ -1451,7 +1445,7 @@ msgstr "Maximale Nutzlastgrösse in Bytes" #: mod_pubsub.erl:3732 msgid "When to send the last published item" -msgstr "Wann soll das letzte veröffentlichte Objekt gesendet werden" +msgstr "Wann das letzte veröffentlichte Objekt gesendet werden soll" #: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" @@ -1477,7 +1471,7 @@ msgstr "Ihr Jabber Konto wurde erfolgreich erstellt." #: mod_register_web.erl:110 msgid "There was an error creating the account: " -msgstr "Es trat ein Fehler beim erstellen des Kontos auf:" +msgstr "Es trat ein Fehler beim Erstellen des Kontos auf: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." @@ -1485,7 +1479,7 @@ msgstr "Ihr Jabber Konto wurde erfolgreich gelöscht." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " -msgstr "Es trat ein Fehler beim Löschen des Kontos auf:" +msgstr "Es trat ein Fehler beim Löschen des Kontos auf: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." @@ -1493,7 +1487,7 @@ msgstr "Das Passwort von ihrem Jabber Konto wurde geändert." #: mod_register_web.erl:140 msgid "There was an error changing the password: " -msgstr "Es trat ein Fehler beim Ändern des Passworts auf:" +msgstr "Es trat ein Fehler beim Ändern des Passworts auf: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" @@ -1599,7 +1593,7 @@ msgstr "Abonnement" #: mod_roster.erl:1438 msgid "Pending" -msgstr "anhängig" +msgstr "Schwebend" #: mod_roster.erl:1439 msgid "Groups" @@ -1679,7 +1673,7 @@ msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "" -"Füllen Sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen " +"Füllen sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen " "(beenden Sie ein Feld mit *, um auch nach Teilzeichenketten zu suchen)" #: mod_vcard.erl:490 mod_vcard.erl:615 @@ -1692,7 +1686,7 @@ msgstr "Zweiter Vorname" #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" -msgstr "Organisation" +msgstr "Name der Organisation" #: mod_vcard.erl:490 mod_vcard.erl:628 msgid "Organization Unit" @@ -1723,7 +1717,7 @@ msgstr "Suchergebnisse für " #: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" msgstr "" -"Füllen Sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen" +"Füllen sie die Felder aus, um nach bestimmten Jabber-Benutzern zu suchen" #~ msgid "Delete" #~ msgstr "Löschen" From 48c5e733218343f7aac347e0147692601ff57bef Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 11 Sep 2015 14:32:58 +0200 Subject: [PATCH 242/695] ext_mod must be started before ejabberd_config --- src/ext_mod.erl | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 002c5dd9161..4b9ddafab15 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -42,15 +42,10 @@ %% -- ejabberd init and commands start() -> - case is_contrib_allowed() of - true -> - [code:add_patha(module_ebin_dir(Module)) - || {Module, _} <- installed()], - application:start(inets), - ejabberd_commands:register_commands(commands()); - false -> - ok - end. + [code:add_patha(module_ebin_dir(Module)) + || {Module, _} <- installed()], + application:start(inets), + ejabberd_commands:register_commands(commands()). stop() -> ejabberd_commands:unregister_commands(commands()). From 25791cfde8e55cae7d4bf82f5c82a7a8ba2991d4 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Sep 2015 14:20:31 +0300 Subject: [PATCH 243/695] Fix MSSQL support --- sql/mssql.sql | Bin 0 -> 56088 bytes sql/mssql2000.sql | 1095 ------------------------- sql/mssql2005.sql | 1802 ----------------------------------------- sql/mssql2012.sql | 1782 ---------------------------------------- src/ejabberd_odbc.erl | 27 +- src/odbc_queries.erl | 341 -------- 6 files changed, 19 insertions(+), 5028 deletions(-) create mode 100644 sql/mssql.sql delete mode 100644 sql/mssql2000.sql delete mode 100644 sql/mssql2005.sql delete mode 100644 sql/mssql2012.sql diff --git a/sql/mssql.sql b/sql/mssql.sql new file mode 100644 index 0000000000000000000000000000000000000000..c3944d9697f985859753d8084740076863941072 GIT binary patch literal 56088 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 0 - BEGIN - BEGIN TRANSACTION - SELECT @dt = DATEADD(d, -3, GETDATE()) - DELETE FROM spool - WITH (ROWLOCK) - WHERE (MustDelete=1) OR (Created < @dt); - - SET @myRowCount = @@RowCount - COMMIT - END -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_last] ******/ -/** Delete an entry from the last table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_last] - @Username varchar(250) -AS -BEGIN - DELETE FROM [last] - WITH (ROWLOCK) - WHERE [last].username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_roster] ******/ -/** Delete an entry from the roster **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_roster] - @Username varchar(250), - @JID varchar(250) -AS -BEGIN - BEGIN TRANSACTION - DELETE FROM rosterusers - WITH (ROWLOCK) - WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID); - - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); - COMMIT -END -GO - - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_spool_msg] ******/ -/** Delete an entry from the spool table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_spool_msg] - @Username varchar(250) -AS -BEGIN - DELETE FROM spool - WITH (ROWLOCK) - WHERE spool.username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user] ******/ -/** Delete an entry from the user table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_user] - @Username varchar(200) -AS -BEGIN - DELETE FROM users - WITH (ROWLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_return_password]**/ -/** Delete an entry from the user table and return user password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_user_return_password] - @Username varchar(250) -AS -DECLARE - @Pwd varchar(50) -BEGIN - EXECUTE @Pwd = dbo.get_password @Username - DELETE FROM users - WITH (ROWLOCK) - WHERE username=@Username - - SELECT @Pwd; -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_roster] **/ -/** Delete the users roster **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_user_roster] - @Username varchar(250) -AS -BEGIN - BEGIN TRANSACTION - DELETE FROM rosterusers - WITH (ROWLOCK) - WHERE rosterusers.username = @Username; - - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE rostergroups.username = @Username; - COMMIT -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_and_del_spool_msg] **/ -/** Fetch and delete the users offline messages **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_and_del_spool_msg] - @Username varchar(250) -AS -DECLARE - @vSpool table( username varchar(1), - xml varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM spool with (nolock) WHERE spool.username=@Username) - BEGIN - SELECT spool.username AS username, - spool.xml AS xml - FROM spool WITH (NOLOCK) - WHERE spool.username=@Username; - - DELETE spool - WITH (ROWLOCK) - WHERE spool.username=@Username - END - ELSE - BEGIN - SELECT * FROM @vSpool; - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_last] **/ -/** Retrive the last user login **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_last] - @Username varchar(250) -AS -BEGIN - SELECT last.seconds AS seconds, - last.state AS state - FROM last WITH (NOLOCK) - WHERE last.username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster] **/ -/** Retrive the user roster **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster] - @Username varchar(250) -AS -DECLARE - @vRosterusers table( username varchar(1), - jid varchar(1), - nick varchar(1), - subscription varchar(1), - ask varchar(1), - askmessage varchar(1), - server varchar(1), - subscribe varchar(1), - type varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username = @Username) - BEGIN - SELECT rosterusers.username AS username, - rosterusers.jid AS jid, - rosterusers.nick AS nick, - rosterusers.subscription AS subscription, - rosterusers.ask AS ask, - rosterusers.askmessage AS askmessage, - rosterusers.server AS server, - rosterusers.subscribe AS subscribe, - rosterusers.type AS type - FROM rosterusers WITH (NOLOCK) - WHERE rosterusers.username = @Username; - END - ELSE - BEGIN - SELECT * FROM @vRosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_by_jid] **/ -/** Retrive the user roster via JID **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_by_jid] - @Username varchar(200), - @JID varchar(250) -AS -DECLARE - @vRosterusers table( username varchar(1), - jid varchar(1), - nick varchar(1), - subscription varchar(1), - ask varchar(1), - askmessage varchar(1), - server varchar(1), - subscribe varchar(1), - type varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID)) - BEGIN - SELECT rosterusers.username AS username, - rosterusers.jid AS jid, - rosterusers.nick AS nick, - rosterusers.subscription AS subscription, - rosterusers.ask AS ask, - rosterusers.askmessage AS askmessage, - rosterusers.server AS server, - rosterusers.subscribe AS subscribe, - rosterusers.type AS type - FROM rosterusers WITH (NOLOCK) - WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID); - END - ELSE - BEGIN - SELECT * FROM @vRosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_jid_groups] **/ -/** Retrieve the user roster groups **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_jid_groups] - @Username varchar(200) -AS -DECLARE - @vrostergroups table( jid varchar(1), - grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username) - BEGIN - SELECT rostergroups.jid AS jid, - rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE rostergroups.username = @Username; - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_groups] **/ -/** Retrive the user roster groups **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_groups] - @Username varchar(200), - @JID varchar(250) -AS -DECLARE - @vrostergroups table( grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username) - BEGIN - SELECT rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_rostergroup_by_jid] **/ -/** Retrive the user roster groups via JID **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_rostergroup_by_jid] - @Username varchar(250), - @JID varchar(250) -AS -DECLARE - @vrostergroups table(grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID) - BEGIN - SELECT rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE rostergroups.username=@Username AND rostergroups.jid=@JID; - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_subscription] **/ -/** Retrive the user subscription requests **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_subscription] - @Username varchar(250), - @JID varchar(250) -AS -DECLARE - @vrosterusers table( subscription varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - SELECT rosterusers.subscription AS subscription - FROM rosterusers WITH (NOLOCK) - WHERE rosterusers.username=@Username AND rosterusers.jid=@JID; - END - ELSE - BEGIN - SELECT * FROM @vrosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[list_users] **/ -/** Retrieve a list of all users **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[list_users] -AS -BEGIN - SELECT users.username AS username FROM users WITH (NOLOCK); -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_last] **/ -/** Update users last login status **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_last] - @Username varchar(250), - @Seconds varchar(50), - @State varchar(100) -AS -BEGIN - IF EXISTS (SELECT username FROM [last] WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE [last] - SET [last].username = @Username, - [last].seconds = @Seconds, - [last].state = @State - WHERE last.username=@Username; - END - ELSE - BEGIN - INSERT INTO [last] - ( [last].username, - [last].seconds, - [last].state - ) - VALUES - ( @Username, - @Seconds, - @State - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_private_data] **/ -/** store user private data by namespace **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_private_data] - @Username varchar(250), - @Namespace varchar(250), - @Data varchar(8000) -AS -BEGIN - IF EXISTS (SELECT username FROM private_storage with (nolock) WHERE private_storage.username = @Username AND private_storage.namespace = @Namespace) - BEGIN - UPDATE [private_storage] - SET [private_storage].username = @Username, - [private_storage].namespace = @Namespace, - [private_storage].data = @Data - WHERE private_storage.username = @Username AND private_storage.namespace = @Namespace; - END - ELSE - BEGIN - INSERT INTO [private_storage] - ( [private_storage].username, - [private_storage].namespace, - [private_storage].data - ) - VALUES - ( @Username, - @Namespace, - @Data - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_private_data] **/ -/** Retrieve user private data by namespace **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_private_data] - @Username varchar(250), - @Namespace varchar(250) -AS -BEGIN - SELECT private_storage.data AS data - FROM private_storage WITH (NOLOCK) - WHERE username=@Username and namespace=@Namespace; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_storage] ******/ -/** Delete private storage area for a given user **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_user_storage] - @Username varchar(250) -AS -BEGIN - DELETE FROM [private_storage] - WITH (ROWLOCK) - WHERE [private_storage].username=@Username; -END -GO - - - diff --git a/sql/mssql2005.sql b/sql/mssql2005.sql deleted file mode 100644 index de4b1bed074..00000000000 --- a/sql/mssql2005.sql +++ /dev/null @@ -1,1802 +0,0 @@ -/* - * ejabberd, Copyright (C) 2002-2015 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -SET ANSI_NULLS ON -GO -SET QUOTED_IDENTIFIER ON -GO - -exec sp_dboption N'ejabberd', N'autoclose', N'false' -GO - -exec sp_dboption N'ejabberd', N'bulkcopy', N'true' -GO - -exec sp_dboption N'ejabberd', N'trunc. log', N'false' -GO - -exec sp_dboption N'ejabberd', N'torn page detection', N'true' -GO - -exec sp_dboption N'ejabberd', N'read only', N'false' -GO - -exec sp_dboption N'ejabberd', N'dbo use', N'false' -GO - -exec sp_dboption N'ejabberd', N'single', N'false' -GO - -exec sp_dboption N'ejabberd', N'autoshrink', N'false' -GO - -exec sp_dboption N'ejabberd', N'ANSI null default', N'false' -GO - -exec sp_dboption N'ejabberd', N'recursive triggers', N'false' -GO - -exec sp_dboption N'ejabberd', N'ANSI nulls', N'false' -GO - -exec sp_dboption N'ejabberd', N'concat null yields null', N'false' -GO - -exec sp_dboption N'ejabberd', N'cursor close on commit', N'false' -GO - -exec sp_dboption N'ejabberd', N'default to local cursor', N'false' -GO - -exec sp_dboption N'ejabberd', N'quoted identifier', N'false' -GO - -exec sp_dboption N'ejabberd', N'ANSI warnings', N'false' -GO - -exec sp_dboption N'ejabberd', N'auto create statistics', N'true' -GO - -exec sp_dboption N'ejabberd', N'auto update statistics', N'true' -GO - -use [ejabberd] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[last]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[last] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rostergroups]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[rostergroups] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rosterusers]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[rosterusers] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spool]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[spool] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[users] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[vcard] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard_search]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[vcard_search] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[private_storage]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[private_storage] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[privacy_default_list]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[privacy_default_list] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[privacy_list]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[privacy_list] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[privacy_list_data]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[privacy_list_data] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[roster_version]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[roster_version] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_node_option]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_node_option] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_node_owner]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_node_owner] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_state]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_state] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_item]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_item] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_subscription_opt]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_subscription_opt] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_node]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_node] -GO - -CREATE TABLE [dbo].[last] ( - [username] [varchar] (250) NOT NULL , - [seconds] [varchar] (50) NOT NULL , - [state] [varchar] (100) NOT NULL , - [Modify_Date] [datetime] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[rostergroups] ( - [username] [varchar] (250) NOT NULL , - [jid] [varchar] (250) NOT NULL , - [grp] [varchar] (100) NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[rosterusers] ( - [username] [varchar] (250) NOT NULL , - [jid] [varchar] (250) NOT NULL , - [nick] [varchar] (50) NOT NULL , - [subscription] [char] (1) NOT NULL , - [ask] [char] (1) NOT NULL , - [askmessage] [varchar] (250) NOT NULL , - [server] [char] (1) NOT NULL , - [subscribe] [varchar] (200) NULL , - [type] [varchar] (50) NULL , -CONSTRAINT [PK_rosterusers] PRIMARY KEY NONCLUSTERED -( - [username] ASC, - [jid] ASC -)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[spool] ( - [id] [numeric](19, 0) IDENTITY (1, 1) NOT NULL , - [username] [varchar] (250) NOT NULL , - [xml] [text] NOT NULL , - [notifyprocessed] [bit] NULL , - [created] [datetime] NULL , - [MustDelete] [bit] NOT NULL -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] -GO - -CREATE TABLE [dbo].[users] ( - [username] [varchar] (250) NOT NULL , - [password] [varchar] (50) NOT NULL , - [created] [datetime] NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[vcard] ( - [username] [varchar] (250) NOT NULL , - [vcard] [text] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[vcard_search] ( - [username] [varchar] (250) NOT NULL , - [lusername] [varchar] (250) NOT NULL , - [fn] [text] NOT NULL , - [lfn] [varchar] (250) NOT NULL , - [family] [text] NOT NULL , - [lfamily] [varchar] (250) NOT NULL , - [given] [text] NOT NULL , - [lgiven] [varchar] (250) NOT NULL , - [middle] [text] NOT NULL , - [lmiddle] [varchar] (250) NOT NULL , - [nickname] [text] NOT NULL , - [lnickname] [varchar] (250) NOT NULL , - [bday] [text] NOT NULL , - [lbday] [varchar] (250) NOT NULL , - [ctry] [text] NOT NULL , - [lctry] [varchar] (250) NOT NULL , - [locality] [text] NOT NULL , - [llocality] [varchar] (250) NOT NULL , - [email] [text] NOT NULL , - [lemail] [varchar] (250) NOT NULL , - [orgname] [text] NOT NULL , - [lorgname] [varchar] (250) NOT NULL , - [orgunit] [text] NOT NULL , - [lorgunit] [varchar] (250) NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[private_storage] ( - [username] [varchar] (250) NOT NULL , - [namespace] [varchar] (250) NOT NULL , - [data] [text] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[privacy_default_list] ( - [username] [varchar] (250) NOT NULL, - [name] [varchar] (250) NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[privacy_list]( - [username] [varchar](250) NOT NULL, - [name] [varchar](250) NOT NULL, - [id] [bigint] IDENTITY(1,1) NOT NULL, - CONSTRAINT [PK_privacy_list] PRIMARY KEY CLUSTERED -( - [id] ASC -)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[privacy_list_data] ( - [id] [bigint] NOT NULL, - [t] [character] (1) NOT NULL, - [value] [text] NOT NULL, - [action] [character] (1) NOT NULL, - [ord] [NUMERIC] NOT NULL, - [match_all] [bit] NOT NULL, - [match_iq] [bit] NOT NULL, - [match_message] [bit] NOT NULL, - [match_presence_in] [bit] NOT NULL, - [match_presence_out] [bit] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[roster_version] ( - [username] [varchar](250) PRIMARY KEY, - [version] [text] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_node] ( - [host] [varchar](250), - [node] [varchar](250), - [parent] [varchar](250), - [type] [varchar](250), - [nodeid] [bigint] IDENTITY(1,1) PRIMARY KEY -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_node_option] ( - [nodeid] [bigint], - [name] [varchar](250), - [val] [varchar](250) -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_node_owner] ( - [nodeid] [bigint], - [owner] [varchar](250) -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_state] ( - [nodeid] [bigint], - [jid] [varchar](250), - [affiliation] [CHAR](1), - [subscriptions] [text], - [stateid] [bigint] IDENTITY(1,1) PRIMARY KEY -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_item] ( - [nodeid] [bigint], - [itemid] [varchar](250), - [publisher] [text], - [creation] [text], - [modification] [text], - [payload] [text] -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_subscription_opt] ( - [subid] [varchar](250), - [opt_name] [varchar](32), - [opt_value] [text] -) ON [PRIMARY] -GO - -/* Constraints to add: -- id in privacy_list is a SERIAL autogenerated number -- id in privacy_list_data must exist in the table privacy_list */ - -ALTER TABLE [dbo].[last] WITH NOCHECK ADD - CONSTRAINT [PK_last] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[rostergroups] WITH NOCHECK ADD - CONSTRAINT [PK_rostergroups] PRIMARY KEY CLUSTERED - ( - [username], - [jid], - [grp] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[spool] WITH NOCHECK ADD - CONSTRAINT [PK_spool] PRIMARY KEY CLUSTERED - ( - [username], - [id] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[users] WITH NOCHECK ADD - CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[vcard] WITH NOCHECK ADD - CONSTRAINT [PK_vcard] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[pubsub_node_option] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_node_option] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [dbo].[pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[pubsub_node_owner] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_node_owner] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[pubsub_state] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_state] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[pubsub_item] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_item] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -CREATE INDEX [IX_vcard_search_lfn] ON [dbo].[vcard_search]([lfn]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lfamily] ON [dbo].[vcard_search]([lfamily]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lgiven] ON [dbo].[vcard_search]([lgiven]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lmiddle] ON [dbo].[vcard_search]([lmiddle]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lnickname] ON [dbo].[vcard_search]([lnickname]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lbday] ON [dbo].[vcard_search]([lbday]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lctry] ON [dbo].[vcard_search]([lctry]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_llocality] ON [dbo].[vcard_search]([llocality]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lemail] ON [dbo].[vcard_search]([lemail]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lorgname] ON [dbo].[vcard_search]([lorgname]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lorgunit] ON [dbo].[vcard_search]([lorgunit]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - -CREATE CLUSTERED INDEX [IX_rosterusers_user] ON [dbo].[rosterusers]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[last] WITH NOCHECK ADD - CONSTRAINT [DF_last_updated] DEFAULT (getdate()) FOR [Modify_Date] -GO - -ALTER TABLE [dbo].[spool] WITH NOCHECK ADD - CONSTRAINT [DF_spool_notifyprocessed] DEFAULT (0) FOR [notifyprocessed], - CONSTRAINT [DF_spool_created] DEFAULT (getdate()) FOR [created], - CONSTRAINT [DF_spool_MustDelete] DEFAULT (0) FOR [MustDelete] -GO - -ALTER TABLE [dbo].[users] WITH NOCHECK ADD - CONSTRAINT [DF_users_created] DEFAULT (getdate()) FOR [created] -GO - -ALTER TABLE [dbo].[privacy_default_list] WITH NOCHECK ADD - CONSTRAINT [PK_privacy_defaut_list] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_rostergroups_jid] ON [dbo].[rostergroups]([jid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_rostergroups_user] ON [dbo].[rostergroups]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_spool_user] ON [dbo].[spool]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_spool_process] ON [dbo].[spool]([created], [notifyprocessed]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IK_Spool_Del] ON [dbo].[spool]([MustDelete]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IK_Spool_Created] ON [dbo].[spool]([created]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_private_user] ON [dbo].[private_storage]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_private_user_ns] ON [dbo].[private_storage]([username], [namespace]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_privacy_list_username] ON [dbo].[privacy_list]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_privacy_list_username_name] ON [dbo].[privacy_list]([username], [name]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_parent] ON [dbo].[pubsub_node]([parent]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_tuple] ON [dbo].[pubsub_node]([host], [node]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_option_nodeid] ON [dbo].[pubsub_node_option]([nodeid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_owner_nodeid] ON [dbo].[pubsub_node_owner]([nodeid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_state_jid] ON [dbo].[pubsub_state]([jid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_state_tuple] ON [dbo].[pubsub_state]([nodeid], [jid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_item_itemid] ON [dbo].[pubsub_item]([itemid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_item_tuple] ON [dbo].[pubsub_item]([nodeid], [itemid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_subscription_opt] ON [dbo].[pubsub_subscription_opt]([subid], [opt_name]) WITH FILLFACTOR = 90 ON [PRIMARY] -Go - -/*********************************************************/ -/** These store procedures are for use with ejabberd **/ -/** 1.1 and Microsoft Sql Server 2000 **/ -/** **/ -/** The stored procedures reduce the need to sql **/ -/** compilation of the database and also allow for also **/ -/** provide each of database integration. The stored **/ -/** procedure have been optimized to increase database **/ -/** performance and a reduction of 80% in CPU was **/ -/** achieved over the use of standard sql. **/ -/*********************************************************/ - -/****** Object: StoredProcedure [dbo].[add_roster] ******/ -/** Add or update user entries in the roster **/ -/*********************************************************/ -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_roster_group]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_roster_group] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_roster_user]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_roster_user] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_roster_groups]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_roster_groups] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_spool]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_spool] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_user]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_user] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_password]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_password] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[clean_spool_msg]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[clean_spool_msg] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_password]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_password] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_last]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_last] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_spool_msg]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_spool_msg] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user_return_password]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user_return_password] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_and_del_spool_msg]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_and_del_spool_msg] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_last]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_last] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster_by_jid]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster_by_jid] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster_jid_groups]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster_jid_groups] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster_groups]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster_groups] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_rostergroup_by_jid]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_rostergroup_by_jid] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_subscription]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_subscription] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[list_users]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[list_users] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_last]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_last] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_private_data]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_private_data] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_private_data]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_private_data] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user_storage]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user_storage] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_vcard]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_vcard] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_vcard]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_vcard] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_default_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_default_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_names]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_names] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_id]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_id] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_data]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_data] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_data_by_id]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_data_by_id] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_default_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_default_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[unset_default_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[unset_default_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[remove_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[remove_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_privacy_list_by_id]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_privacy_list_by_id] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_privacy_lists]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_privacy_lists] -GO - -CREATE PROCEDURE [dbo].[add_roster] - @Username varchar(250), - @JID varchar(250), - @Nick varchar(50), - @Subscription char(1), - @Ask char(1), - @AskMessage varchar(250), - @Server char(1), - @Subscribe varchar(200), - @Type varchar(50), - @Grp varchar(100) -AS -BEGIN - BEGIN TRANSACTION - --- Update Roster if user exist else add roster item - IF EXISTS (SELECT username FROM rosterusers WITH (NOLOCK) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - UPDATE rosterusers - SET rosterusers.username=@Username, - rosterusers.jid=@JID, - rosterusers.nick=@Nick, - rosterusers.subscription=@Subscription, - rosterusers.ask=@Ask, - rosterusers.askmessage=@AskMessage, - rosterusers.server=@Server, - rosterusers.subscribe=@Subscribe, - rosterusers.type=@Type - WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID); - END - ELSE - BEGIN - INSERT INTO rosterusers - ( rosterusers.username, - rosterusers.jid, - rosterusers.nick, - rosterusers.subscription, - rosterusers.ask, - rosterusers.askmessage, - rosterusers.server, - rosterusers.subscribe, - rosterusers.type - ) - VALUES - ( @Username, - @JID, - @Nick, - @Subscription, - @Ask, - @AskMessage, - @Server, - @Subscribe, - @Type - ); - END - - --- Update Roster Groups if exist else add group entry - IF NOT EXISTS (SELECT username FROM rostergroups WITH (NOLOCK) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp) - BEGIN - INSERT INTO rostergroups - ( rostergroups.username, - rostergroups.jid, - rostergroups.grp - ) - VALUES - ( @Username, - @JID, - @Grp - ); - END - - COMMIT -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_roster_group] ******/ -/** Add or update user group entries in the roster groups **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_roster_group] - @Username varchar(250), - @JID varchar(250), - @Grp varchar(100) -AS -BEGIN - --- Update Roster Groups if exist else add group - IF NOT EXISTS (SELECT username FROM rostergroups WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp) - BEGIN - INSERT INTO rostergroups - ( rostergroups.username, - rostergroups.jid, - rostergroups.grp - ) - VALUES - ( @Username, - @JID, - @Grp - ) - END -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_roster_user] ******/ -/** Add or update user entries in the roster **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_roster_user] - @Username varchar(250), - @JID varchar(250), - @Nick varchar(50), - @Subscription char(1), - @Ask char(1), - @AskMessage varchar(250), - @Server char(1), - @Subscribe varchar(200), - @Type varchar(50), - @Grp varchar(100) = Null -AS -BEGIN - BEGIN TRANSACTION - --- Update Roster Users if exist of add new user - IF EXISTS (SELECT username FROM rosterusers WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - UPDATE rosterusers - SET rosterusers.username=@Username, - rosterusers.jid=@JID, - rosterusers.nick=@Nick, - rosterusers.subscription=@Subscription, - rosterusers.ask=@Ask, - rosterusers.askmessage=@AskMessage, - rosterusers.server=@Server, - rosterusers.subscribe=@Subscribe, - rosterusers.type=@Type - WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID); - END - ELSE - BEGIN - INSERT INTO rosterusers - ( rosterusers.username, - rosterusers.jid, - rosterusers.nick, - rosterusers.subscription, - rosterusers.ask, - rosterusers.askmessage, - rosterusers.server, - rosterusers.subscribe, - rosterusers.type - ) - VALUES - ( @Username, - @JID, - @Nick, - @Subscription, - @Ask, - @AskMessage, - @Server, - @Subscribe, - @Type - ); - END - - --- Update Roster Group if exist of add new group - IF @Grp IS NOT NULL - EXECUTE [dbo].[add_roster_group] @Username, @JID, @Grp - - COMMIT -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_roster_groups] ******/ -/** Remove user group entries from the roster groups table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_roster_groups] - @Username varchar(250), - @JID varchar(250) -AS -BEGIN - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_spool] ******/ -/** Add a entry to the spool table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_spool] - @Username varchar(250), - @XML varchar(8000) -AS -BEGIN - INSERT INTO spool - ( spool.username, - spool.xml - ) - VALUES - ( @Username, - @XML - ) -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_user] ******/ -/** Add or update user entries to jabber **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_user] - @Username varchar(200), - @Password varchar(50) -AS -BEGIN - INSERT INTO users - ( [username], - [password] - ) - VALUES - ( @Username, - @Password - ); -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_password] **/ -/** Update users password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_password] - @Username varchar(200), - @Password varchar(50) -AS -BEGIN - IF EXISTS (SELECT username FROM users WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE users SET username=@Username, password=@Password WHERE username=@Username; - END - ELSE - BEGIN - INSERT INTO users (username, password) VALUES (@Username, @Password); - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_password] **/ -/** Retrive the user password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_password] - @Username varchar(200) -AS -BEGIN - SELECT users.password as password - FROM users WITH (NOLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_roster_version] **/ -/** Update users roster_version **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_roster_version] - @Username varchar(200), - @Version varchar(8000) -AS -BEGIN - IF EXISTS (SELECT username FROM roster_version WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE roster_version SET username=@Username, version=@Version WHERE username=@Username; - END - ELSE - BEGIN - INSERT INTO roster_version (username, version) VALUES (@Username, @Version); - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_version] **/ -/** Retrive the user roster_version **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_version] - @Username varchar(200) -AS -BEGIN - SELECT roster_version.version as version - FROM roster_version WITH (NOLOCK) - WHERE username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/ -/** Delete messages older that 3 days from spool **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[clean_spool_msg] -AS -DECLARE - @dt datetime, - @myRowCount int -BEGIN - -- Delete small amounts because if locks the database table - SET ROWCOUNT 500 - SET @myRowCount = 1 - - WHILE (@myRowCount) > 0 - BEGIN - BEGIN TRANSACTION - SELECT @dt = DATEADD(d, -3, GETDATE()) - DELETE FROM spool - WITH (ROWLOCK) - WHERE (MustDelete=1) OR (Created < @dt); - - SET @myRowCount = @@RowCount - COMMIT - END -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_last] ******/ -/** Delete an entry from the last table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_last] - @Username varchar(250) -AS -BEGIN - DELETE FROM [last] - WITH (ROWLOCK) - WHERE [last].username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_roster] ******/ -/** Delete an entry from the roster **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_roster] - @Username varchar(250), - @JID varchar(250) -AS -BEGIN - BEGIN TRANSACTION - DELETE FROM rosterusers - WITH (ROWLOCK) - WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID); - - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); - COMMIT -END -GO - - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_spool_msg] ******/ -/** Delete an entry from the spool table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_spool_msg] - @Username varchar(250) -AS -BEGIN - DELETE FROM spool - WITH (ROWLOCK) - WHERE spool.username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user] ******/ -/** Delete an entry from the user table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_user] - @Username varchar(200) -AS -BEGIN - DELETE FROM users - WITH (ROWLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_return_password]**/ -/** Delete an entry from the user table and return user password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_user_return_password] - @Username varchar(250) -AS -DECLARE - @Pwd varchar(50) -BEGIN - EXECUTE @Pwd = dbo.get_password @Username - DELETE FROM users - WITH (ROWLOCK) - WHERE username=@Username - - SELECT @Pwd; -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_roster] **/ -/** Delete the users roster **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_user_roster] - @Username varchar(250) -AS -BEGIN - BEGIN TRANSACTION - DELETE FROM rosterusers - WITH (ROWLOCK) - WHERE rosterusers.username = @Username; - - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE rostergroups.username = @Username; - COMMIT -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_and_del_spool_msg] **/ -/** Fetch and delete the users offline messages **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_and_del_spool_msg] - @Username varchar(250) -AS -DECLARE - @vSpool table( username varchar(1), - xml varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM spool with (nolock) WHERE spool.username=@Username) - BEGIN - SELECT spool.username AS username, - spool.xml AS xml - FROM spool WITH (NOLOCK) - WHERE spool.username=@Username; - - DELETE spool - WITH (ROWLOCK) - WHERE spool.username=@Username - END - ELSE - BEGIN - SELECT * FROM @vSpool; - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_last] **/ -/** Retrive the last user login **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_last] - @Username varchar(250) -AS -BEGIN - SELECT last.seconds AS seconds, - last.state AS state - FROM last WITH (NOLOCK) - WHERE last.username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster] **/ -/** Retrive the user roster **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster] - @Username varchar(250) -AS -DECLARE - @vRosterusers table( username varchar(1), - jid varchar(1), - nick varchar(1), - subscription varchar(1), - ask varchar(1), - askmessage varchar(1), - server varchar(1), - subscribe varchar(1), - type varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username = @Username) - BEGIN - SELECT rosterusers.username AS username, - rosterusers.jid AS jid, - rosterusers.nick AS nick, - rosterusers.subscription AS subscription, - rosterusers.ask AS ask, - rosterusers.askmessage AS askmessage, - rosterusers.server AS server, - rosterusers.subscribe AS subscribe, - rosterusers.type AS type - FROM rosterusers WITH (NOLOCK) - WHERE rosterusers.username = @Username; - END - ELSE - BEGIN - SELECT * FROM @vRosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_by_jid] **/ -/** Retrive the user roster via JID **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_by_jid] - @Username varchar(200), - @JID varchar(250) -AS -DECLARE - @vRosterusers table( username varchar(1), - jid varchar(1), - nick varchar(1), - subscription varchar(1), - ask varchar(1), - askmessage varchar(1), - server varchar(1), - subscribe varchar(1), - type varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID)) - BEGIN - SELECT rosterusers.username AS username, - rosterusers.jid AS jid, - rosterusers.nick AS nick, - rosterusers.subscription AS subscription, - rosterusers.ask AS ask, - rosterusers.askmessage AS askmessage, - rosterusers.server AS server, - rosterusers.subscribe AS subscribe, - rosterusers.type AS type - FROM rosterusers WITH (NOLOCK) - WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID); - END - ELSE - BEGIN - SELECT * FROM @vRosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_jid_groups] **/ -/** Retrieve the user roster groups **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_jid_groups] - @Username varchar(200) -AS -DECLARE - @vrostergroups table( jid varchar(1), - grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username) - BEGIN - SELECT rostergroups.jid AS jid, - rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE rostergroups.username = @Username; - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_groups] **/ -/** Retrive the user roster groups **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_groups] - @Username varchar(200), - @JID varchar(250) -AS -DECLARE - @vrostergroups table( grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username) - BEGIN - SELECT rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_rostergroup_by_jid] **/ -/** Retrive the user roster groups via JID **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_rostergroup_by_jid] - @Username varchar(250), - @JID varchar(250) -AS -DECLARE - @vrostergroups table(grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID) - BEGIN - SELECT rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE rostergroups.username=@Username AND rostergroups.jid=@JID; - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_subscription] **/ -/** Retrive the user subscription requests **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_subscription] - @Username varchar(250), - @JID varchar(250) -AS -DECLARE - @vrosterusers table( subscription varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - SELECT rosterusers.subscription AS subscription - FROM rosterusers WITH (NOLOCK) - WHERE rosterusers.username=@Username AND rosterusers.jid=@JID; - END - ELSE - BEGIN - SELECT * FROM @vrosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[list_users] **/ -/** Retrieve a list of all users **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[list_users] -AS -BEGIN - SELECT users.username AS username FROM users WITH (NOLOCK); -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_last] **/ -/** Update users last login status **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_last] - @Username varchar(250), - @Seconds varchar(50), - @State varchar(100) -AS -BEGIN - IF EXISTS (SELECT username FROM [last] WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE [last] - SET [last].username = @Username, - [last].seconds = @Seconds, - [last].state = @State - WHERE last.username=@Username; - END - ELSE - BEGIN - INSERT INTO [last] - ( [last].username, - [last].seconds, - [last].state - ) - VALUES - ( @Username, - @Seconds, - @State - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_private_data] **/ -/** store user private data by namespace **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_private_data] - @Username varchar(250), - @Namespace varchar(250), - @Data varchar(8000) -AS -BEGIN - IF EXISTS (SELECT username FROM private_storage with (nolock) WHERE private_storage.username = @Username AND private_storage.namespace = @Namespace) - BEGIN - UPDATE [private_storage] - SET [private_storage].username = @Username, - [private_storage].namespace = @Namespace, - [private_storage].data = @Data - WHERE private_storage.username = @Username AND private_storage.namespace = @Namespace; - END - ELSE - BEGIN - INSERT INTO [private_storage] - ( [private_storage].username, - [private_storage].namespace, - [private_storage].data - ) - VALUES - ( @Username, - @Namespace, - @Data - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_private_data] **/ -/** Retrieve user private data by namespace **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_private_data] - @Username varchar(250), - @Namespace varchar(250) -AS -BEGIN - SELECT private_storage.data AS data - FROM private_storage WITH (NOLOCK) - WHERE username=@Username and namespace=@Namespace; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_storage] ******/ -/** Delete private storage area for a given user **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_user_storage] - @Username varchar(250) -AS -BEGIN - DELETE FROM [private_storage] - WITH (ROWLOCK) - WHERE [private_storage].username=@Username; -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_vcard] **/ -/** Set the user's vCard **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_vcard] - @VCard varchar(8000), - @Username varchar(250), - @Lusername varchar(250), - @Fn varchar(8000), - @Lfn varchar(250), - @Family varchar(8000), - @Lfamily varchar(250), - @Given varchar(8000), - @Lgiven varchar(250), - @Middle varchar(8000), - @Lmiddle varchar(250), - @Nickname varchar(8000), - @Lnickname varchar(250), - @Bday varchar(8000), - @Lbday varchar(250), - @Ctry varchar(8000), - @Lctry varchar(250), - @Locality varchar(8000), - @Llocality varchar(250), - @Email varchar(8000), - @Lemail varchar(250), - @Orgname varchar(8000), - @Lorgname varchar(250), - @Orgunit varchar(8000), - @Lorgunit varchar(250) -AS -BEGIN - IF EXISTS (SELECT username FROM vcard with (nolock) WHERE vcard.username = @Username) - BEGIN - UPDATE [vcard] - SET [vcard].username = @LUsername, - [vcard].vcard = @Vcard - WHERE vcard.username = @LUsername; - - UPDATE [vcard_search] - SET [vcard_search].username = @Username, - [vcard_search].lusername = @Lusername, - [vcard_search].fn = @Fn, - [vcard_search].lfn = @Lfn, - [vcard_search].family = @Family, - [vcard_search].lfamily = @Lfamily, - [vcard_search].given = @Given, - [vcard_search].lgiven = @Lgiven, - [vcard_search].middle = @Middle, - [vcard_search].lmiddle = @Lmiddle, - [vcard_search].nickname = @Nickname, - [vcard_search].lnickname = @Lnickname, - [vcard_search].bday = @Bday, - [vcard_search].lbday = @Lbday, - [vcard_search].ctry = @Ctry, - [vcard_search].lctry = @Lctry, - [vcard_search].locality = @Locality, - [vcard_search].llocality = @Llocality, - [vcard_search].email = @Email, - [vcard_search].lemail = @Lemail, - [vcard_search].orgname = @Orgname, - [vcard_search].lorgname = @Lorgname, - [vcard_search].orgunit = @Orgunit, - [vcard_search].lorgunit = @Lorgunit - WHERE vcard_search.lusername = @LUsername; - END - ELSE - BEGIN - INSERT INTO [vcard] - ( [vcard].username, - [vcard].vcard - ) - VALUES - ( @lUsername, - @Vcard - ); - - INSERT INTO [vcard_search] - ( - [vcard_search].username , - [vcard_search].lusername , - [vcard_search].fn , - [vcard_search].lfn , - [vcard_search].family , - [vcard_search].lfamily , - [vcard_search].given , - [vcard_search].lgiven , - [vcard_search].middle , - [vcard_search].lmiddle , - [vcard_search].nickname, - [vcard_search].lnickname, - [vcard_search].bday, - [vcard_search].lbday, - [vcard_search].ctry, - [vcard_search].lctry, - [vcard_search].locality, - [vcard_search].llocality, - [vcard_search].email, - [vcard_search].lemail, - [vcard_search].orgname, - [vcard_search].lorgname, - [vcard_search].orgunit, - [vcard_search].lorgunit - ) - VALUES - ( - @Username, - @Lusername, - @Fn, - @Lfn, - @Family, - @Lfamily, - @Given, - @Lgiven, - @Middle, - @Lmiddle, - @Nickname, - @Lnickname, - @Bday, - @Lbday, - @Ctry, - @Lctry, - @Locality, - @Llocality, - @Email, - @Lemail, - @Orgname, - @Lorgname, - @Orgunit, - @Lorgunit - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_vcard] **/ -/** Retrive the user's vCard **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_vcard] - @Username varchar(250) -AS -BEGIN - SELECT vcard.vcard as vcard - FROM vcard WITH (NOLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_default_privacy_list]**/ -/** Retrive the user's default privacy list **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_default_privacy_list] - @Username varchar(250) -AS -BEGIN - SELECT list.name - FROM privacy_default_list list WITH (NOLOCK) - WHERE list.username=@Username -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_names] **/ -/** Retrive the user's default privacy list names **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_names] - @username varchar(250) -AS -BEGIN - SELECT list.name - FROM privacy_list list WITH (NOLOCK) - WHERE list.username=@Username -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_id] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_id] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - SELECT id FROM privacy_list - WHERE username=@Username - AND name=@SName -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_data] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_data] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - SELECT l_data.t, - l_data.value, - l_data.action, - l_data.ord, - l_data.match_all, - l_data.match_iq, - l_data.match_message, - l_data.match_presence_in, - l_data.match_presence_out - FROM privacy_list_data l_data (NOLOCK) - WHERE l_data.id = (SELECT list.id - FROM privacy_list list - WHERE list.username=@username - AND list.name=@SName) - ORDER BY l_data.ord -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_data_by_id]**/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_data_by_id] - @Id bigint -AS -BEGIN - SELECT l_data.t, - l_data.value, - l_data.action, - l_data.ord, - l_data.match_all, - l_data.match_iq, - l_data.match_message, - l_data.match_presence_in, - l_data.match_presence_out - FROM privacy_list_data l_data (NOLOCK) - WHERE l_data.id=@ID - ORDER BY l_data.ord -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_default_privacy_list]**/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_default_privacy_list] - @username varchar(250), - @Sname varchar(250) -AS -BEGIN - IF EXISTS (SELECT username FROM privacy_default_list with (nolock) WHERE privacy_default_list.username = @Username AND privacy_default_list.name = @Sname) - BEGIN - UPDATE [privacy_default_list] - SET [privacy_default_list].username = @Username, - [privacy_default_list].name = @Sname - WHERE privacy_default_list.username = @Username - END - ELSE - BEGIN - INSERT INTO [privacy_default_list] - ( [privacy_default_list].username, - [privacy_default_list].name - ) - VALUES - ( @Username, - @SName - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[unset_default_privacy_list]**/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[unset_default_privacy_list] - @username varchar(250) -AS -BEGIN - DELETE - FROM privacy_default_list - WHERE privacy_default_list.username=@username -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[remove_privacy_list] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[remove_privacy_list] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - DELETE - FROM privacy_list - WHERE privacy_list.username=@username - AND privacy_list.name=@SName -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[add_privacy_list] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[add_privacy_list] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - INSERT INTO privacy_list(username, name) - VALUES (@username, @SName) -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_privacy_list] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_privacy_list] - @Id bigint, - @t char(1), - @value text, - @action char(1), - @ord numeric, - @match_all bit, - @match_iq bit, - @match_message bit, - @match_presence_in bit, - @match_presence_out bit -AS -BEGIN - insert into privacy_list_data ( - id, - t, - value, - action, - ord, - match_all, - match_iq, - match_message, - match_presence_in, - match_presence_out - ) - values (@Id, - @t, - @value, - @action, - @ord, - @match_all, - @match_iq, - @match_message, - @match_presence_in, - @match_presence_out - ) - -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_privacy_list_by_id] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_privacy_list_by_id] - @Id bigint -AS -BEGIN - DELETE FROM privacy_list_data - WHERE privacy_list_data.id=@Id -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_privacy_lists] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_privacy_lists] - @Server varchar(250), - @username varchar(250) -AS -BEGIN - DELETE FROM privacy_list WHERE username=@username - DELETE FROM privacy_list_data WHERE convert(varchar,value)=@username+'@'+@Server - DELETE FROM privacy_default_list WHERE username=@username -END -GO diff --git a/sql/mssql2012.sql b/sql/mssql2012.sql deleted file mode 100644 index 4bb95f2164f..00000000000 --- a/sql/mssql2012.sql +++ /dev/null @@ -1,1782 +0,0 @@ -/* - * ejabberd, Copyright (C) 2002-2015 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., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -SET ANSI_NULLS ON -GO -SET QUOTED_IDENTIFIER ON -GO - -use [ejabber] -GO - -ALTER DATABASE CURRENT SET AUTO_CLOSE OFF - -ALTER DATABASE CURRENT SET RECOVERY BULK_LOGGED - -ALTER DATABASE CURRENT SET RECOVERY FULL - -ALTER DATABASE CURRENT SET TORN_PAGE_DETECTION ON - -ALTER DATABASE CURRENT SET READ_WRITE - -ALTER DATABASE CURRENT SET MULTI_USER - -ALTER DATABASE CURRENT SET MULTI_USER - -ALTER DATABASE CURRENT SET AUTO_SHRINK OFF - -ALTER DATABASE CURRENT SET ANSI_NULL_DEFAULT OFF - -ALTER DATABASE CURRENT SET RECURSIVE_TRIGGERS OFF - -ALTER DATABASE CURRENT SET ANSI_NULLS OFF - -ALTER DATABASE CURRENT SET CONCAT_NULL_YIELDS_NULL OFF - -ALTER DATABASE CURRENT SET CURSOR_CLOSE_ON_COMMIT OFF - -ALTER DATABASE CURRENT SET CURSOR_DEFAULT GLOBAL - -ALTER DATABASE CURRENT SET QUOTED_IDENTIFIER OFF - -ALTER DATABASE CURRENT SET ANSI_WARNINGS OFF - -ALTER DATABASE CURRENT SET AUTO_CREATE_STATISTICS ON - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[last]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[last] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rostergroups]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[rostergroups] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[rosterusers]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[rosterusers] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[spool]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[spool] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[users] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[vcard] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[vcard_search]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[vcard_search] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[private_storage]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[private_storage] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[privacy_default_list]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[privacy_default_list] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[privacy_list]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[privacy_list] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[privacy_list_data]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[privacy_list_data] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[roster_version]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[roster_version] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_node_option]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_node_option] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_node_owner]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_node_owner] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_state]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_state] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_item]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_item] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_subscription_opt]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_subscription_opt] -GO - -if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[pubsub_node]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) -drop table [dbo].[pubsub_node] -GO - -CREATE TABLE [dbo].[last] ( - [username] [varchar] (250) NOT NULL , - [seconds] [varchar] (50) NOT NULL , - [state] [varchar] (100) NOT NULL , - [Modify_Date] [datetime] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[rostergroups] ( - [username] [varchar] (250) NOT NULL , - [jid] [varchar] (250) NOT NULL , - [grp] [varchar] (100) NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[rosterusers] ( - [username] [varchar] (250) NOT NULL , - [jid] [varchar] (250) NOT NULL , - [nick] [varchar] (50) NOT NULL , - [subscription] [char] (1) NOT NULL , - [ask] [char] (1) NOT NULL , - [askmessage] [varchar] (250) NOT NULL , - [server] [char] (1) NOT NULL , - [subscribe] [varchar] (200) NULL , - [type] [varchar] (50) NULL , -CONSTRAINT [PK_rosterusers] PRIMARY KEY NONCLUSTERED -( - [username] ASC, - [jid] ASC -)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[spool] ( - [id] [numeric](19, 0) IDENTITY (1, 1) NOT NULL , - [username] [varchar] (250) NOT NULL , - [xml] [text] NOT NULL , - [notifyprocessed] [bit] NULL , - [created] [datetime] NULL , - [MustDelete] [bit] NOT NULL -) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] -GO - -CREATE TABLE [dbo].[users] ( - [username] [varchar] (250) NOT NULL , - [password] [varchar] (50) NOT NULL , - [created] [datetime] NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[vcard] ( - [username] [varchar] (250) NOT NULL , - [vcard] [text] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[vcard_search] ( - [username] [varchar] (250) NOT NULL , - [lusername] [varchar] (250) NOT NULL , - [fn] [text] NOT NULL , - [lfn] [varchar] (250) NOT NULL , - [family] [text] NOT NULL , - [lfamily] [varchar] (250) NOT NULL , - [given] [text] NOT NULL , - [lgiven] [varchar] (250) NOT NULL , - [middle] [text] NOT NULL , - [lmiddle] [varchar] (250) NOT NULL , - [nickname] [text] NOT NULL , - [lnickname] [varchar] (250) NOT NULL , - [bday] [text] NOT NULL , - [lbday] [varchar] (250) NOT NULL , - [ctry] [text] NOT NULL , - [lctry] [varchar] (250) NOT NULL , - [locality] [text] NOT NULL , - [llocality] [varchar] (250) NOT NULL , - [email] [text] NOT NULL , - [lemail] [varchar] (250) NOT NULL , - [orgname] [text] NOT NULL , - [lorgname] [varchar] (250) NOT NULL , - [orgunit] [text] NOT NULL , - [lorgunit] [varchar] (250) NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[private_storage] ( - [username] [varchar] (250) NOT NULL , - [namespace] [varchar] (250) NOT NULL , - [data] [text] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[privacy_default_list] ( - [username] [varchar] (250) NOT NULL, - [name] [varchar] (250) NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[privacy_list]( - [username] [varchar](250) NOT NULL, - [name] [varchar](250) NOT NULL, - [id] [bigint] IDENTITY(1,1) NOT NULL, - CONSTRAINT [PK_privacy_list] PRIMARY KEY CLUSTERED -( - [id] ASC -)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[privacy_list_data] ( - [id] [bigint] NOT NULL, - [t] [character] (1) NOT NULL, - [value] [text] NOT NULL, - [action] [character] (1) NOT NULL, - [ord] [NUMERIC] NOT NULL, - [match_all] [bit] NOT NULL, - [match_iq] [bit] NOT NULL, - [match_message] [bit] NOT NULL, - [match_presence_in] [bit] NOT NULL, - [match_presence_out] [bit] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[roster_version] ( - [username] [varchar](250) PRIMARY KEY, - [version] [text] NOT NULL -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_node] ( - [host] [varchar](250), - [node] [varchar](250), - [parent] [varchar](250), - [type] [varchar](250), - [nodeid] [bigint] IDENTITY(1,1) PRIMARY KEY -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_node_option] ( - [nodeid] [bigint], - [name] [varchar](250), - [val] [varchar](250) -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_node_owner] ( - [nodeid] [bigint], - [owner] [varchar](250) -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_state] ( - [nodeid] [bigint], - [jid] [varchar](250), - [affiliation] [CHAR](1), - [subscriptions] [text], - [stateid] [bigint] IDENTITY(1,1) PRIMARY KEY -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_item] ( - [nodeid] [bigint], - [itemid] [varchar](250), - [publisher] [text], - [creation] [text], - [modification] [text], - [payload] [text] -) ON [PRIMARY] -GO - -CREATE TABLE [dbo].[pubsub_subscription_opt] ( - [subid] [varchar](250), - [opt_name] [varchar](32), - [opt_value] [text] -) ON [PRIMARY] -GO - -/* Constraints to add: -- id in privacy_list is a SERIAL autogenerated number -- id in privacy_list_data must exist in the table privacy_list */ - -ALTER TABLE [dbo].[last] WITH NOCHECK ADD - CONSTRAINT [PK_last] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[rostergroups] WITH NOCHECK ADD - CONSTRAINT [PK_rostergroups] PRIMARY KEY CLUSTERED - ( - [username], - [jid], - [grp] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[spool] WITH NOCHECK ADD - CONSTRAINT [PK_spool] PRIMARY KEY CLUSTERED - ( - [username], - [id] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[users] WITH NOCHECK ADD - CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[vcard] WITH NOCHECK ADD - CONSTRAINT [PK_vcard] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[pubsub_node_option] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_node_option] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [dbo].[pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[pubsub_node_owner] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_node_owner] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[pubsub_state] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_state] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -ALTER TABLE [dbo].[pubsub_item] WITH NOCHECK ADD - CONSTRAINT [FK_pubsub_item] FOREIGN KEY - ( - [nodeid] - ) REFERENCES [pubsub_node] - ( - [nodeid] - ) -ON DELETE CASCADE -GO - -CREATE INDEX [IX_vcard_search_lfn] ON [dbo].[vcard_search]([lfn]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lfamily] ON [dbo].[vcard_search]([lfamily]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lgiven] ON [dbo].[vcard_search]([lgiven]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lmiddle] ON [dbo].[vcard_search]([lmiddle]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lnickname] ON [dbo].[vcard_search]([lnickname]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lbday] ON [dbo].[vcard_search]([lbday]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lctry] ON [dbo].[vcard_search]([lctry]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_llocality] ON [dbo].[vcard_search]([llocality]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lemail] ON [dbo].[vcard_search]([lemail]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lorgname] ON [dbo].[vcard_search]([lorgname]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO -CREATE INDEX [IX_vcard_search_lorgunit] ON [dbo].[vcard_search]([lorgunit]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - -CREATE CLUSTERED INDEX [IX_rosterusers_user] ON [dbo].[rosterusers]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - -ALTER TABLE [dbo].[last] WITH NOCHECK ADD - CONSTRAINT [DF_last_updated] DEFAULT (getdate()) FOR [Modify_Date] -GO - -ALTER TABLE [dbo].[spool] WITH NOCHECK ADD - CONSTRAINT [DF_spool_notifyprocessed] DEFAULT (0) FOR [notifyprocessed], - CONSTRAINT [DF_spool_created] DEFAULT (getdate()) FOR [created], - CONSTRAINT [DF_spool_MustDelete] DEFAULT (0) FOR [MustDelete] -GO - -ALTER TABLE [dbo].[users] WITH NOCHECK ADD - CONSTRAINT [DF_users_created] DEFAULT (getdate()) FOR [created] -GO - -ALTER TABLE [dbo].[privacy_default_list] WITH NOCHECK ADD - CONSTRAINT [PK_privacy_defaut_list] PRIMARY KEY CLUSTERED - ( - [username] - ) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_rostergroups_jid] ON [dbo].[rostergroups]([jid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_rostergroups_user] ON [dbo].[rostergroups]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_spool_user] ON [dbo].[spool]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_spool_process] ON [dbo].[spool]([created], [notifyprocessed]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IK_Spool_Del] ON [dbo].[spool]([MustDelete]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IK_Spool_Created] ON [dbo].[spool]([created]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_private_user] ON [dbo].[private_storage]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_private_user_ns] ON [dbo].[private_storage]([username], [namespace]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_privacy_list_username] ON [dbo].[privacy_list]([username]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_privacy_list_username_name] ON [dbo].[privacy_list]([username], [name]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_parent] ON [dbo].[pubsub_node]([parent]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_tuple] ON [dbo].[pubsub_node]([host], [node]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_option_nodeid] ON [dbo].[pubsub_node_option]([nodeid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_node_owner_nodeid] ON [dbo].[pubsub_node_owner]([nodeid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_state_jid] ON [dbo].[pubsub_state]([jid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_state_tuple] ON [dbo].[pubsub_state]([nodeid], [jid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_item_itemid] ON [dbo].[pubsub_item]([itemid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_item_tuple] ON [dbo].[pubsub_item]([nodeid], [itemid]) WITH FILLFACTOR = 90 ON [PRIMARY] -GO - - CREATE INDEX [IX_pubsub_subscription_opt] ON [dbo].[pubsub_subscription_opt]([subid], [opt_name]) WITH FILLFACTOR = 90 ON [PRIMARY] -Go - -/*********************************************************/ -/** These store procedures are for use with ejabberd **/ -/** 1.1 and Microsoft Sql Server 2000 **/ -/** **/ -/** The stored procedures reduce the need to sql **/ -/** compilation of the database and also allow for also **/ -/** provide each of database integration. The stored **/ -/** procedure have been optimized to increase database **/ -/** performance and a reduction of 80% in CPU was **/ -/** achieved over the use of standard sql. **/ -/*********************************************************/ - -/****** Object: StoredProcedure [dbo].[add_roster] ******/ -/** Add or update user entries in the roster **/ -/*********************************************************/ -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_roster_group]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_roster_group] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_roster_user]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_roster_user] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_roster_groups]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_roster_groups] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_spool]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_spool] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_user]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_user] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_password]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_password] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[clean_spool_msg]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[clean_spool_msg] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_password]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_password] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_last]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_last] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_spool_msg]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_spool_msg] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user_return_password]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user_return_password] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_and_del_spool_msg]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_and_del_spool_msg] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_last]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_last] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster_by_jid]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster_by_jid] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster_jid_groups]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster_jid_groups] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_roster_groups]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_roster_groups] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_rostergroup_by_jid]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_rostergroup_by_jid] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_subscription]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_subscription] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[list_users]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[list_users] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_last]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_last] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_private_data]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_private_data] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_private_data]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_private_data] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_user_storage]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_user_storage] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_vcard]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_vcard] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_vcard]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_vcard] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_default_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_default_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_names]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_names] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_id]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_id] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_data]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_data] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[get_privacy_list_data_by_id]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[get_privacy_list_data_by_id] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_default_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_default_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[unset_default_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[unset_default_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[remove_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[remove_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[add_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[add_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[set_privacy_list]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[set_privacy_list] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_privacy_list_by_id]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_privacy_list_by_id] -GO -IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[del_privacy_lists]') AND type in (N'P', N'PC')) -DROP PROCEDURE [dbo].[del_privacy_lists] -GO - -CREATE PROCEDURE [dbo].[add_roster] - @Username varchar(250), - @JID varchar(250), - @Nick varchar(50), - @Subscription char(1), - @Ask char(1), - @AskMessage varchar(250), - @Server char(1), - @Subscribe varchar(200), - @Type varchar(50), - @Grp varchar(100) -AS -BEGIN - BEGIN TRANSACTION - --- Update Roster if user exist else add roster item - IF EXISTS (SELECT username FROM rosterusers WITH (NOLOCK) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - UPDATE rosterusers - SET rosterusers.username=@Username, - rosterusers.jid=@JID, - rosterusers.nick=@Nick, - rosterusers.subscription=@Subscription, - rosterusers.ask=@Ask, - rosterusers.askmessage=@AskMessage, - rosterusers.server=@Server, - rosterusers.subscribe=@Subscribe, - rosterusers.type=@Type - WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID); - END - ELSE - BEGIN - INSERT INTO rosterusers - ( rosterusers.username, - rosterusers.jid, - rosterusers.nick, - rosterusers.subscription, - rosterusers.ask, - rosterusers.askmessage, - rosterusers.server, - rosterusers.subscribe, - rosterusers.type - ) - VALUES - ( @Username, - @JID, - @Nick, - @Subscription, - @Ask, - @AskMessage, - @Server, - @Subscribe, - @Type - ); - END - - --- Update Roster Groups if exist else add group entry - IF NOT EXISTS (SELECT username FROM rostergroups WITH (NOLOCK) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp) - BEGIN - INSERT INTO rostergroups - ( rostergroups.username, - rostergroups.jid, - rostergroups.grp - ) - VALUES - ( @Username, - @JID, - @Grp - ); - END - - COMMIT -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_roster_group] ******/ -/** Add or update user group entries in the roster groups **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_roster_group] - @Username varchar(250), - @JID varchar(250), - @Grp varchar(100) -AS -BEGIN - --- Update Roster Groups if exist else add group - IF NOT EXISTS (SELECT username FROM rostergroups WHERE rostergroups.username=@Username AND rostergroups.jid=@JID AND rostergroups.grp=@Grp) - BEGIN - INSERT INTO rostergroups - ( rostergroups.username, - rostergroups.jid, - rostergroups.grp - ) - VALUES - ( @Username, - @JID, - @Grp - ) - END -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_roster_user] ******/ -/** Add or update user entries in the roster **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_roster_user] - @Username varchar(250), - @JID varchar(250), - @Nick varchar(50), - @Subscription char(1), - @Ask char(1), - @AskMessage varchar(250), - @Server char(1), - @Subscribe varchar(200), - @Type varchar(50), - @Grp varchar(100) = Null -AS -BEGIN - BEGIN TRANSACTION - --- Update Roster Users if exist of add new user - IF EXISTS (SELECT username FROM rosterusers WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - UPDATE rosterusers - SET rosterusers.username=@Username, - rosterusers.jid=@JID, - rosterusers.nick=@Nick, - rosterusers.subscription=@Subscription, - rosterusers.ask=@Ask, - rosterusers.askmessage=@AskMessage, - rosterusers.server=@Server, - rosterusers.subscribe=@Subscribe, - rosterusers.type=@Type - WHERE (rosterusers.username=@Username) AND (rosterusers.jid=@JID); - END - ELSE - BEGIN - INSERT INTO rosterusers - ( rosterusers.username, - rosterusers.jid, - rosterusers.nick, - rosterusers.subscription, - rosterusers.ask, - rosterusers.askmessage, - rosterusers.server, - rosterusers.subscribe, - rosterusers.type - ) - VALUES - ( @Username, - @JID, - @Nick, - @Subscription, - @Ask, - @AskMessage, - @Server, - @Subscribe, - @Type - ); - END - - --- Update Roster Group if exist of add new group - IF @Grp IS NOT NULL - EXECUTE [dbo].[add_roster_group] @Username, @JID, @Grp - - COMMIT -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_roster_groups] ******/ -/** Remove user group entries from the roster groups table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_roster_groups] - @Username varchar(250), - @JID varchar(250) -AS -BEGIN - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_spool] ******/ -/** Add a entry to the spool table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_spool] - @Username varchar(250), - @XML varchar(8000) -AS -BEGIN - INSERT INTO spool - ( spool.username, - spool.xml - ) - VALUES - ( @Username, - @XML - ) -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[add_user] ******/ -/** Add or update user entries to jabber **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[add_user] - @Username varchar(200), - @Password varchar(50) -AS -BEGIN - INSERT INTO users - ( [username], - [password] - ) - VALUES - ( @Username, - @Password - ); -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_password] **/ -/** Update users password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_password] - @Username varchar(200), - @Password varchar(50) -AS -BEGIN - IF EXISTS (SELECT username FROM users WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE users SET username=@Username, password=@Password WHERE username=@Username; - END - ELSE - BEGIN - INSERT INTO users (username, password) VALUES (@Username, @Password); - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_password] **/ -/** Retrive the user password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_password] - @Username varchar(200) -AS -BEGIN - SELECT users.password as password - FROM users WITH (NOLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_roster_version] **/ -/** Update users roster_version **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_roster_version] - @Username varchar(200), - @Version varchar(8000) -AS -BEGIN - IF EXISTS (SELECT username FROM roster_version WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE roster_version SET username=@Username, version=@Version WHERE username=@Username; - END - ELSE - BEGIN - INSERT INTO roster_version (username, version) VALUES (@Username, @Version); - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_version] **/ -/** Retrive the user roster_version **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_version] - @Username varchar(200) -AS -BEGIN - SELECT roster_version.version as version - FROM roster_version WITH (NOLOCK) - WHERE username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[clean_spool_msg] ******/ -/** Delete messages older that 3 days from spool **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[clean_spool_msg] -AS -DECLARE - @dt datetime, - @myRowCount int -BEGIN - -- Delete small amounts because if locks the database table - SET ROWCOUNT 500 - SET @myRowCount = 1 - - WHILE (@myRowCount) > 0 - BEGIN - BEGIN TRANSACTION - SELECT @dt = DATEADD(d, -3, GETDATE()) - DELETE FROM spool - WITH (ROWLOCK) - WHERE (MustDelete=1) OR (Created < @dt); - - SET @myRowCount = @@RowCount - COMMIT - END -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_last] ******/ -/** Delete an entry from the last table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_last] - @Username varchar(250) -AS -BEGIN - DELETE FROM [last] - WITH (ROWLOCK) - WHERE [last].username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_roster] ******/ -/** Delete an entry from the roster **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_roster] - @Username varchar(250), - @JID varchar(250) -AS -BEGIN - BEGIN TRANSACTION - DELETE FROM rosterusers - WITH (ROWLOCK) - WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID); - - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); - COMMIT -END -GO - - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_spool_msg] ******/ -/** Delete an entry from the spool table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_spool_msg] - @Username varchar(250) -AS -BEGIN - DELETE FROM spool - WITH (ROWLOCK) - WHERE spool.username=@Username; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user] ******/ -/** Delete an entry from the user table **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_user] - @Username varchar(200) -AS -BEGIN - DELETE FROM users - WITH (ROWLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_return_password]**/ -/** Delete an entry from the user table and return user password **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_user_return_password] - @Username varchar(250) -AS -DECLARE - @Pwd varchar(50) -BEGIN - EXECUTE @Pwd = dbo.get_password @Username - DELETE FROM users - WITH (ROWLOCK) - WHERE username=@Username - - SELECT @Pwd; -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_roster] **/ -/** Delete the users roster **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_user_roster] - @Username varchar(250) -AS -BEGIN - BEGIN TRANSACTION - DELETE FROM rosterusers - WITH (ROWLOCK) - WHERE rosterusers.username = @Username; - - DELETE FROM rostergroups - WITH (ROWLOCK) - WHERE rostergroups.username = @Username; - COMMIT -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_and_del_spool_msg] **/ -/** Fetch and delete the users offline messages **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_and_del_spool_msg] - @Username varchar(250) -AS -DECLARE - @vSpool table( username varchar(1), - xml varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM spool with (nolock) WHERE spool.username=@Username) - BEGIN - SELECT spool.username AS username, - spool.xml AS xml - FROM spool WITH (NOLOCK) - WHERE spool.username=@Username; - - DELETE spool - WITH (ROWLOCK) - WHERE spool.username=@Username - END - ELSE - BEGIN - SELECT * FROM @vSpool; - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_last] **/ -/** Retrive the last user login **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_last] - @Username varchar(250) -AS -BEGIN - SELECT last.seconds AS seconds, - last.state AS state - FROM last WITH (NOLOCK) - WHERE last.username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster] **/ -/** Retrive the user roster **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster] - @Username varchar(250) -AS -DECLARE - @vRosterusers table( username varchar(1), - jid varchar(1), - nick varchar(1), - subscription varchar(1), - ask varchar(1), - askmessage varchar(1), - server varchar(1), - subscribe varchar(1), - type varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username = @Username) - BEGIN - SELECT rosterusers.username AS username, - rosterusers.jid AS jid, - rosterusers.nick AS nick, - rosterusers.subscription AS subscription, - rosterusers.ask AS ask, - rosterusers.askmessage AS askmessage, - rosterusers.server AS server, - rosterusers.subscribe AS subscribe, - rosterusers.type AS type - FROM rosterusers WITH (NOLOCK) - WHERE rosterusers.username = @Username; - END - ELSE - BEGIN - SELECT * FROM @vRosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_by_jid] **/ -/** Retrive the user roster via JID **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_by_jid] - @Username varchar(200), - @JID varchar(250) -AS -DECLARE - @vRosterusers table( username varchar(1), - jid varchar(1), - nick varchar(1), - subscription varchar(1), - ask varchar(1), - askmessage varchar(1), - server varchar(1), - subscribe varchar(1), - type varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID)) - BEGIN - SELECT rosterusers.username AS username, - rosterusers.jid AS jid, - rosterusers.nick AS nick, - rosterusers.subscription AS subscription, - rosterusers.ask AS ask, - rosterusers.askmessage AS askmessage, - rosterusers.server AS server, - rosterusers.subscribe AS subscribe, - rosterusers.type AS type - FROM rosterusers WITH (NOLOCK) - WHERE (rosterusers.username = @Username) AND (rosterusers.jid = @JID); - END - ELSE - BEGIN - SELECT * FROM @vRosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_jid_groups] **/ -/** Retrieve the user roster groups **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_jid_groups] - @Username varchar(200) -AS -DECLARE - @vrostergroups table( jid varchar(1), - grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username) - BEGIN - SELECT rostergroups.jid AS jid, - rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE rostergroups.username = @Username; - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_roster_groups] **/ -/** Retrive the user roster groups **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_roster_groups] - @Username varchar(200), - @JID varchar(250) -AS -DECLARE - @vrostergroups table( grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username = @Username) - BEGIN - SELECT rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE (rostergroups.username = @Username) AND (rostergroups.jid = @JID); - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_rostergroup_by_jid] **/ -/** Retrive the user roster groups via JID **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_rostergroup_by_jid] - @Username varchar(250), - @JID varchar(250) -AS -DECLARE - @vrostergroups table(grp varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rostergroups with (nolock) WHERE rostergroups.username=@Username AND rostergroups.jid=@JID) - BEGIN - SELECT rostergroups.grp AS grp - FROM rostergroups WITH (NOLOCK) - WHERE rostergroups.username=@Username AND rostergroups.jid=@JID; - END - ELSE - BEGIN - SELECT * FROM @vrostergroups - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_subscription] **/ -/** Retrive the user subscription requests **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_subscription] - @Username varchar(250), - @JID varchar(250) -AS -DECLARE - @vrosterusers table( subscription varchar(1)) -BEGIN - IF EXISTS (SELECT username FROM rosterusers with (nolock) WHERE rosterusers.username=@Username AND rosterusers.jid=@JID) - BEGIN - SELECT rosterusers.subscription AS subscription - FROM rosterusers WITH (NOLOCK) - WHERE rosterusers.username=@Username AND rosterusers.jid=@JID; - END - ELSE - BEGIN - SELECT * FROM @vrosterusers - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[list_users] **/ -/** Retrieve a list of all users **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[list_users] -AS -BEGIN - SELECT users.username AS username FROM users WITH (NOLOCK); -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_last] **/ -/** Update users last login status **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_last] - @Username varchar(250), - @Seconds varchar(50), - @State varchar(100) -AS -BEGIN - IF EXISTS (SELECT username FROM [last] WITH (NOLOCK) WHERE username=@Username) - BEGIN - UPDATE [last] - SET [last].username = @Username, - [last].seconds = @Seconds, - [last].state = @State - WHERE last.username=@Username; - END - ELSE - BEGIN - INSERT INTO [last] - ( [last].username, - [last].seconds, - [last].state - ) - VALUES - ( @Username, - @Seconds, - @State - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_private_data] **/ -/** store user private data by namespace **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_private_data] - @Username varchar(250), - @Namespace varchar(250), - @Data varchar(8000) -AS -BEGIN - IF EXISTS (SELECT username FROM private_storage with (nolock) WHERE private_storage.username = @Username AND private_storage.namespace = @Namespace) - BEGIN - UPDATE [private_storage] - SET [private_storage].username = @Username, - [private_storage].namespace = @Namespace, - [private_storage].data = @Data - WHERE private_storage.username = @Username AND private_storage.namespace = @Namespace; - END - ELSE - BEGIN - INSERT INTO [private_storage] - ( [private_storage].username, - [private_storage].namespace, - [private_storage].data - ) - VALUES - ( @Username, - @Namespace, - @Data - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_private_data] **/ -/** Retrieve user private data by namespace **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_private_data] - @Username varchar(250), - @Namespace varchar(250) -AS -BEGIN - SELECT private_storage.data AS data - FROM private_storage WITH (NOLOCK) - WHERE username=@Username and namespace=@Namespace; -END -GO - -/***************************************************************/ -/****** Object: StoredProcedure [dbo].[del_user_storage] ******/ -/** Delete private storage area for a given user **/ -/***************************************************************/ -CREATE PROCEDURE [dbo].[del_user_storage] - @Username varchar(250) -AS -BEGIN - DELETE FROM [private_storage] - WITH (ROWLOCK) - WHERE [private_storage].username=@Username; -END -GO - - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_vcard] **/ -/** Set the user's vCard **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_vcard] - @VCard varchar(8000), - @Username varchar(250), - @Lusername varchar(250), - @Fn varchar(8000), - @Lfn varchar(250), - @Family varchar(8000), - @Lfamily varchar(250), - @Given varchar(8000), - @Lgiven varchar(250), - @Middle varchar(8000), - @Lmiddle varchar(250), - @Nickname varchar(8000), - @Lnickname varchar(250), - @Bday varchar(8000), - @Lbday varchar(250), - @Ctry varchar(8000), - @Lctry varchar(250), - @Locality varchar(8000), - @Llocality varchar(250), - @Email varchar(8000), - @Lemail varchar(250), - @Orgname varchar(8000), - @Lorgname varchar(250), - @Orgunit varchar(8000), - @Lorgunit varchar(250) -AS -BEGIN - IF EXISTS (SELECT username FROM vcard with (nolock) WHERE vcard.username = @Username) - BEGIN - UPDATE [vcard] - SET [vcard].username = @LUsername, - [vcard].vcard = @Vcard - WHERE vcard.username = @LUsername; - - UPDATE [vcard_search] - SET [vcard_search].username = @Username, - [vcard_search].lusername = @Lusername, - [vcard_search].fn = @Fn, - [vcard_search].lfn = @Lfn, - [vcard_search].family = @Family, - [vcard_search].lfamily = @Lfamily, - [vcard_search].given = @Given, - [vcard_search].lgiven = @Lgiven, - [vcard_search].middle = @Middle, - [vcard_search].lmiddle = @Lmiddle, - [vcard_search].nickname = @Nickname, - [vcard_search].lnickname = @Lnickname, - [vcard_search].bday = @Bday, - [vcard_search].lbday = @Lbday, - [vcard_search].ctry = @Ctry, - [vcard_search].lctry = @Lctry, - [vcard_search].locality = @Locality, - [vcard_search].llocality = @Llocality, - [vcard_search].email = @Email, - [vcard_search].lemail = @Lemail, - [vcard_search].orgname = @Orgname, - [vcard_search].lorgname = @Lorgname, - [vcard_search].orgunit = @Orgunit, - [vcard_search].lorgunit = @Lorgunit - WHERE vcard_search.lusername = @LUsername; - END - ELSE - BEGIN - INSERT INTO [vcard] - ( [vcard].username, - [vcard].vcard - ) - VALUES - ( @lUsername, - @Vcard - ); - - INSERT INTO [vcard_search] - ( - [vcard_search].username , - [vcard_search].lusername , - [vcard_search].fn , - [vcard_search].lfn , - [vcard_search].family , - [vcard_search].lfamily , - [vcard_search].given , - [vcard_search].lgiven , - [vcard_search].middle , - [vcard_search].lmiddle , - [vcard_search].nickname, - [vcard_search].lnickname, - [vcard_search].bday, - [vcard_search].lbday, - [vcard_search].ctry, - [vcard_search].lctry, - [vcard_search].locality, - [vcard_search].llocality, - [vcard_search].email, - [vcard_search].lemail, - [vcard_search].orgname, - [vcard_search].lorgname, - [vcard_search].orgunit, - [vcard_search].lorgunit - ) - VALUES - ( - @Username, - @Lusername, - @Fn, - @Lfn, - @Family, - @Lfamily, - @Given, - @Lgiven, - @Middle, - @Lmiddle, - @Nickname, - @Lnickname, - @Bday, - @Lbday, - @Ctry, - @Lctry, - @Locality, - @Llocality, - @Email, - @Lemail, - @Orgname, - @Lorgname, - @Orgunit, - @Lorgunit - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_vcard] **/ -/** Retrive the user's vCard **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_vcard] - @Username varchar(250) -AS -BEGIN - SELECT vcard.vcard as vcard - FROM vcard WITH (NOLOCK) - WHERE username=@Username; -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_default_privacy_list]**/ -/** Retrive the user's default privacy list **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_default_privacy_list] - @Username varchar(250) -AS -BEGIN - SELECT list.name - FROM privacy_default_list list WITH (NOLOCK) - WHERE list.username=@Username -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_names] **/ -/** Retrive the user's default privacy list names **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_names] - @username varchar(250) -AS -BEGIN - SELECT list.name - FROM privacy_list list WITH (NOLOCK) - WHERE list.username=@Username -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_id] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_id] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - SELECT id FROM privacy_list - WHERE username=@Username - AND name=@SName -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_data] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_data] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - SELECT l_data.t, - l_data.value, - l_data.action, - l_data.ord, - l_data.match_all, - l_data.match_iq, - l_data.match_message, - l_data.match_presence_in, - l_data.match_presence_out - FROM privacy_list_data l_data (NOLOCK) - WHERE l_data.id = (SELECT list.id - FROM privacy_list list - WHERE list.username=@username - AND list.name=@SName) - ORDER BY l_data.ord -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[get_privacy_list_data_by_id]**/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[get_privacy_list_data_by_id] - @Id bigint -AS -BEGIN - SELECT l_data.t, - l_data.value, - l_data.action, - l_data.ord, - l_data.match_all, - l_data.match_iq, - l_data.match_message, - l_data.match_presence_in, - l_data.match_presence_out - FROM privacy_list_data l_data (NOLOCK) - WHERE l_data.id=@ID - ORDER BY l_data.ord -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_default_privacy_list]**/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_default_privacy_list] - @username varchar(250), - @Sname varchar(250) -AS -BEGIN - IF EXISTS (SELECT username FROM privacy_default_list with (nolock) WHERE privacy_default_list.username = @Username AND privacy_default_list.name = @Sname) - BEGIN - UPDATE [privacy_default_list] - SET [privacy_default_list].username = @Username, - [privacy_default_list].name = @Sname - WHERE privacy_default_list.username = @Username - END - ELSE - BEGIN - INSERT INTO [privacy_default_list] - ( [privacy_default_list].username, - [privacy_default_list].name - ) - VALUES - ( @Username, - @SName - ) - END -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[unset_default_privacy_list]**/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[unset_default_privacy_list] - @username varchar(250) -AS -BEGIN - DELETE - FROM privacy_default_list - WHERE privacy_default_list.username=@username -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[remove_privacy_list] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[remove_privacy_list] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - DELETE - FROM privacy_list - WHERE privacy_list.username=@username - AND privacy_list.name=@SName -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[add_privacy_list] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[add_privacy_list] - @username varchar(250), - @SName varchar(250) -AS -BEGIN - INSERT INTO privacy_list(username, name) - VALUES (@username, @SName) -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[set_privacy_list] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[set_privacy_list] - @Id bigint, - @t char(1), - @value text, - @action char(1), - @ord numeric, - @match_all bit, - @match_iq bit, - @match_message bit, - @match_presence_in bit, - @match_presence_out bit -AS -BEGIN - insert into privacy_list_data ( - id, - t, - value, - action, - ord, - match_all, - match_iq, - match_message, - match_presence_in, - match_presence_out - ) - values (@Id, - @t, - @value, - @action, - @ord, - @match_all, - @match_iq, - @match_message, - @match_presence_in, - @match_presence_out - ) - -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_privacy_list_by_id] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_privacy_list_by_id] - @Id bigint -AS -BEGIN - DELETE FROM privacy_list_data - WHERE privacy_list_data.id=@Id -END -GO - -/******************************************************************/ -/****** Object: StoredProcedure [dbo].[del_privacy_lists] **/ -/** **/ -/******************************************************************/ -CREATE PROCEDURE [dbo].[del_privacy_lists] - @Server varchar(250), - @username varchar(250) -AS -BEGIN - DELETE FROM privacy_list WHERE username=@username - DELETE FROM privacy_list_data WHERE convert(varchar,value)=@username+'@'+@Server - DELETE FROM privacy_default_list WHERE username=@username -END -GO diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index eca781951f4..5cbd3e931d4 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -432,13 +432,13 @@ outer_transaction(F, NRestarts, _Reason) -> [T]), erlang:exit(implementation_faulty) end, - sql_query_internal(<<"begin;">>), + sql_query_internal([<<"begin;">>]), put(?NESTING_KEY, PreviousNestingLevel + 1), Result = (catch F()), put(?NESTING_KEY, PreviousNestingLevel), case Result of {aborted, Reason} when NRestarts > 0 -> - sql_query_internal(<<"rollback;">>), + sql_query_internal([<<"rollback;">>]), outer_transaction(F, NRestarts - 1, Reason); {aborted, Reason} when NRestarts =:= 0 -> ?ERROR_MSG("SQL transaction restarts exceeded~n** " @@ -447,11 +447,11 @@ outer_transaction(F, NRestarts, _Reason) -> "== ~p", [?MAX_TRANSACTION_RESTARTS, Reason, erlang:get_stacktrace(), get(?STATE_KEY)]), - sql_query_internal(<<"rollback;">>), + sql_query_internal([<<"rollback;">>]), {aborted, Reason}; {'EXIT', Reason} -> - sql_query_internal(<<"rollback;">>), {aborted, Reason}; - Res -> sql_query_internal(<<"commit;">>), {atomic, Res} + sql_query_internal([<<"rollback;">>]), {aborted, Reason}; + Res -> sql_query_internal([<<"commit;">>]), {atomic, Res} end. execute_bloc(F) -> @@ -463,6 +463,7 @@ execute_bloc(F) -> sql_query_internal(Query) -> State = get(?STATE_KEY), + ?DEBUG("SQL: \"~s\"", [Query]), Res = case State#state.db_type of odbc -> to_odbc(odbc:sql_query(State#state.db_ref, Query, @@ -512,8 +513,10 @@ abort_on_driver_error(Reply, From) -> %% Open an ODBC database connection odbc_connect(SQLServer) -> ejabberd:start_app(odbc), - odbc:connect(binary_to_list(SQLServer), [{scrollable_cursors, off}, - {binary_strings, on}]). + odbc:connect(binary_to_list(SQLServer), + [{scrollable_cursors, off}, + {tuple_row, off}, + {binary_strings, on}]). %% == Native SQLite code @@ -638,7 +641,15 @@ mysql_item_to_odbc(Columns, Recs) -> {selected, [element(2, Column) || Column <- Columns], Recs}. to_odbc({selected, Columns, Recs}) -> - {selected, [list_to_binary(Column) || Column <- Columns], [tuple_to_list(Rec) || Rec <- Recs]}; + Rows = [lists:map( + fun(I) when is_integer(I) -> + jlib:integer_to_binary(I); + (B) -> + B + end, Row) || Row <- Recs], + {selected, [list_to_binary(C) || C <- Columns], Rows}; +to_odbc({error, Reason}) when is_list(Reason) -> + {error, list_to_binary(Reason)}; to_odbc(Res) -> Res. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 6d76610af87..b90c2f2d554 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -58,17 +58,6 @@ escape/1, count_records_where/3, get_roster_version/2, set_roster_version/2, opt_type/1]). -%% We have only two compile time options for db queries: -%-define(generic, true). -%-define(mssql, true). --ifndef(mssql). - --undef(generic). - --define(generic, true). - --endif. - -include("ejabberd.hrl"). -include("logger.hrl"). @@ -78,10 +67,6 @@ join([], _Sep) -> []; join([H | T], Sep) -> [H, [[Sep, X] || X <- T]]. -%% ----------------- -%% Generic queries --ifdef(generic). - get_db_type() -> generic. %% Safe atomic update. @@ -662,332 +647,6 @@ set_roster_version(LUser, Version) -> [<<"username">>, <<"version">>], [LUser, Version], [<<"username = '">>, LUser, <<"'">>]). --endif. - -%% ----------------- -%% MSSQL queries --ifdef(mssql). - -%% Queries can be either a fun or a list of queries -get_db_type() -> mssql. - -sql_transaction(LServer, Queries) - when is_list(Queries) -> - F = fun () -> - lists:foreach(fun (Query) -> - ejabberd_odbc:sql_query(LServer, Query) - end, - Queries) - end, - {atomic, catch F()}; -sql_transaction(_LServer, FQueries) -> - {atomic, catch FQueries()}. - -get_last(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_last '">>, Username, <<"'">>]). - -set_last_t(LServer, Username, Seconds, State) -> - Result = ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.set_last '">>, Username, - <<"', '">>, Seconds, <<"', '">>, State, - <<"'">>]), - {atomic, Result}. - -del_last(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_last '">>, Username, <<"'">>]). - -get_password(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_password '">>, Username, - <<"'">>]). - -set_password_t(LServer, Username, Pass) -> - Result = ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.set_password '">>, - Username, <<"', '">>, Pass, <<"'">>]), - {atomic, Result}. - -add_user(LServer, Username, Pass) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.add_user '">>, Username, <<"', '">>, - Pass, <<"'">>]). - -del_user(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_user '">>, Username, <<"'">>]). - -del_user_return_password(LServer, Username, Pass) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_user_return_password '">>, - Username, <<"'">>]), - Pass. - -list_users(LServer) -> - ejabberd_odbc:sql_query(LServer, - <<"EXECUTE dbo.list_users">>). - -list_users(LServer, _) -> list_users(LServer). - -users_number(LServer) -> - ejabberd_odbc:sql_query(LServer, - <<"select count(*) from users with (nolock)">>). - -users_number(LServer, _) -> users_number(LServer). - -add_spool_sql(Username, XML) -> - [<<"EXECUTE dbo.add_spool '">>, Username, <<"' , '">>, - XML, <<"'">>]. - -add_spool(LServer, Queries) -> - lists:foreach(fun (Query) -> - ejabberd_odbc:sql_query(LServer, Query) - end, - Queries). - -get_and_del_spool_msg_t(LServer, Username) -> - [Result] = case ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_and_del_spool_msg '">>, - Username, <<"'">>]) - of - Rs when is_list(Rs) -> - lists:filter(fun ({selected, _Header, _Row}) -> true; - ({updated, _N}) -> false - end, - Rs); - Rs -> [Rs] - end, - {atomic, Result}. - -del_spool_msg(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_spool_msg '">>, Username, - <<"'">>]). - -get_roster(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_roster '">>, Username, - <<"'">>]). - -get_roster_jid_groups(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_roster_jid_groups '">>, - Username, <<"'">>]). - -get_roster_groups(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_roster_groups '">>, Username, - <<"' , '">>, SJID, <<"'">>]). - -del_user_roster_t(LServer, Username) -> - Result = ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_user_roster '">>, - Username, <<"'">>]), - {atomic, Result}. - -get_roster_by_jid(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_roster_by_jid '">>, Username, - <<"' , '">>, SJID, <<"'">>]). - -get_rostergroup_by_jid(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_rostergroup_by_jid '">>, - Username, <<"' , '">>, SJID, <<"'">>]). - -del_roster(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_roster '">>, Username, - <<"', '">>, SJID, <<"'">>]). - -del_roster_sql(Username, SJID) -> - [<<"EXECUTE dbo.del_roster '">>, Username, <<"', '">>, - SJID, <<"'">>]. - -update_roster(LServer, Username, SJID, ItemVals, - ItemGroups) -> - Query1 = [<<"EXECUTE dbo.del_roster '">>, Username, - <<"', '">>, SJID, <<"' ">>], - ejabberd_odbc:sql_query(LServer, lists:flatten(Query1)), - Query2 = [<<"EXECUTE dbo.add_roster_user ">>, ItemVals], - ejabberd_odbc:sql_query(LServer, lists:flatten(Query2)), - Query3 = [<<"EXECUTE dbo.del_roster_groups '">>, - Username, <<"', '">>, SJID, <<"' ">>], - ejabberd_odbc:sql_query(LServer, lists:flatten(Query3)), - lists:foreach(fun (ItemGroup) -> - Query = [<<"EXECUTE dbo.add_roster_group ">>, - ItemGroup], - ejabberd_odbc:sql_query(LServer, lists:flatten(Query)) - end, - ItemGroups). - -update_roster_sql(Username, SJID, ItemVals, - ItemGroups) -> - [<<"BEGIN TRANSACTION ">>, - <<"EXECUTE dbo.del_roster_groups '">>, Username, - <<"','">>, SJID, <<"' ">>, - <<"EXECUTE dbo.add_roster_user ">>, ItemVals, <<" ">>] - ++ - [lists:flatten(<<"EXECUTE dbo.add_roster_group ">>, - ItemGroup, <<" ">>) - || ItemGroup <- ItemGroups] - ++ [<<"COMMIT">>]. - -roster_subscribe(LServer, _Username, _SJID, ItemVals) -> - catch ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.add_roster_user ">>, - ItemVals]). - -get_subscription(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_subscription '">>, Username, - <<"' , '">>, SJID, <<"'">>]). - -set_private_data(LServer, Username, LXMLNS, SData) -> - ejabberd_odbc:sql_query(LServer, - set_private_data_sql(Username, LXMLNS, SData)). - -set_private_data_sql(Username, LXMLNS, SData) -> - [<<"EXECUTE dbo.set_private_data '">>, Username, - <<"' , '">>, LXMLNS, <<"' , '">>, SData, <<"'">>]. - -get_private_data(LServer, Username, LXMLNS) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_private_data '">>, Username, - <<"' , '">>, LXMLNS, <<"'">>]). - -del_user_private_storage(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_user_storage '">>, Username, - <<"'">>]). - -set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, - SFamily, SGiven, SLBDay, SLCTRY, SLEMail, SLFN, - SLFamily, SLGiven, SLLocality, SLMiddle, SLNickname, - SLOrgName, SLOrgUnit, SLocality, SMiddle, SNickname, - SOrgName, SOrgUnit, SVCARD, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.set_vcard '">>, SVCARD, <<"' , '">>, - Username, <<"' , '">>, LUsername, <<"' , '">>, SFN, - <<"' , '">>, SLFN, <<"' , '">>, SFamily, - <<"' , '">>, SLFamily, <<"' , '">>, SGiven, - <<"' , '">>, SLGiven, <<"' , '">>, SMiddle, - <<"' , '">>, SLMiddle, <<"' , '">>, SNickname, - <<"' , '">>, SLNickname, <<"' , '">>, SBDay, - <<"' , '">>, SLBDay, <<"' , '">>, SCTRY, - <<"' , '">>, SLCTRY, <<"' , '">>, SLocality, - <<"' , '">>, SLLocality, <<"' , '">>, SEMail, - <<"' , '">>, SLEMail, <<"' , '">>, SOrgName, - <<"' , '">>, SLOrgName, <<"' , '">>, SOrgUnit, - <<"' , '">>, SLOrgUnit, <<"'">>]). - -get_vcard(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_vcard '">>, Username, <<"'">>]). - -get_default_privacy_list(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_default_privacy_list '">>, - Username, <<"'">>]). - -get_default_privacy_list_t(Username) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_default_privacy_list '">>, - Username, <<"'">>]). - -get_privacy_list_names(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_privacy_list_names '">>, - Username, <<"'">>]). - -get_privacy_list_names_t(Username) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_privacy_list_names '">>, - Username, <<"'">>]). - -get_privacy_list_id(LServer, Username, SName) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_privacy_list_id '">>, Username, - <<"' , '">>, SName, <<"'">>]). - -get_privacy_list_id_t(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_privacy_list_id '">>, - Username, <<"' , '">>, SName, <<"'">>]). - -get_privacy_list_data(LServer, Username, SName) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_privacy_list_data '">>, - Username, <<"' , '">>, SName, <<"'">>]). - -get_privacy_list_data_by_id(LServer, ID) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_privacy_list_data_by_id '">>, - ID, <<"'">>]). - -get_privacy_list_data_by_id_t(ID) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.get_privacy_list_data_by_id '">>, - ID, <<"'">>]). - -set_default_privacy_list(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.set_default_privacy_list '">>, - Username, <<"' , '">>, SName, <<"'">>]). - -unset_default_privacy_list(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.unset_default_privacy_list '">>, - Username, <<"'">>]). - -remove_privacy_list(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.remove_privacy_list '">>, - Username, <<"' , '">>, SName, <<"'">>]). - -add_privacy_list(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.add_privacy_list '">>, - Username, <<"' , '">>, SName, <<"'">>]). - -set_privacy_list(ID, RItems) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.del_privacy_list_by_id '">>, - ID, <<"'">>]), - lists:foreach(fun (Items) -> - ejabberd_odbc:sql_query_t([<<"EXECUTE dbo.set_privacy_list '">>, - ID, <<"', '">>, - join(Items, <<"', '">>), - <<"'">>]) - end, - RItems). - -del_privacy_lists(LServer, Server, Username) -> -%% Characters to escape -%% Count number of records in a table given a where clause - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.del_privacy_lists @Server='">>, - Server, <<"' @username='">>, Username, <<"'">>]). - -escape($\000) -> <<"\\0">>; -escape($\t) -> <<"\\t">>; -escape($\b) -> <<"\\b">>; -escape($\r) -> <<"\\r">>; -escape($') -> <<"''">>; -escape($") -> <<"\\\"">>; -escape(C) -> C. - -count_records_where(LServer, Table, WhereClause) -> - ejabberd_odbc:sql_query(LServer, - [<<"select count(*) from ">>, Table, - <<" with (nolock) ">>, WhereClause]). - -get_roster_version(LServer, LUser) -> - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.get_roster_version '">>, LUser, - <<"'">>]). - -set_roster_version(Username, Version) -> - LServer = (?MYNAME), - ejabberd_odbc:sql_query(LServer, - [<<"EXECUTE dbo.set_roster_version '">>, Username, - <<"', '">>, Version, <<"'">>]). - --endif. - opt_type(odbc_type) -> fun (pgsql) -> pgsql; (mysql) -> mysql; From fc7d3a44b8c9987af7975da6741f15e1fc62fcd6 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Sep 2015 17:41:54 +0300 Subject: [PATCH 244/695] Simplify MSSQL configuration --- src/ejabberd_odbc.erl | 98 ++++++++++++++++++++++++++++++++++++++- src/ejabberd_odbc_sup.erl | 4 ++ src/ejabberd_rdbms.erl | 6 +++ src/odbc_queries.erl | 1 + 4 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 5cbd3e931d4..df49d0e8ba7 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -46,6 +46,10 @@ sqlite_file/1, encode_term/1, decode_term/1, + odbc_config/0, + freetds_config/0, + odbcinst_config/0, + init_mssql/1, keep_alive/1]). %% gen_fsm callbacks @@ -62,7 +66,7 @@ -record(state, {db_ref = self() :: pid(), - db_type = odbc :: pgsql | mysql | sqlite | odbc, + db_type = odbc :: pgsql | mysql | sqlite | odbc | mssql, start_interval = 0 :: non_neg_integer(), host = <<"">> :: binary(), max_pending_requests_len :: non_neg_integer(), @@ -78,6 +82,8 @@ -define(MYSQL_PORT, 3306). +-define(MSSQL_PORT, 1433). + -define(MAX_TRANSACTION_RESTARTS, 10). -define(TRANSACTION_TIMEOUT, 60000). @@ -665,6 +671,7 @@ db_opts(Host) -> fun(mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end, odbc), Server = ejabberd_config:get_option({odbc_server, Host}, @@ -680,6 +687,7 @@ db_opts(Host) -> {odbc_port, Host}, fun(P) when is_integer(P), P > 0, P < 65536 -> P end, case Type of + mssql -> ?MSSQL_PORT; mysql -> ?MYSQL_PORT; pgsql -> ?PGSQL_PORT end), @@ -692,9 +700,96 @@ db_opts(Host) -> Pass = ejabberd_config:get_option({odbc_password, Host}, fun iolist_to_binary/1, <<"">>), + case Type of + mssql -> + Username = get_mssql_user(Server, User), + [odbc, <<"DSN=", Host/binary, ";UID=", Username/binary, + ";PWD=", Pass/binary>>]; + _ -> [Type, Server, Port, DB, User, Pass] + end + end. + +init_mssql(Host) -> + Server = ejabberd_config:get_option({odbc_server, Host}, + fun iolist_to_binary/1, + <<"localhost">>), + Port = ejabberd_config:get_option( + {odbc_port, Host}, + fun(P) when is_integer(P), P > 0, P < 65536 -> P end, + ?MSSQL_PORT), + DB = ejabberd_config:get_option({odbc_database, Host}, + fun iolist_to_binary/1, + <<"ejabberd">>), + FreeTDS = io_lib:fwrite("[~s]~n" + "\thost = ~s~n" + "\tport = ~p~n" + "\ttds version = 7.1~n", + [Host, Server, Port]), + ODBCINST = io_lib:fwrite("[freetds]~n" + "Description = MSSQL connection~n" + "Driver = libtdsodbc.so~n" + "Setup = libtdsS.so~n" + "UsageCount = 1~n" + "FileUsage = 1~n", []), + ODBCINI = io_lib:fwrite("[~s]~n" + "Description = MS SQL~n" + "Driver = freetds~n" + "Servername = ~s~n" + "Database = ~s~n" + "Port = ~p~n", + [Host, Host, DB, Port]), + ?DEBUG("~s:~n~s", [freetds_config(), FreeTDS]), + ?DEBUG("~s:~n~s", [odbcinst_config(), ODBCINST]), + ?DEBUG("~s:~n~s", [odbc_config(), ODBCINI]), + case filelib:ensure_dir(freetds_config()) of + ok -> + try + ok = file:write_file(freetds_config(), FreeTDS, [append]), + ok = file:write_file(odbcinst_config(), ODBCINST), + ok = file:write_file(odbc_config(), ODBCINI, [append]), + os:putenv("ODBCSYSINI", tmp_dir()), + os:putenv("FREETDS", freetds_config()), + os:putenv("FREETDSCONF", freetds_config()), + ok + catch error:{badmatch, {error, Reason} = Err} -> + ?ERROR_MSG("failed to create temporary files in ~s: ~s", + [tmp_dir(), file:format_error(Reason)]), + Err + end; + {error, Reason} = Err -> + ?ERROR_MSG("failed to create temporary directory ~s: ~s", + [tmp_dir(), file:format_error(Reason)]), + Err end. +get_mssql_user(Server, User) -> + HostName = case inet_parse:address(binary_to_list(Server)) of + {ok, _} -> + Server; + {error, _} -> + hd(str:tokens(Server, <<".">>)) + end, + UserName = case str:chr(User, $@) of + 0 -> + <>; + _ -> + User + end, + UserName. + +tmp_dir() -> + filename:join(["/tmp", "ejabberd"]). + +odbc_config() -> + filename:join(tmp_dir(), "odbc.ini"). + +freetds_config() -> + filename:join(tmp_dir(), "freetds.conf"). + +odbcinst_config() -> + filename:join(tmp_dir(), "odbcinst.ini"). + max_fsm_queue() -> ejabberd_config:get_option( max_fsm_queue, @@ -719,6 +814,7 @@ opt_type(odbc_type) -> fun (mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end; opt_type(odbc_username) -> fun iolist_to_binary/1; diff --git a/src/ejabberd_odbc_sup.erl b/src/ejabberd_odbc_sup.erl index 4a1498964d5..fa44853487c 100644 --- a/src/ejabberd_odbc_sup.erl +++ b/src/ejabberd_odbc_sup.erl @@ -73,11 +73,14 @@ init([Host]) -> fun(mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end, odbc), case Type of sqlite -> check_sqlite_db(Host); + mssql -> + ejabberd_odbc:init_mssql(Host); _ -> ok end, @@ -216,6 +219,7 @@ opt_type(odbc_type) -> fun (mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end; opt_type(_) -> diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl index 23f1a857e1a..f4bfbd6000c 100644 --- a/src/ejabberd_rdbms.erl +++ b/src/ejabberd_rdbms.erl @@ -35,6 +35,9 @@ -include("logger.hrl"). start() -> + file:delete(ejabberd_odbc:freetds_config()), + file:delete(ejabberd_odbc:odbc_config()), + file:delete(ejabberd_odbc:odbcinst_config()), case lists:any(fun(H) -> needs_odbc(H) /= false end, ?MYHOSTS) of true -> @@ -77,11 +80,13 @@ needs_odbc(Host) -> fun(mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end, undefined) of mysql -> {true, p1_mysql}; pgsql -> {true, p1_pgsql}; sqlite -> {true, sqlite3}; + mssql -> {true, odbc}; odbc -> {true, odbc}; undefined -> false end. @@ -90,6 +95,7 @@ opt_type(odbc_type) -> fun (mysql) -> mysql; (pgsql) -> pgsql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end; opt_type(_) -> [odbc_type]. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index b90c2f2d554..e33af54e258 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -651,6 +651,7 @@ opt_type(odbc_type) -> fun (pgsql) -> pgsql; (mysql) -> mysql; (sqlite) -> sqlite; + (mssql) -> mssql; (odbc) -> odbc end; opt_type(pgsql_users_number_estimate) -> From ab857b1a5e9d45071f95720ceb1fb535a8733225 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 14 Sep 2015 14:05:07 +0300 Subject: [PATCH 245/695] Improve MSSQL schema --- sql/mssql.sql | Bin 56088 -> 49868 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sql/mssql.sql b/sql/mssql.sql index c3944d9697f985859753d8084740076863941072..36ce50f4a5f761f5297c11a070d0ec235e51cf7b 100644 GIT binary patch delta 121 zcmV-<0EYjVwgb$C1F$#-lZt+LvltB06tfU3=1!9?i42nvg%Y#mgUk|>iU<;uMk5-N zAdU>P*p|ov1#maW04x9?0C1C!a_f^26ArWRnFIloke?otoR}1ofO`a! b{t*b1&X^jLOiI|3z#DLrkem#&aGR(-eGC9C&+4#n{3pn;ckJuK^ien1K)}calVLeZf1t=Ttv0ru1ANN^2=(i(>wiuq|v^C>b zt4J8rdObPln|QG?iuiKZM>48~x=gu}h&_QTveo6% z-dvvK%uy^Sv1=5rTN>>DdjOi?L2^b~HGOv#dp8^;@C-QFaq6Q>VSt1@`0 zEDD_LME`DsiFJadAk);$T;*GCtKRK1C3Li?Zfx!xsDVSRYXT(4OjA-9tEIw04yq|$ zBoY)%H~W{8v@U_8`cGGrpCko_z*z^Xj}%XuACbn&ogR2CN$~9je;~x>k%3@`3xxN) zg@&F4kVB!(;W`9Uekc5%7GS)62n4TS%IIzQcR+~n>RJ|j1wPme07*yRcE>?bvo+MB z`?zZn+SG+BR9P3~}x2`gu~PH!O#{ W^b>w{cWc=a&w Date: Tue, 15 Sep 2015 22:42:22 +0200 Subject: [PATCH 246/695] XEP-0198: Improve handling of non-message stanzas When an XEP-0198 session times out, always return an error for unacknowledged IQ stanzas, and always drop presence stanzas. That is, the "resend_on_timeout" option no longer applies to those stanzas types, but only to messages. --- src/ejabberd_c2s.erl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 10ff01b211c..2c06fef05fc 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2920,7 +2920,13 @@ handle_unacked_stanzas(StateData) ejabberd_router:route(To, From, Err) end end, - F = fun(From, To, El, Time) -> + F = fun(From, _To, #xmlel{name = <<"presence">>}, _Time) -> + ?DEBUG("Dropping presence stanza from ~s", + [jlib:jid_to_string(From)]); + (From, To, #xmlel{name = <<"iq">>} = El, _Time) -> + Err = jlib:make_error_reply(El, ?ERR_SERVICE_UNAVAILABLE), + ejabberd_router:route(To, From, Err); + (From, To, El, Time) -> %% We'll drop the stanza if it was by some %% encapsulating protocol as per XEP-0297. One such protocol is %% XEP-0280, which says: "When a receiving server attempts to @@ -2930,7 +2936,7 @@ handle_unacked_stanzas(StateData) %% stanza could easily lead to unexpected results as well. case is_encapsulated_forward(El) of true -> - ?DEBUG("Dropping forwarded stanza from ~s", + ?DEBUG("Dropping forwarded message stanza from ~s", [xml:get_attr_s(<<"from">>, El#xmlel.attrs)]); false -> ReRoute(From, To, El, Time) From e6279123e5d4532bafb6d270c6c956c556b9708f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 16 Sep 2015 11:08:21 +0200 Subject: [PATCH 247/695] Update polish translation --- priv/msgs/pl.po | 64 ++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/priv/msgs/pl.po b/priv/msgs/pl.po index b62633fbfaf..961307d32da 100644 --- a/priv/msgs/pl.po +++ b/priv/msgs/pl.po @@ -3,9 +3,9 @@ msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" "PO-Revision-Date: \n" -"Last-Translator: Zbyszek Żółkiewski \n" +"Last-Translator: Paweł Chmielowski \n" "Language-Team: \n" -"Language: \n" +"Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -14,6 +14,7 @@ msgstr "" "X-Additional-Translator: Marcin Owsiany\n" "X-Additional-Translator: Andrzej Smyk\n" "X-Additional-Translator: Mateusz Gajewski\n" +"X-Generator: Poedit 1.8.4\n" #: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" @@ -34,7 +35,7 @@ msgstr "został wyrzucony" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Zbyt wiele niepotwierdzonych pakietów" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -126,8 +127,7 @@ msgstr "Wirtualne Hosty" msgid "Users" msgstr "Użytkownicy" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 mod_configure.erl:524 msgid "Online Users" msgstr "Użytkownicy zalogowani" @@ -159,8 +159,7 @@ msgstr "Pokaż zwykłą tabelę" msgid "Show Integral Table" msgstr "Pokaż tabelę całkowitą" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statystyki" @@ -184,8 +183,8 @@ msgstr "Host" msgid "Registered Users" msgstr "Użytkownicy zarejestrowani" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 mod_register.erl:262 +#: mod_vcard.erl:490 msgid "User" msgstr "Użytkownik" @@ -246,9 +245,8 @@ msgid "Change Password" msgstr "Zmień hasło" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Użytkownik " +msgstr "Użytkownik ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" @@ -280,9 +278,8 @@ msgid "Stopped Nodes" msgstr "Zatrzymane węzły" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Węzeł " +msgstr "Węzeł ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -319,9 +316,8 @@ msgid "RPC Call Error" msgstr "Błąd żądania RPC" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Tabele bazy na " +msgstr "Tabele bazy na ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -344,9 +340,8 @@ msgid "Error" msgstr "Błąd" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Kopia zapasowa " +msgstr "Kopia zapasowa ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -407,7 +402,7 @@ msgstr "" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Wyeksportuj wszystkie tabele jako zapytania SQL do pliku:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -422,9 +417,8 @@ msgid "Listened Ports at " msgstr "Porty nasłuchujące na " #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Moduły na " +msgstr "Moduły na ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -455,9 +449,8 @@ msgid "Transactions Logged:" msgstr "Transakcje zalogowane:" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Uaktualnij " +msgstr "Uaktualnij ~p" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -839,10 +832,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Zbyt wiele (~p) nieudanych prób logowanie z tego adresu IP (~s). Ten adres " +"zostanie odblokowany o ~s UTC" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Ten adres IP został zablokowany w ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -966,8 +961,8 @@ msgstr "Rejestracja nazwy użytkownika na " msgid "Enter nickname you want to register" msgstr "Wprowadz nazwę użytkownika którego chcesz zarejestrować" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Nazwa użytkownika" @@ -978,26 +973,23 @@ msgstr "Moduł MUC" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Wieloosobowa rozmowa" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Pokoje rozmów" +msgstr "Wszystkich pokoi" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "opuszcza pokój" +msgstr "Stałych pokoi" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Użytkownicy zarejestrowani" +msgstr "Zarejestrowanych nicków" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Lista pokoi" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1267,7 +1259,7 @@ msgstr "Pokój zabezpieczony captchą" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Włącz archiwizowanie rozmów" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1315,11 +1307,11 @@ msgstr "hasło to:" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "Serwis multicast ejabbera" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" From 18d3329f8f94ad6123d33d3a8f11c9e0a4ae9ce0 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 16 Sep 2015 11:14:20 +0200 Subject: [PATCH 248/695] Update French translation --- priv/msgs/fr.po | 80 ++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 45 deletions(-) diff --git a/priv/msgs/fr.po b/priv/msgs/fr.po index d7ba74f8a64..19e3f8ab32b 100644 --- a/priv/msgs/fr.po +++ b/priv/msgs/fr.po @@ -5,7 +5,7 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: Nicolas Vérité \n" "Language-Team: \n" -"Language: \n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -13,6 +13,7 @@ msgstr "" "X-Additional-Translator: Christophe Romain\n" "X-Additional-Translator: Mickaël Rémond\n" "X-Additional-Translator: Vincent Ricard\n" +"X-Generator: Poedit 1.8.4\n" #: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 msgid "Use of STARTTLS required" @@ -33,7 +34,7 @@ msgstr "a été expulsé" #: ejabberd_c2s.erl:2490 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Trop de stanzas sans accusé de réception (ack)" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -126,8 +127,7 @@ msgstr "Serveurs virtuels" msgid "Users" msgstr "Utilisateurs" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 mod_configure.erl:524 msgid "Online Users" msgstr "Utilisateurs en ligne" @@ -159,8 +159,7 @@ msgstr "Montrer la table ordinaire" msgid "Show Integral Table" msgstr "Montrer la table intégralement" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 mod_muc_admin.erl:246 msgid "Statistics" msgstr "Statistiques" @@ -184,8 +183,8 @@ msgstr "Serveur" msgid "Registered Users" msgstr "Utilisateurs enregistrés" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 mod_register.erl:262 +#: mod_vcard.erl:490 msgid "User" msgstr "Utilisateur" @@ -280,9 +279,8 @@ msgid "Stopped Nodes" msgstr "Noeuds arrêtés" #: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 -#, fuzzy msgid "Node ~p" -msgstr "Noeud " +msgstr "Noeud ~p" #: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -319,9 +317,8 @@ msgid "RPC Call Error" msgstr "Erreur d'appel RPC" #: ejabberd_web_admin.erl:1855 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Tables de base de données sur " +msgstr "Tables de base de données sur ~p" #: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -344,9 +341,8 @@ msgid "Error" msgstr "Erreur" #: ejabberd_web_admin.erl:1893 -#, fuzzy msgid "Backup of ~p" -msgstr "Sauvegarde de " +msgstr "Sauvegarde de ~p" #: ejabberd_web_admin.erl:1897 msgid "" @@ -408,7 +404,7 @@ msgstr "" #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Exporter toutes les tables en tant que requêtes SQL vers un fichier:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -423,9 +419,8 @@ msgid "Listened Ports at " msgstr "Ports ouverts sur " #: ejabberd_web_admin.erl:2082 -#, fuzzy msgid "Modules at ~p" -msgstr "Modules sur " +msgstr "Modules sur ~p" #: ejabberd_web_admin.erl:2113 msgid "Statistics of ~p" @@ -456,9 +451,8 @@ msgid "Transactions Logged:" msgstr "Transactions journalisées :" #: ejabberd_web_admin.erl:2181 -#, fuzzy msgid "Update ~p" -msgstr "Mise à jour " +msgstr "Mise à jour de ~p" #: ejabberd_web_admin.erl:2192 msgid "Update plan" @@ -840,10 +834,12 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Trop (~p) d'authentification ont échoué pour cette adresse IP (~s). " +"L'adresse sera débloquée à ~s UTC" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Cette adresse IP est blacklistée dans ~s" #: mod_irc.erl:431 msgid "IRC Transport" @@ -970,8 +966,8 @@ msgstr "Enregistrement d'un pseudo sur " msgid "Enter nickname you want to register" msgstr "Entrez le pseudo que vous souhaitez enregistrer" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Pseudo" @@ -982,26 +978,23 @@ msgstr "Module MUC ejabberd" #: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 #: mod_muc_admin.erl:319 msgid "Multi-User Chat" -msgstr "" +msgstr "Discussion de groupe" #: mod_muc_admin.erl:248 -#, fuzzy msgid "Total rooms" -msgstr "Salons de discussion" +msgstr "Nombre de salons" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Permanent rooms" -msgstr "quitte le salon" +msgstr "Salons persistent" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Registered nicknames" -msgstr "Utilisateurs enregistrés" +msgstr "Pseudos enregistrés" #: mod_muc_admin.erl:253 msgid "List of rooms" -msgstr "" +msgstr "Liste des salons" #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" @@ -1236,13 +1229,12 @@ msgid "Allow users to send private messages" msgstr "Autoriser les utilisateurs à envoyer des messages privés" #: mod_muc_room.erl:3479 -#, fuzzy msgid "Allow visitors to send private messages to" -msgstr "Autoriser les utilisateurs à envoyer des messages privés" +msgstr "Autoriser les visiteurs à envoyer des messages privés" #: mod_muc_room.erl:3497 msgid "nobody" -msgstr "" +msgstr "personne" #: mod_muc_room.erl:3522 msgid "Allow users to query other users" @@ -1262,13 +1254,12 @@ msgid "Allow visitors to change nickname" msgstr "Autoriser les visiteurs à changer de pseudo" #: mod_muc_room.erl:3535 -#, fuzzy msgid "Allow visitors to send voice requests" -msgstr "Permettre aux utilisateurs d'envoyer des invitations" +msgstr "Permettre aux visiteurs d'envoyer des demandes de 'voice'" #: mod_muc_room.erl:3538 msgid "Minimum interval between voice requests (in seconds)" -msgstr "" +msgstr "Intervalle minimum entre les demandes de 'voice' (en secondes)" #: mod_muc_room.erl:3545 msgid "Make room CAPTCHA protected" @@ -1276,11 +1267,11 @@ msgstr "Protéger le salon par un CAPTCHA" #: mod_muc_room.erl:3552 msgid "Enable message archiving" -msgstr "" +msgstr "Activer l'archivage de messages" #: mod_muc_room.erl:3558 msgid "Exclude Jabber IDs from CAPTCHA challenge" -msgstr "" +msgstr "Exempter des Jabberd IDs du test CAPTCHA" #: mod_muc_room.erl:3567 msgid "Enable logging" @@ -1301,20 +1292,19 @@ msgstr "privé" #: mod_muc_room.erl:4237 msgid "Voice request" -msgstr "" +msgstr "Demande de 'voice'" #: mod_muc_room.erl:4242 msgid "Either approve or decline the voice request." -msgstr "" +msgstr "Approuver ou refuser la demande de 'voice'" #: mod_muc_room.erl:4262 -#, fuzzy msgid "User JID" -msgstr "Utilisateur " +msgstr "JID de l'utilisateur " #: mod_muc_room.erl:4266 msgid "Grant voice to this person?" -msgstr "" +msgstr "Accorder 'voice' à cet utilisateur" #: mod_muc_room.erl:4409 msgid "~s invites you to the room ~s" @@ -1326,11 +1316,11 @@ msgstr "le mot de passe est" #: mod_multicast.erl:273 msgid "Multicast" -msgstr "" +msgstr "Multidiffusion" #: mod_multicast.erl:288 msgid "ejabberd Multicast service" -msgstr "" +msgstr "Service de Multidiffusion d'ejabberd" #: mod_offline.erl:783 msgid "~s's Offline Messages Queue" From a8d6439a4b96e4db7294a69b308f5b3f4aba5027 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 16 Sep 2015 11:33:00 +0200 Subject: [PATCH 249/695] Update French translation --- priv/msgs/fr.po | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/priv/msgs/fr.po b/priv/msgs/fr.po index 19e3f8ab32b..84000a60a40 100644 --- a/priv/msgs/fr.po +++ b/priv/msgs/fr.po @@ -245,9 +245,8 @@ msgid "Change Password" msgstr "Modifier le mot de passe" #: ejabberd_web_admin.erl:1610 -#, fuzzy msgid "User ~s" -msgstr "Utilisateur " +msgstr "Utilisateur ~s" #: ejabberd_web_admin.erl:1621 msgid "Connected Resources:" From 5593ebbbca5bd64ae564fd97e58ed826b2a22e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 16 Sep 2015 12:19:54 +0200 Subject: [PATCH 250/695] Properly handle define_macros in merged config files --- src/ejabberd_config.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 971d6dbd653..253e7ab11a3 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -120,12 +120,7 @@ read_file(File) -> {include_modules_configs, true}]). read_file(File, Opts) -> - Terms1 = get_plain_terms_file(File, Opts), - Terms_macros = case proplists:get_bool(replace_macros, Opts) of - true -> replace_macros(Terms1); - false -> Terms1 - end, - Terms = transform_terms(Terms_macros), + Terms = get_plain_terms_file(File, Opts), State = lists:foldl(fun search_hosts/2, #state{}, Terms), {Head, Tail} = lists:partition( fun({host_config, _}) -> false; @@ -211,11 +206,16 @@ get_plain_terms_file(File1, Opts) -> [] end, BinTerms = BinTerms1 ++ [{include_config_file, list_to_binary(V)} || V <- ModInc], + BinTerms2 = case proplists:get_bool(replace_macros, Opts) of + true -> replace_macros(BinTerms); + false -> BinTerms + end, + BinTerms3 = transform_terms(BinTerms2), case proplists:get_bool(include_files, Opts) of true -> - include_config_files(BinTerms); + include_config_files(BinTerms3); false -> - BinTerms + BinTerms3 end; {error, Reason} -> ?ERROR_MSG(Reason, []), From ae5127731619725209e5f2c30f4213ec77ecc0a1 Mon Sep 17 00:00:00 2001 From: Quan Zhuo Date: Wed, 16 Sep 2015 22:52:36 +0800 Subject: [PATCH 251/695] Comment unused type, unused term --- src/ejabberd_auth_external.erl | 2 +- src/gen_iq_handler.erl | 4 ++-- src/mod_configure.erl | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 67477f27aaf..9dcf3410f47 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -281,7 +281,7 @@ is_fresh_enough(TimeStampLast, CacheTime) -> get_last_access(User, Server) -> case ejabberd_sm:get_user_resources(User, Server) of [] -> - _US = {User, Server}, +%% _US = {User, Server}, case get_last_info(User, Server) of mod_last_required -> mod_last_required; not_found -> never; diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index bbad1eca756..c015b893953 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -44,9 +44,9 @@ -record(state, {host, module, function}). --type component() :: ejabberd_sm | ejabberd_local. +%%-type component() :: ejabberd_sm | ejabberd_local. -type type() :: no_queue | one_queue | pos_integer() | parallel. --type opts() :: no_queue | {one_queue, pid()} | {queues, [pid()]} | parallel. +%%-type opts() :: no_queue | {one_queue, pid()} | {queues, [pid()]} | parallel. %%==================================================================== %% API diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 8faf7be735c..6b07c9840e5 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -1912,7 +1912,7 @@ set_form(From, Host, Server) of [] -> - _US = {User, Server}, +%% _US = {User, Server}, case get_last_info(User, Server) of not_found -> ?T(Lang, <<"Never">>); {ok, Timestamp, _Status} -> From 4a4065c9c62a74a6a8b493595ac40e87f637b814 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 17 Sep 2015 00:33:08 +0200 Subject: [PATCH 252/695] Let BOSH/WebSocket support "max_resume_timeout" Allow for specifying the "max_resume_timeout" option in an ejabberd_http listener for ejabberd_http_bind and/or ejabberd_http_ws. --- src/ejabberd_http_bind.erl | 1 + src/ejabberd_http_ws.erl | 1 + 2 files changed, 2 insertions(+) diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index 21c6887f00d..4277f4c54a5 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -335,6 +335,7 @@ init([Sid, Key, IP, HOpts]) -> SOpts = lists:filtermap(fun({stream_managment, _}) -> true; ({max_ack_queue, _}) -> true; ({resume_timeout, _}) -> true; + ({max_resume_timeout, _}) -> true; ({resend_on_timeout, _}) -> true; (_) -> false end, HOpts), diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index dd6854f8c32..65a80b0046d 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -115,6 +115,7 @@ init([{#ws{ip = IP, http_opts = HOpts}, _} = WS]) -> SOpts = lists:filtermap(fun({stream_managment, _}) -> true; ({max_ack_queue, _}) -> true; ({resume_timeout, _}) -> true; + ({max_resume_timeout, _}) -> true; ({resend_on_timeout, _}) -> true; (_) -> false end, HOpts), From f6b892b36623bb35b1140682544202c52583dd0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 17 Sep 2015 11:36:45 +0200 Subject: [PATCH 253/695] Guard against passing undefined C2SPid to xml parser before become_controller gets called Our new nif xml parser don't handle this gracefully, so we better don't call it that way. This is only triggered on old style ssl sockets, where ssl layer must be activated early, before association between socket and c2s is established --- src/ejabberd_receiver.erl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index f63ae1ccb91..3f8f979dc12 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -159,8 +159,13 @@ handle_call({starttls, TLSSocket}, _From, c2s_pid = C2SPid, max_stanza_size = MaxStanzaSize} = State) -> close_stream(XMLStreamState), - NewXMLStreamState = xml_stream:new(C2SPid, - MaxStanzaSize), + NewXMLStreamState = case C2SPid of + undefined -> + XMLStreamState; + _ -> + xml_stream:new(C2SPid, + MaxStanzaSize) + end, NewState = State#state{socket = TLSSocket, sock_mod = p1_tls, xml_stream_state = NewXMLStreamState}, @@ -347,7 +352,12 @@ process_data(Data, shaper_state = ShaperState, c2s_pid = C2SPid} = State) -> ?DEBUG("Received XML on stream = ~p", [(Data)]), - XMLStreamState1 = xml_stream:parse(XMLStreamState, Data), + XMLStreamState1 = case XMLStreamState of + undefined -> + XMLStreamState; + _ -> + xml_stream:parse(XMLStreamState, Data) + end, {NewShaperState, Pause} = shaper:update(ShaperState, byte_size(Data)), if C2SPid == undefined -> From a1a7beb24da27b9faaee97f17dfda202f11eb539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 14 Aug 2015 12:12:55 +0200 Subject: [PATCH 254/695] Make sure that lager is first on our deps list --- rebar.config.script | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rebar.config.script b/rebar.config.script index 43bb8f0efbe..7ec52722b85 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -167,6 +167,12 @@ TestConfig = case file:read_file_info(TestConfigFile) of "" end, +AllDeps0 = Deps ++ CfgDeps, +AllDeps = case lists:keytake(lager, 1, AllDeps0) of + {value, Tuple, Rest} -> [Tuple|Rest]; + false -> AllDeps0 + end, + Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++ [{src_dirs, [asn1, src | SrcDirs]}]}, {sub_dirs, ["rel"]}, @@ -180,7 +186,7 @@ Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++ [{"(XC - UC) || (XU - X - B - " ++ string:join(CfgXrefs, " - ") ++ ")", []}]}, {post_hooks, PostHooks ++ CfgPostHooks}, - {deps, Deps ++ CfgDeps}] ++ ElixirConfig, + {deps, AllDeps}] ++ ElixirConfig, %%io:format("ejabberd configuration:~n ~p~n", [Config]), Config. From ec1969ddcadd1757f90428c6d45ce464d77bd712 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 4 Sep 2015 12:36:33 +0200 Subject: [PATCH 255/695] Remove unused functions from old get_items api --- src/node_flat.erl | 15 +++------------ src/node_flat_odbc.erl | 30 +++++++++++++----------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/node_flat.erl b/src/node_flat.erl index 736bbdfe188..6388dfc5a63 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -46,8 +46,7 @@ get_entity_subscriptions/2, get_node_subscriptions/1, get_subscriptions/2, set_subscriptions/4, get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, - get_items/7, get_items/3, get_item/7, + set_state/1, get_items/7, get_items/3, get_item/7, get_item/2, set_item/1, get_item_name/3, node_to_path/1, path_to_node/1, can_fetch_item/2, is_subscribed/1]). @@ -698,19 +697,11 @@ del_state(Nidx, Key) -> %% mod_pubsub module.

    %%

    PubSub plugins can store the items where they wants (for example in a %% relational database), or they can even decide not to persist any items.

    -%%

    If a PubSub plugin wants to delegate the item storage to the default node, -%% they can implement this function like this: -%% ```get_items(Nidx, From) -> -%% node_default:get_items(Nidx, From).'''

    -get_items(Nidx, From) -> - get_items(Nidx, From, none). get_items(Nidx, _From, _RSM) -> Items = mnesia:match_object(#pubsub_item{itemid = {'_', Nidx}, _ = '_'}), {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), none}}. -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RSM) -> +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), GenState = get_state(Nidx, GenKey), @@ -743,7 +734,7 @@ get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, _RS %% % Payment is required for a subscription %% {error, ?ERR_PAYMENT_REQUIRED}; true -> - get_items(Nidx, JID) + get_items(Nidx, JID, RSM) end. %% @doc

    Returns an item (one item list), given its reference.

    diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index c3f9c7e2694..68492cdc43d 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -46,8 +46,7 @@ get_entity_subscriptions/2, get_node_subscriptions/1, get_subscriptions/2, set_subscriptions/4, get_pending_nodes/2, get_states/1, get_state/2, - set_state/1, get_items/6, get_items/2, - get_items/7, get_items/3, get_item/7, + set_state/1, get_items/7, get_items/3, get_item/7, get_item/2, set_item/1, get_item_name/3, node_to_path/1, path_to_node/1, get_entity_subscriptions_for_send_last/2, get_last_items/3]). @@ -623,18 +622,18 @@ del_state(Nidx, JID) -> J, <<"' and nodeid='">>, Nidx, <<"';">>]), ok. -get_items(Nidx, _From) -> - case catch - ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " - "from pubsub_item where nodeid='">>, Nidx, - <<"' order by modification desc;">>]) - of - {selected, - [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> - {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; - _ -> - {result, []} - end. +%get_items(Nidx, _From) -> +% case catch +% ejabberd_odbc:sql_query_t([<<"select itemid, publisher, creation, modification, payload " +% "from pubsub_item where nodeid='">>, Nidx, +% <<"' order by modification desc;">>]) +% of +% {selected, +% [<<"itemid">>, <<"publisher">>, <<"creation">>, <<"modification">>, <<"payload">>], RItems} -> +% {result, [raw_to_item(Nidx, RItem) || RItem <- RItems]}; +% _ -> +% {result, []} +% end. get_items(Nidx, From, none) -> MaxItems = case catch @@ -719,9 +718,6 @@ get_items(Nidx, _From, {result, {[], none}} end. -get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> - get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, none). - get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> SubKey = jlib:jid_tolower(JID), GenKey = jlib:jid_remove_resource(SubKey), From df3862cf846ca1f788acf167bb283d1c32c80655 Mon Sep 17 00:00:00 2001 From: Jerome Sautret Date: Mon, 21 Sep 2015 17:07:44 +0200 Subject: [PATCH 256/695] Add set_loglevel command (EJABS-2524) --- src/ejabberd_admin.erl | 12 ++++++++++++ src/ejabberd_logger.erl | 7 +++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 80342eecd27..dc4c10c8701 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -29,6 +29,7 @@ -export([start/0, stop/0, %% Server status/0, reopen_log/0, + set_loglevel/1, stop_kindly/2, send_service_message_all_mucs/2, registered_vhosts/0, reload_config/0, @@ -102,6 +103,11 @@ commands() -> {levelatom, atom}, {leveldesc, string} ]}}}, + #ejabberd_commands{name = set_loglevel, tags = [logs, server], + desc = "Set the loglevel (0 to 5)", + module = ?MODULE, function = set_loglevel, + args = [{loglevel, integer}], + result = {logger, atom}}, #ejabberd_commands{name = update_list, tags = [server], desc = "List modified modules that can be updated", @@ -252,6 +258,12 @@ reopen_log() -> ejabberd_hooks:run(reopen_log_hook, []), ejabberd_logger:reopen_log(). + +set_loglevel(LogLevel) -> + {module, Module} = ejabberd_logger:set(LogLevel), + Module. + + %%% %%% Stop Kindly %%% diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 3bfe37c80aa..d1d039e1e08 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -157,7 +157,8 @@ set(LogLevel) when is_integer(LogLevel) -> 2 -> error; 3 -> warning; 4 -> info; - 5 -> debug + 5 -> debug; + E -> throw({wrong_loglevel, E}) end, case lager:get_loglevel(lager_console_backend) of LagerLogLevel -> @@ -194,8 +195,10 @@ reopen_log() -> get() -> p1_loglevel:get(). +set(LogLevel) when LogLevel >=0, LogLevel =< 5 -> + p1_loglevel:set(LogLevel); set(LogLevel) -> - p1_loglevel:set(LogLevel). + throw({wrong_loglevel, LogLevel}). %%%=================================================================== %%% Internal functions From e57c1896f716bf53d2256feab6a08ce41c358c9e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 21 Sep 2015 17:51:13 +0200 Subject: [PATCH 257/695] Avoid wrong failing cases on make install (#468) --- Makefile.in | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Makefile.in b/Makefile.in index ffd1d30f73b..f7b30d4689e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -137,9 +137,9 @@ install: all $(INSTALL) -m 550 $(G_USER) ejabberdctl.example $(SBINDIR)/ejabberdctl # Elixir binaries [ -d $(BINDIR) ] || $(INSTALL) -d -m 755 $(BINDIR) - -[ -f deps/elixir/bin/iex ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/iex $(BINDIR)/iex - -[ -f deps/elixir/bin/elixir ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/elixir $(BINDIR)/elixir - -[ -f deps/elixir/bin/mix ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/mix $(BINDIR)/mix + [ -f deps/elixir/bin/iex ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/iex $(BINDIR)/iex || true + [ -f deps/elixir/bin/elixir ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/elixir $(BINDIR)/elixir || true + [ -f deps/elixir/bin/mix ] && $(INSTALL) -m 550 $(G_USER) deps/elixir/bin/mix $(BINDIR)/mix || true # # Init script $(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*" \ @@ -168,22 +168,23 @@ install: all $(INSTALL) -m 750 $(O_USER) tools/captcha.sh $(PBINDIR) $(INSTALL) -m 750 $(O_USER) tools/joincluster $(PBINDIR) $(INSTALL) -m 750 $(O_USER) tools/leavecluster $(PBINDIR) - -[ -f deps/p1_pam/priv/bin/epam ] \ - && $(INSTALL) -m 750 $(O_USER) deps/p1_pam/priv/bin/epam $(PBINDIR) + [ -f deps/p1_pam/priv/bin/epam ] \ + && $(INSTALL) -m 750 $(O_USER) deps/p1_pam/priv/bin/epam $(PBINDIR) \ + || true # # Binary system libraries $(INSTALL) -d $(SODIR) $(INSTALL) -m 644 $(DLLs) $(SODIR) - -[ -f $(SODIR)/jiffy.so ] && (cd $(PRIVDIR); ln -s lib/jiffy.so; true) - -[ -f $(SODIR)/sqlite3_drv.so ] && (cd $(PRIVDIR); ln -s lib/sqlite3_drv.so; true) + [ -f $(SODIR)/jiffy.so ] && (cd $(PRIVDIR); ln -s lib/jiffy.so; true) || true + [ -f $(SODIR)/sqlite3_drv.so ] && (cd $(PRIVDIR); ln -s lib/sqlite3_drv.so; true) || true # # Translated strings $(INSTALL) -d $(MSGSDIR) $(INSTALL) -m 644 priv/msgs/*.msg $(MSGSDIR) # # Copy lite.sql - -[ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR) - -[ -d deps/sqlite3 ] && $(INSTALL) -m 644 sql/lite.sql $(SQLDIR) + [ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR) || true + [ -d deps/sqlite3 ] && $(INSTALL) -m 644 sql/lite.sql $(SQLDIR) || true # # Spool directory $(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR) From 70b1dc479c77b23532b06376a24c9eeb9436db13 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Sep 2015 12:18:06 +0300 Subject: [PATCH 258/695] Add MAM (XEP-0313) v0.4 support --- include/ns.hrl | 1 + src/mod_mam.erl | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/ns.hrl b/include/ns.hrl index 71f454cadf8..0685ae65c68 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -143,6 +143,7 @@ -define(NS_BOB, <<"urn:xmpp:bob">>). -define(NS_MAM_TMP, <<"urn:xmpp:mam:tmp">>). -define(NS_MAM_0, <<"urn:xmpp:mam:0">>). +-define(NS_MAM_1, <<"urn:xmpp:mam:1">>). -define(NS_PING, <<"urn:xmpp:ping">>). -define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>). -define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>). diff --git a/src/mod_mam.erl b/src/mod_mam.erl index b476ff68169..cd9dd7e400d 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -75,6 +75,10 @@ start(Host, Opts) -> ?NS_MAM_0, ?MODULE, process_iq_v0_3, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM_0, ?MODULE, process_iq_v0_3, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_MAM_1, ?MODULE, process_iq_v0_3, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_MAM_1, ?MODULE, process_iq_v0_3, IQDisc), ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, user_receive_packet, 500), ejabberd_hooks:add(user_send_packet, Host, ?MODULE, @@ -123,6 +127,8 @@ stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_TMP), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_0), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_0), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_1), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_1), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, @@ -716,7 +722,7 @@ send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> end, CompleteAttr = if NS == ?NS_MAM_TMP -> []; - NS == ?NS_MAM_0 -> + NS == ?NS_MAM_0; NS == ?NS_MAM_1 -> [{<<"complete">>, jlib:atom_to_binary(IsComplete)}] end, Els = lists:map( @@ -728,14 +734,13 @@ send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> children = [El]}]} end, Msgs), RSMOut = make_rsm_out(Msgs, RSM, Count, QIDAttr ++ CompleteAttr, NS), - case NS of - ?NS_MAM_TMP -> + if NS == ?NS_MAM_TMP; NS == ?NS_MAM_1 -> lists:foreach( fun(El) -> ejabberd_router:route(To, From, El) end, Els), IQ#iq{type = result, sub_el = RSMOut}; - ?NS_MAM_0 -> + NS == ?NS_MAM_0 -> ejabberd_router:route( To, From, jlib:iq_to_xml(IQ#iq{type = result, sub_el = []})), lists:foreach( From 23a1aceac0e2654980029f4e5138768495b33dca Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 22 Sep 2015 12:49:55 +0200 Subject: [PATCH 259/695] Improve external module configuration management (EJAB-1746) --- src/ejabberd_config.erl | 7 +++++-- src/ext_mod.erl | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 253e7ab11a3..c3355591351 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -201,9 +201,12 @@ get_plain_terms_file(File1, Opts) -> BinTerms1 = strings_to_binary(Terms), ModInc = case proplists:get_bool(include_modules_configs, Opts) of true -> - filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.{yml,yaml}"); + Files = [{filename:rootname(filename:basename(F)), F} + || F <- filelib:wildcard(ext_mod:config_dir() ++ "/*.{yml,yaml}") + ++ filelib:wildcard(ext_mod:modules_dir() ++ "/*/conf/*.{yml,yaml}")], + [proplists:get_value(F,Files) || F <- proplists:get_keys(Files)]; _ -> - [] + [] end, BinTerms = BinTerms1 ++ [{include_config_file, list_to_binary(V)} || V <- ModInc], BinTerms2 = case proplists:get_bool(replace_macros, Opts) of diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 4b9ddafab15..765d38b4f6b 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -33,7 +33,7 @@ installed_command/0, installed/0, installed/1, install/1, uninstall/1, upgrade/0, upgrade/1, add_sources/2, del_sources/1, modules_dir/0, - opt_type/1]). + config_dir/0, opt_type/1]). -include("ejabberd_commands.hrl"). @@ -350,6 +350,10 @@ modules_dir() -> sources_dir() -> filename:join(modules_dir(), "sources"). +config_dir() -> + DefaultDir = filename:join(modules_dir(), "conf"), + getenv("CONTRIB_MODULES_CONF_DIR", DefaultDir). + module_lib_dir(Package) -> filename:join(modules_dir(), Package). From e28934497261e3d8d0feef8d54af9af43cee8e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 22 Sep 2015 15:33:31 +0200 Subject: [PATCH 260/695] Nameprep host name passed to http-bind before using in (EJAB-1658) --- src/ejabberd_http_bind.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index 4277f4c54a5..42be5256132 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -220,8 +220,9 @@ process_request(Data, IP, HOpts) -> "dressing' xmlns='", (?NS_HTTP_BIND)/binary, "'/>">>}; XmppDomain -> + NXmppDomain = jlib:nameprep(XmppDomain), Sid = p1_sha:sha(term_to_binary({now(), make_ref()})), - case start(XmppDomain, Sid, <<"">>, IP, HOpts) of + case start(NXmppDomain, Sid, <<"">>, IP, HOpts) of {error, _} -> {500, ?HEADER, <<"Internal Server Error">>}; {ok, Pid} -> - handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, + handle_session_start(Pid, NXmppDomain, Sid, Rid, Attrs, Payload, PayloadSize, IP) end end; From 3300c8d9941fb1809c8fbeb683fad1f5034c0cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 22 Sep 2015 15:42:34 +0200 Subject: [PATCH 261/695] Set disable caching headers in http-bind responses (EJAB-1643) --- include/http_bind.hrl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/http_bind.hrl b/include/http_bind.hrl index 446e471051c..7c0e04a9802 100644 --- a/include/http_bind.hrl +++ b/include/http_bind.hrl @@ -38,9 +38,12 @@ -define(AC_MAX_AGE, {<<"Access-Control-Max-Age">>, <<"86400">>}). +-define(NO_CACHE, + {<<"Cache-Control">>, <<"max-age=0, no-cache, no-store">>}). + -define(OPTIONS_HEADER, [?CT_PLAIN, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_METHODS, ?AC_ALLOW_HEADERS, ?AC_MAX_AGE]). -define(HEADER, - [?CT_XML, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_HEADERS]). + [?CT_XML, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_HEADERS, ?NO_CACHE]). From c360326cdbc4797c519d732f29d10506ef10f196 Mon Sep 17 00:00:00 2001 From: Johan Oudinet Date: Tue, 22 Sep 2015 17:07:39 +0200 Subject: [PATCH 262/695] Allow root to run join_cluster and leave_cluster Prefix the call to joincluster and leavecluster in ejabberdctl by $EXEC_CMD. Avoid using sh -c in these scripts. Should fix #676. --- ejabberdctl.template | 4 ++-- tools/joincluster | 2 +- tools/leavecluster | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 4704c85c4a5..04ede34718a 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -444,11 +444,11 @@ check_start() # cluster setup join_cluster() { - $EJABBERD_BIN_PATH/joincluster $* + $EXEC_CMD "$EJABBERD_BIN_PATH/joincluster $*" } leave_cluster() { - $EJABBERD_BIN_PATH/leavecluster $* + $EXEC_CMD "$EJABBERD_BIN_PATH/leavecluster $*" } # allow sync calls diff --git a/tools/joincluster b/tools/joincluster index ff2e0380f51..99b96bdb3cc 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -145,7 +145,7 @@ start() -> EOF $ERLC -o $PA $CLUSTERSETUP_ERL -sh -c "$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia extra_db_nodes \"['$REMOTE']\" dir \"\\\"$SPOOL_DIR\\\"\" -s mnesia -s $CLUSTERSETUP start" +$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia extra_db_nodes "['$REMOTE']" dir "\"$SPOOL_DIR\"" -s mnesia -s $CLUSTERSETUP start cd - rm -Rf $PA diff --git a/tools/leavecluster b/tools/leavecluster index b2dfea0c721..688b6032ba0 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -101,7 +101,7 @@ start() -> EOF $ERLC -o $PA $CLUSTERSETUP_ERL -sh -c "$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia dir \"\\\"$SPOOL_DIR\\\"\" -s mnesia -s $CLUSTERSETUP start" +$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia dir "\"$SPOOL_DIR\"" -s mnesia -s $CLUSTERSETUP start cd - rm -Rf $PA From 89b3471742615cec6dd04745c6551f99a93bdcdf Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Sep 2015 21:15:34 +0300 Subject: [PATCH 263/695] Add (XEP-0359) to archived messages --- include/ns.hrl | 1 + src/mod_mam.erl | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/ns.hrl b/include/ns.hrl index 0685ae65c68..85cf762effb 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -144,6 +144,7 @@ -define(NS_MAM_TMP, <<"urn:xmpp:mam:tmp">>). -define(NS_MAM_0, <<"urn:xmpp:mam:0">>). -define(NS_MAM_1, <<"urn:xmpp:mam:1">>). +-define(NS_SID_0, <<"urn:xmpp:sid:0">>). -define(NS_PING, <<"urn:xmpp:ping">>). -define(NS_CARBONS_2, <<"urn:xmpp:carbons:2">>). -define(NS_CARBONS_1, <<"urn:xmpp:carbons:1">>). diff --git a/src/mod_mam.erl b/src/mod_mam.erl index cd9dd7e400d..3e3e0873de3 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -169,7 +169,11 @@ user_receive_packet(Pkt, C2SState, JID, Peer, _To) -> attrs = [{<<"by">>, LServer}, {<<"xmlns">>, ?NS_MAM_TMP}, {<<"id">>, ID}]}, - NewEls = [Archived|NewPkt#xmlel.children], + StanzaID = #xmlel{name = <<"stanza-id">>, + attrs = [{<<"by">>, LServer}, + {<<"xmlns">>, ?NS_SID_0}, + {<<"id">>, ID}]}, + NewEls = [Archived, StanzaID|NewPkt#xmlel.children], NewPkt#xmlel{children = NewEls}; _ -> NewPkt @@ -194,9 +198,19 @@ user_send_packet(Pkt, C2SState, JID, Peer) -> muc_filter_message(Pkt, #state{config = Config} = MUCState, RoomJID, From, FromNick) -> if Config#config.mam -> - NewPkt = strip_my_archived_tag(Pkt, MUCState#state.server_host), - store_muc(MUCState, NewPkt, RoomJID, From, FromNick), - NewPkt; + By = jlib:jid_to_string(RoomJID), + NewPkt = strip_my_archived_tag(Pkt, By), + case store_muc(MUCState, NewPkt, RoomJID, From, FromNick) of + {ok, ID} -> + StanzaID = #xmlel{name = <<"stanza-id">>, + attrs = [{<<"by">>, By}, + {<<"xmlns">>, ?NS_SID_0}, + {<<"id">>, ID}]}, + NewEls = [StanzaID|NewPkt#xmlel.children], + NewPkt#xmlel{children = NewEls}; + _ -> + NewPkt + end; true -> Pkt end. @@ -345,8 +359,8 @@ should_archive(#xmlel{}) -> strip_my_archived_tag(Pkt, LServer) -> NewEls = lists:filter( - fun(#xmlel{name = <<"archived">>, - attrs = Attrs}) -> + fun(#xmlel{name = Tag, attrs = Attrs}) + when Tag == <<"archived">>; Tag == <<"stanza-id">> -> case catch jlib:nameprep( xml:get_attr_s( <<"by">>, Attrs)) of From 484fd1f51f314dd413772200db2e534d61345788 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 24 Sep 2015 12:00:59 +0200 Subject: [PATCH 264/695] Log TLS errors as [debug] messages only Closes #652 and closes #679. --- src/ejabberd_receiver.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 3f8f979dc12..9652e526802 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -250,7 +250,7 @@ handle_info({Tag, _TCPSocket, Data}, ?HIBERNATE_TIMEOUT}; {error, Reason} -> if is_binary(Reason) -> - ?ERROR_MSG("TLS error = ~s", [Reason]); + ?DEBUG("TLS error = ~s", [Reason]); true -> ok end, From 1f4d8fd4d77a1f6042d768339d5f141357c8edfb Mon Sep 17 00:00:00 2001 From: Johan Oudinet Date: Thu, 24 Sep 2015 15:09:39 +0200 Subject: [PATCH 265/695] Remove bashisms in {join,leave}cluster scripts So they can run in any POSIX shell, not bash only. --- tools/joincluster | 6 +++--- tools/leavecluster | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/joincluster b/tools/joincluster index ff2e0380f51..8379622360a 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Add the current ejabberd node in a cluster @@ -15,7 +15,7 @@ # 30 : network issue # 31 : node names incompatibility -function error +error() { echo "Error: $1" >&2 exit $2 @@ -67,7 +67,7 @@ CTL=$(which ejabberdctl) echo "Using commands:" [ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 -. $CTL stop 2>/dev/null >/dev/null +$CTL stop 2>/dev/null >/dev/null ERLC=${ERL}c [ -x $ERL ] && echo $ERL || error "can't find erl" 11 diff --git a/tools/leavecluster b/tools/leavecluster index b2dfea0c721..feacdce2dd9 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # Remove the current ejabberd node in a cluster @@ -11,7 +11,7 @@ # 12 : erlc not found # 22 : temporary dir can not be created -function error +error() { echo "Error: $1" >&2 exit $2 @@ -45,7 +45,7 @@ CTL=$(which ejabberdctl) echo "Using commands:" [ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 -. $CTL stop 2>/dev/null >/dev/null +$CTL stop 2>/dev/null >/dev/null ERLC=${ERL}c [ -x $ERL ] && echo $ERL || error "can't find erl" 11 From ee456cc2afaa223f5086c54a17fdbcb3e90aaf8d Mon Sep 17 00:00:00 2001 From: Badlop Date: Thu, 24 Sep 2015 17:21:14 +0200 Subject: [PATCH 266/695] Fix regression introduced when code was binarized (EJAB-641) --- src/ejabberd_auth_external.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 9dcf3410f47..4d11507ee97 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -311,7 +311,9 @@ get_mod_last_configured(Server) -> end. is_configured(Host, Module) -> - gen_mod:is_loaded(Host, Module). + Os = ejabberd_config:get_local_option({modules, Host}, + fun(M) when is_list(M) -> M end), + lists:keymember(Module, 1, Os). opt_type(extauth_cache) -> fun (false) -> undefined; From deccf91280f3ed47719f965f03f0122297f51848 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 25 Sep 2015 13:35:03 +0200 Subject: [PATCH 267/695] Fix calling problem introduced when reducing bashisms (#748) --- tools/joincluster | 2 +- tools/leavecluster | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/joincluster b/tools/joincluster index 8379622360a..7385e169749 100755 --- a/tools/joincluster +++ b/tools/joincluster @@ -67,7 +67,7 @@ CTL=$(which ejabberdctl) echo "Using commands:" [ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 -$CTL stop 2>/dev/null >/dev/null +exec $CTL stop 2>/dev/null >/dev/null ERLC=${ERL}c [ -x $ERL ] && echo $ERL || error "can't find erl" 11 diff --git a/tools/leavecluster b/tools/leavecluster index feacdce2dd9..3e42c700f0c 100755 --- a/tools/leavecluster +++ b/tools/leavecluster @@ -45,7 +45,7 @@ CTL=$(which ejabberdctl) echo "Using commands:" [ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 -$CTL stop 2>/dev/null >/dev/null +exec $CTL stop 2>/dev/null >/dev/null ERLC=${ERL}c [ -x $ERL ] && echo $ERL || error "can't find erl" 11 From a1129dc96b4782800c3046ea6de6a77049f2293e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 25 Sep 2015 14:53:25 +0200 Subject: [PATCH 268/695] Add OAuth support (thanks to Aleksey) --- configure.ac | 15 +- include/ejabberd_commands.hrl | 1 + rebar.config.script | 5 + src/cyrsasl.erl | 1 + src/cyrsasl_oauth.erl | 96 +++++++ src/ejabberd_app.erl | 1 + src/ejabberd_commands.erl | 185 +++++++++++-- src/ejabberd_ctl.erl | 10 +- src/ejabberd_http.erl | 3 + src/ejabberd_oauth.erl | 473 ++++++++++++++++++++++++++++++++++ src/ejabberd_xmlrpc.erl | 91 ++++--- src/mod_http_api.erl | 392 ++++++++++++++++++++++++++++ vars.config.in | 1 + 13 files changed, 1207 insertions(+), 67 deletions(-) create mode 100644 src/cyrsasl_oauth.erl create mode 100644 src/ejabberd_oauth.erl create mode 100644 src/mod_http_api.erl diff --git a/configure.ac b/configure.ac index d30a490d080..69fd3cef52d 100644 --- a/configure.ac +++ b/configure.ac @@ -108,10 +108,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools --enable-oauth (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; - no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; + yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true oauth=true ;; + no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false oauth=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -227,6 +227,14 @@ AC_ARG_ENABLE(lager, *) AC_MSG_ERROR(bad value ${enableval} for --enable-lager) ;; esac],[if test "x$lager" = "x"; then lager=true; fi]) +AC_ARG_ENABLE(oauth, +[AC_HELP_STRING([--enable-oauth], [enable oauth support (default: yes)])], +[case "${enableval}" in + yes) oauth=true ;; + no) oauth=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-oauth) ;; +esac],[if test "x$oauth" = "x"; then oauth=false; fi]) + AC_CONFIG_FILES([Makefile vars.config src/ejabberd.app.src]) @@ -273,5 +281,6 @@ AC_SUBST(iconv) AC_SUBST(debug) AC_SUBST(lager) AC_SUBST(tools) +AC_SUBST(oauth) AC_OUTPUT diff --git a/include/ejabberd_commands.hrl b/include/ejabberd_commands.hrl index 3ab15ca31f5..82ee891c3a6 100644 --- a/include/ejabberd_commands.hrl +++ b/include/ejabberd_commands.hrl @@ -34,6 +34,7 @@ module :: atom(), function :: atom(), args = [] :: [aterm()] | '_' | '$1' | '$2', + policy = restricted :: open | restricted | admin | user, result = {res, rescode} :: rterm() | '_' | '$2'}). -type ejabberd_commands() :: #ejabberd_commands{name :: atom(), diff --git a/rebar.config.script b/rebar.config.script index 7ec52722b85..2ecb39c2584 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -110,6 +110,11 @@ CfgDeps = lists:flatmap( [{meck, "0.*", {git, "https://github.com/eproxus/meck"}}]; ({redis, true}) -> [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; + ({oauth, true}) -> + %% ejabberd oauth support does not depends directly on xmlrpc. + %% However, we include xmlrpc as it is convenient to document and test oauth + [{oauth2, ".*", {git, "https://github.com/IvanMartinez/oauth2.git"}}, + {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}]; (_) -> [] end, Cfg), diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 970da5bb9bc..518bb84ff50 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -84,6 +84,7 @@ start() -> cyrsasl_digest:start([]), cyrsasl_scram:start([]), cyrsasl_anonymous:start([]), + cyrsasl_oauth:start([]), ok. %% diff --git a/src/cyrsasl_oauth.erl b/src/cyrsasl_oauth.erl new file mode 100644 index 00000000000..fc5a9c6cf48 --- /dev/null +++ b/src/cyrsasl_oauth.erl @@ -0,0 +1,96 @@ +%%%---------------------------------------------------------------------- +%%% File : cyrsasl_oauth.erl +%%% Author : Alexey Shchepin +%%% Purpose : X-OAUTH2 SASL mechanism +%%% Created : 17 Sep 2015 by Alexey Shchepin +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-module(cyrsasl_oauth). + +-author('alexey@process-one.net'). + +-export([start/1, stop/0, mech_new/6, mech_step/2, parse/1]). + +-behaviour(cyrsasl). + +-record(state, {host, is_user_exists}). + +start(_Opts) -> + cyrsasl:register_mechanism(<<"X-OAUTH2">>, ?MODULE, plain), + ok. + +stop() -> ok. + +mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest, + IsUserExists, _ClientCertFile) -> + {ok, #state{host = Host, is_user_exists = IsUserExists}}. + +mech_step(State, ClientIn) -> + case prepare(ClientIn) of + [AuthzId, User, Token] -> + case (State#state.is_user_exists)(User) of + true -> + case ejabberd_oauth:check_token( + User, State#state.host, <<"sasl_auth">>, Token) of + true -> + {ok, + [{username, User}, {authzid, AuthzId}, + {auth_module, ejabberd_oauth}]}; + false -> + {error, <<"not-authorized">>, User} + end; + _ -> {error, <<"not-authorized">>, User} + end; + _ -> {error, <<"bad-protocol">>} + end. + +prepare(ClientIn) -> + case parse(ClientIn) of + [<<"">>, UserMaybeDomain, Token] -> + case parse_domain(UserMaybeDomain) of + %% login@domainpwd + [User, _Domain] -> [UserMaybeDomain, User, Token]; + %% loginpwd + [User] -> [<<"">>, User, Token] + end; + %% login@domainloginpwd + [AuthzId, User, Token] -> [AuthzId, User, Token]; + _ -> error + end. + +parse(S) -> parse1(binary_to_list(S), "", []). + +parse1([0 | Cs], S, T) -> + parse1(Cs, "", [list_to_binary(lists:reverse(S)) | T]); +parse1([C | Cs], S, T) -> parse1(Cs, [C | S], T); +%parse1([], [], T) -> +% lists:reverse(T); +parse1([], S, T) -> + lists:reverse([list_to_binary(lists:reverse(S)) | T]). + +parse_domain(S) -> parse_domain1(binary_to_list(S), "", []). + +parse_domain1([$@ | Cs], S, T) -> + parse_domain1(Cs, "", [list_to_binary(lists:reverse(S)) | T]); +parse_domain1([C | Cs], S, T) -> + parse_domain1(Cs, [C | S], T); +parse_domain1([], S, T) -> + lists:reverse([list_to_binary(lists:reverse(S)) | T]). diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 319e494c223..657785ff982 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -69,6 +69,7 @@ start(normal, _Args) -> %ejabberd_debug:fprof_start(), maybe_add_nameservers(), ejabberd_auth:start(), + ejabberd_oauth:start(), start_modules(), ejabberd_listener:start_listeners(), ?INFO_MSG("ejabberd ~s is started in the node ~p", [?VERSION, node()]), diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index a5ba98ae808..34297e006b4 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -211,12 +211,15 @@ -export([init/0, list_commands/0, get_command_format/1, + get_command_format/2, get_command_definition/1, get_tags_commands/0, + get_commands/0, register_commands/1, unregister_commands/1, execute_command/2, - execute_command/4 + execute_command/4, + opt_type/1 ]). -include("ejabberd_commands.hrl"). @@ -265,19 +268,39 @@ list_commands() -> _ = '_'}), [{A, B, C} || [A, B, C] <- Commands]. +-spec list_commands_policy() -> [{atom(), [aterm()], string(), atom()}]. + +%% @doc Get a list of all the available commands, arguments, description, and +%% policy. +list_commands_policy() -> + Commands = ets:match(ejabberd_commands, + #ejabberd_commands{name = '$1', + args = '$2', + desc = '$3', + policy = '$4', + _ = '_'}), + [{A, B, C, D} || [A, B, C, D] <- Commands]. + -spec get_command_format(atom()) -> {[aterm()], rterm()} | {error, command_unknown}. %% @doc Get the format of arguments and result of a command. get_command_format(Name) -> + get_command_format(Name, noauth). + +get_command_format(Name, Auth) -> + Admin = is_admin(Name, Auth), Matched = ets:match(ejabberd_commands, #ejabberd_commands{name = Name, args = '$1', result = '$2', + policy = '$3', _ = '_'}), case Matched of [] -> {error, command_unknown}; - [[Args, Result]] -> + [[Args, Result, user]] when Admin -> + {[{user, binary}, {server, binary} | Args], Result}; + [[Args, Result, _]] -> {Args, Result} end. @@ -295,24 +318,54 @@ get_command_definition(Name) -> execute_command(Name, Arguments) -> execute_command([], noauth, Name, Arguments). +-spec execute_command([{atom(), [atom()], [any()]}], + {binary(), binary(), binary(), boolean()} | + noauth | admin, + atom(), + [any()] + ) -> any(). + %% @spec (AccessCommands, Auth, Name::atom(), Arguments) -> ResultTerm | {error, Error} %% where %% AccessCommands = [{Access, CommandNames, Arguments}] -%% Auth = {User::string(), Server::string(), Password::string()} | noauth +%% Auth = {User::string(), Server::string(), Password::string(), Admin::boolean()} +%% | noauth +%% | admin %% Method = atom() %% Arguments = [any()] %% Error = command_unknown | account_unprivileged | invalid_account_data | no_auth_provided -execute_command(AccessCommands, Auth, Name, Arguments) -> +execute_command(AccessCommands1, Auth1, Name, Arguments) -> + Auth = case is_admin(Name, Auth1) of + true -> admin; + false -> Auth1 + end, case ets:lookup(ejabberd_commands, Name) of [Command] -> + AccessCommands = get_access_commands(AccessCommands1), try check_access_commands(AccessCommands, Auth, Name, Command, Arguments) of - ok -> execute_command2(Command, Arguments) + ok -> execute_command2(Auth, Command, Arguments) catch {error, Error} -> {error, Error} end; [] -> {error, command_unknown} end. +execute_command2( + _Auth, #ejabberd_commands{policy = open} = Command, Arguments) -> + execute_command2(Command, Arguments); +execute_command2( + _Auth, #ejabberd_commands{policy = restricted} = Command, Arguments) -> + execute_command2(Command, Arguments); +execute_command2( + _Auth, #ejabberd_commands{policy = admin} = Command, Arguments) -> + execute_command2(Command, Arguments); +execute_command2( + admin, #ejabberd_commands{policy = user} = Command, Arguments) -> + execute_command2(Command, Arguments); +execute_command2( + {User, Server, _, _}, #ejabberd_commands{policy = user} = Command, Arguments) -> + execute_command2(Command, [User, Server | Arguments]). + execute_command2(Command, Arguments) -> Module = Command#ejabberd_commands.module, Function = Command#ejabberd_commands.function, @@ -372,11 +425,20 @@ get_tags_commands() -> %% Error = account_unprivileged | invalid_account_data check_access_commands([], _Auth, _Method, _Command, _Arguments) -> ok; -check_access_commands(AccessCommands, Auth, Method, Command, Arguments) -> +check_access_commands(AccessCommands, Auth, Method, Command1, Arguments) -> + Command = + case {Command1#ejabberd_commands.policy, Auth} of + {user, admin} -> + Command1#ejabberd_commands{ + args = [{user, binary}, {server, binary} | + Command1#ejabberd_commands.args]}; + _ -> + Command1 + end, AccessCommandsAllowed = lists:filter( fun({Access, Commands, ArgumentRestrictions}) -> - case check_access(Access, Auth) of + case check_access(Command, Access, Auth) of true -> check_access_command(Commands, Command, ArgumentRestrictions, Method, Arguments); @@ -385,7 +447,7 @@ check_access_commands(AccessCommands, Auth, Method, Command, Arguments) -> end; ({Access, Commands}) -> ArgumentRestrictions = [], - case check_access(Access, Auth) of + case check_access(Command, Access, Auth) of true -> check_access_command(Commands, Command, ArgumentRestrictions, Method, Arguments); @@ -399,29 +461,48 @@ check_access_commands(AccessCommands, Auth, Method, Command, Arguments) -> L when is_list(L) -> ok end. --spec check_auth(noauth) -> noauth_provided; - ({binary(), binary(), binary()}) -> {ok, binary(), binary()}. +-spec check_auth(ejabberd_commands(), noauth) -> noauth_provided; + (ejabberd_commands(), + {binary(), binary(), binary(), boolean()}) -> + {ok, binary(), binary()}. -check_auth(noauth) -> +check_auth(_Command, noauth) -> no_auth_provided; -check_auth({User, Server, Password}) -> +check_auth(Command, {User, Server, {oauth, Token}, _}) -> + Scope = erlang:atom_to_binary(Command#ejabberd_commands.name, utf8), + case ejabberd_oauth:check_token(User, Server, Scope, Token) of + true -> + {ok, User, Server}; + false -> + throw({error, invalid_account_data}) + end; +check_auth(_Command, {User, Server, Password, _}) when is_binary(Password) -> %% Check the account exists and password is valid case ejabberd_auth:check_password(User, Server, Password) of true -> {ok, User, Server}; _ -> throw({error, invalid_account_data}) end. -check_access(all, _) -> +check_access(Command, all, _) + when Command#ejabberd_commands.policy == open -> + true; +check_access(_Command, _Access, admin) -> true; -check_access(Access, Auth) -> - case check_auth(Auth) of +check_access(_Command, _Access, {_User, _Server, _, true}) -> + false; +check_access(Command, Access, Auth) + when Command#ejabberd_commands.policy == open; + Command#ejabberd_commands.policy == user -> + case check_auth(Command, Auth) of {ok, User, Server} -> - check_access(Access, User, Server); + check_access2(Access, User, Server); _ -> false - end. + end; +check_access(_Command, _Access, _Auth) -> + false. -check_access(Access, User, Server) -> +check_access2(Access, User, Server) -> %% Check this user has access permission case acl:match_rule(Server, Access, jlib:make_jid(User, Server, <<"">>)) of allow -> true; @@ -452,3 +533,71 @@ tag_arguments(ArgsDefs, Args) -> end, ArgsDefs, Args). + + +get_access_commands(undefined) -> + Cmds = get_commands(), + [{all, Cmds, []}]; +get_access_commands(AccessCommands) -> + AccessCommands. + +get_commands() -> + Opts = ejabberd_config:get_option( + commands, + fun(V) when is_list(V) -> V end, + []), + CommandsList = list_commands_policy(), + OpenCmds = [N || {N, _, _, open} <- CommandsList], + RestrictedCmds = [N || {N, _, _, restricted} <- CommandsList], + AdminCmds = [N || {N, _, _, admin} <- CommandsList], + UserCmds = [N || {N, _, _, user} <- CommandsList], + Cmds = + lists:foldl( + fun({add_commands, L}, Acc) -> + Cmds = case L of + open -> OpenCmds; + restricted -> RestrictedCmds; + admin -> AdminCmds; + user -> UserCmds; + _ when is_list(L) -> L + end, + lists:usort(Cmds ++ Acc); + ({remove_commands, L}, Acc) -> + Cmds = case L of + open -> OpenCmds; + restricted -> RestrictedCmds; + admin -> AdminCmds; + user -> UserCmds; + _ when is_list(L) -> L + end, + Acc -- Cmds; + (_, Acc) -> Acc + end, AdminCmds ++ UserCmds, Opts), + Cmds. + +is_admin(_Name, noauth) -> + false; +is_admin(_Name, admin) -> + true; +is_admin(_Name, {_User, _Server, _, false}) -> + false; +is_admin(Name, {User, Server, _, true} = Auth) -> + AdminAccess = ejabberd_config:get_option( + commands_admin_access, + fun(A) when is_atom(A) -> A end, + none), + case acl:match_rule(Server, AdminAccess, + jlib:make_jid(User, Server, <<"">>)) of + allow -> + case catch check_auth(get_command_definition(Name), Auth) of + {ok, _, _} -> true; + _ -> false + end; + deny -> false + end. + +opt_type(commands_admin_access) -> + fun(A) when is_atom(A) -> A end; +opt_type(commands) -> + fun(V) when is_list(V) -> V end; +opt_type(_) -> [commands, commands_admin_access]. diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 82ac6b134f9..8b6f1852079 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -211,7 +211,7 @@ process(Args) -> process2(["--auth", User, Server, Pass | Args], AccessCommands) -> process2(Args, {list_to_binary(User), list_to_binary(Server), list_to_binary(Pass)}, AccessCommands); process2(Args, AccessCommands) -> - process2(Args, noauth, AccessCommands). + process2(Args, admin, AccessCommands). process2(Args, Auth, AccessCommands) -> case try_run_ctp(Args, Auth, AccessCommands) of @@ -283,7 +283,7 @@ call_command([CmdString | Args], Auth, AccessCommands) -> CmdStringU = ejabberd_regexp:greplace( list_to_binary(CmdString), <<"-">>, <<"_">>), Command = list_to_atom(binary_to_list(CmdStringU)), - case ejabberd_commands:get_command_format(Command) of + case ejabberd_commands:get_command_format(Command, Auth) of {error, command_unknown} -> {error, command_unknown}; {ArgsFormat, ResultFormat} -> @@ -412,7 +412,8 @@ get_list_commands() -> end. %% Return: {string(), [string()], string()} -tuple_command_help({Name, Args, Desc}) -> +tuple_command_help({Name, _Args, Desc}) -> + {Args, _} = ejabberd_commands:get_command_format(Name, admin), Arguments = [atom_to_list(ArgN) || {ArgN, _ArgF} <- Args], Prepend = case is_supported_args(Args) of true -> ""; @@ -723,12 +724,13 @@ print_usage_command(Cmd, C, MaxC, ShCode) -> tags = TagsAtoms, desc = Desc, longdesc = LongDesc, - args = ArgsDef, result = ResultDef} = C, NameFmt = [" ", ?B("Command Name"), ": ", Cmd, "\n"], %% Initial indentation of result is 13 = length(" Arguments: ") + {ArgsDef, _} = ejabberd_commands:get_command_format( + C#ejabberd_commands.name, admin), Args = [format_usage_ctype(ArgDef, 13) || ArgDef <- ArgsDef], ArgsMargin = lists:duplicate(13, $\s), ArgsListFmt = case Args of diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 61ce6473411..4c647ab5807 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -766,6 +766,9 @@ parse_auth(<<"Basic ", Auth64/binary>>) -> {User, <<$:, Pass/binary>>} = erlang:split_binary(Auth, Pos-1), {User, Pass} end; +parse_auth(<<"Bearer ", SToken/binary>>) -> + Token = str:strip(SToken), + {oauth, Token, []}; parse_auth(<<_/binary>>) -> undefined. parse_urlencoded(S) -> diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl new file mode 100644 index 00000000000..0295b9d87e2 --- /dev/null +++ b/src/ejabberd_oauth.erl @@ -0,0 +1,473 @@ +%%%------------------------------------------------------------------- +%%% File : ejabberd_oauth.erl +%%% Author : Alexey Shchepin +%%% Purpose : OAUTH2 support +%%% Created : 20 Mar 2015 by Alexey Shchepin +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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(ejabberd_oauth). + +-behaviour(gen_server). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, + handle_info/2, terminate/2, code_change/3]). + +-export([start/0, + start_link/0, + get_client_identity/2, + verify_redirection_uri/3, + authenticate_user/2, + authenticate_client/2, + verify_resowner_scope/3, + associate_access_code/3, + associate_access_token/3, + associate_refresh_token/3, + check_token/4, + check_token/2, + process/2, + opt_type/1]). + +-include("jlib.hrl"). + +-include("ejabberd.hrl"). +-include("logger.hrl"). + +-include("ejabberd_http.hrl"). +-include("ejabberd_web_admin.hrl"). + +-record(oauth_token, { + token = {<<"">>, <<"">>} :: {binary(), binary()}, + us = {<<"">>, <<"">>} :: {binary(), binary()}, + scope = [] :: [binary()], + expire :: integer() + }). + +-define(EXPIRE, 3600). + +start() -> + init_db(mnesia, ?MYNAME), + Expire = expire(), + application:set_env(oauth2, backend, ejabberd_oauth), + application:set_env(oauth2, expiry_time, Expire), + application:start(oauth2), + ChildSpec = {?MODULE, {?MODULE, start_link, []}, + temporary, 1000, worker, [?MODULE]}, + supervisor:start_child(ejabberd_sup, ChildSpec), + ok. + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + + +init([]) -> + erlang:send_after(expire() * 1000, self(), clean), + {ok, ok}. + +handle_call(_Request, _From, State) -> + {reply, bad_request, State}. + +handle_cast(_Msg, State) -> {noreply, State}. + +handle_info(clean, State) -> + {MegaSecs, Secs, MiniSecs} = os:timestamp(), + TS = 1000000 * MegaSecs + Secs, + F = fun() -> + Ts = mnesia:select( + oauth_token, + [{#oauth_token{expire = '$1', _ = '_'}, + [{'<', '$1', TS}], + ['$_']}]), + lists:foreach(fun mnesia:delete_object/1, Ts) + end, + mnesia:async_dirty(F), + erlang:send_after(trunc(expire() * 1000 * (1 + MiniSecs / 1000000)), + self(), clean), + {noreply, State}; +handle_info(_Info, State) -> {noreply, State}. + +terminate(_Reason, _State) -> ok. + +code_change(_OldVsn, State, _Extra) -> {ok, State}. + + +init_db(mnesia, _Host) -> + mnesia:create_table(oauth_token, + [{disc_copies, [node()]}, + {attributes, + record_info(fields, oauth_token)}]), + mnesia:add_table_copy(oauth_token, node(), disc_copies); +init_db(_, _) -> + ok. + + +get_client_identity(Client, Ctx) -> {ok, {Ctx, {client, Client}}}. + +verify_redirection_uri(_, _, Ctx) -> {ok, Ctx}. + +authenticate_user({User, Server}, {password, Password} = Ctx) -> + case ejabberd_auth:check_password(User, Server, Password) of + true -> + {ok, {Ctx, {user, User, Server}}}; + false -> + {error, badpass} + end. + +authenticate_client(Client, Ctx) -> {ok, {Ctx, {client, Client}}}. + +verify_resowner_scope({user, User, Server}, Scope, Ctx) -> + Cmds = ejabberd_commands:get_commands(), + Cmds1 = [sasl_auth | Cmds], + RegisteredScope = [atom_to_binary(C, utf8) || C <- Cmds1], + case oauth2_priv_set:is_subset(oauth2_priv_set:new(Scope), + oauth2_priv_set:new(RegisteredScope)) of + true -> + {ok, {Ctx, Scope}}; + false -> + {error, badscope} + end; +verify_resowner_scope(_, _, _) -> + {error, badscope}. + + +associate_access_code(AccessCode, Context, AppContext) -> + %put(?ACCESS_CODE_TABLE, AccessCode, Context), + {ok, AppContext}. + +associate_access_token(AccessToken, Context, AppContext) -> + {user, User, Server} = + proplists:get_value(<<"resource_owner">>, Context, <<"">>), + Scope = proplists:get_value(<<"scope">>, Context, []), + Expire = proplists:get_value(<<"expiry_time">>, Context, 0), + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + R = #oauth_token{ + token = AccessToken, + us = {LUser, LServer}, + scope = Scope, + expire = Expire + }, + mnesia:dirty_write(R), + {ok, AppContext}. + +associate_refresh_token(RefreshToken, Context, AppContext) -> + %put(?REFRESH_TOKEN_TABLE, RefreshToken, Context), + {ok, AppContext}. + + +check_token(User, Server, Scope, Token) -> + LUser = jlib:nodeprep(User), + LServer = jlib:nameprep(Server), + case catch mnesia:dirty_read(oauth_token, Token) of + [#oauth_token{us = {LUser, LServer}, + scope = TokenScope, + expire = Expire}] -> + {MegaSecs, Secs, _} = os:timestamp(), + TS = 1000000 * MegaSecs + Secs, + oauth2_priv_set:is_member( + Scope, oauth2_priv_set:new(TokenScope)) andalso + Expire > TS; + _ -> + false + end. + +check_token(Scope, Token) -> + case catch mnesia:dirty_read(oauth_token, Token) of + [#oauth_token{us = {LUser, LServer}, + scope = TokenScope, + expire = Expire}] -> + {MegaSecs, Secs, _} = os:timestamp(), + TS = 1000000 * MegaSecs + Secs, + case oauth2_priv_set:is_member( + Scope, oauth2_priv_set:new(TokenScope)) andalso + Expire > TS of + true -> {ok, LUser, LServer}; + false -> false + end; + _ -> + false + end. + + +expire() -> + ejabberd_config:get_option( + oauth_expire, + fun(I) when is_integer(I) -> I end, + ?EXPIRE). + +-define(DIV(Class, Els), + ?XAE(<<"div">>, [{<<"class">>, Class}], Els)). +-define(INPUTID(Type, Name, Value), + ?XA(<<"input">>, + [{<<"type">>, Type}, {<<"name">>, Name}, + {<<"value">>, Value}, {<<"id">>, Name}])). +-define(LABEL(ID, Els), + ?XAE(<<"label">>, [{<<"for">>, ID}], Els)). + +process(_Handlers, + #request{method = 'GET', q = Q, lang = Lang, + path = [_, <<"authorization_token">>]}) -> + ResponseType = proplists:get_value(<<"response_type">>, Q, <<"">>), + ClientId = proplists:get_value(<<"client_id">>, Q, <<"">>), + RedirectURI = proplists:get_value(<<"redirect_uri">>, Q, <<"">>), + Scope = proplists:get_value(<<"scope">>, Q, <<"">>), + State = proplists:get_value(<<"state">>, Q, <<"">>), + Form = + ?XAE(<<"form">>, + [{<<"action">>, <<"authorization_token">>}, + {<<"method">>, <<"post">>}], + [?LABEL(<<"username">>, [?CT(<<"User">>), ?C(<<": ">>)]), + ?INPUTID(<<"text">>, <<"username">>, <<"">>), + ?BR, + ?LABEL(<<"server">>, [?CT(<<"Server">>), ?C(<<": ">>)]), + ?INPUTID(<<"text">>, <<"server">>, <<"">>), + ?BR, + ?LABEL(<<"password">>, [?CT(<<"Password">>), ?C(<<": ">>)]), + ?INPUTID(<<"password">>, <<"password">>, <<"">>), + ?INPUT(<<"hidden">>, <<"response_type">>, ResponseType), + ?INPUT(<<"hidden">>, <<"client_id">>, ClientId), + ?INPUT(<<"hidden">>, <<"redirect_uri">>, RedirectURI), + ?INPUT(<<"hidden">>, <<"scope">>, Scope), + ?INPUT(<<"hidden">>, <<"state">>, State), + ?BR, + ?INPUTT(<<"submit">>, <<"">>, <<"Accept">>) + ]), + Top = + ?DIV(<<"section">>, + [?DIV(<<"block">>, + [?A(<<"https://www.ejabberd.im">>, + [?XA(<<"img">>, + [{<<"height">>, <<"32">>}, + {<<"src">>, logo()}])] + )])]), + Middle = + ?DIV(<<"white section">>, + [?DIV(<<"block">>, + [?XC(<<"h1">>, <<"Authorization request">>), + ?XE(<<"p">>, + [?C(<<"Application ">>), + ?XC(<<"em">>, ClientId), + ?C(<<" wants to access scope ">>), + ?XC(<<"em">>, Scope)]), + Form + ])]), + Bottom = + ?DIV(<<"section">>, + [?DIV(<<"block">>, + [?XAC(<<"a">>, + [{<<"href">>, <<"https://www.ejabberd.im">>}, + {<<"title">>, <<"ejabberd XMPP server">>}], + <<"ejabberd">>), + ?C(" is maintained by "), + ?XAC(<<"a">>, + [{<<"href">>, <<"https://www.process-one.net">>}, + {<<"title">>, <<"ProcessOne - Leader in Instant Messaging and Push Solutions">>}], + <<"ProcessOne">>) + ])]), + Body = ?DIV(<<"container">>, [Top, Middle, Bottom]), + ejabberd_web:make_xhtml(web_head(), [Body]); +process(_Handlers, + #request{method = 'POST', q = Q, lang = _Lang, + path = [_, <<"authorization_token">>]}) -> + ResponseType = proplists:get_value(<<"response_type">>, Q, <<"">>), + ClientId = proplists:get_value(<<"client_id">>, Q, <<"">>), + RedirectURI = proplists:get_value(<<"redirect_uri">>, Q, <<"">>), + SScope = proplists:get_value(<<"scope">>, Q, <<"">>), + Username = proplists:get_value(<<"username">>, Q, <<"">>), + Server = proplists:get_value(<<"server">>, Q, <<"">>), + Password = proplists:get_value(<<"password">>, Q, <<"">>), + State = proplists:get_value(<<"state">>, Q, <<"">>), + Scope = str:tokens(SScope, <<" ">>), + case oauth2:authorize_password({Username, Server}, + ClientId, + RedirectURI, + Scope, + {password, Password}) of + {ok, {_AppContext, Authorization}} -> + {ok, {_AppContext2, Response}} = + oauth2:issue_token(Authorization, none), + {ok, AccessToken} = oauth2_response:access_token(Response), + {ok, Type} = oauth2_response:token_type(Response), + {ok, Expires} = oauth2_response:expires_in(Response), + {ok, VerifiedScope} = oauth2_response:scope(Response), + %oauth2_wrq:redirected_access_token_response(ReqData, + % RedirectURI, + % AccessToken, + % Type, + % Expires, + % VerifiedScope, + % State, + % Context); + {302, [{<<"Location">>, + <>))/binary, + "&state=", State/binary>> + }], + ejabberd_web:make_xhtml([?XC(<<"h1">>, <<"302 Found">>)])}; + {error, Error} when is_atom(Error) -> + %oauth2_wrq:redirected_error_response( + % ReqData, RedirectURI, Error, State, Context) + {302, [{<<"Location">>, + <>, <<"302 Found">>)])} + end; +process(_Handlers, _Request) -> + ejabberd_web:error(not_found). + + + + +web_head() -> + [?XA(<<"meta">>, [{<<"http-equiv">>, <<"X-UA-Compatible">>}, + {<<"content">>, <<"IE=edge">>}]), + ?XA(<<"meta">>, [{<<"name">>, <<"viewport">>}, + {<<"content">>, + <<"width=device-width, initial-scale=1">>}]), + ?XC(<<"title">>, <<"Authorization request">>), + ?XC(<<"style">>, css()) + ]. + +css() -> + <<" + body { + margin: 0; + padding: 0; + + font-family: sans-serif; + color: #fff; + } + + h1 { + font-size: 3em; + color: #444; + } + + p { + line-height: 1.5em; + color: #888; + } + + a { + color: #fff; + } + a:hover, + a:active { + text-decoration: underline; + } + + em { + display: inline-block; + padding: 0 5px; + + background: #f4f4f4; + border-radius: 5px; + + font-style: normal; + font-weight: bold; + color: #444; + } + + form { + color: #444; + } + label { + display: block; + font-weight: bold; + } + + input[type=text], + input[type=password] { + margin-bottom: 1em; + padding: 0.4em; + + max-width: 330px; + width: 100%; + + border: 1px solid #c4c4c4; + border-radius: 5px; + outline: 0; + + font-size: 1.2em; + } + input[type=text]:focus, + input[type=password]:focus, + input[type=text]:active, + input[type=password]:active { + border-color: #41AFCA; + } + + input[type=submit] { + font-size: 1em; + } + + .container { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + + background: #424A55; + background-image: -webkit-linear-gradient(270deg, rgba(48,52,62,0) 24%, #30353e 100%); + background-image: linear-gradient(-180deg, rgba(48,52,62,0) 24%, #30353e 100%); + } + + .section { + padding: 3em; + } + .white.section { + background: #fff; + border-bottom: 4px solid #41AFCA; + } + + .white.section a { + text-decoration: none; + color: #41AFCA; + } + .white.section a:hover, + .white.section a:active { + text-decoration: underline; + } + + .container > .section { + background: #424A55; + } + + .block { + margin: 0 auto; + max-width: 900px; + width: 100%; + } +">>. + +logo() -> + <<"data:image/png;base64,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">>. + +opt_type(oauth_expire) -> + fun(I) when is_integer(I), I >= 0 -> I end; +opt_type(_) -> [oauth_expire]. diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 1d50bf45b56..db109920cbd 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -198,33 +198,35 @@ socket_type() -> raw. process(_, #request{method = 'POST', data = Data, opts = Opts}) -> AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts, fun(L) when is_list(L) -> L end, - []), - AccessCommands = lists:flatmap( - fun({Ac, AcOpts}) -> - Commands = gen_mod:get_opt( - commands, AcOpts, - fun(A) when is_atom(A) -> - A; - (L) when is_list(L) -> - true = lists:all( - fun is_atom/1, - L), - L - end, all), - CommOpts = gen_mod:get_opt( - options, AcOpts, - fun(L) when is_list(L) -> L end, - []), - [{Ac, Commands, CommOpts}]; - (Wrong) -> - ?WARNING_MSG("wrong options format for ~p: ~p", - [?MODULE, Wrong]), - [] - end, AccessCommandsOpts), - GetAuth = case [ACom || {Ac, _, _} = ACom <- AccessCommands, Ac /= all] of - [] -> false; - _ -> true - end, + undefined), + AccessCommands = + case AccessCommandsOpts of + undefined -> undefined; + _ -> + lists:flatmap( + fun({Ac, AcOpts}) -> + Commands = gen_mod:get_opt( + commands, AcOpts, + fun(A) when is_atom(A) -> + A; + (L) when is_list(L) -> + true = lists:all( + fun is_atom/1, + L), + L + end, all), + CommOpts = gen_mod:get_opt( + options, AcOpts, + fun(L) when is_list(L) -> L end, + []), + [{Ac, Commands, CommOpts}]; + (Wrong) -> + ?WARNING_MSG("wrong options format for ~p: ~p", + [?MODULE, Wrong]), + [] + end, AccessCommandsOpts) + end, + GetAuth = true, State = #state{access_commands = AccessCommands, get_auth = GetAuth}, case xml_stream:parse_element(Data) of {error, _} -> @@ -257,17 +259,22 @@ process(_, _) -> %% ----------------------------- get_auth(AuthList) -> - [User, Server, Password] = try get_attrs([user, server, - password], - AuthList) - of - [U, S, P] -> [U, S, P] - catch - exit:{attribute_not_found, Attr, _} -> - throw({error, missing_auth_arguments, - Attr}) - end, - {User, Server, Password}. + Admin = + case lists:keysearch(admin, 1, AuthList) of + {value, {admin, true}} -> true; + _ -> false + end, + try get_attrs([user, server, token], AuthList) of + [U, S, T] -> {U, S, {oauth, T}, Admin} + catch + exit:{attribute_not_found, _Attr, _} -> + try get_attrs([user, server, password], AuthList) of + [U, S, P] -> {U, S, P, Admin} + catch + exit:{attribute_not_found, Attr, _} -> + throw({error, missing_auth_arguments, Attr}) + end + end. %% ----------------------------- %% Handlers @@ -297,9 +304,9 @@ handler(#state{get_auth = true, auth = noauth} = State, {call, Method, [{struct, AuthList} | Arguments] = AllArgs}) -> try get_auth(AuthList) of - Auth -> - handler(State#state{get_auth = false, auth = Auth}, - {call, Method, Arguments}) + Auth -> + handler(State#state{get_auth = false, auth = Auth}, + {call, Method, Arguments}) catch {error, missing_auth_arguments, _Attr} -> handler(State#state{get_auth = false, auth = noauth}, @@ -328,7 +335,7 @@ handler(State, {call, Command, []}) -> handler(State, {call, Command, [{struct, []}]}); handler(State, {call, Command, [{struct, AttrL}]} = Payload) -> - case ejabberd_commands:get_command_format(Command) of + case ejabberd_commands:get_command_format(Command, State#state.auth) of {error, command_unknown} -> build_fault_response(-112, "Unknown call: ~p", [Payload]); diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl new file mode 100644 index 00000000000..d12af0c99e2 --- /dev/null +++ b/src/mod_http_api.erl @@ -0,0 +1,392 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_http_api.erl +%%% Author : Christophe romain +%%% Purpose : Implements REST API for ejabberd using JSON data +%%% Created : 15 Sep 2014 by Christophe Romain +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +%% Example config: +%% +%% in ejabberd_http listener +%% request_handlers: +%% "/api": mod_http_api +%% +%% Access rights are defined with: +%% commands_admin_access: configure +%% commands: +%% - add_commands: user +%% +%% +%% add_commands allow exporting a class of commands, from +%% open: methods is not risky and can be called by without any access check +%% restricted (default): the same, but will appear only in ejabberdctl list. +%% admin – auth is required with XMLRPC and HTTP API and checked for admin priviledges, works as usual in ejabberdctl. +%% user - can be used through XMLRPC and HTTP API, even by user. Only admin can use the commands for other users. +%% +%% Then to perform an action, send a POST request to the following URL: +%% http://localhost:5280/api/ + +-module(mod_http_api). + +-author('cromain@process-one.net'). + +-behaviour(gen_mod). + +-export([start/2, stop/1, process/2, mod_opt_type/1]). + +-include("ejabberd.hrl"). +-include("jlib.hrl"). +-include("logger.hrl"). +-include("ejabberd_http.hrl"). + +-define(CT_PLAIN, + {<<"Content-Type">>, <<"text/plain">>}). + +-define(CT_XML, + {<<"Content-Type">>, <<"text/xml; charset=utf-8">>}). + +-define(CT_JSON, + {<<"Content-Type">>, <<"application/json">>}). + +-define(AC_ALLOW_ORIGIN, + {<<"Access-Control-Allow-Origin">>, <<"*">>}). + +-define(AC_ALLOW_METHODS, + {<<"Access-Control-Allow-Methods">>, + <<"GET, POST, OPTIONS">>}). + +-define(AC_ALLOW_HEADERS, + {<<"Access-Control-Allow-Headers">>, + <<"Content-Type">>}). + +-define(AC_MAX_AGE, + {<<"Access-Control-Max-Age">>, <<"86400">>}). + +-define(OPTIONS_HEADER, + [?CT_PLAIN, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_METHODS, + ?AC_ALLOW_HEADERS, ?AC_MAX_AGE]). + +-define(HEADER(CType), + [CType, ?AC_ALLOW_ORIGIN, ?AC_ALLOW_HEADERS]). + +%% ------------------- +%% Module control +%% ------------------- + +start(_Host, _Opts) -> + ok. + +stop(_Host) -> + ok. + + +%% ---------- +%% basic auth +%% ---------- + +check_permissions(#request{auth = HTTPAuth, headers = Headers}, Command) + when HTTPAuth /= undefined -> + case catch binary_to_existing_atom(Command, utf8) of + Call when is_atom(Call) -> + Admin = + case lists:keysearch(<<"X-Admin">>, 1, Headers) of + {value, {_, <<"true">>}} -> true; + _ -> false + end, + Auth = + case HTTPAuth of + {SJID, Pass} -> + case jlib:string_to_jid(SJID) of + #jid{user = User, server = Server} -> + case ejabberd_auth:check_password(User, Server, Pass) of + true -> {ok, {User, Server, Pass, Admin}}; + false -> false + end; + _ -> + false + end; + {oauth, Token, _} -> + case ejabberd_oauth:check_token(Command, Token) of + {ok, User, Server} -> + {ok, {User, Server, {oauth, Token}, Admin}}; + false -> + false + end; + _ -> + false + end, + case Auth of + {ok, A} -> {allowed, Call, A}; + _ -> unauthorized_response() + end; + _ -> + unauthorized_response() + end; +check_permissions(_, _Command) -> + unauthorized_response(). + +%% ------------------ +%% command processing +%% ------------------ + +process(_, #request{method = 'POST', data = <<>>}) -> + ?DEBUG("Bad Request: no data", []), + badrequest_response(); +process([Call], #request{method = 'POST', data = Data, ip = IP} = Req) -> + try + Args = case jiffy:decode(Data) of + List when is_list(List) -> List; + {List} when is_list(List) -> List; + Other -> [Other] + end, + log(Call, Args, IP), + case check_permissions(Req, Call) of + {allowed, Cmd, Auth} -> + {Code, Result} = handle(Cmd, Auth, Args), + json_response(Code, jiffy:encode(Result)); + ErrorResponse -> + ErrorResponse + end + catch _:Error -> + ?DEBUG("Bad Request: ~p", [Error]), + badrequest_response() + end; +process([Call], #request{method = 'GET', q = Data, ip = IP} = Req) -> + try + Args = case Data of + [{nokey, <<>>}] -> []; + _ -> Data + end, + log(Call, Args, IP), + case check_permissions(Req, Call) of + {allowed, Cmd, Auth} -> + {Code, Result} = handle(Cmd, Auth, Args), + json_response(Code, jiffy:encode(Result)); + ErrorResponse -> + ErrorResponse + end + catch _:Error -> + ?DEBUG("Bad Request: ~p", [Error]), + badrequest_response() + end; +process([], #request{method = 'OPTIONS', data = <<>>}) -> + {200, ?OPTIONS_HEADER, []}; +process(_Path, Request) -> + ?DEBUG("Bad Request: no handler ~p", [Request]), + badrequest_response(). + +%% ---------------- +%% command handlers +%% ---------------- + +% generic ejabberd command handler +handle(Call, Auth, Args) when is_atom(Call), is_list(Args) -> + case ejabberd_commands:get_command_format(Call, Auth) of + {ArgsSpec, _} when is_list(ArgsSpec) -> + Args2 = [{jlib:binary_to_atom(Key), Value} || {Key, Value} <- Args], + Spec = lists:foldr( + fun ({Key, binary}, Acc) -> + [{Key, <<>>}|Acc]; + ({Key, string}, Acc) -> + [{Key, <<>>}|Acc]; + ({Key, integer}, Acc) -> + [{Key, 0}|Acc]; + ({Key, {list, _}}, Acc) -> + [{Key, []}|Acc]; + ({Key, atom}, Acc) -> + [{Key, undefined}|Acc] + end, [], ArgsSpec), + handle2(Call, Auth, match(Args2, Spec)); + {error, Msg} -> + {400, Msg}; + _Error -> + {400, <<"Error">>} + end. + +handle2(Call, Auth, Args) when is_atom(Call), is_list(Args) -> + {ArgsF, _ResultF} = ejabberd_commands:get_command_format(Call, Auth), + ArgsFormatted = format_args(Args, ArgsF), + case ejabberd_command(Auth, Call, ArgsFormatted, 400) of + 0 -> {200, <<"OK">>}; + 1 -> {500, <<"500 Internal server error">>}; + 400 -> {400, <<"400 Bad Request">>}; + 404 -> {404, <<"404 Not found">>}; + Res -> format_command_result(Call, Auth, Res) + end. + +get_elem_delete(A, L) -> + case proplists:get_all_values(A, L) of + [Value] -> {Value, proplists:delete(A, L)}; + [_, _ | _] -> + %% Crash reporting the error + exit({duplicated_attribute, A, L}); + [] -> + %% Report the error and then force a crash + exit({attribute_not_found, A, L}) + end. + +format_args(Args, ArgsFormat) -> + {ArgsRemaining, R} = lists:foldl(fun ({ArgName, + ArgFormat}, + {Args1, Res}) -> + {ArgValue, Args2} = + get_elem_delete(ArgName, + Args1), + Formatted = format_arg(ArgValue, + ArgFormat), + {Args2, Res ++ [Formatted]} + end, + {Args, []}, ArgsFormat), + case ArgsRemaining of + [] -> R; + L when is_list(L) -> exit({additional_unused_args, L}) + end. + +format_arg({array, Elements}, + {list, {ElementDefName, ElementDefFormat}}) + when is_list(Elements) -> + lists:map(fun ({struct, [{ElementName, ElementValue}]}) when + ElementDefName == ElementName -> + format_arg(ElementValue, ElementDefFormat) + end, + Elements); +format_arg({array, [{struct, Elements}]}, + {list, {ElementDefName, ElementDefFormat}}) + when is_list(Elements) -> + lists:map(fun ({ElementName, ElementValue}) -> + true = ElementDefName == ElementName, + format_arg(ElementValue, ElementDefFormat) + end, + Elements); +format_arg({array, [{struct, Elements}]}, + {tuple, ElementsDef}) + when is_list(Elements) -> + FormattedList = format_args(Elements, ElementsDef), + list_to_tuple(FormattedList); +format_arg({array, Elements}, {list, ElementsDef}) + when is_list(Elements) and is_atom(ElementsDef) -> + [format_arg(Element, ElementsDef) + || Element <- Elements]; +format_arg(Arg, integer) when is_integer(Arg) -> Arg; +format_arg(Arg, binary) when is_list(Arg) -> process_unicode_codepoints(Arg); +format_arg(Arg, binary) when is_binary(Arg) -> Arg; +format_arg(Arg, string) when is_list(Arg) -> process_unicode_codepoints(Arg); +format_arg(Arg, string) when is_binary(Arg) -> Arg; +format_arg(undefined, binary) -> <<>>; +format_arg(undefined, string) -> <<>>; +format_arg(Arg, Format) -> + ?ERROR_MSG("don't know how to format Arg ~p for format ~p", [Arg, Format]), + error. + +process_unicode_codepoints(Str) -> + iolist_to_binary(lists:map(fun(X) when X > 255 -> unicode:characters_to_binary([X]); + (Y) -> Y + end, Str)). + +%% ---------------- +%% internal helpers +%% ---------------- + +match(Args, Spec) -> + [{Key, proplists:get_value(Key, Args, Default)} || {Key, Default} <- Spec]. + +ejabberd_command(Auth, Cmd, Args, Default) -> + case catch ejabberd_commands:execute_command(undefined, Auth, Cmd, Args) of + {'EXIT', _} -> Default; + {error, _} -> Default; + Result -> Result + end. + +format_command_result(Cmd, Auth, Result) -> + {_, ResultFormat} = ejabberd_commands:get_command_format(Cmd, Auth), + case {ResultFormat, Result} of + {{_, rescode}, V} when V == true; V == ok -> + {200, <<"">>}; + {{_, rescode}, _} -> + {500, <<"">>}; + {{_, restuple}, {V1, Text1}} when V1 == true; V1 == ok -> + {200, iolist_to_binary(Text1)}; + {{_, restuple}, {_, Text2}} -> + {500, iolist_to_binary(Text2)}; + {{_, {list, _}}, _V} -> + {_, L} = format_result(Result, ResultFormat), + {200, L}; + {{_, {tuple, _}}, _V} -> + {_, T} = format_result(Result, ResultFormat), + {200, T}; + _ -> + {200, {[format_result(Result, ResultFormat)]}} + end. + +format_result(Atom, {Name, atom}) -> + {jlib:atom_to_binary(Name), jlib:atom_to_binary(Atom)}; + +format_result(Int, {Name, integer}) -> + {jlib:atom_to_binary(Name), Int}; + +format_result(String, {Name, string}) -> + {jlib:atom_to_binary(Name), iolist_to_binary(String)}; + +format_result(Code, {Name, rescode}) -> + {jlib:atom_to_binary(Name), Code == true orelse Code == ok}; + +format_result({Code, Text}, {Name, restuple}) -> + {jlib:atom_to_binary(Name), + {[{<<"res">>, Code == true orelse Code == ok}, + {<<"text">>, iolist_to_binary(Text)}]}}; + +format_result(Els, {Name, {list, {_, {tuple, [{_, atom}, _]}} = Fmt}}) -> + {jlib:atom_to_binary(Name), {[format_result(El, Fmt) || El <- Els]}}; + +format_result(Els, {Name, {list, Def}}) -> + {jlib:atom_to_binary(Name), [element(2, format_result(El, Def)) || El <- Els]}; + +format_result(Tuple, {_Name, {tuple, [{_, atom}, ValFmt]}}) -> + {Name2, Val} = Tuple, + {_, Val2} = format_result(Val, ValFmt), + {jlib:atom_to_binary(Name2), Val2}; + +format_result(Tuple, {Name, {tuple, Def}}) -> + Els = lists:zip(tuple_to_list(Tuple), Def), + {jlib:atom_to_binary(Name), {[format_result(El, ElDef) || {El, ElDef} <- Els]}}; + +format_result(404, {_Name, _}) -> + "not_found". + +unauthorized_response() -> + {401, ?HEADER(?CT_XML), + #xmlel{name = <<"h1">>, attrs = [], + children = [{xmlcdata, <<"401 Unauthorized">>}]}}. + +badrequest_response() -> + {400, ?HEADER(?CT_XML), + #xmlel{name = <<"h1">>, attrs = [], + children = [{xmlcdata, <<"400 Bad Request">>}]}}. +json_response(Code, Body) when is_integer(Code) -> + {Code, ?HEADER(?CT_JSON), Body}. + +log(Call, Args, {Addr, Port}) -> + AddrS = jlib:ip_to_list({Addr, Port}), + ?INFO_MSG("Admin call ~s ~p from ~s:~p", [Call, Args, AddrS, Port]). + +mod_opt_type(access) -> + fun(Access) when is_atom(Access) -> Access end; +mod_opt_type(_) -> [access]. diff --git a/vars.config.in b/vars.config.in index 2cd5d8e9a6f..74904724aba 100644 --- a/vars.config.in +++ b/vars.config.in @@ -31,6 +31,7 @@ {elixir, @elixir@}. {lager, @lager@}. {iconv, @iconv@}. +{oauth, @oauth@}. %% Version {vsn, "@PACKAGE_VERSION@"}. From 5eab6e315e9390d918fa3e185ff679e1fb3b90c4 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 25 Sep 2015 16:08:34 +0200 Subject: [PATCH 269/695] Revert "Remove "--enable-json" flag" This reverts commit 5bb137940c11fbd5d0c4da493e3a4560fbfe2d97. This is needed for mod_http_api --- configure.ac | 15 ++++++++++++--- rebar.config.script | 4 ++++ rel/reltool.config.script | 1 + vars.config.in | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 69fd3cef52d..85d208c1008 100644 --- a/configure.ac +++ b/configure.ac @@ -108,10 +108,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools --enable-oauth (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools --enable-oauth (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true oauth=true ;; - no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false oauth=false ;; + yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true oauth=true ;; + no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false json=false redis=false elixir=false iconv=false debug=false lager=false tools=false oauth=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -195,6 +195,14 @@ AC_ARG_ENABLE(redis, *) AC_MSG_ERROR(bad value ${enableval} for --enable-redis) ;; esac],[if test "x$redis" = "x"; then redis=false; fi]) +AC_ARG_ENABLE(json, +[AC_HELP_STRING([--enable-json], [enable JSON support for mod_bosh (default: no)])], +[case "${enableval}" in + yes) json=true ;; + no) json=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-json) ;; +esac],[if test "x$json" = "x"; then json=false; fi]) + AC_ARG_ENABLE(elixir, [AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])], [case "${enableval}" in @@ -276,6 +284,7 @@ AC_SUBST(pam) AC_SUBST(zlib) AC_SUBST(riak) AC_SUBST(redis) +AC_SUBST(json) AC_SUBST(elixir) AC_SUBST(iconv) AC_SUBST(debug) diff --git a/rebar.config.script b/rebar.config.script index 2ecb39c2584..fb5f4126ef8 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -97,6 +97,8 @@ CfgDeps = lists:flatmap( [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; ({riak, true}) -> [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; + ({json, true}) -> + [{jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}]; ({elixir, true}) -> [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; @@ -142,6 +144,8 @@ CfgXrefs = lists:flatmap( ({riak, true}) -> % used in map-reduce function called from riak vm ["(\"riak_object\":_/_)"]; + ({json, false}) -> + ["(\"jiffy\":_/_)"]; ({zlib, false}) -> ["(\"ezlib\":_/_)"]; ({http, false}) -> diff --git a/rel/reltool.config.script b/rel/reltool.config.script index 7d495b8a403..09dd8365765 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -36,6 +36,7 @@ DepConfiguredApps = lists:flatmap( ({pam, true}) -> [p1_pam]; ({zlib, true}) -> [p1_zlib]; ({stun, true}) -> [p1_stun]; + ({json, true}) -> [jiffy]; ({iconv, true}) -> [p1_iconv]; ({lager, true}) -> [lager, goldrush]; ({lager, false}) -> [p1_logger]; diff --git a/vars.config.in b/vars.config.in index 74904724aba..bb5b2ae0cbb 100644 --- a/vars.config.in +++ b/vars.config.in @@ -28,6 +28,7 @@ {zlib, @zlib@}. {riak, @riak@}. {redis, @redis@}. +{json, @json@}. {elixir, @elixir@}. {lager, @lager@}. {iconv, @iconv@}. From e2cc45933fcb80e1c5cfa4f12436dba0b91ffdd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 25 Sep 2015 16:39:47 +0200 Subject: [PATCH 270/695] Enable oauth unconditionally --- configure.ac | 15 +++------------ rebar.config.script | 9 +++------ vars.config.in | 1 - 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 85d208c1008..d03b50718cf 100644 --- a/configure.ac +++ b/configure.ac @@ -108,10 +108,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools --enable-oauth (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true oauth=true ;; - no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false json=false redis=false elixir=false iconv=false debug=false lager=false tools=false oauth=false ;; + yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;; + no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false json=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -235,14 +235,6 @@ AC_ARG_ENABLE(lager, *) AC_MSG_ERROR(bad value ${enableval} for --enable-lager) ;; esac],[if test "x$lager" = "x"; then lager=true; fi]) -AC_ARG_ENABLE(oauth, -[AC_HELP_STRING([--enable-oauth], [enable oauth support (default: yes)])], -[case "${enableval}" in - yes) oauth=true ;; - no) oauth=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-oauth) ;; -esac],[if test "x$oauth" = "x"; then oauth=false; fi]) - AC_CONFIG_FILES([Makefile vars.config src/ejabberd.app.src]) @@ -290,6 +282,5 @@ AC_SUBST(iconv) AC_SUBST(debug) AC_SUBST(lager) AC_SUBST(tools) -AC_SUBST(oauth) AC_OUTPUT diff --git a/rebar.config.script b/rebar.config.script index fb5f4126ef8..0176db1750b 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -61,7 +61,9 @@ Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, {esip, ".*", {git, "https://github.com/processone/p1_sip"}}, {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, - {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}], + {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}, + {oauth2, ".*", {git, "https://github.com/IvanMartinez/oauth2.git"}}, + {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], ConfigureCmd = fun(Pkg, Flags) -> {'get-deps', @@ -112,11 +114,6 @@ CfgDeps = lists:flatmap( [{meck, "0.*", {git, "https://github.com/eproxus/meck"}}]; ({redis, true}) -> [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; - ({oauth, true}) -> - %% ejabberd oauth support does not depends directly on xmlrpc. - %% However, we include xmlrpc as it is convenient to document and test oauth - [{oauth2, ".*", {git, "https://github.com/IvanMartinez/oauth2.git"}}, - {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}]; (_) -> [] end, Cfg), diff --git a/vars.config.in b/vars.config.in index bb5b2ae0cbb..2ccd5c76f42 100644 --- a/vars.config.in +++ b/vars.config.in @@ -32,7 +32,6 @@ {elixir, @elixir@}. {lager, @lager@}. {iconv, @iconv@}. -{oauth, @oauth@}. %% Version {vsn, "@PACKAGE_VERSION@"}. From 1781a589296124a17422db594c1f19701fbb00df Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 25 Sep 2015 17:00:00 +0200 Subject: [PATCH 271/695] Strip Nick element in message stanzas sent to a room (#686) --- include/ns.hrl | 1 + src/mod_muc_room.erl | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/ns.hrl b/include/ns.hrl index 85cf762effb..eb4223d9d3d 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -152,3 +152,4 @@ -define(NS_CLIENT_STATE, <<"urn:xmpp:csi:0">>). -define(NS_STREAM_MGMT_2, <<"urn:xmpp:sm:2">>). -define(NS_STREAM_MGMT_3, <<"urn:xmpp:sm:3">>). +-define(NS_NICK, <<"http://jabber.org/protocol/nick">>). diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index b7621829252..39e045d9e64 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -972,7 +972,8 @@ process_groupchat_message(From, of drop -> {next_state, normal_state, StateData}; - NewPacket -> + NewPacket1 -> + NewPacket = xml:remove_subtags(NewPacket1, <<"nick">>, {<<"xmlns">>, ?NS_NICK}), send_multiple(jlib:jid_replace_resource(StateData#state.jid, FromNick), StateData#state.server_host, From 88a206400a2e5b84b7c2aa1429b8463f55ddcd5d Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Fri, 25 Sep 2015 19:47:27 +0300 Subject: [PATCH 272/695] Add oauth_access option --- src/ejabberd_oauth.erl | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl index 0295b9d87e2..c7138981fa0 100644 --- a/src/ejabberd_oauth.erl +++ b/src/ejabberd_oauth.erl @@ -125,10 +125,25 @@ get_client_identity(Client, Ctx) -> {ok, {Ctx, {client, Client}}}. verify_redirection_uri(_, _, Ctx) -> {ok, Ctx}. authenticate_user({User, Server}, {password, Password} = Ctx) -> - case ejabberd_auth:check_password(User, Server, Password) of - true -> - {ok, {Ctx, {user, User, Server}}}; - false -> + case jlib:make_jid(User, Server, <<"">>) of + #jid{} = JID -> + Access = + ejabberd_config:get_option( + {oauth_access, JID#jid.lserver}, + fun(A) when is_atom(A) -> A end, + none), + case acl:match_rule(JID#jid.lserver, Access, JID) of + allow -> + case ejabberd_auth:check_password(User, Server, Password) of + true -> + {ok, {Ctx, {user, User, Server}}}; + false -> + {error, badpass} + end; + deny -> + {error, badpass} + end; + error -> {error, badpass} end. @@ -470,4 +485,6 @@ logo() -> opt_type(oauth_expire) -> fun(I) when is_integer(I), I >= 0 -> I end; -opt_type(_) -> [oauth_expire]. +opt_type(oauth_access) -> + fun(A) when is_atom(A) -> A end; +opt_type(_) -> [oauth_expire, oauth_access]. From 846b520edc9e7efb295cbeacf818ac9de91b67d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 28 Sep 2015 10:08:15 +0200 Subject: [PATCH 273/695] oauth uses jiffy so fetch it unconditionally --- configure.ac | 15 +++------------ rebar.config.script | 5 +---- vars.config.in | 1 - 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index d03b50718cf..d30a490d080 100644 --- a/configure.ac +++ b/configure.ac @@ -108,10 +108,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-json --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true json=true elixir=true iconv=true debug=true lager=true tools=true ;; - no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false json=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; + yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; + no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -195,14 +195,6 @@ AC_ARG_ENABLE(redis, *) AC_MSG_ERROR(bad value ${enableval} for --enable-redis) ;; esac],[if test "x$redis" = "x"; then redis=false; fi]) -AC_ARG_ENABLE(json, -[AC_HELP_STRING([--enable-json], [enable JSON support for mod_bosh (default: no)])], -[case "${enableval}" in - yes) json=true ;; - no) json=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-json) ;; -esac],[if test "x$json" = "x"; then json=false; fi]) - AC_ARG_ENABLE(elixir, [AC_HELP_STRING([--enable-elixir], [enable Elixir support (default: no)])], [case "${enableval}" in @@ -276,7 +268,6 @@ AC_SUBST(pam) AC_SUBST(zlib) AC_SUBST(riak) AC_SUBST(redis) -AC_SUBST(json) AC_SUBST(elixir) AC_SUBST(iconv) AC_SUBST(debug) diff --git a/rebar.config.script b/rebar.config.script index 0176db1750b..64f0f63637b 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -62,6 +62,7 @@ Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}, + {jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}, {oauth2, ".*", {git, "https://github.com/IvanMartinez/oauth2.git"}}, {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], @@ -99,8 +100,6 @@ CfgDeps = lists:flatmap( [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; ({riak, true}) -> [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; - ({json, true}) -> - [{jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}]; ({elixir, true}) -> [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; @@ -141,8 +140,6 @@ CfgXrefs = lists:flatmap( ({riak, true}) -> % used in map-reduce function called from riak vm ["(\"riak_object\":_/_)"]; - ({json, false}) -> - ["(\"jiffy\":_/_)"]; ({zlib, false}) -> ["(\"ezlib\":_/_)"]; ({http, false}) -> diff --git a/vars.config.in b/vars.config.in index 2ccd5c76f42..2cd5d8e9a6f 100644 --- a/vars.config.in +++ b/vars.config.in @@ -28,7 +28,6 @@ {zlib, @zlib@}. {riak, @riak@}. {redis, @redis@}. -{json, @json@}. {elixir, @elixir@}. {lager, @lager@}. {iconv, @iconv@}. From cf975da8f29aab78befe0a1f7bd5d6e6c7dd42e3 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 28 Sep 2015 15:25:43 +0300 Subject: [PATCH 274/695] Update several commands for recent ejabberd_commands changes --- src/ejabberd_s2s.erl | 2 ++ src/ejabberd_sm.erl | 5 ++++- src/mod_admin_extra.erl | 15 ++++++++++++++- src/mod_muc_admin.erl | 1 + 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index ef17fc89f6d..b5604eb7c7e 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -531,6 +531,7 @@ commands() -> desc = "Number of incoming s2s connections on " "the node", + policy = admin, module = ?MODULE, function = incoming_s2s_number, args = [], result = {s2s_incoming, integer}}, #ejabberd_commands{name = outgoing_s2s_number, @@ -538,6 +539,7 @@ commands() -> desc = "Number of outgoing s2s connections on " "the node", + policy = admin, module = ?MODULE, function = outgoing_s2s_number, args = [], result = {s2s_outgoing, integer}}]. diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index e2590237441..cfaf24dfa45 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -763,18 +763,21 @@ commands() -> [#ejabberd_commands{name = connected_users, tags = [session], desc = "List all established sessions", + policy = admin, module = ?MODULE, function = connected_users, args = [], result = {connected_users, {list, {sessions, string}}}}, #ejabberd_commands{name = connected_users_number, tags = [session, stats], desc = "Get the number of established sessions", + policy = admin, module = ?MODULE, function = connected_users_number, args = [], result = {num_sessions, integer}}, #ejabberd_commands{name = user_resources, tags = [session], desc = "List user's connected resources", + policy = user, module = ?MODULE, function = user_resources, - args = [{user, binary}, {host, binary}], + args = [], result = {resources, {list, {resource, string}}}}, #ejabberd_commands{name = kick_user, tags = [session], diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 436108ead4f..30e2a32eb10 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -115,6 +115,7 @@ commands() -> #ejabberd_commands{name = num_active_users, tags = [accounts, stats], desc = "Get number of users active in the last days", + policy = admin, module = ?MODULE, function = num_active_users, args = [{host, binary}, {days, integer}], result = {users, integer}}, @@ -173,11 +174,13 @@ commands() -> result = {res, rescode}}, #ejabberd_commands{name = status_num_host, tags = [session, stats], desc = "Number of logged users with this status in host", + policy = admin, module = ?MODULE, function = status_num, args = [{host, binary}, {status, binary}], result = {users, integer}}, #ejabberd_commands{name = status_num, tags = [session, stats], desc = "Number of logged users with this status", + policy = admin, module = ?MODULE, function = status_num, args = [{status, binary}], result = {users, integer}}, @@ -361,8 +364,9 @@ commands() -> }}}, #ejabberd_commands{name = get_roster, tags = [roster], desc = "Get roster of a local user", + policy = user, module = ?MODULE, function = get_roster, - args = [{user, binary}, {host, binary}], + args = [], result = {contacts, {list, {contact, {tuple, [ {jid, string}, {nick, string}, @@ -456,6 +460,13 @@ commands() -> args = [{user, binary}, {host, binary}, {group, binary}, {grouphost, binary}], result = {res, rescode}}, + #ejabberd_commands{name = get_offline_count, + tags = [offline], + desc = "Get the number of unread offline messages", + policy = user, + module = mod_offline, function = get_queue_length, + args = [], + result = {res, integer}}, #ejabberd_commands{name = send_message, tags = [stanza], desc = "Send a message to a local or remote bare of full JID", module = ?MODULE, function = send_message, @@ -475,11 +486,13 @@ commands() -> #ejabberd_commands{name = stats, tags = [stats], desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds", + policy = admin, module = ?MODULE, function = stats, args = [{name, binary}], result = {stat, integer}}, #ejabberd_commands{name = stats_host, tags = [stats], desc = "Get statistical value for this host: registeredusers onlineusers", + policy = admin, module = ?MODULE, function = stats, args = [{name, binary}, {host, binary}], result = {stat, integer}} diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index b779f4e0b0c..923428b3fba 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -59,6 +59,7 @@ commands() -> [ #ejabberd_commands{name = muc_online_rooms, tags = [muc], desc = "List existing rooms ('global' to get all vhosts)", + policy = admin, module = ?MODULE, function = muc_online_rooms, args = [{host, binary}], result = {rooms, {list, {room, string}}}}, From d08f73da4734a8188b8ed674728dc5e60804aecb Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 29 Sep 2015 08:19:44 +0200 Subject: [PATCH 275/695] Recompile translations --- priv/msgs/ca.msg | 32 +- priv/msgs/ca.po | 137 ++++---- priv/msgs/cs.msg | 2 - priv/msgs/cs.po | 137 ++++---- priv/msgs/de.msg | 68 ++-- priv/msgs/de.po | 137 ++++---- priv/msgs/ejabberd.pot | 138 ++++---- priv/msgs/el.msg | 2 - priv/msgs/el.po | 137 ++++---- priv/msgs/eo.msg | 21 +- priv/msgs/eo.po | 137 ++++---- priv/msgs/es.msg | 1 + priv/msgs/es.po | 137 ++++---- priv/msgs/fr.msg | 29 +- priv/msgs/fr.po | 143 ++++---- priv/msgs/gl.msg | 2 - priv/msgs/gl.po | 137 ++++---- priv/msgs/he.msg | 3 +- priv/msgs/he.po | 137 ++++---- priv/msgs/id.msg | 2 - priv/msgs/id.po | 137 ++++---- priv/msgs/it.msg | 2 - priv/msgs/it.po | 137 ++++---- priv/msgs/ja.msg | 166 +++++----- priv/msgs/ja.po | 137 ++++---- priv/msgs/nl.msg | 28 +- priv/msgs/nl.po | 137 ++++---- priv/msgs/no.msg | 2 - priv/msgs/no.po | 137 ++++---- priv/msgs/pl.msg | 20 +- priv/msgs/pl.po | 143 ++++---- priv/msgs/pt-br.msg | 49 ++- priv/msgs/pt-br.po | 137 ++++---- priv/msgs/pt.msg | 1 - priv/msgs/pt.po | 137 ++++---- priv/msgs/ru.msg | 20 +- priv/msgs/ru.po | 724 +++++++++++++++++++++++------------------ priv/msgs/sk.msg | 2 - priv/msgs/sk.po | 137 ++++---- priv/msgs/sv.msg | 2 - priv/msgs/sv.po | 137 ++++---- priv/msgs/th.msg | 2 - priv/msgs/th.po | 137 ++++---- priv/msgs/tr.msg | 2 - priv/msgs/tr.po | 137 ++++---- priv/msgs/uk.msg | 2 - priv/msgs/uk.po | 137 ++++---- priv/msgs/vi.msg | 2 - priv/msgs/vi.po | 137 ++++---- priv/msgs/wa.msg | 2 - priv/msgs/wa.po | 137 ++++---- priv/msgs/zh.msg | 2 - priv/msgs/zh.po | 137 ++++---- 53 files changed, 2613 insertions(+), 2152 deletions(-) diff --git a/priv/msgs/ca.msg b/priv/msgs/ca.msg index fd45982668c..a9765c2ae1f 100644 --- a/priv/msgs/ca.msg +++ b/priv/msgs/ca.msg @@ -18,7 +18,7 @@ {"Allow users to query other users","Permetre que els usuaris fagen peticions a altres usuaris"}. {"Allow users to send invites","Permetre que els usuaris envien invitacions"}. {"Allow users to send private messages","Permetre que els usuaris envien missatges privats"}. -{"Allow visitors to change nickname","Permetre als visitants canviar el Nickname"}. +{"Allow visitors to change nickname","Permetre als visitants canviar el sobrenom"}. {"Allow visitors to send private messages to","Permetre als visitants enviar missatges privats a"}. {"Allow visitors to send status text in presence updates","Permetre als visitants enviar text d'estat en les actualitzacions de presència"}. {"Allow visitors to send voice requests","Permetre als visitants enviar peticions de veu"}. @@ -29,6 +29,7 @@ {"August","Agost"}. {"Backup","Guardar còpia de seguretat"}. {"Backup Management","Gestió de còpia de seguretat"}. +{"Backup of ~p","Còpia de seguretat de ~p"}. {"Backup to File at ","Desar còpia de seguretat a fitxer en "}. {"Bad format","Format erroni"}. {"Birthday","Aniversari"}. @@ -55,10 +56,10 @@ {"Country","Pais"}. {"CPU Time:","Temps de CPU"}. {"Database","Base de dades"}. +{"Database Tables at ~p","Taules de la base de dades en ~p"}. {"Database Tables Configuration at ","Configuració de la base de dades en "}. {"December","Decembre"}. {"Default users as participants","Els usuaris són participants per defecte"}. -{"Delete","Eliminar"}. {"Delete message of the day","Eliminar el missatge del dia"}. {"Delete message of the day on all hosts","Elimina el missatge del dis de tots els hosts"}. {"Delete Selected","Eliminar els seleccionats"}. @@ -75,6 +76,7 @@ {"Either approve or decline the voice request.","Aprova o denega la petició de veu"}. {"ejabberd IRC module","mòdul ejabberd IRC"}. {"ejabberd MUC module","mòdul ejabberd MUC"}. +{"ejabberd Multicast service","Servei de Multicast d'ejabberd"}. {"ejabberd Publish-Subscribe module","Mòdul ejabberd Publicar-Subscriure"}. {"ejabberd SOCKS5 Bytestreams module","mòdul ejabberd SOCKS5 Bytestreams"}. {"ejabberd vCard module","Mòdul ejabberd vCard"}. @@ -82,10 +84,11 @@ {"Elements","Elements"}. {"Email","Email"}. {"Enable logging","Habilitar el registre de la conversa"}. +{"Enable message archiving","Activar l'emmagatzematge de missatges"}. {"Encoding for server ~b","Codificació pel servidor ~b"}. {"End User Session","Finalitzar Sesió d'Usuari"}. {"Enter list of {Module, [Options]}","Introdueix llista de {mòdul, [opcions]}"}. -{"Enter nickname you want to register","Introdueix el nickname que vols registrar"}. +{"Enter nickname you want to register","Introdueix el sobrenom que vols registrar"}. {"Enter path to backup file","Introdueix ruta al fitxer de còpia de seguretat"}. {"Enter path to jabberd14 spool dir","Introdueix la ruta al directori de jabberd14 spools"}. {"Enter path to jabberd14 spool file","Introdueix ruta al fitxer jabberd14 spool"}. @@ -97,6 +100,7 @@ {"Error","Error"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Exemple: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Excloure Jabber IDs de la comprovació CAPTCHA"}. +{"Export all tables as SQL queries to a file:","Exporta totes les taules a un fitxer SQL:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportar dades de tots els usuaris del servidor a arxius PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportar dades d'usuaris d'un host a arxius PIEFXIS (XEP-0227):"}. {"Family Name","Cognom"}. @@ -161,6 +165,7 @@ {"Listened Ports at ","Ports a la escolta en "}. {"Listened Ports","Ports a l'escolta"}. {"List of modules to start","Llista de mòduls a iniciar"}. +{"List of rooms","Llista de sales"}. {"Low level update script","Script d'actualització de baix nivell"}. {"Make participants list public","Crear una llista de participants pública"}. {"Make room CAPTCHA protected","Crear una sala protegida per CAPTCHA"}. @@ -183,20 +188,24 @@ {"moderators only","només moderadors"}. {"Modified modules","Mòduls modificats"}. {"Module","Mòdul"}. +{"Modules at ~p","Mòduls en ~p"}. {"Modules","Mòduls"}. {"Monday","Dilluns"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Multi-Usuari Converses"}. {"Name:","Nom:"}. {"Name","Nom"}. {"Never","Mai"}. {"New Password:","Nova Contrasenya:"}. -{"Nickname","Nickname"}. -{"Nickname Registration at ","Registre del Nickname en "}. -{"Nickname ~s does not exist in the room","El Nickname ~s no existeix a la sala"}. +{"Nickname Registration at ","Registre del sobrenom en "}. +{"Nickname ~s does not exist in the room","El sobrenom ~s no existeix a la sala"}. +{"Nickname","Sobrenom"}. {"nobody","ningú"}. {"No body provided for announce message","No hi ha proveedor per al missatge anunci"}. {"No Data","No hi ha dades"}. {"Node ID","ID del Node"}. {"Node not found","Node no trobat"}. +{"Node ~p","Node ~p"}. {"Nodes","Nodes"}. {"No limit","Sense Llímit"}. {"None","Cap"}. @@ -236,6 +245,7 @@ {"Path to File","Ruta al fitxer"}. {"Pending","Pendent"}. {"Period: ","Període: "}. +{"Permanent rooms","Sales permanents"}. {"Persist items to storage","Persistir elements al guardar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Recorda que aquestes opcions només fan còpia de seguretat de la base de dades Mnesia. Si estàs utilitzant el mòdul d'ODBC també deus de fer una còpia de seguretat de la base de dades de SQL a part."}. @@ -253,6 +263,7 @@ {"Raw","en format text"}. {"Really delete message of the day?","Segur que vols eliminar el missatge del dia?"}. {"Register a Jabber account","Registrar un compte Jabber"}. +{"Registered nicknames","Sobrenoms registrats"}. {"Registered Users:","Usuaris registrats:"}. {"Registered Users","Usuaris registrats"}. {"Register","Registrar"}. @@ -329,15 +340,18 @@ {"There was an error changing the password: ","Hi ha hagut un error canviant la contrasenya: "}. {"There was an error creating the account: ","Hi ha hagut un error creant el compte: "}. {"There was an error deleting the account: ","Hi ha hagut un error esborrant el compte: "}. +{"This IP address is blacklisted in ~s","Esta adreça IP està a la llista negra en ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Això no distingeix majúscules de minúscules: macbeth es el mateix que MacBeth i Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Aquesta pàgina permet crear un compte Jabber en aquest servidor Jabber. El teu JID (Jabber IDentifier; Identificador Jabber) tindrà aquesta forma: usuari@servidor. Si us plau, llegeix amb cura les instruccions per emplenar correctament els camps."}. {"This page allows to unregister a Jabber account in this Jabber server.","Aquesta pàgina permet anul·lar el registre d'un compte Jabber en aquest servidor Jabber."}. -{"This room is not anonymous","Aquesta sala no és anònima"}. {"Thursday","Dijous"}. {"Time","Data"}. {"Time delay","Temps de retard"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Massa autenticacions (~p) han fallat des d'aquesta adreça IP (~s). L'adreça serà desbloquejada en ~s UTC"}. +{"Too many unacked stanzas","Massa missatges sense haver reconegut la seva recepció"}. {"To","Per a"}. {"To ~s","A ~s"}. +{"Total rooms","Nombre total de sales"}. {"Transactions Aborted:","Transaccions Avortades"}. {"Transactions Committed:","Transaccions Realitzades:"}. {"Transactions Logged:","Transaccions registrades"}. @@ -349,6 +363,7 @@ {"Update","Actualitzar"}. {"Update message of the day (don't send)","Actualitzar el missatge del dia (no enviar)"}. {"Update message of the day on all hosts (don't send)","Actualitza el missatge del dia en tots els hosts (no enviar)"}. +{"Update ~p","Actualitzar ~p"}. {"Update plan","Pla d'actualització"}. {"Update script","Script d'actualització"}. {"Uptime:","Temps en marxa"}. @@ -357,6 +372,7 @@ {"User Management","Gestió d'Usuaris"}. {"Username:","Nom d'usuari:"}. {"Users Last Activity","Última activitat d'usuari"}. +{"User ~s","Usuari ~s"}. {"Users","Usuaris"}. {"User","Usuari"}. {"Validate","Validar"}. @@ -368,7 +384,7 @@ {"Whether to allow subscriptions","Permetre subscripcions"}. {"You can later change your password using a Jabber client.","Podràs canviar la teva contrasenya més endavant utilitzant un client Jabber."}. {"You need a client that supports x:data and CAPTCHA to register","Necessites un client amb suport x:data i de CAPTCHA para poder registrar-te"}. -{"You need a client that supports x:data to register the nickname","Necessites un client amb suport x:data per a poder registrar el Nickname"}. +{"You need a client that supports x:data to register the nickname","Necessites un client amb suport x:data per a poder registrar el sobrenom"}. {"You need an x:data capable client to configure mod_irc settings","Necessites un client amb suport x:data per a configurar les opcions de mod_irc"}. {"You need an x:data capable client to configure room","Necessites un client amb suport x:data per a configurar la sala"}. {"You need an x:data capable client to search","Necessites un client amb suport x:data per a poder buscar"}. diff --git a/priv/msgs/ca.po b/priv/msgs/ca.po index d9a377a7651..ba23d682cd9 100644 --- a/priv/msgs/ca.po +++ b/priv/msgs/ca.po @@ -57,6 +57,26 @@ msgstr "Pàgina web del CAPTCHA" msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es vàlid." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Usuari" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Servidor:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Contrasenya" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -161,7 +181,7 @@ msgid "Show Integral Table" msgstr "Mostrar Taula Integral" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estadístiques" @@ -185,17 +205,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Usuaris registrats" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Usuari" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Contrasenya" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -945,7 +954,7 @@ msgstr "Codificació pel servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Sales de xat" @@ -962,7 +971,7 @@ msgstr "Registre del sobrenom en " msgid "Enter nickname you want to register" msgstr "Introdueix el sobrenom que vols registrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Sobrenom" @@ -971,24 +980,24 @@ msgstr "Sobrenom" msgid "ejabberd MUC module" msgstr "mòdul ejabberd MUC" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Multi-Usuari Converses" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Nombre total de sales" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Sales permanents" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Sobrenoms registrats" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Llista de sales" @@ -1128,184 +1137,184 @@ msgstr "Configuració de la sala" msgid "Room Occupants" msgstr "Nombre d'ocupants" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Només els moderadors i participants poden canviar l'assumpte d'aquesta sala" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Només els moderadors poden canviar l'assumpte d'aquesta sala" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no és vàlid" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "El sobrenom ~s no existeix a la sala" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiliació invàlida: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Rol invàlid: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Configuració de la sala ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Títol de la sala" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Descripció de la sala:" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Crear una sala persistent" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Crear una sala pública" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Crear una llista de participants pública" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Crear una sala amb contrasenya" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Número màxim d'ocupants" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Sense Llímit" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Presentar Jabber ID's reals a" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "només moderadors" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "qualsevol" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Crear una sala de \"només membres\"" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Crear una sala moderada" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Els usuaris són participants per defecte" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Permetre que els usuaris canviin el tema" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Permetre que els usuaris envien missatges privats" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Permetre als visitants enviar missatges privats a" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "ningú" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Permetre que els usuaris fagen peticions a altres usuaris" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Permetre que els usuaris envien invitacions" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permetre als visitants enviar text d'estat en les actualitzacions de " "presència" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Permetre als visitants canviar el sobrenom" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Permetre als visitants enviar peticions de veu" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Interval mínim entre peticions de veu (en segons)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Crear una sala protegida per CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Activar l'emmagatzematge de missatges" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excloure Jabber IDs de la comprovació CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Habilitar el registre de la conversa" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Necessites un client amb suport x:data per a configurar la sala" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Número d'ocupants" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privat" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Petició de veu" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Aprova o denega la petició de veu" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "JID del usuari " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Concedir veu a aquesta persona?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s et convida a la sala ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "la contrasenya és" diff --git a/priv/msgs/cs.msg b/priv/msgs/cs.msg index 3a6a6cd517e..63597b9b2ae 100644 --- a/priv/msgs/cs.msg +++ b/priv/msgs/cs.msg @@ -61,7 +61,6 @@ {"Delete message of the day on all hosts","Smazat zprávu dne na všech hostitelích"}. {"Delete message of the day","Smazat zprávu dne"}. {"Delete Selected","Smazat vybrané"}. -{"Delete","Smazat"}. {"Delete User","Smazat uživatele"}. {"Deliver event notifications","Doručovat upozornění na události"}. {"Deliver payloads with event notifications","Doručovat náklad s upozorněním na událost"}. @@ -332,7 +331,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Zde nezáleží na velikosti písmen: macbeth je stejný jako MacBeth a Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Na této stránce si můžete vytvořit účet na tomto serveru Jabberu. Vaše JID (Jabber IDentifikátor) bude mít tvar: uživatelskéjméno@server. Přečtěte si prosím pozorně instrukce pro vyplnění údajů."}. {"This page allows to unregister a Jabber account in this Jabber server.","Zde můžete zrušit registraci účtu na tomto serveru Jabberu."}. -{"This room is not anonymous","Tato místnost není anonymní"}. {"Thursday","Čtvrtek"}. {"Time","Čas"}. {"Time delay","Časový posun"}. diff --git a/priv/msgs/cs.po b/priv/msgs/cs.po index ad9901c2828..6e651729f00 100644 --- a/priv/msgs/cs.po +++ b/priv/msgs/cs.po @@ -49,6 +49,26 @@ msgstr "Webová stránka CAPTCHA" msgid "The CAPTCHA is valid." msgstr "CAPTCHA souhlasí." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Uživatel" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Heslo" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -153,7 +173,7 @@ msgid "Show Integral Table" msgstr "Zobrazit kompletní tabulku" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiky" @@ -177,17 +197,6 @@ msgstr "Hostitel" msgid "Registered Users" msgstr "Registrovaní uživatelé" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Uživatel" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Heslo" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -936,7 +945,7 @@ msgstr "Kódování pro server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Konference" @@ -952,7 +961,7 @@ msgstr "Registrace přezdívky na " msgid "Enter nickname you want to register" msgstr "Zadejte přezdívku, kterou chcete zaregistrovat" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Přezdívka" @@ -961,27 +970,27 @@ msgstr "Přezdívka" msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Konference" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "opustil(a) místnost" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrovaní uživatelé" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1121,181 +1130,181 @@ msgstr "Nastavení místnosti" msgid "Room Occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Jen moderátoři a účastníci mají povoleno měnit téma této místnosti" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Jen moderátoři mají povoleno měnit téma místnosti" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s je neplatné" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Přezdívka ~s v místnosti neexistuje" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Neplatné přiřazení: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Neplatná role: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Konfigurace místnosti ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Název místnosti" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Popis místnosti" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Nastavit místnost jako stálou" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Nastavit místnost jako veřejnou" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Nastavit seznam účastníků jako veřejný" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Chránit místnost heslem" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Odhalovat skutečná Jabber ID" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "moderátorům" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "každému" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Zpřístupnit místnost jen členům" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Nastavit místnost jako moderovanou" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Uživatelé jsou implicitně členy" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Povolit uživatelům měnit téma místnosti" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Povolit uživatelům odesílat soukromé zprávy" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Povolit návštěvníkům odesílat soukromé zprávy" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "nikdo" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Povolit uživatelům odesílat požadavky (query) ostatním uživatelům" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Povolit uživatelům posílání pozvánek" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Povolit návštěvníkům posílat stavové zprávy ve statusu" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Povolit návštěvníkům měnit přezdívku" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Povolit uživatelům posílat žádosti o voice práva" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimální interval mezi žádostmi o voice práva (v sekundách)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Chránit místnost pomocí CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Vyloučit Jabber ID z procesu CAPTCHA ověřování" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Zaznamenávat konverzace" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Ke konfiguraci místnosti potřebujete klienta podporujícího x:data" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "soukromá, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Žádost o voice práva" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Povolit nebo odmítnout voice žádost." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Jabber ID uživatele" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Udělit voice práva této osobě?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s vás zve do místnosti ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "heslo je" diff --git a/priv/msgs/de.msg b/priv/msgs/de.msg index a43e17f33f1..e3ca5906afe 100644 --- a/priv/msgs/de.msg +++ b/priv/msgs/de.msg @@ -7,7 +7,7 @@ {"Access Rules","Zugangsregeln"}. {"Action on user","Aktion auf Benutzer"}. {"Add Jabber ID","Jabber-ID hinzufügen"}. -{"Add New","Neue hinzufügen"}. +{"Add New","Neue(n) hinzufügen"}. {"Add User","Benutzer hinzufügen"}. {"Administration of ","Administration von "}. {"Administration","Verwaltung"}. @@ -18,7 +18,7 @@ {"Allow users to query other users","Erlaube Benutzern Informationen über andere Benutzer abzufragen"}. {"Allow users to send invites","Erlaube Benutzern Einladungen zu senden"}. {"Allow users to send private messages","Erlaube Benutzern private Nachrichten zu senden"}. -{"Allow visitors to change nickname","Erlaube Besuchern ihren Spitznamen zu ändern"}. +{"Allow visitors to change nickname","Erlaube Besuchern ihren Benutzernamen zu ändern"}. {"Allow visitors to send private messages to","Erlaube Besuchern das Senden von privaten Nachrichten an"}. {"Allow visitors to send status text in presence updates","Erlaube Besuchern einen Text bei Statusänderung zu senden"}. {"Allow visitors to send voice requests","Anfragen von Sprachrechten für Benutzer erlauben"}. @@ -29,6 +29,7 @@ {"August","August"}. {"Backup","Datensicherung"}. {"Backup Management","Datensicherungsverwaltung"}. +{"Backup of ~p","Sicherung von ~p"}. {"Backup to File at ","Datensicherung in die Datei "}. {"Bad format","Ungültiges Format"}. {"Birthday","Geburtsdatum"}. @@ -45,7 +46,7 @@ {"Choose a username and password to register with this server","Wählen sie zum Registrieren einen Benutzernamen und ein Passwort"}. {"Choose modules to stop","Wähle zu stoppende Module"}. {"Choose storage type of tables","Wähle Speichertyp der Tabellen"}. -{"Choose whether to approve this entity's subscription.","Wähle Sie, ob dieses Abonnement akzeptiert werden soll."}. +{"Choose whether to approve this entity's subscription.","Wählen sie, ob dieses Abonnement akzeptiert werden soll."}. {"City","Stadt"}. {"Commands","Befehle"}. {"Configuration","Konfiguration"}. @@ -55,10 +56,10 @@ {"Country","Land"}. {"CPU Time:","CPU-Zeit:"}. {"Database","Datenbank"}. +{"Database Tables at ~p","Datenbanktabellen auf ~p"}. {"Database Tables Configuration at ","Datenbanktabellen-Konfiguration auf "}. {"December","Dezember"}. {"Default users as participants","Benutzer werden standardmäßig vollwertige Teilnehmer"}. -{"Delete","Löschen"}. {"Delete message of the day","Lösche Nachricht des Tages"}. {"Delete message of the day on all hosts","Lösche Nachricht des Tages auf allen Hosts"}. {"Delete Selected","Markierte löschen"}. @@ -75,6 +76,7 @@ {"Either approve or decline the voice request.","Diese Anfrage für Sprachrechte bestätigen oder ablehnen."}. {"ejabberd IRC module","ejabberd IRC-Modul"}. {"ejabberd MUC module","ejabberd MUC-Modul"}. +{"ejabberd Multicast service","ejabberd Multicast Dienst"}. {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe-Modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5-Bytestreams-Modul"}. {"ejabberd vCard module","ejabberd vCard-Modul"}. @@ -82,27 +84,29 @@ {"Elements","Elemente"}. {"Email","E-Mail"}. {"Enable logging","Protokollierung aktivieren"}. +{"Enable message archiving","Nachrichtenarchivierung aktivieren"}. {"Encoding for server ~b","Kodierung für Server ~b"}. {"End User Session","Benutzer-Sitzung beenden"}. {"Enter list of {Module, [Options]}","Geben sie eine Liste bestehend aus {Modul, [Optionen]} ein"}. {"Enter nickname you want to register","Geben sie den zu registrierenden Benutzernamen ein"}. {"Enter path to backup file","Geben sie den Pfad zur Datensicherung ein"}. -{"Enter path to jabberd14 spool dir","Geben Sie den Pfad zum jabberd14-Spool-Verzeichnis ein"}. -{"Enter path to jabberd14 spool file","Geben Sie den Pfad zur jabberd14-Spool-Datei ein"}. +{"Enter path to jabberd14 spool dir","Geben sie den Pfad zum jabberd14-Spool-Verzeichnis ein"}. +{"Enter path to jabberd14 spool file","Geben sie den Pfad zur jabberd14-Spool-Datei ein"}. {"Enter path to text file","Geben sie den Pfad zur Textdatei ein"}. {"Enter the text you see","Geben sie den Text den sie sehen ein"}. {"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","Geben sie Benutzernamen und Kodierung für Verbindungen zu IRC Servern an. Drücken sie 'Mehr' um leere Felder hinzuzufügen. Drücken sie 'Beenden' um die Einstellungen zu speichern."}. -{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Geben Sie Benutzernamen und Zeichenkodierung für die Verbindung zum IRC-Server an"}. +{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Geben sie den Benutzernamen, Zeichenkodierung, Ports und Passwörter, die sie für die Verbindung zum IRC-Server verwenden wollen, an"}. {"Erlang Jabber Server","Erlang Jabber Server"}. {"Error","Fehler"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Beispiel: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Von CAPTCHA Überprüfung ausgeschlossene Jabber IDs"}. +{"Export all tables as SQL queries to a file:","Alle Tabellen als SQL Abfragen in eine Datei exportieren:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Alle Benutzerdaten des Servers in PIEFXIS Dateien (XEP-0227) exportieren:"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Alle Benutzerdaten des Hosts in PIEFXIS Dateien (XEP-0227) exportieren:"}. {"Family Name","Nachname"}. {"February","Februar"}. -{"Fill in fields to search for any matching Jabber User","Füllen Sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen"}. -{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Füllen Sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen (beenden Sie ein Feld mit *, um auch nach Teilzeichenketten zu suchen)"}. +{"Fill in fields to search for any matching Jabber User","Füllen sie die Felder aus, um nach bestimmten Jabber-Benutzern zu suchen"}. +{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","Füllen sie die Felder aus, um nach passenden Jabber-Benutzern zu suchen (beenden Sie ein Feld mit *, um auch nach Teilzeichenketten zu suchen)"}. {"Friday","Freitag"}. {"From ~s","Von ~s"}. {"From","Von"}. @@ -116,10 +120,10 @@ {"Group ","Gruppe "}. {"Groups","Gruppen"}. {"has been banned","wurde gebannt"}. -{"has been kicked because of an affiliation change","wurde wegen Änderung des Mitgliederstatus gekickt"}. -{"has been kicked because of a system shutdown","wurde wegen Systemabschaltung gekickt"}. -{"has been kicked because the room has been changed to members-only","wurde gekickt weil der Raum auf Nur-Mitglieder umgestellt wurde"}. -{"has been kicked","wurde gekickt"}. +{"has been kicked because of an affiliation change","wurde wegen Änderung des Mitgliederstatus entfernt"}. +{"has been kicked because of a system shutdown","wurde wegen einer Systemabschaltung entfernt"}. +{"has been kicked because the room has been changed to members-only","wurde entfernt weil der Raum auf Nur-Mitglieder umgestellt wurde"}. +{"has been kicked","wurde entfernt"}. {" has set the subject to: "," hat das Thema geändert auf: "}. {"Host","Host"}. {"If you don't see the CAPTCHA image here, visit the web page.","Wenn sie das CAPTCHA Bild nicht sehen, besuchen sie bitte die Webseite."}. @@ -161,6 +165,7 @@ {"Listened Ports","Aktive Ports"}. {"Listened Ports at ","Aktive Ports bei"}. {"List of modules to start","Liste der zu startenden Module"}. +{"List of rooms","Liste von Chaträumen"}. {"Low level update script","Low level Aktualisierungsscript"}. {"Make participants list public","Teilnehmerliste öffentlich machen"}. {"Make room CAPTCHA protected","Raum mit Verifizierung (Captcha) versehen"}. @@ -183,8 +188,11 @@ {"moderators only","ausschliesslich Moderatoren"}. {"Modified modules","Geänderte Module"}. {"Module","Modul"}. +{"Modules at ~p","Module bei ~p"}. {"Modules","Module"}. {"Monday","Montag"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Mehrbenutzer-Chat (MUC)"}. {"Name:","Name:"}. {"Name","Vorname"}. {"Never","Nie"}. @@ -193,10 +201,11 @@ {"Nickname Registration at ","Registrieren des Benutzernames auf"}. {"Nickname ~s does not exist in the room","Der Benutzername ~s existiert im Raum nicht"}. {"nobody","niemanden"}. -{"No body provided for announce message","Kein Text für die Ankündigung angegeben"}. +{"No body provided for announce message","Kein Text für die Ankündigungsnachricht angegeben"}. {"No Data","Keine Daten"}. {"Node ID","Knoten-ID"}. {"Node not found","Knoten nicht gefunden"}. +{"Node ~p","Knoten ~p"}. {"Nodes","Knoten"}. {"No limit","Keine Begrenzung"}. {"None","Keine"}. @@ -221,7 +230,7 @@ {"Only moderators and participants are allowed to change the subject in this room","Nur Moderatoren und Mitglieder dürfen das Thema in diesem Raum ändern"}. {"Only moderators are allowed to change the subject in this room","Nur Moderatoren dürfen das Thema in diesem Raum ändern"}. {"Options","Optionen"}. -{"Organization Name","Organisation"}. +{"Organization Name","Name der Organisation"}. {"Organization Unit","Abteilung"}. {"Outgoing s2s Connections:","Ausgehende s2s-Verbindungen:"}. {"Outgoing s2s Connections","Ausgehende s2s-Verbindungen"}. @@ -234,8 +243,9 @@ {"Password Verification","Passwort bestätigen"}. {"Path to Dir","Pfad zum Verzeichnis"}. {"Path to File","Pfad zur Datei"}. -{"Pending","anhängig"}. +{"Pending","Schwebend"}. {"Period: ","Zeitraum: "}. +{"Permanent rooms","permanente Chaträume"}. {"Persist items to storage","Einträge dauerhaft speichern"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Beachten sie, das diese Optionen nur die eingebaute Mnesia-Datenbank sichern. Wenn sie das ODBC-Modul verwenden, müssen sie die SQL-Datenbank manuell sichern."}. @@ -254,6 +264,7 @@ {"Really delete message of the day?","Die Nachricht des Tages wirklich löschen?"}. {"Register a Jabber account","Jabber Konto registrieren"}. {"Register","Anmelden"}. +{"Registered nicknames","Registrierte Benutzernamen"}. {"Registered Users:","Registrierte Benutzer:"}. {"Registered Users","Registrierte Benutzer"}. {"Registration in mod_irc for ","Registrierung in mod_irc für "}. @@ -295,10 +306,10 @@ {"Set message of the day and send to online users","Setze Nachricht des Tages und sende sie an alle angemeldeten Benutzer"}. {"Set message of the day on all hosts and send to online users","Setze Nachricht des Tages auf allen Hosts und sende sie an alle angemeldeten Benutzer"}. {"Shared Roster Groups","Gruppen der gemeinsamen Kontaktliste"}. -{"Show Integral Table","Vollständige Tabelle anzeigen"}. -{"Show Ordinary Table","Normale Tabelle anzeigen"}. +{"Show Integral Table","Integrale Tabelle anzeigen"}. +{"Show Ordinary Table","Gewöhnliche Tabelle anzeigen"}. {"Shut Down Service","Dienst herunterfahren"}. -{"~s invites you to the room ~s","~s lädt Sie in den Raum ~s ein"}. +{"~s invites you to the room ~s","~s lädt sie in den Raum ~s ein"}. {"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Einige Jabber Client Programme speichern ihr Passwort auf ihrem Computer. Verwenden sie diese Möglichkeit nur auf Computern, die sie als sicher einstufen."}. {"Specify the access model","Geben sie das Zugangsmodell an"}. {"Specify the event message type","Geben sie den Ereignis-Nachrichtentyp an"}. @@ -308,10 +319,10 @@ {"Start Modules","Module starten"}. {"Start","Starten"}. {"Statistics of ~p","Statistiken von ~p"}. -{"Statistics","Statistik"}. +{"Statistics","Statistiken"}. {"Stop Modules at ","Stoppe Module auf "}. {"Stop Modules","Module stoppen"}. -{"Stopped Nodes","Inaktive Knoten"}. +{"Stopped Nodes","Angehaltene Knoten"}. {"Stop","Stoppen"}. {"Storage Type","Speichertyp"}. {"Store binary backup:","Speichere binäre Sicherung:"}. @@ -326,18 +337,21 @@ {"The collections with which a node is affiliated","Sammlungen, mit denen ein Knoten verknüpft ist"}. {"the password is","das Passwort lautet"}. {"The password of your Jabber account was successfully changed.","Das Passwort von ihrem Jabber Konto wurde geändert."}. -{"There was an error changing the password: ","Es trat ein Fehler beim Ändern des Passworts auf:"}. -{"There was an error creating the account: ","Es trat ein Fehler beim erstellen des Kontos auf:"}. -{"There was an error deleting the account: ","Es trat ein Fehler beim Löschen des Kontos auf:"}. +{"There was an error changing the password: ","Es trat ein Fehler beim Ändern des Passworts auf: "}. +{"There was an error creating the account: ","Es trat ein Fehler beim Erstellen des Kontos auf: "}. +{"There was an error deleting the account: ","Es trat ein Fehler beim Löschen des Kontos auf: "}. +{"This IP address is blacklisted in ~s","Diese IP Adresse ist blockiert in ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Groß/Klein-Schreibung spielt hierbei keine Rolle: macbeth ist gleich MacBeth und Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Diese Seite erlaubt das anlegen eines Jabber Kontos auf diesem Jabber Server. Ihre JID (Jabber IDentifier) setzt sich folgend zusammen: benutzername@server. Bitte lesen sie die Hinweise genau durch, um die Felder korrekt auszufüllen."}. {"This page allows to unregister a Jabber account in this Jabber server.","Diese Seite erlaubt es, ein Jabber Konto von diesem Server zu entfernen."}. -{"This room is not anonymous","Dieser Raum ist nicht anonym"}. {"Thursday","Donnerstag"}. {"Time delay","Zeitverzögerung"}. {"Time","Zeit"}. {"To","An"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Zu viele (~p) fehlgeschlagene Anmeldeversuche von dieser IP Adresse (~s). Die Adresse wird bis ~s UTC blockiert."}. +{"Too many unacked stanzas","Zu viele unbestätigte Stanzas"}. {"To ~s","An ~s"}. +{"Total rooms","Alle Chaträume"}. {"Transactions Aborted:","Abgebrochene Transaktionen:"}. {"Transactions Committed:","Durchgeführte Transaktionen:"}. {"Transactions Logged:","Protokollierte Transaktionen:"}. @@ -349,6 +363,7 @@ {"Update","Aktualisieren"}. {"Update message of the day (don't send)","Aktualisiere Nachricht des Tages (nicht senden)"}. {"Update message of the day on all hosts (don't send)","Aktualisiere Nachricht des Tages auf allen Hosts (nicht senden)"}. +{"Update ~p","Aktualisierung ~p"}. {"Update plan","Aktualisierungsplan"}. {"Update script","Aktualisierungsscript"}. {"Uptime:","Betriebszeit:"}. @@ -358,13 +373,14 @@ {"User Management","Benutzerverwaltung"}. {"Username:","Benutzername:"}. {"Users","Benutzer"}. +{"User ~s","Benutzer ~s"}. {"Users Last Activity","Letzte Benutzeraktivität"}. {"Validate","Validieren"}. {"vCard User Search","vCard-Benutzer-Suche"}. {"Virtual Hosts","Virtuelle Hosts"}. {"Voice request","Anfrage für Sprachrechte"}. {"Wednesday","Mittwoch"}. -{"When to send the last published item","Wann soll das letzte veröffentlichte Objekt gesendet werden"}. +{"When to send the last published item","Wann das letzte veröffentlichte Objekt gesendet werden soll"}. {"Whether to allow subscriptions","Ob Abonnements erlaubt sind"}. {"You can later change your password using a Jabber client.","Sie können das Passwort später mit einem Jabber Client Programm ändern."}. {"You need a client that supports x:data and CAPTCHA to register","Sie benötigen einen Client, der x:data und CAPTCHA unterstützt, um Ihren Benutzernamen zu registrieren"}. diff --git a/priv/msgs/de.po b/priv/msgs/de.po index 56c55a798d6..ec5565dabb7 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -61,6 +61,26 @@ msgstr "CAPTCHA Webseite" msgid "The CAPTCHA is valid." msgstr "Die Verifizierung ist gültig." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Benutzer" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Passwort" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -165,7 +185,7 @@ msgid "Show Integral Table" msgstr "Integrale Tabelle anzeigen" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiken" @@ -189,17 +209,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Registrierte Benutzer" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Benutzer" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Passwort" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -950,7 +959,7 @@ msgstr "Kodierung für Server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Chaträume" @@ -968,7 +977,7 @@ msgstr "Registrieren des Benutzernames auf" msgid "Enter nickname you want to register" msgstr "Geben sie den zu registrierenden Benutzernamen ein" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Benutzername" @@ -977,24 +986,24 @@ msgstr "Benutzername" msgid "ejabberd MUC module" msgstr "ejabberd MUC-Modul" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Mehrbenutzer-Chat (MUC)" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Alle Chaträume" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "permanente Chaträume" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Registrierte Benutzernamen" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Liste von Chaträumen" @@ -1134,183 +1143,183 @@ msgstr "Raum-Konfiguration" msgid "Room Occupants" msgstr "Teilnehmer in diesem Raum" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Nur Moderatoren und Mitglieder dürfen das Thema in diesem Raum ändern" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Nur Moderatoren dürfen das Thema in diesem Raum ändern" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Die Jabber-ID ~s ist ungültig" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Der Benutzername ~s existiert im Raum nicht" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Ungültige Mitgliedschaft: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Ungültige Rolle: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Konfiguration für Raum ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Raumname" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Raum Beschreibung" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Raum persistent machen" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Raum öffentlich suchbar machen" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Teilnehmerliste öffentlich machen" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Raum mit Passwort schützen" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Maximale Anzahl von Teilnehmern" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Keine Begrenzung" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Echte Jabber-IDs anzeigen für" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "ausschliesslich Moderatoren" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "jeden" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Raum nur für Mitglieder zugänglich machen" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Raum moderiert machen" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Benutzer werden standardmäßig vollwertige Teilnehmer" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Erlaube Benutzern das Thema zu ändern" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Erlaube Benutzern private Nachrichten zu senden" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Erlaube Besuchern das Senden von privaten Nachrichten an" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "niemanden" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Erlaube Benutzern Informationen über andere Benutzer abzufragen" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Erlaube Benutzern Einladungen zu senden" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Erlaube Besuchern einen Text bei Statusänderung zu senden" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Erlaube Besuchern ihren Benutzernamen zu ändern" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Anfragen von Sprachrechten für Benutzer erlauben" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Mindestdauer zwischen Anfragen für Sprachrechte (in Sekunden)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Raum mit Verifizierung (Captcha) versehen" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Nachrichtenarchivierung aktivieren" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Von CAPTCHA Überprüfung ausgeschlossene Jabber IDs" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Protokollierung aktivieren" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um den Raum zu " "konfigurieren" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Anzahl der Teilnehmer" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Anfrage für Sprachrechte" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Diese Anfrage für Sprachrechte bestätigen oder ablehnen." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Benutzer JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Sprachrechte dieser Person erteilen?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s lädt sie in den Raum ~s ein" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "das Passwort lautet" diff --git a/priv/msgs/ejabberd.pot b/priv/msgs/ejabberd.pot index 877be09efad..c1862d97ae6 100644 --- a/priv/msgs/ejabberd.pot +++ b/priv/msgs/ejabberd.pot @@ -1,6 +1,6 @@ msgid "" msgstr "" -"Project-Id-Version: 15.07.57\n" +"Project-Id-Version: 15.07\n" "X-Language: Language Name\n" "Last-Translator: Translator name and contact method\n" "MIME-Version: 1.0\n" @@ -48,6 +48,25 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "" + +#: ejabberd_oauth.erl:256 +msgid "Server" +msgstr "" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -152,7 +171,7 @@ msgid "Show Integral Table" msgstr "" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "" @@ -176,17 +195,6 @@ msgstr "" msgid "Registered Users" msgstr "" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -913,7 +921,7 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "" @@ -929,7 +937,7 @@ msgstr "" msgid "Enter nickname you want to register" msgstr "" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "" @@ -938,24 +946,24 @@ msgstr "" msgid "ejabberd MUC module" msgstr "" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1095,181 +1103,181 @@ msgstr "" msgid "Room Occupants" msgstr "" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "" diff --git a/priv/msgs/el.msg b/priv/msgs/el.msg index e54a36b83f1..9a53ca7eb83 100644 --- a/priv/msgs/el.msg +++ b/priv/msgs/el.msg @@ -62,7 +62,6 @@ {"Delete message of the day","Διαγράψτε το μήνυμα της ημέρας"}. {"Delete Selected","Διαγραφή επιλεγμένων"}. {"Delete User","Διαγραφή Χρήστη"}. -{"Delete","Διαγραφή"}. {"Deliver event notifications","Κοινοποιήσεις παράδοσης"}. {"Deliver payloads with event notifications","Κοινοποιήσεις με την παράδοση φορτίων"}. {"Description:","Περιγραφή:"}. @@ -332,7 +331,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Ανεξαρτήτως με πεζά ή κεφαλαία: 'μιαλεξη' είναι το ίδιο με 'ΜιαΛέξη' και 'Μιαλέξη'."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Αυτή η σελίδα σας επιτρέπει να δημιουργήσετε ένα λογαριασμό Jabber σε αυτόν το διακομιστή Jabber. JID σας (Jabber Identifier) θα είναι της μορφής: όνομα_χρήστη@διακομιστής_Jabber. Παρακαλώ διαβάστε προσεκτικά τις οδηγίες για να συμπληρώσετε σωστά τα πεδία."}. {"This page allows to unregister a Jabber account in this Jabber server.","Η σελίδα αυτή δίνει τη δυνατότητα να καταργήσετε την καταχώρηση ενός λογαριασμό Jabber σε αυτόν το διακομιστή Jabber."}. -{"This room is not anonymous","Η αίθουσα αυτή δεν είναι ανώνυμη"}. {"Thursday","Πέμπτη"}. {"Time delay","Χρόνος καθυστέρησης"}. {"Time","Χρόνος"}. diff --git a/priv/msgs/el.po b/priv/msgs/el.po index 0e63ad5ed37..60b47dffcff 100644 --- a/priv/msgs/el.po +++ b/priv/msgs/el.po @@ -53,6 +53,26 @@ msgstr "Ιστοσελίδα CAPTCHA " msgid "The CAPTCHA is valid." msgstr "Το CAPTCHA είναι έγκυρο." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Χρήστης" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Διακομιστής:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Κωδικός Πρόσβασης" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -157,7 +177,7 @@ msgid "Show Integral Table" msgstr "Δείτε Ολοκληρωτικό Πίνακα" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Στατιστικές" @@ -181,17 +201,6 @@ msgstr "Κεντρικός Υπολογιστής" msgid "Registered Users" msgstr "Εγγεγραμμένοι Χρήστες" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Χρήστης" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Κωδικός Πρόσβασης" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -955,7 +964,7 @@ msgstr "Κωδικοποίηση για διακομιστή ~b" msgid "Server ~b" msgstr "Διακομιστής ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Αίθουσες σύνεδριασης" @@ -971,7 +980,7 @@ msgstr "Εγγραφή με Ψευδώνυμο στο " msgid "Enter nickname you want to register" msgstr "Πληκτρολογήστε το ψευδώνυμο που θέλετε να εγγραφείτε" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Ψευδώνυμο" @@ -980,27 +989,27 @@ msgstr "Ψευδώνυμο" msgid "ejabberd MUC module" msgstr "ejabberd MUC module" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Αίθουσες σύνεδριασης" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "εγκαταλείπει την αίθουσα" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Εγγεγραμμένοι Χρήστες" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1140,7 +1149,7 @@ msgstr "Διαμόρφωση Αίθουσας σύνεδριασης" msgid "Room Occupants" msgstr "Συμετεχόντες Αίθουσας σύνεδριασης" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1148,177 +1157,177 @@ msgstr "" "Μόνο οι συντονιστές και οι συμμετέχοντες μπορούν να αλλάξουν το θέμα αυτής " "της αίθουσας" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Μόνο οι συντονιστές μπορούν να αλλάξουν το θέμα αυτής της αίθουσας" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Η Jabber Ταυτότητα ~s είναι άκυρη" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Ψευδώνυμο ~s δεν υπάρχει σε αυτή την αίθουσα" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Άκυρη υπαγωγή: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Άκυρος ρόλο: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Διαμόρφωση Αίθουσας σύνεδριασης ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Τίτλος Αίθουσας " -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Περιγραφή Αίθουσας" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Κάντε αίθουσα μόνιμη" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Κάντε την δημόσια αναζήτηση δυνατή για αυτή την αίθουσα" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Κάντε κοινό τον κατάλογο συμμετεχόντων" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Κάντε την αίθουσα προστατεύομενη με κωδικό πρόσβασης" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Μέγιστος αριθμός συμετεχόντων" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Χωρίς όριο" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Παρούσιαση πραγματικών ταυτοτήτων Jabber σε" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "συντονιστές μόνο" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "οποιοσδήποτε" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Κάντε την αίθουσα μόνο για μέλη" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Κάντε την αίθουσα εποπτεύονομενη" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Προεπιλογη χρήστων ως συμμετέχοντες" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Επιτρέψετε στους χρήστες να αλλάζουν το θέμα" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν ιδιωτικά μηνύματα" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν ιδιωτικά μηνύματα σε" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "κανείς" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Επιτρέπστε στους χρήστες να ερωτούν άλλους χρήστες" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν προσκλήσεις" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Επιτρέψτε στους επισκέπτες να αποστέλλουν κατάσταση στις ενημερώσεις " "παρουσίας" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Επιτρέψετε στους επισκέπτες να αλλάζου ψευδώνυμο" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Επιτρέψτε στους επισκέπτες να στέλνουν αιτήματα φωνής" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ελάχιστο χρονικό διάστημα μεταξύ αιτημάτων φωνής (σε δευτερόλεπτα)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Κάντε την αίθουσα CAPTCHA προστατεύονομενη" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Εξαίρεση από τις ταυτότητες Jabber, ή CAPTCHA πρόκληση" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Ενεργοποίηση καταγραφής" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε την αίθουσα " -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Αριθμός συμετεχόντων" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "ιδιωτικό," -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Αίτημα φωνής" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Είτε εγκρίνετε ή απορρίψτε το αίτημα φωνής." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "JID Χρήστη" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Παραχώρηση φωνής σε αυτό το άτομο;" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s σας προσκαλεί στην αίθουσα ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "ο κωδικός πρόσβασης είναι" diff --git a/priv/msgs/eo.msg b/priv/msgs/eo.msg index 68f2a06c64b..32509b9bb60 100644 --- a/priv/msgs/eo.msg +++ b/priv/msgs/eo.msg @@ -29,6 +29,7 @@ {"August","Aŭgusto"}. {"Backup","Faru Sekurkopion"}. {"Backup Management","Mastrumado de sekurkopioj"}. +{"Backup of ~p","Sekurkopio de ~p"}. {"Backup to File at ","Faru sekurkopion je "}. {"Bad format","Malĝusta formo"}. {"Birthday","Naskiĝtago"}. @@ -55,10 +56,10 @@ {"Country","Lando"}. {"CPU Time:","CPU-tempo"}. {"Database","Datumbazo"}. +{"Database Tables at ~p","Datumbaz-tabeloj je ~p"}. {"Database Tables Configuration at ","Agordo de datumbaz-tabeloj je "}. {"December","Decembro"}. {"Default users as participants","Kutime farigu uzantojn kiel partpoprenantoj"}. -{"Delete","Forigu"}. {"Delete message of the day","Forigu mesaĝo de la tago"}. {"Delete message of the day on all hosts","Forigu mesaĝo de la tago je ĉiu gastigo"}. {"Delete Selected","Forigu elektata(j)n"}. @@ -75,6 +76,7 @@ {"Either approve or decline the voice request.","Ĉu aprobu, aŭ malaprobu la voĉ-peton."}. {"ejabberd IRC module","ejabberd IRC-modulo"}. {"ejabberd MUC module","ejabberd MUC-modulo"}. +{"ejabberd Multicast service","ejabberd Multicast-servo"}. {"ejabberd Publish-Subscribe module","ejabberd Public-Abonada modulo"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bajtfluo modulo"}. {"ejabberd vCard module","ejabberd vCard-modulo"}. @@ -82,6 +84,7 @@ {"Elements","Eroj"}. {"Email","Retpoŝto"}. {"Enable logging","Ŝaltu protokoladon"}. +{"Enable message archiving","Ŝaltu mesaĝo-arkivo"}. {"Encoding for server ~b","Enkodigo por servilo ~b"}. {"End User Session","Haltigu Uzant-seancon"}. {"Enter list of {Module, [Options]}","Enmetu liston de {Modulo, [Elektebloj]}"}. @@ -91,11 +94,13 @@ {"Enter path to jabberd14 spool file","Enmetu vojon al jabberd14-uzantdosiero"}. {"Enter path to text file","Enmetu vojon al plata teksto"}. {"Enter the text you see","Enmetu montrita teksto"}. +{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","Enmetu uzantnomon kaj enkodigojn kiujn vi volas uzi por konektoj al IRC-serviloj. Elektu 'Sekvonto' por ekhavi pliajn kampojn. Elektu 'Kompletigu' por savi agordojn."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Enmetu uzantnomon,j enkodigojn, pordojn kaj pasvortojn kiujn vi volas uzi por konektoj al IRC-serviloj"}. {"Erlang Jabber Server","Erlang-a Jabber-Servilo"}. {"Error","Eraro"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Ekzemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"sekreto\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.iutestservilo.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Esceptu Ĵabber-identigilojn je CAPTCHA-defio"}. +{"Export all tables as SQL queries to a file:","Eksportu ĉiuj tabeloj kiel SQL-informmendo al dosierujo:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Eksportu datumojn de ĉiuj uzantoj en servilo al PIEFXIS dosieroj (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Eksportu datumoj de uzantoj en gastigo al PIEFXIS dosieroj (XEP-0227):"}. {"Family Name","Lasta Nomo"}. @@ -160,6 +165,7 @@ {"Listened Ports at ","Atentataj pordoj je "}. {"Listened Ports","Atentataj pordoj"}. {"List of modules to start","Listo de moduloj por starti"}. +{"List of rooms","Listo de babilejoj"}. {"Low level update script","Bazanivela ĝisdatigo-skripto"}. {"Make participants list public","Farigu partoprento-liston publika"}. {"Make room CAPTCHA protected","Farigu babilejon protektata per CAPTCHA"}. @@ -182,8 +188,11 @@ {"moderators only","moderantoj sole"}. {"Modified modules","Ĝisdatigitaj moduloj"}. {"Module","Modulo"}. +{"Modules at ~p","Moduloj je ~p"}. {"Modules","Moduloj"}. {"Monday","Lundo"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Grupbabilado"}. {"Name:","Nomo:"}. {"Name","Nomo"}. {"Never","Neniam"}. @@ -196,6 +205,7 @@ {"No Data","Neniu datumo"}. {"Node ID","Nodo ID"}. {"Node not found","Nodo ne trovita"}. +{"Node ~p","Nodo ~p"}. {"Nodes","Nodoj"}. {"No limit","Neniu limigo"}. {"None","Nenio"}. @@ -235,6 +245,7 @@ {"Path to File","Voje de dosiero"}. {"Pending","Atendanta"}. {"Period: ","Periodo: "}. +{"Permanent rooms","Permanentaj babilejoj"}. {"Persist items to storage","Savu erojn en konservado"}. {"Ping","Sondaĵo"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Rimarku ke ĉi tiuj elektebloj nur sekurkopias la propran Mnesia-datumbazon. Se vi uzas la ODBC-modulon, vi ankaŭ devas sekurkopii tiujn SQL-datumbazoj aparte."}. @@ -252,6 +263,7 @@ {"Raw","Kruda"}. {"Really delete message of the day?","Ĉu vere forigi mesaĝon de la tago?"}. {"Register a Jabber account","Registru Ĵabber-konton"}. +{"Registered nicknames","Registritaj uzantnomoj"}. {"Registered Users:","Registritaj uzantoj:"}. {"Registered Users","Registritaj uzantoj"}. {"Register","Registru"}. @@ -328,15 +340,18 @@ {"There was an error changing the password: ","Estis eraro dum ŝanĝi de la pasvortro:"}. {"There was an error creating the account: ","Estis eraro dum kreado de la konto:"}. {"There was an error deleting the account: ","Estis eraro dum forigado de la konto:"}. +{"This IP address is blacklisted in ~s","Ĉi tiu IP-adreso estas barata in ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Uskleco ne signifas: macbeth estas la sama ol MacBeth kaj Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Jena paĝo ebligas kreadon de Ĵabber-konto je ĉi-Ĵabber-servilo. Via JID (Ĵabber-IDentigilo) estos ĉi-tiel: uzantnomo@servilo. Bonvolu legu bone la instrukciojn por korekta enmetigo de la kampoj. "}. {"This page allows to unregister a Jabber account in this Jabber server.","Jena pagxo ebligas malregistri Jxabber-konton je ĉi-servilo."}. -{"This room is not anonymous","Ĉi tiu babilejo ne estas anonima"}. {"Thursday","Ĵaŭdo"}. {"Time delay","Prokrasto"}. {"Time","Tempo"}. {"To","Ĝis"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Tro da malsukcesaj aŭtentprovoj (~p) de ĉi tiu IP-adreso (~s). La adreso estos malbarata je ~s UTC."}. +{"Too many unacked stanzas","Tro da neagnoskitaj stancoj"}. {"To ~s","Al ~s"}. +{"Total rooms","Babilejoj"}. {"Transactions Aborted:","Transakcioj nuligitaj"}. {"Transactions Committed:","Transakcioj enmetitaj"}. {"Transactions Logged:","Transakcioj protokolitaj"}. @@ -348,6 +363,7 @@ {"Update","Ĝisdatigu"}. {"Update message of the day (don't send)","Ŝanĝu mesaĝon de la tago (ne sendu)"}. {"Update message of the day on all hosts (don't send)","Ŝanĝu mesaĝon de la tago je ĉiu gastigo (ne sendu)"}. +{"Update ~p","Ĝisdatigu ~p-n"}. {"Update plan","Ĝisdatigo-plano"}. {"Update script","Ĝisdatigo-skripto"}. {"Uptime:","Daŭro de funkciado"}. @@ -357,6 +373,7 @@ {"Username:","Uzantnomo"}. {"Users Last Activity","Lasta aktiveco de uzanto"}. {"Users","Uzantoj"}. +{"User ~s","Uzanto ~s"}. {"User","Uzanto"}. {"Validate","Validigu"}. {"vCard User Search","Serĉado de vizitkartoj"}. diff --git a/priv/msgs/eo.po b/priv/msgs/eo.po index 59fd981c36a..ba0b8d91a12 100644 --- a/priv/msgs/eo.po +++ b/priv/msgs/eo.po @@ -53,6 +53,26 @@ msgstr "CAPTCHA teksaĵ-paĝo" msgid "The CAPTCHA is valid." msgstr "La CAPTCHA ĝustas" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Uzanto" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Servilo:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Pasvorto" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -157,7 +177,7 @@ msgid "Show Integral Table" msgstr "Montru integran tabelon" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistikoj" @@ -181,17 +201,6 @@ msgstr "Gastigo" msgid "Registered Users" msgstr "Registritaj uzantoj" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Uzanto" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Pasvorto" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -936,7 +945,7 @@ msgstr "Enkodigo por servilo ~b" msgid "Server ~b" msgstr "Servilo ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Babilejoj" @@ -952,7 +961,7 @@ msgstr "Kaŝnomo-registrado je " msgid "Enter nickname you want to register" msgstr "Enmetu kaŝnomon kiun vi volas registri" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Kaŝnomo" @@ -961,24 +970,24 @@ msgstr "Kaŝnomo" msgid "ejabberd MUC module" msgstr "ejabberd MUC-modulo" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Grupbabilado" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Babilejoj" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Permanentaj babilejoj" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Registritaj uzantnomoj" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Listo de babilejoj" @@ -1118,182 +1127,182 @@ msgstr "Babilejo-agordo" msgid "Room Occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Nur moderigantoj kaj partoprenantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Nur moderigantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s estas nevalida" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Kaŝnomo ~s ne ekzistas en la babilejo" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Nevalida aparteneco: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Nevalida rolo: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Agordo de babilejo ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Babilejo-nomo" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Babilejo-priskribo" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Farigu babilejon daŭra" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Farigu babilejon publike trovebla" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Farigu partoprento-liston publika" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Farigu babilejon protektata per pasvorto" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Limigo de nombro de partoprenantoj" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Neniu limigo" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Montru verajn Jabber ID-ojn al" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "moderantoj sole" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "iu ajn" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Farigu babilejon sole por membroj" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Farigu babilejon moderigata" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Kutime farigu uzantojn kiel partpoprenantoj" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Permesu uzantojn ŝanĝi la temon" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Permesu uzantojn sendi privatajn mesaĝojn" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Permesu uzantojn sendi privatajn mesaĝojn al" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "neniu" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Permesu uzantojn informpeti aliajn uzantojn" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Permesu uzantojn sendi invitojn" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Permesu al vizitantoj sendi statmesaĝon en ĉeest-sciigoj" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Permesu al vizitantoj ŝanĝi siajn kaŝnomojn" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Permesu uzantojn sendi voĉ-petojn" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimuma intervalo inter voĉ-petoj (je sekundoj)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Farigu babilejon protektata per CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Ŝaltu mesaĝo-arkivo" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Esceptu Ĵabber-identigilojn je CAPTCHA-defio" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Ŝaltu protokoladon" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Vi bezonas klienton kun x:data-funkcio por agordi la babilejon" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privata, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Voĉ-peto" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Ĉu aprobu, aŭ malaprobu la voĉ-peton." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Uzant-JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Koncedu voĉon al ĉi-persono?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s invitas vin al la babilejo ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "la pasvorto estas" diff --git a/priv/msgs/es.msg b/priv/msgs/es.msg index a5ebb840da3..8173df0e359 100644 --- a/priv/msgs/es.msg +++ b/priv/msgs/es.msg @@ -84,6 +84,7 @@ {"Elements","Elementos"}. {"Email","correo"}. {"Enable logging","Guardar históricos"}. +{"Enable message archiving","Activar el almacenamiento de mensajes"}. {"Encoding for server ~b","Codificación del servidor ~b"}. {"End User Session","Cerrar sesión de usuario"}. {"Enter list of {Module, [Options]}","Introduce lista de {módulo, [opciones]}"}. diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 2d8c2b46183..24eda50d4f0 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -56,6 +56,26 @@ msgstr "Página web de CAPTCHA" msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es válido." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Usuario" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Servidor:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Contraseña" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -160,7 +180,7 @@ msgid "Show Integral Table" msgstr "Mostrar Tabla Integral" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estadísticas" @@ -184,17 +204,6 @@ msgstr "Dominio" msgid "Registered Users" msgstr "Usuarios registrados" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Usuario" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Contraseña" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -946,7 +955,7 @@ msgstr "Codificación del servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salas de charla" @@ -963,7 +972,7 @@ msgstr "Registro del apodo en " msgid "Enter nickname you want to register" msgstr "Introduce el apodo que quieras registrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Apodo" @@ -972,24 +981,24 @@ msgstr "Apodo" msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Salas de Charla" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Salas totales" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Salas permanentes" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Apodos registrados" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lista de salas" @@ -1129,184 +1138,184 @@ msgstr "Configuración de la sala" msgid "Room Occupants" msgstr "Ocupantes de la sala" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Solo los moderadores y participantes pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no es válido" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "El apodo ~s no existe en la sala" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiliación no válida: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Rol no válido: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Configuración para la sala ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Título de la sala" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Descripción de la sala" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Sala públicamente visible" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "La lista de participantes es pública" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Proteger la sala con contraseña" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Sin límite" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Los Jabber ID reales pueden verlos" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "solo moderadores" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "cualquiera" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Sala sólo para miembros" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Sala moderada" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Los usuarios son participantes por defecto" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Permitir a los usuarios cambiar el asunto" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Permitir a los usuarios enviar mensajes privados" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Permitir a los visitantes enviar mensajes privados a" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "nadie" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Permitir a los usuarios consultar a otros usuarios" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Permitir a los usuarios enviar invitaciones" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir a los visitantes enviar texto de estado en las actualizaciones de " "presencia" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Permitir a los visitantes cambiarse el apodo" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Permitir a los visitantes enviar peticiones de voz" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalo mínimo entre peticiones de voz (en segundos)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Proteger la sala con CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Activar el almacenamiento de mensajes" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir Jabber IDs de las pruebas de CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Guardar históricos" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar la sala" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Petición de voz" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Aprueba o rechaza la petición de voz." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Jabber ID del usuario" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "¿Conceder voz a esta persona?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s te invita a la sala ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "la contraseña es" diff --git a/priv/msgs/fr.msg b/priv/msgs/fr.msg index af0d0b691e5..738abd648e3 100644 --- a/priv/msgs/fr.msg +++ b/priv/msgs/fr.msg @@ -19,13 +19,16 @@ {"Allow users to send invites","Permettre aux utilisateurs d'envoyer des invitations"}. {"Allow users to send private messages","Autoriser les utilisateurs à envoyer des messages privés"}. {"Allow visitors to change nickname","Autoriser les visiteurs à changer de pseudo"}. +{"Allow visitors to send private messages to","Autoriser les visiteurs à envoyer des messages privés"}. {"Allow visitors to send status text in presence updates","Autoriser les visiteurs à envoyer un message d'état avec leur présence"}. +{"Allow visitors to send voice requests","Permettre aux visiteurs d'envoyer des demandes de 'voice'"}. {"All Users","Tous les utilisateurs"}. {"Announcements","Annonces"}. {"anyone","tout le monde"}. {"April","Avril"}. {"August","Août"}. {"Backup Management","Gestion des sauvegardes"}. +{"Backup of ~p","Sauvegarde de ~p"}. {"Backup","Sauvegarde"}. {"Backup to File at ","Sauvegarde sur fichier sur "}. {"Bad format","Mauvais format"}. @@ -53,13 +56,13 @@ {"Country","Pays"}. {"CPU Time:","Temps CPU :"}. {"Database","Base de données"}. +{"Database Tables at ~p","Tables de base de données sur ~p"}. {"Database Tables Configuration at ","Configuration des tables de base de données sur "}. {"December","Décembre"}. {"Default users as participants","Les utilisateurs sont par défaut participant"}. {"Delete message of the day on all hosts","Supprimer le message du jour sur tous les domaines"}. {"Delete message of the day","Supprimer le message du jour"}. {"Delete Selected","Suppression des éléments sélectionnés"}. -{"Delete","Supprimer"}. {"Delete User","Supprimer l'utilisateur"}. {"Deliver event notifications","Envoyer les notifications d'événement"}. {"Deliver payloads with event notifications","Inclure le contenu du message avec la notification"}. @@ -70,8 +73,10 @@ {"Dump Backup to Text File at ","Enregistrer la sauvegarde dans un fichier texte sur "}. {"Dump to Text File","Sauvegarder dans un fichier texte"}. {"Edit Properties","Modifier les propriétés"}. +{"Either approve or decline the voice request.","Approuver ou refuser la demande de 'voice'"}. {"ejabberd IRC module","Module IRC ejabberd"}. {"ejabberd MUC module","Module MUC ejabberd"}. +{"ejabberd Multicast service","Service de Multidiffusion d'ejabberd"}. {"ejabberd Publish-Subscribe module","Module Publish-Subscribe d'ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","Module vCard ejabberd"}. @@ -79,6 +84,7 @@ {"Elements","Éléments"}. {"Email","Email"}. {"Enable logging","Activer l'archivage"}. +{"Enable message archiving","Activer l'archivage de messages"}. {"Encoding for server ~b","Codage pour le serveur ~b"}. {"End User Session","Terminer la session de l'utilisateur"}. {"Enter list of {Module, [Options]}","Entrez une liste de {Module, [Options]}"}. @@ -93,6 +99,8 @@ {"Erlang Jabber Server","Serveur Jabber Erlang"}. {"Error","Erreur"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Exemple: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. +{"Exclude Jabber IDs from CAPTCHA challenge","Exempter des Jabberd IDs du test CAPTCHA"}. +{"Export all tables as SQL queries to a file:","Exporter toutes les tables en tant que requêtes SQL vers un fichier:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exporter les données de tous les utilisateurs du serveur vers un fichier PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exporter les données utilisateurs d'un hôte vers un fichier PIEFXIS (XEP-0227):"}. {"Family Name","Nom de famille"}. @@ -108,6 +116,7 @@ {"Get User Last Login Time","Récupérer la dernière date de connexion de l'utilisateur"}. {"Get User Password","Récupérer le mot de passe de l'utilisateur"}. {"Get User Statistics","Récupérer les statistiques de l'utilisateur"}. +{"Grant voice to this person?","Accorder 'voice' à cet utilisateur"}. {"Group ","Groupe "}. {"Groups","Groupes"}. {"has been banned","a été banni"}. @@ -156,6 +165,7 @@ {"Listened Ports at ","Ports ouverts sur "}. {"Listened Ports","Ports ouverts"}. {"List of modules to start","Liste des modules à démarrer"}. +{"List of rooms","Liste des salons"}. {"Low level update script","Script de mise à jour de bas-niveau"}. {"Make participants list public","Rendre la liste des participants publique"}. {"Make room CAPTCHA protected","Protéger le salon par un CAPTCHA"}. @@ -174,11 +184,15 @@ {"Memory","Mémoire"}. {"Message body","Corps du message"}. {"Middle Name","Autre nom"}. +{"Minimum interval between voice requests (in seconds)","Intervalle minimum entre les demandes de 'voice' (en secondes)"}. {"moderators only","modérateurs seulement"}. {"Modified modules","Modules mis à jour"}. {"Module","Module"}. +{"Modules at ~p","Modules sur ~p"}. {"Modules","Modules"}. {"Monday","Lundi"}. +{"Multicast","Multidiffusion"}. +{"Multi-User Chat","Discussion de groupe"}. {"Name:","Nom :"}. {"Name","Nom"}. {"Never","Jamais"}. @@ -186,10 +200,12 @@ {"Nickname","Pseudo"}. {"Nickname Registration at ","Enregistrement d'un pseudo sur "}. {"Nickname ~s does not exist in the room","Le pseudo ~s n'existe pas dans ce salon"}. +{"nobody","personne"}. {"No body provided for announce message","Pas de corps de message pour l'annonce"}. {"No Data","Aucune information disponible"}. {"Node ID","Identifiant du nœud"}. {"Node not found","Noeud non trouvé"}. +{"Node ~p","Noeud ~p"}. {"Nodes","Noeuds"}. {"No limit","Pas de limite"}. {"None","Aucun"}. @@ -229,6 +245,7 @@ {"Path to File","Chemin vers le fichier"}. {"Pending","En suspens"}. {"Period: ","Période :"}. +{"Permanent rooms","Salons persistent"}. {"Persist items to storage","Stockage persistant des éléments"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Ces options sauvegardent uniquement la base de données interne Mnesia. Si vous utilisez le module ODBC vous devez sauvegarde votre base SQL séparément."}. @@ -246,6 +263,7 @@ {"Raw","Brut"}. {"Really delete message of the day?","Confirmer la suppression du message du jour ?"}. {"Register a Jabber account","Enregistrer un compte Jabber"}. +{"Registered nicknames","Pseudos enregistrés"}. {"Registered Users:","Utilisateurs enregistrés:"}. {"Registered Users","Utilisateurs enregistrés"}. {"Register","Enregistrer"}. @@ -322,15 +340,18 @@ {"There was an error changing the password: ","Il y a eu une erreur en changeant le mot de passe :"}. {"There was an error creating the account: ","Il y a eu une erreur en créant le compte :"}. {"There was an error deleting the account: ","Il y a eu une erreur en effaçant le compte :"}. +{"This IP address is blacklisted in ~s","Cette adresse IP est blacklistée dans ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","C'est insensible à la casse : macbeth est identique à MacBeth et Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Cette page permet de créer un compte Jabber sur ce serveur Jabber. Votre JID (Jabber IDentifier, identifiant Jabber) sera de la forme : nom@serveur. Prière de lire avec attention les instructions pour remplir correctement ces champs."}. {"This page allows to unregister a Jabber account in this Jabber server.","Cette page permet d'effacer un compte Jabber sur ce serveur Jabber."}. -{"This room is not anonymous","Ce salon n'est pas anonyme"}. {"Thursday","Jeudi"}. {"Time delay","Délais"}. {"Time","Heure"}. {"To","A"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Trop (~p) d'authentification ont échoué pour cette adresse IP (~s). L'adresse sera débloquée à ~s UTC"}. +{"Too many unacked stanzas","Trop de stanzas sans accusé de réception (ack)"}. {"To ~s","A ~s"}. +{"Total rooms","Nombre de salons"}. {"Transactions Aborted:","Transactions annulées :"}. {"Transactions Committed:","Transactions commitées :"}. {"Transactions Logged:","Transactions journalisées :"}. @@ -343,17 +364,21 @@ {"Update message of the day on all hosts (don't send)","Mettre à jour le message du jour sur tous les domaines (ne pas envoyer)"}. {"Update","Mettre à jour"}. {"Update plan","Plan de mise à jour"}. +{"Update ~p","Mise à jour de ~p"}. {"Update script","Script de mise à jour"}. {"Uptime:","Temps depuis le démarrage :"}. {"Use of STARTTLS required","L'utilisation de STARTTLS est impérative"}. +{"User JID","JID de l'utilisateur "}. {"User Management","Gestion des utilisateurs"}. {"Username:","Nom d'utilisateur :"}. {"Users Last Activity","Dernière activité des utilisateurs"}. +{"User ~s","Utilisateur ~s"}. {"Users","Utilisateurs"}. {"User","Utilisateur"}. {"Validate","Valider"}. {"vCard User Search","Recherche dans l'annnuaire"}. {"Virtual Hosts","Serveurs virtuels"}. +{"Voice request","Demande de 'voice'"}. {"Wednesday","Mercredi"}. {"When to send the last published item","A quel moment envoyer le dernier élément publié"}. {"Whether to allow subscriptions","Autoriser l'abonnement ?"}. diff --git a/priv/msgs/fr.po b/priv/msgs/fr.po index 84000a60a40..4d03a7845ba 100644 --- a/priv/msgs/fr.po +++ b/priv/msgs/fr.po @@ -57,6 +57,26 @@ msgstr "Page web de CAPTCHA" msgid "The CAPTCHA is valid." msgstr "Le CAPTCHA est valide" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Utilisateur" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Serveur :" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Mot de passe" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -127,7 +147,8 @@ msgstr "Serveurs virtuels" msgid "Users" msgstr "Utilisateurs" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 mod_configure.erl:524 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Utilisateurs en ligne" @@ -159,7 +180,8 @@ msgstr "Montrer la table ordinaire" msgid "Show Integral Table" msgstr "Montrer la table intégralement" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 mod_muc_admin.erl:246 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiques" @@ -183,17 +205,6 @@ msgstr "Serveur" msgid "Registered Users" msgstr "Utilisateurs enregistrés" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 mod_register.erl:262 -#: mod_vcard.erl:490 -msgid "User" -msgstr "Utilisateur" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Mot de passe" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -947,7 +958,7 @@ msgstr "Codage pour le serveur ~b" msgid "Server ~b" msgstr "Serveur ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salons de discussion" @@ -965,8 +976,8 @@ msgstr "Enregistrement d'un pseudo sur " msgid "Enter nickname you want to register" msgstr "Entrez le pseudo que vous souhaitez enregistrer" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 mod_vcard.erl:490 -#: mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Pseudo" @@ -974,24 +985,24 @@ msgstr "Pseudo" msgid "ejabberd MUC module" msgstr "Module MUC ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Discussion de groupe" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Nombre de salons" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Salons persistent" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Pseudos enregistrés" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Liste des salons" @@ -1131,7 +1142,7 @@ msgstr "Configuration du salon" msgid "Room Occupants" msgstr "Occupants du salon" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1139,177 +1150,177 @@ msgstr "" "Seuls les modérateurs et les participants peuvent changer le sujet dans ce " "salon" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Seuls les modérateurs peuvent changer le sujet dans ce salon" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Le Jabber ID ~s n'est pas valide" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Le pseudo ~s n'existe pas dans ce salon" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Affiliation invalide : ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Role invalide : ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Configuration pour le salon ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Titre du salon" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Description :" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Rendre le salon persistant" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Rendre le salon public" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Rendre la liste des participants publique" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Protéger le salon par mot de passe" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Nombre maximum d'occupants" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Pas de limite" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Rendre le Jabber ID réel visible pour" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "modérateurs seulement" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "tout le monde" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Réserver le salon aux membres uniquement" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Rendre le salon modéré" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Les utilisateurs sont par défaut participant" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Autoriser les utilisateurs à changer le sujet" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Autoriser les utilisateurs à envoyer des messages privés" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Autoriser les visiteurs à envoyer des messages privés" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "personne" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "" "Permettre aux utilisateurs d'envoyer des requêtes aux autres utilisateurs" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Permettre aux utilisateurs d'envoyer des invitations" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Autoriser les visiteurs à envoyer un message d'état avec leur présence" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Autoriser les visiteurs à changer de pseudo" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Permettre aux visiteurs d'envoyer des demandes de 'voice'" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalle minimum entre les demandes de 'voice' (en secondes)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Protéger le salon par un CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Activer l'archivage de messages" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Exempter des Jabberd IDs du test CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Activer l'archivage" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "Vous avez besoin d'un client supportant x:data pour configurer le salon" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Nombre d'occupants" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privé" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Demande de 'voice'" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Approuver ou refuser la demande de 'voice'" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "JID de l'utilisateur " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Accorder 'voice' à cet utilisateur" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s vous a invité dans la salle de discussion ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "le mot de passe est" diff --git a/priv/msgs/gl.msg b/priv/msgs/gl.msg index fb9b5b6fc09..ae5ece73012 100644 --- a/priv/msgs/gl.msg +++ b/priv/msgs/gl.msg @@ -50,7 +50,6 @@ {"Database Tables Configuration at ","Configuración de táboas da base de datos en "}. {"December","Decembro"}. {"Default users as participants","Os usuarios son participantes por defecto"}. -{"Delete","Eliminar"}. {"Delete message of the day","Borrar mensaxe do dia"}. {"Delete message of the day on all hosts","Borrar a mensaxe do día en todos os dominios"}. {"Delete Selected","Eliminar os seleccionados"}. @@ -299,7 +298,6 @@ {"The CAPTCHA is valid.","O CAPTCHA é válido."}. {"The collections with which a node is affiliated","As coleccións coas que un nodo está afiliado"}. {"the password is","a contrasinal é"}. -{"This room is not anonymous","Sala non anónima"}. {"Thursday","Xoves"}. {"Time","Data"}. {"Time delay","Atraso temporal"}. diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index df4e333bacd..50b23c1b348 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -49,6 +49,26 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é válido." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Usuario" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Servidor ~b" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Contrasinal" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -153,7 +173,7 @@ msgid "Show Integral Table" msgstr "Mostrar Táboa Integral" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" @@ -177,17 +197,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Usuarios rexistrados" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Usuario" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Contrasinal" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -943,7 +952,7 @@ msgstr "Codificación de servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salas de charla" @@ -961,7 +970,7 @@ msgstr "Rexistro do alcume en " msgid "Enter nickname you want to register" msgstr "Introduce o alcume que queiras rexistrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Alcume" @@ -970,27 +979,27 @@ msgstr "Alcume" msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Salas de charla" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "sae da sala" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Usuarios rexistrados" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1134,7 +1143,7 @@ msgstr "Configuración da Sala" msgid "Room Occupants" msgstr "Ocupantes da sala" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1142,179 +1151,179 @@ msgstr "" "Só os moderadores e os participantes se lles permite cambiar o tema nesta " "sala" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Só os moderadores están autorizados a cambiar o tema nesta sala" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s non é válido" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "O alcume ~s non existe na sala" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiliación non válida: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Rol non válido: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Configuración para a sala ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Descrición da sala" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Sala publicamente visible" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "A lista de participantes é pública" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Protexer a sala con contrasinal" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Sen límite" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Os Jabber ID reais poden velos" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "só moderadores" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "calquera" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Sala só para membros" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Facer sala moderada" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Os usuarios son participantes por defecto" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Permitir aos usuarios cambiar o asunto" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Permitir aos usuarios enviar mensaxes privadas" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir aos usuarios enviar mensaxes privadas" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Permitir aos usuarios consultar a outros usuarios" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Permitir aos usuarios enviar invitacións" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir aos visitantes enviar texto de estado nas actualizacións depresenza" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Permitir aos visitantes cambiarse o alcume" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir aos usuarios enviar invitacións" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Protexer a sala con CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Gardar históricos" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar a sala" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Usuario " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s invítache á sala ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "a contrasinal é" diff --git a/priv/msgs/he.msg b/priv/msgs/he.msg index b5b1eafff5b..ae1946cf9c4 100644 --- a/priv/msgs/he.msg +++ b/priv/msgs/he.msg @@ -83,7 +83,8 @@ {"ejabberd Web Admin","מנהל רשת ejabberd"}. {"Elements","אלמנטים"}. {"Email","דוא״ל"}. -{"Enable logging","אפשור רישום פעילות"}. +{"Enable logging","אפשר רישום פעילות"}. +{"Enable message archiving","אפשר אחסון הודעות"}. {"Encoding for server ~b","קידוד עבור שרת ~b"}. {"End User Session","סיים סשן משתמש"}. {"Enter list of {Module, [Options]}","הזן רשימה של {מודול, [אפשרויות]}"}. diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 2007c0c17ca..71cac1f8033 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -60,6 +60,26 @@ msgstr "עמוד רשת CAPTCHA" msgid "The CAPTCHA is valid." msgstr "‏CAPTCHA הינה בתוקף." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "משתמש" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "שרת:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "סיסמה" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -168,7 +188,7 @@ msgid "Show Integral Table" msgstr "הצג טבלה אינטגרלית" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "סטטיסטיקה" @@ -192,17 +212,6 @@ msgstr "מארח" msgid "Registered Users" msgstr "משתמשים רשומים" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "משתמש" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "סיסמה" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -962,7 +971,7 @@ msgstr "קידוד עבור שרת ~b" msgid "Server ~b" msgstr "שרת ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "חדרי שיחה" @@ -980,7 +989,7 @@ msgstr "רישום שם כינוי אצל " msgid "Enter nickname you want to register" msgstr "הזן שם כינוי אשר ברצונך לרושמו" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "שם כינוי" @@ -989,24 +998,24 @@ msgstr "שם כינוי" msgid "ejabberd MUC module" msgstr "מודול MUC של ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "שיחה מרובת משתמשים" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "חדרים סה״כ" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "חדרים קבועים" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "שמות כינוי רשומים" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "רשימה של חדרים" @@ -1146,187 +1155,187 @@ msgstr "תצורת חדר" msgid "Room Occupants" msgstr "נוכחי חדר" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "רק אחראים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "מזהה Jabber ‏~s הינו שגוי" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "שם כינוי ~s לא קיים בחדר" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "סינוף שגוי: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "תפקיד שגוי: ~s" # תצורה של חדר -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "תצורת חדר ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "כותרת חדר" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "תיאור חדר" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "הפוך חדר אל קבוע" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "הפוך חדר אל בר חיפוש פומבי" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "הפוך רשימת משתתפים אל פומבית" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "הפוך חדר אל מוגן במילת מעבר" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "מספר מרבי של נוכחים" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "ללא הגבלה" # הצג כתובות JID ממשיות ל -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "הצג כתובות JID ממשיות" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "לאחראים בלבד" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "לכל אחד" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "הפוך חדר אל חברים-בלבד" # חדר מבוקר חדר תחת ביקורת -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "הפוך חדר אל מבוקר" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "משתמשים משתמטים כמשתתפים" # התרה -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "התר למשתמשים לשנות את הנושא" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "התר למשתמשים לשלוח הודעות פרטיות" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "התר למבקרים לשלוח הודעות פרטיות אל" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "אף אחד" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "התר למשתמשים לתשאל משתמשים אחרים" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "התר למשתמשים לשלוח הזמנות" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "התר למבקרים לשנות שם כינוי" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "התר למבקרים לשלוח בקשות ביטוי" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "תדירות מינימלית בין בקשות ביטוי (בשניות)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "הפוך חדר אל מוגן CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "אפשר אחסון הודעות" # זהויות -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "הוצא כתובות של Jabber מתוך אתגר CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "אפשר רישום פעילות" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר חדר" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "מספר של נוכחים" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "פרטי, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "בקשת ביטוי" # אשר או דחה -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "או שתאשר או שתדחה את בקשת הביטוי." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "‏JID משתמש" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "להעניק ביטוי לאישיות זו?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "‫~s מזמינך לחדר ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "הסיסמה היא" diff --git a/priv/msgs/id.msg b/priv/msgs/id.msg index c868cc5eb44..c66234d1cd3 100644 --- a/priv/msgs/id.msg +++ b/priv/msgs/id.msg @@ -56,7 +56,6 @@ {"Database Tables Configuration at ","Database Tabel Konfigurasi pada"}. {"December","Desember"}. {"Default users as participants","pengguna pertama kali masuk sebagai participant"}. -{"Delete","Hapus"}. {"Delete message of the day","Hapus pesan harian"}. {"Delete message of the day on all hosts","Hapus pesan harian pada semua host"}. {"Delete Selected","Hapus Yang Terpilih"}. @@ -325,7 +324,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Pada bagian ini huruf besar dan kecil tidak dibedakan: Misalnya macbeth adalah sama dengan MacBeth juga Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Halaman ini memungkinkan untuk membuat akun Jabber di layanan Jabber ini. JID Anda (Jabber Pengenal) akan berbentuk: namapengguna@layanan. Harap baca dengan seksama petunjuk-petunjuk untuk mengisi kolom dengan benar."}. {"This page allows to unregister a Jabber account in this Jabber server.","Pada bagian ini memungkinkan Anda untuk membatalkan pendaftaran akun Jabber pada layanan Jabber ini."}. -{"This room is not anonymous","Ruangan ini tidak dikenal"}. {"Thursday","Kamis"}. {"Time delay","Waktu tunda"}. {"Time","Waktu"}. diff --git a/priv/msgs/id.po b/priv/msgs/id.po index a027b2bd5bb..67b4018d188 100644 --- a/priv/msgs/id.po +++ b/priv/msgs/id.po @@ -55,6 +55,26 @@ msgstr "CAPTCHA laman web" msgid "The CAPTCHA is valid." msgstr "Captcha ini benar." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Pengguna" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Layanan:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Sandi" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -159,7 +179,7 @@ msgid "Show Integral Table" msgstr "Tampilkan Tabel Terpisah" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistik" @@ -183,17 +203,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Pengguna Terdaftar" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Pengguna" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Sandi" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -945,7 +954,7 @@ msgstr "Pengkodean untuk layanan ~b" msgid "Server ~b" msgstr "Layanan ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Ruangan Chat" @@ -961,7 +970,7 @@ msgstr "Pendaftaran Julukan pada" msgid "Enter nickname you want to register" msgstr "Masukkan nama julukan Anda jika ingin mendaftar" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nama Julukan" @@ -970,27 +979,27 @@ msgstr "Nama Julukan" msgid "ejabberd MUC module" msgstr "ejabberd MUC Module" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Ruangan Chat" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "meninggalkan ruangan" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Pengguna Terdaftar" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1130,7 +1139,7 @@ msgstr "Konfigurasi Ruangan" msgid "Room Occupants" msgstr "Penghuni Ruangan" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1138,179 +1147,179 @@ msgstr "" "Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan " "di ruangan ini" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "" "Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s tidak valid" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Nama Julukan ~s tidak berada di dalam ruangan" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiliasi tidak valid: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Peran tidak valid: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Pengaturan ruangan ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Nama Ruangan" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Keterangan ruangan" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Buat ruangan menjadi permanent" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Buat ruangan dapat dicari" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Buat daftar participant diketahui oleh public" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Buat ruangan yang dilindungi dengan kata sandi" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Maksimum Jumlah Penghuni" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Tidak terbatas" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Tampilkan Jabber ID secara lengkap" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "Hanya moderator" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "Siapapun" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Buat ruangan hanya untuk member saja" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Buat ruangan hanya untuk moderator saja" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "pengguna pertama kali masuk sebagai participant" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Perbolehkan pengguna untuk mengganti topik" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Perbolehkan pengguna untuk mengetahui pengguna lain" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Perbolehkan pengguna mengirimkan undangan" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Izinkan pengunjung untuk mengirim teks status terbaru" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Perbolehkan visitor mengganti nama julukan" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Perbolehkan pengguna mengirimkan undangan" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Buat ruangan dilindungi dengan CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Aktifkan catatan" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Jumlah Penghuni" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "pribadi, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Pengguna" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s mengundang anda ke ruangan ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "kata sandi yaitu:" diff --git a/priv/msgs/it.msg b/priv/msgs/it.msg index fdc78886272..b29c8fb0c64 100644 --- a/priv/msgs/it.msg +++ b/priv/msgs/it.msg @@ -58,7 +58,6 @@ {"Database Tables Configuration at ","Configurazione delle tabelle del database su "}. {"December","Dicembre"}. {"Default users as participants","Definire per default gli utenti come partecipanti"}. -{"Delete","Eliminare"}. {"Delete message of the day","Eliminare il messaggio del giorno (MOTD)"}. {"Delete message of the day on all hosts","Eliminare il messaggio del giorno (MOTD) su tutti gli host"}. {"Delete Selected","Eliminare gli elementi selezionati"}. @@ -332,7 +331,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Non fa differenza fra minuscolo e maiuscolo: macbeth, MacBeth e Macbeth si equivalgono."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Questa pagina consente di creare un account Jabber in questo server Jabber. Il tuo JID (Jabber IDentifier) avrà la forma: nome_utente@server. Leggi attentamente le istruzioni per compilare i campi correttamente."}. {"This page allows to unregister a Jabber account in this Jabber server.","Questa pagina consente di eliminare un account Jabber da questo server Jabber."}. -{"This room is not anonymous","Questa stanza non è anonima"}. {"Thursday","Giovedì"}. {"Time delay","Ritardo"}. {"Time","Ora"}. diff --git a/priv/msgs/it.po b/priv/msgs/it.po index 2da104fb6d0..1c703633dff 100644 --- a/priv/msgs/it.po +++ b/priv/msgs/it.po @@ -56,6 +56,26 @@ msgstr "Pagina web CAPTCHA" msgid "The CAPTCHA is valid." msgstr "Il CAPTCHA è valido." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Utente" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Password" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -160,7 +180,7 @@ msgid "Show Integral Table" msgstr "Mostrare la tabella integrale" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiche" @@ -184,17 +204,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Utenti registrati" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Utente" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Password" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -950,7 +959,7 @@ msgstr "Codifica per il server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Stanze" @@ -966,7 +975,7 @@ msgstr "Registrazione di un nickname su " msgid "Enter nickname you want to register" msgstr "Immettere il nickname che si vuole registrare" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nickname" @@ -975,27 +984,27 @@ msgstr "Nickname" msgid "ejabberd MUC module" msgstr "Modulo MUC per ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Stanze" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "esce dalla stanza" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Utenti registrati" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1135,7 +1144,7 @@ msgstr "Configurazione della stanza" msgid "Room Occupants" msgstr "Presenti nella stanza" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1143,179 +1152,179 @@ msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai " "moderatori e ai partecipanti" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Il Jabber ID ~s non è valido" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Il nickname ~s non esiste nella stanza" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Affiliazione non valida: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Ruolo non valido: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Configurazione per la stanza ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Titolo della stanza" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Descrizione della stanza" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Rendere la stanza persistente" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Rendere la sala visibile al pubblico" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Rendere pubblica la lista dei partecipanti" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Rendere la stanza protetta da password" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Numero massimo di occupanti" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Nessun limite" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Rendere visibile il Jabber ID reale a" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "moderatori soltanto" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "tutti" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Rendere la stanza riservata ai membri" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Rendere la stanza moderata" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Definire per default gli utenti come partecipanti" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Consentire agli utenti di cambiare l'oggetto" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Consentire agli utenti l'invio di messaggi privati" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Consentire agli ospiti l'invio di messaggi privati a" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "nessuno" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Consentire agli utenti query verso altri utenti" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Consentire agli utenti l'invio di inviti" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Consentire ai visitatori l'invio di testo sullo stato in aggiornamenti sulla " "presenza" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Consentire ai visitatori di cambiare il nickname" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Consentire agli ospiti l'invio di richieste di parola" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervallo minimo fra due richieste di parola (in secondi)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Rendere la stanza protetta da CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Escludi degli ID Jabber dal passaggio CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Abilitare i log" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "Per la configurazione della stanza è necessario un client che supporti x:data" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Numero di presenti" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privato, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Richiesta di parola" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Approva oppure respingi la richiesta di parola." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "JID utente" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Dare parola a questa persona?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s ti invita nella stanza ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "la password è" diff --git a/priv/msgs/ja.msg b/priv/msgs/ja.msg index 90469fd6456..d9dcf05751b 100644 --- a/priv/msgs/ja.msg +++ b/priv/msgs/ja.msg @@ -1,19 +1,17 @@ %% -*- coding: latin-1 -*- -{" has set the subject to: "," は件名を設定しました: "}. -{"A friendly name for the node","ノードのフレンドリネーム"}. {"Access Configuration","アクセス設定"}. {"Access Control List Configuration","アクセスコントロールリスト設定"}. -{"Access Control Lists","アクセスコントロールリスト"}. -{"Access Rules","アクセスルール"}. {"Access control lists","アクセスコントロールリスト"}. +{"Access Control Lists","アクセスコントロールリスト"}. {"Access rules","アクセスルール"}. +{"Access Rules","アクセスルール"}. {"Action on user","ユーザー操作"}. {"Add Jabber ID","Jabber ID を追加"}. {"Add New","新規追加"}. {"Add User","ユーザーを追加"}. {"Administration of ","管理: "}. {"Administration","管理"}. -{"All Users","全ユーザー"}. +{"A friendly name for the node","ノードのフレンドリネーム"}. {"All activity","すべて"}. {"Allow this Jabber ID to subscribe to this pubsub node?","この Jabber ID に、この pubsubノードの購読を許可しますか ?"}. {"Allow users to change the subject","ユーザーによる件名の変更を許可"}. @@ -24,17 +22,18 @@ {"Allow visitors to send private messages to","傍聴者によるプライベートメッセージの送信を次の相手に許可"}. {"Allow visitors to send status text in presence updates","傍聴者によるプレゼンス更新のステータス文の送信を許可"}. {"Allow visitors to send voice requests","傍聴者による発言権の要求を許可"}. +{"All Users","全ユーザー"}. {"Announcements","アナウンス"}. +{"anyone","誰にでも"}. {"April","4月"}. {"August","8月"}. +{"Backup","バックアップ"}. {"Backup Management","バックアップ管理"}. {"Backup of ~p","バックアップ: ~p"}. {"Backup to File at ","ファイルにバックアップ: "}. -{"Backup","バックアップ"}. {"Bad format","不正なフォーマット"}. {"Birthday","誕生日"}. {"CAPTCHA web page","CAPTCHA ウェブページ"}. -{"CPU Time:","CPU時間:"}. {"Change Password","パスワードを変更"}. {"Change User Password","パスワードを変更"}. {"Characters not allowed:","使用できない文字:"}. @@ -55,16 +54,16 @@ {"Connected Resources:","接続リソース:"}. {"Connections parameters","接続パラメーター"}. {"Country","国"}. -{"Database Tables Configuration at ","データーベーステーブル設定 "}. -{"Database Tables at ~p","データーベーステーブル: ~p"}. +{"CPU Time:","CPU時間:"}. {"Database","データーベース"}. +{"Database Tables at ~p","データーベーステーブル: ~p"}. +{"Database Tables Configuration at ","データーベーステーブル設定 "}. {"December","12月"}. {"Default users as participants","デフォルトのユーザーは参加者"}. -{"Delete Selected","選択した項目を削除"}. -{"Delete User","ユーザーを削除"}. {"Delete message of the day on all hosts","全ホストのお知らせメッセージを削除"}. {"Delete message of the day","お知らせメッセージを削除"}. -{"Delete","削除"}. +{"Delete Selected","選択した項目を削除"}. +{"Delete User","ユーザーを削除"}. {"Deliver event notifications","イベント通知を配送する"}. {"Deliver payloads with event notifications","イベント通知と同時にペイロードを配送する"}. {"Description:","説明:"}. @@ -75,9 +74,17 @@ {"Dump to Text File","テキストファイルに出力"}. {"Edit Properties","プロパティを編集"}. {"Either approve or decline the voice request.","発言権の要求を承認または却下します。"}. +{"ejabberd IRC module","ejabberd IRC module"}. +{"ejabberd MUC module","ejabberd MUCモジュール"}. +{"ejabberd Multicast service","ejabberdマルチキャストサービス"}. +{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe モジュール"}. +{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams モジュール"}. +{"ejabberd vCard module","ejabberd vCard モジュール"}. +{"ejabberd Web Admin","ejabberd ウェブ管理"}. {"Elements","要素"}. {"Email","メールアドレス"}. {"Enable logging","ロギングを有効"}. +{"Enable message archiving","メッセージアーカイブを有効化"}. {"Encoding for server ~b","サーバーのエンコーディング ~b"}. {"End User Session","エンドユーザーセッション"}. {"Enter list of {Module, [Options]}","{モジュール, [オプション]}のリストを入力してください"}. @@ -112,32 +119,40 @@ {"Grant voice to this person?","この人に発言権を与えますか ?"}. {"Group ","グループ"}. {"Groups","グループ"}. +{"has been banned","はバンされました"}. +{"has been kicked","はキックされました"}. +{"has been kicked because of an affiliation change","は分掌が変更されたためキックされました"}. +{"has been kicked because of a system shutdown","はシステムシャットダウンのためキックされました"}. +{"has been kicked because the room has been changed to members-only","はチャットルームがメンバー制に変更されたためキックされました"}. +{" has set the subject to: "," は件名を設定しました: "}. {"Host","ホスト"}. -{"IP addresses","IP アドレス"}. -{"IP","IP"}. -{"IRC Transport","IRCトランスポート"}. -{"IRC Username","IRC ユーザー名"}. -{"IRC channel (don't put the first #)","IRC チャンネル (先頭に#は不要)"}. -{"IRC server","IRC サーバー"}. -{"IRC settings","IRC 設定"}. -{"IRC username","IRC ユーザー名"}. {"If you don't see the CAPTCHA image here, visit the web page.","ここに CAPTCHA 画像が表示されない場合、ウェブページを参照してください。"}. {"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","別のポートやパスワード、文字エンコーディングを使用したい場合、'{\"irc server\", \"encoding\", port, \"password\"}' という形式のリストを入力してください。デフォルトでエンコーディングは \"~s\" を使用し、ポートは ~p、パスワードは空になっています。"}. {"Import Directory","ディレクトリインポート"}. {"Import File","ファイルからインポート"}. -{"Import User from File at ","ファイルからユーザーをインポート: "}. -{"Import Users From jabberd14 Spool Files","jabberd14 Spool ファイルからユーザーをインポート"}. -{"Import Users from Dir at ","ディレクトリからユーザーをインポート: "}. {"Import user data from jabberd14 spool file:","ユーザーデータを jabberd14 Spool ファイルからインポート:"}. +{"Import User from File at ","ファイルからユーザーをインポート: "}. {"Import users data from a PIEFXIS file (XEP-0227):","ユーザーデータを PIEFXIS ファイルからインポート (XEP-0227):"}. {"Import users data from jabberd14 spool directory:","ユーザーデータを jabberd14 Spool ディレクトリからインポート:"}. +{"Import Users from Dir at ","ディレクトリからユーザーをインポート: "}. +{"Import Users From jabberd14 Spool Files","jabberd14 Spool ファイルからユーザーをインポート"}. {"Invalid affiliation: ~s","無効な分掌です: ~s"}. {"Invalid role: ~s","無効な役です: ~s"}. +{"IP addresses","IP アドレス"}. +{"IP","IP"}. +{"IRC channel (don't put the first #)","IRC チャンネル (先頭に#は不要)"}. +{"IRC server","IRC サーバー"}. +{"IRC settings","IRC 設定"}. +{"IRC Transport","IRCトランスポート"}. +{"IRC username","IRC ユーザー名"}. +{"IRC Username","IRC ユーザー名"}. +{"is now known as","は名前を変更しました: "}. {"Jabber Account Registration","Jabber アカウント登録"}. -{"Jabber ID ~s is invalid","Jabber ID ~s は無効です"}. {"Jabber ID","Jabber ID"}. +{"Jabber ID ~s is invalid","Jabber ID ~s は無効です"}. {"January","1月"}. {"Join IRC channel","IRC チャンネルに参加"}. +{"joins the room","がチャットルームに参加しました"}. {"Join the IRC channel here.","この IRC チャンネルに参加します。"}. {"Join the IRC channel in this Jabber ID: ~s","Jabber ID: ~s でこの IRC チャンネルに参加"}. {"July","7月"}. @@ -146,9 +161,11 @@ {"Last login","最終ログイン"}. {"Last month","先月"}. {"Last year","去年"}. -{"List of modules to start","起動モジュールの一覧"}. +{"leaves the room","がチャットルームから退出しました"}. {"Listened Ports at ","Listen ポート "}. {"Listened Ports","Listen ポート"}. +{"List of modules to start","起動モジュールの一覧"}. +{"List of rooms","チャットルームの一覧"}. {"Low level update script","低レベル更新スクリプト"}. {"Make participants list public","参加者一覧を公開"}. {"Make room CAPTCHA protected","チャットルームを CAPTCHA で保護"}. @@ -158,9 +175,9 @@ {"Make room persistent","チャットルームを永続化"}. {"Make room public searchable","チャットルームを検索可"}. {"March","3月"}. +{"Maximum Number of Occupants","最大在室者数"}. {"Max # of items to persist","アイテムの最大保存数"}. {"Max payload size in bytes","最大ぺイロードサイズ (byte)"}. -{"Maximum Number of Occupants","最大在室者数"}. {"May","5月"}. {"Members:","メンバー:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","パスワードは記憶するか、紙に書いて安全な場所に保管してください。もしあなたがパスワードを忘れてしまった場合、Jabber ではパスワードのリカバリを自動的に行うことはできません。"}. @@ -168,27 +185,31 @@ {"Message body","本文"}. {"Middle Name","ミドルネーム"}. {"Minimum interval between voice requests (in seconds)","発言権の要求の最小時間間隔 (秒)"}. +{"moderators only","モデレーターにのみ"}. {"Modified modules","更新されたモジュール"}. {"Module","モジュール"}. -{"Modules at ~p","モジュール ~p"}. {"Modules","モジュール"}. +{"Modules at ~p","モジュール ~p"}. {"Monday","月曜日"}. +{"Multicast","マルチキャスト"}. +{"Multi-User Chat","マルチユーザーチャット"}. {"Name","名"}. {"Name:","名前:"}. {"Never","なし"}. {"New Password:","新しいパスワード:"}. +{"Nickname","ニックネーム"}. {"Nickname Registration at ","ニックネーム登録: "}. {"Nickname ~s does not exist in the room","ニックネーム ~s はこのチャットルームにいません"}. -{"Nickname","ニックネーム"}. -{"No Data","データなし"}. {"No body provided for announce message","アナウンスメッセージはありませんでした"}. -{"No limit","制限なし"}. -{"No resource provided","リソースが提供されませんでした"}. +{"nobody","誰にも許可しない"}. +{"No Data","データなし"}. {"Node ID","ノードID"}. {"Node not found","ノードが見つかりません"}. {"Node ~p","ノード ~p"}. {"Nodes","ノード"}. +{"No limit","制限なし"}. {"None","なし"}. +{"No resource provided","リソースが提供されませんでした"}. {"Not Found","見つかりません"}. {"Notify subscribers when items are removed from the node","アイテムがノードから消された時に購読者へ通知する"}. {"Notify subscribers when the node configuration changes","ノード設定に変更があった時に購読者へ通知する"}. @@ -197,53 +218,55 @@ {"Number of occupants","在室者の数"}. {"Number of online users","オンラインユーザー数"}. {"Number of registered users","登録ユーザー数"}. -{"OK","OK"}. {"October","10月"}. -{"Offline Messages","オフラインメッセージ"}. {"Offline Messages:","オフラインメッセージ:"}. +{"Offline Messages","オフラインメッセージ"}. +{"OK","OK"}. {"Old Password:","古いパスワード:"}. -{"Online Users","オンラインユーザー"}. -{"Online Users:","オンラインユーザー:"}. {"Online","オンライン"}. +{"Online Users:","オンラインユーザー:"}. +{"Online Users","オンラインユーザー"}. {"Only deliver notifications to available users","有効なユーザーにのみ告知を送信する"}. {"Only moderators and participants are allowed to change the subject in this room","モデレーターと参加者のみがチャットルームの件名を変更できます"}. {"Only moderators are allowed to change the subject in this room","モデレーターのみがチャットルームの件名を変更できます"}. {"Options","オプション"}. {"Organization Name","会社名"}. {"Organization Unit","部署名"}. -{"Outgoing s2s Connections","外向き s2s コネクション"}. {"Outgoing s2s Connections:","外向き s2s コネクション:"}. +{"Outgoing s2s Connections","外向き s2s コネクション"}. {"Outgoing s2s Servers:","外向き s2s サービス:"}. {"Packet","パケット"}. -{"Password Verification","パスワード (確認)"}. -{"Password Verification:","パスワード (確認):"}. -{"Password ~b","パスワード ~b"}. -{"Password","パスワード"}. {"Password:","パスワード"}. +{"Password","パスワード"}. +{"Password ~b","パスワード ~b"}. +{"Password Verification:","パスワード (確認):"}. +{"Password Verification","パスワード (確認)"}. {"Path to Dir","ディレクトリのパス"}. {"Path to File","ファイルのパス"}. {"Pending","保留"}. {"Period: ","期間: "}. +{"Permanent rooms","永続チャットルーム"}. {"Persist items to storage","アイテムをストレージに保存する"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","これらのオプションは組み込みの Mnesia データーベースのバックアップのみを行うことに注意してください。もし ODBC モジュールを使用している場合は、SQL データーベースのバックアップを別に行う必要があります。"}. {"Pong","Pong"}. -{"Port ~b","ポート ~b"}. {"Port","ポート"}. +{"Port ~b","ポート ~b"}. {"Present real Jabber IDs to","本当の Jabber ID を公開"}. +{"private, ","プライベート、"}. {"Protocol","プロトコル"}. -{"PubSub subscriber request","PubSub 購読者のリクエスト"}. {"Publish-Subscribe","Publish-Subscribe"}. +{"PubSub subscriber request","PubSub 購読者のリクエスト"}. {"Purge all items when the relevant publisher goes offline","公開者がオフラインになるときに、すべてのアイテムを削除"}. {"RAM and disc copy","RAM, ディスクコピー"}. {"RAM copy","RAM コピー"}. -{"RPC Call Error","RPC 呼び出しエラー"}. {"Raw","Raw"}. {"Really delete message of the day?","本当にお知らせメッセージを削除しますか ?"}. {"Register a Jabber account","Jabber アカウントを登録"}. -{"Register","登録"}. -{"Registered Users","登録ユーザー"}. +{"Registered nicknames","登録ニックネーム"}. {"Registered Users:","登録ユーザー:"}. +{"Registered Users","登録ユーザー"}. +{"Register","登録"}. {"Registration in mod_irc for ","mod_irc での登録: "}. {"Remote copy","リモートコピー"}. {"Remove All Offline Messages","すべてのオフラインメッセージを削除"}. @@ -253,20 +276,22 @@ {"Resources","リソース"}. {"Restart Service","サービスを再起動"}. {"Restart","再起動"}. +{"Restore","リストア"}. {"Restore Backup from File at ","ファイルからバックアップをリストア: "}. {"Restore binary backup after next ejabberd restart (requires less memory):","ejabberd の再起動時にバイナリバックアップからリストア (メモリ少):"}. {"Restore binary backup immediately:","直ちにバイナリバックアップからリストア:"}. {"Restore plain text backup immediately:","直ちにプレーンテキストバックアップからリストア:"}. -{"Restore","リストア"}. {"Room Configuration","チャットルームの設定"}. -{"Room Occupants","在室者"}. {"Room description","チャットルームの説明"}. +{"Room Occupants","在室者"}. {"Room title","チャットルームのタイトル"}. {"Roster groups allowed to subscribe","名簿グループは購読を許可しました"}. {"Roster of ","名簿: "}. {"Roster size","名簿サイズ"}. {"Roster","名簿"}. +{"RPC Call Error","RPC 呼び出しエラー"}. {"Running Nodes","起動ノード"}. +{"~s access rule configuration","~s アクセスルール設定"}. {"Saturday","土曜日"}. {"Script check","スクリプトチェック"}. {"Search Results for ","検索結果: "}. @@ -276,18 +301,20 @@ {"Send announcement to all users on all hosts","全ホストのユーザーにアナウンスを送信"}. {"Send announcement to all users","すべてのユーザーにアナウンスを送信"}. {"September","9月"}. -{"Server ~b","サーバー ~b"}. {"Server:","サーバー:"}. +{"Server ~b","サーバー ~b"}. {"Set message of the day and send to online users","お知らせメッセージを設定し、オンラインユーザーに送信"}. {"Set message of the day on all hosts and send to online users","全ホストのお知らせメッセージを設定し、オンラインユーザーに送信"}. {"Shared Roster Groups","共有名簿グループ"}. {"Show Integral Table","累積の表を表示"}. {"Show Ordinary Table","通常の表を表示"}. {"Shut Down Service","サービスを停止"}. +{"~s invites you to the room ~s","~s はあなたをチャットルーム ~s に招待しています"}. {"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Jabber クライアントはコンピューターにパスワードを記憶できます。コンピューターが安全であると信頼できる場合にのみ、この機能を使用してください。"}. {"Specify the access model","アクセスモデルを設定する"}. {"Specify the event message type","イベントメッセージ種別を設定"}. {"Specify the publisher model","公開モデルを指定する"}. +{"~s's Offline Messages Queue","~s' のオフラインメッセージキュー"}. {"Start Modules at ","モジュールを開始: "}. {"Start Modules","モジュールを起動"}. {"Start","開始"}. @@ -295,19 +322,20 @@ {"Statistics","統計"}. {"Stop Modules at ","モジュールを停止: "}. {"Stop Modules","モジュールを停止"}. -{"Stop","停止"}. {"Stopped Nodes","停止ノード"}. +{"Stop","停止"}. {"Storage Type","ストレージタイプ"}. {"Store binary backup:","バイナリバックアップを保存:"}. {"Store plain text backup:","プレーンテキストバックアップを保存:"}. {"Subject","件名"}. -{"Submit","送信"}. {"Submitted","送信完了"}. +{"Submit","送信"}. {"Subscriber Address","購読者のアドレス"}. {"Subscription","認可"}. {"Sunday","日曜日"}. {"The CAPTCHA is valid.","CAPTCHA は有効です。"}. {"The collections with which a node is affiliated","提携されたノードの集合です"}. +{"the password is","パスワードは"}. {"The password of your Jabber account was successfully changed.","Jabber アカウントのパスワード変更に成功しました。"}. {"There was an error changing the password: ","パスワードの変更中にエラーが発生しました: "}. {"There was an error creating the account: ","アカウントの作成中にエラーが発生しました: "}. @@ -316,14 +344,14 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","大文字と小文字は区別しません: macbeth は MacBeth や Macbeth と同じです。"}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","ここはこの Jabber サーバーにアカウントを作成するページです。あなたの JID (JabberID) は username@server のような形式になります。注意事項どおり、正しく項目を記入してください。"}. {"This page allows to unregister a Jabber account in this Jabber server.","ここはこの Jabber サーバーのアカウントを削除するページです。"}. -{"This room is not anonymous","このチャットルームは非匿名です"}. {"Thursday","木曜日"}. {"Time delay","遅延時間"}. {"Time","時間"}. -{"To ~s","宛先 ~s"}. -{"To","宛先"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。"}. {"Too many unacked stanzas","多くのスタンザが応答していません"}. +{"To ~s","宛先 ~s"}. +{"Total rooms","チャットルーム数"}. +{"To","宛先"}. {"Transactions Aborted:","トランザクションの失敗:"}. {"Transactions Committed:","トランザクションのコミット:"}. {"Transactions Logged:","トランザクションのログ: "}. @@ -335,19 +363,20 @@ {"Update message of the day (don't send)","お知らせメッセージを更新 (送信しない)"}. {"Update message of the day on all hosts (don't send)","全ホストのお知らせメッセージを更新 (送信しない)"}. {"Update plan","更新計画"}. -{"Update script","スクリプトの更新"}. {"Update ~p","更新 ~p"}. +{"Update script","スクリプトの更新"}. {"Update","更新"}. {"Uptime:","起動時間:"}. {"Use of STARTTLS required","STARTTLS の使用が必要です"}. +{"User","ユーザー"}. {"User JID","ユーザー JID"}. {"User Management","ユーザー管理"}. -{"User ~s","ユーザー ~s"}. -{"User","ユーザー"}. {"Username:","ユーザー名:"}. -{"Users Last Activity","ユーザーの活動履歴"}. {"Users","ユーザー"}. +{"Users Last Activity","ユーザーの活動履歴"}. +{"User ~s","ユーザー ~s"}. {"Validate","検証"}. +{"vCard User Search","vCard検索"}. {"Virtual Hosts","バーチャルホスト"}. {"Voice request","発言権を要求"}. {"Wednesday","水曜日"}. @@ -362,26 +391,3 @@ {"Your Jabber account was successfully created.","Jabber アカウントの作成に成功しました。"}. {"Your Jabber account was successfully deleted.","Jabber アカウントの削除に成功しました。"}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","~s 宛のメッセージはブロックされています。解除するにはこちらを見てください ~s"}. -{"anyone","誰にでも"}. -{"ejabberd IRC module","ejabberd IRC module"}. -{"ejabberd MUC module","ejabberd MUCモジュール"}. -{"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe モジュール"}. -{"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams モジュール"}. -{"ejabberd Web Admin","ejabberd ウェブ管理"}. -{"ejabberd vCard module","ejabberd vCard モジュール"}. -{"has been banned","はバンされました"}. -{"has been kicked because of a system shutdown","はシステムシャットダウンのためキックされました"}. -{"has been kicked because of an affiliation change","は分掌が変更されたためキックされました"}. -{"has been kicked because the room has been changed to members-only","はチャットルームがメンバー制に変更されたためキックされました"}. -{"has been kicked","はキックされました"}. -{"is now known as","は名前を変更しました: "}. -{"joins the room","がチャットルームに参加しました"}. -{"leaves the room","がチャットルームから退出しました"}. -{"moderators only","モデレーターにのみ"}. -{"nobody","誰にも許可しない"}. -{"private, ","プライベート、"}. -{"the password is","パスワードは"}. -{"vCard User Search","vCard検索"}. -{"~s access rule configuration","~s アクセスルール設定"}. -{"~s invites you to the room ~s","~s はあなたをチャットルーム ~s に招待しています"}. -{"~s's Offline Messages Queue","~s' のオフラインメッセージキュー"}. diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index e7cdabc8153..0434da69995 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -53,6 +53,26 @@ msgstr "CAPTCHA ウェブページ" msgid "The CAPTCHA is valid." msgstr "CAPTCHA は有効です。" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "ユーザー" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "サーバー:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "パスワード" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -157,7 +177,7 @@ msgid "Show Integral Table" msgstr "累積の表を表示" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "統計" @@ -181,17 +201,6 @@ msgstr "ホスト" msgid "Registered Users" msgstr "登録ユーザー" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "ユーザー" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "パスワード" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -935,7 +944,7 @@ msgstr "サーバーのエンコーディング ~b" msgid "Server ~b" msgstr "サーバー ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "チャットルーム" @@ -951,7 +960,7 @@ msgstr "ニックネーム登録: " msgid "Enter nickname you want to register" msgstr "登録するニックネームを入力してください" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "ニックネーム" @@ -960,24 +969,24 @@ msgstr "ニックネーム" msgid "ejabberd MUC module" msgstr "ejabberd MUCモジュール" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "マルチユーザーチャット" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "チャットルーム数" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "永続チャットルーム" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "登録ニックネーム" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "チャットルームの一覧" @@ -1117,182 +1126,182 @@ msgstr "チャットルームの設定" msgid "Room Occupants" msgstr "在室者" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "モデレーターと参加者のみがチャットルームの件名を変更できます" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "モデレーターのみがチャットルームの件名を変更できます" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s は無効です" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "ニックネーム ~s はこのチャットルームにいません" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "無効な分掌です: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "無効な役です: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "チャットルーム ~s の設定" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "チャットルームのタイトル" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "チャットルームの説明" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "チャットルームを永続化" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "チャットルームを検索可" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "参加者一覧を公開" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "チャットルームをパスワードで保護" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "最大在室者数" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "制限なし" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "本当の Jabber ID を公開" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "モデレーターにのみ" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "誰にでも" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "チャットルームをメンバーのみに制限" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "チャットルームをモデレート化" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "デフォルトのユーザーは参加者" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "ユーザーによる件名の変更を許可" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "ユーザーによるプライベートメッセージの送信を許可" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "傍聴者によるプライベートメッセージの送信を次の相手に許可" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "誰にも許可しない" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "ユーザーによる他のユーザーへのクエリーを許可" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "ユーザーによる招待を許可" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "傍聴者によるプレゼンス更新のステータス文の送信を許可" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "傍聴者のニックネームの変更を許可" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "傍聴者による発言権の要求を許可" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "発言権の要求の最小時間間隔 (秒)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "チャットルームを CAPTCHA で保護" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "メッセージアーカイブを有効化" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA 試験を免除する Jabber ID" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "ロギングを有効" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "チャットルームを設定するには x:data をサポートするクライアントが必要です" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "在室者の数" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "プライベート、" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "発言権を要求" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "発言権の要求を承認または却下します。" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "ユーザー JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "この人に発言権を与えますか ?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s はあなたをチャットルーム ~s に招待しています" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "パスワードは" diff --git a/priv/msgs/nl.msg b/priv/msgs/nl.msg index c8bb9512638..c93584cc51d 100644 --- a/priv/msgs/nl.msg +++ b/priv/msgs/nl.msg @@ -29,8 +29,9 @@ {"August","Augustus"}. {"Backup","Backup"}. {"Backup Management","Backup"}. +{"Backup of ~p","Backup maken van ~p"}. {"Backup to File at ","Binaire backup maken op "}. -{"Bad format","Slecht formaat"}. +{"Bad format","Verkeerd formaat"}. {"Birthday","Geboortedatum"}. {"CAPTCHA web page","CAPTCHA webpagina."}. {"Change Password","Wachtwoord wijzigen"}. @@ -55,6 +56,7 @@ {"Country","Land"}. {"CPU Time:","Processortijd:"}. {"Database","Database"}. +{"Database Tables at ~p","Databasetabellen van ~p"}. {"Database Tables Configuration at ","Instellingen van databasetabellen op "}. {"December","December"}. {"Default users as participants","Gebruikers standaard instellen als deelnemers"}. @@ -62,7 +64,6 @@ {"Delete message of the day on all hosts","Verwijder bericht-van-de-dag op alle hosts"}. {"Delete Selected","Geselecteerde verwijderen"}. {"Delete User","Verwijder Gebruiker"}. -{"Delete","Verwijderen"}. {"Deliver event notifications","Gebeurtenisbevestigingen Sturen"}. {"Deliver payloads with event notifications","Berichten bezorgen samen met gebeurtenisnotificaties"}. {"Description:","Beschrijving:"}. @@ -75,6 +76,7 @@ {"Either approve or decline the voice request.","Keur stemaanvraag goed of af."}. {"ejabberd IRC module","ejabberd's IRC-module"}. {"ejabberd MUC module","ejabberd's MUC module"}. +{"ejabberd Multicast service","ejabberd Multicast service"}. {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe module"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams module"}. {"ejabberd vCard module","ejabberd's vCard-module"}. @@ -82,6 +84,7 @@ {"Elements","Elementen"}. {"Email","E-mail"}. {"Enable logging","Logs aanzetten"}. +{"Enable message archiving","Zet bericht-archivering aan"}. {"Encoding for server ~b","Karakterset voor server ~b"}. {"End User Session","Verwijder Gebruikers-sessie"}. {"Enter list of {Module, [Options]}","Voer lijst met op te starten modules als volgt in: {Module, [Opties]}"}. @@ -97,6 +100,7 @@ {"Error","Fout"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Voorbeeld: [{\"irc.example.org\", \"koi8-r\", 6667, \"geheim\"}, {\"vendetta.example.net\", \"iso8859-1\", 7000}, {irc,testserver.nl\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Geen CAPTCHA test voor Jabber IDs"}. +{"Export all tables as SQL queries to a file:","Exporteer alle tabellen als SQL-queries naar een bestand:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exporteer data van alle gebruikers in de server naar PIEFXIS-bestanden (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exporteer data van alle gebruikers van een host naar PIEXFIS-bestanden (XEP-0227):"}. {"Family Name","Achternaam"}. @@ -115,11 +119,11 @@ {"Grant voice to this person?","Stemaanvraag honoreren voor deze persoon?"}. {"Group ","Groep "}. {"Groups","Groepen"}. -{"has been banned","werd verbannen"}. +{"has been banned","is verbannen"}. {"has been kicked because of an affiliation change","is weggestuurd vanwege een affiliatieverandering"}. {"has been kicked because of a system shutdown","is weggestuurd omdat het systeem gestopt wordt"}. {"has been kicked because the room has been changed to members-only","is weggestuurd omdat de chatruimte vanaf heden alleen toegankelijk is voor leden"}. -{"has been kicked","werd gekicked"}. +{"has been kicked","is weggestuurd"}. {" has set the subject to: "," veranderde het onderwerp in: "}. {"Host","Host"}. {"If you don't see the CAPTCHA image here, visit the web page.","Als U het CAPTCHA-plaatje niet ziet, bezoek dan de webpagina."}. @@ -139,7 +143,7 @@ {"IRC channel (don't put the first #)","IRC kanaal (zonder eerste #)"}. {"IRC server","IRC-server"}. {"IRC settings","IRC instellingen"}. -{"IRC Transport","IRC Transport"}. +{"IRC Transport","IRC-transport"}. {"IRC username","Gebruikersnaam voor IRC"}. {"IRC Username","Gebruikersnaam voor IRC:"}. {"is now known as","heet nu"}. @@ -161,6 +165,7 @@ {"Listened Ports at ","Openstaande poorten op "}. {"Listened Ports","Openstaande poorten"}. {"List of modules to start","Lijst met op te starten modules"}. +{"List of rooms","Lijst van groepsgesprekken"}. {"Low level update script","Lowlevel script voor de opwaardering"}. {"Make participants list public","Deelnemerslijst publiek maken"}. {"Make room CAPTCHA protected","Chatruimte beveiligen met een geautomatiseerde Turing test"}. @@ -183,8 +188,11 @@ {"moderators only","moderators"}. {"Modified modules","Gewijzigde modules"}. {"Module","Module"}. +{"Modules at ~p","Modules op ~p"}. {"Modules","Modules"}. {"Monday","Maandag"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Groepschat"}. {"Name:","Naam:"}. {"Name","Naam"}. {"Never","Nooit"}. @@ -197,6 +205,7 @@ {"No Data","Geen gegevens"}. {"Node ID","Node ID"}. {"Node not found","Node niet gevonden"}. +{"Node ~p","Node ~p"}. {"Nodes","Nodes"}. {"No limit","Geen limiet"}. {"None","Geen"}. @@ -236,6 +245,7 @@ {"Path to File","Pad naar bestand"}. {"Pending","Bezig"}. {"Period: ","Periode: "}. +{"Permanent rooms","Permanente groepsgesprekken"}. {"Persist items to storage","Items in het geheugen bewaren"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Merk op dat volgende opties enkel backups maken van de ingebouwde database Mnesia. Als U de ODBC module gebruikt dan moeten daarvan afzonderlijke backups gemaakt worden."}. @@ -253,6 +263,7 @@ {"Raw","Ruw"}. {"Really delete message of the day?","Wilt u het bericht van de dag verwijderen?"}. {"Register a Jabber account","Registreer een Jabber-account"}. +{"Registered nicknames","Geregistreerde gebruikersnamen"}. {"Registered Users:","Geregistreerde gebruikers:"}. {"Registered Users","Geregistreerde gebruikers"}. {"Register","Registreer"}. @@ -329,15 +340,18 @@ {"There was an error changing the password: ","Er was een fout bij het veranderen van het wachtwoord:"}. {"There was an error creating the account: ","Er was een fout bij het creeern van de account:"}. {"There was an error deleting the account: ","Er was een fout bij het verwijderen van de account."}. +{"This IP address is blacklisted in ~s","Dit IP-adres is geblokkeerd in ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Dit is niet hoofdlettergevoelig: macbeth is hetzelfde als MacBeth en Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Deze pagina maakt het mogelijk een Jabber-account te registreren op deze server. Uw JID (Jabber IDentiteit) zal er als volg uit zien: gebruikersnaam@server. Lees de instructies zorgvuldig teneinde de velden correct in te vullen."}. {"This page allows to unregister a Jabber account in this Jabber server.","Deze pagina maakt het mogelijk een Jabber-account op deze server op te heffen."}. -{"This room is not anonymous","Deze chatruimte is niet anoniem"}. {"Thursday","Donderdag"}. {"Time delay","Vertraging"}. {"Time","Tijd"}. {"To","Aan"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Te veel (~p) mislukte authenticatie-pogingen van dit IP-adres (~s). Dit adres zal worden gedeblokkeerd om ~s UTC"}. +{"Too many unacked stanzas","Te veel niet-bevestigde stanzas"}. {"To ~s","Naar ~s"}. +{"Total rooms","Aantal groepsgesprekken"}. {"Transactions Aborted:","Afgebroken transacties:"}. {"Transactions Committed:","Bevestigde transacties:"}. {"Transactions Logged:","Gelogde transacties:"}. @@ -350,6 +364,7 @@ {"Update message of the day (don't send)","Bericht van de dag bijwerken (niet verzenden)"}. {"Update message of the day on all hosts (don't send)","Verander bericht-van-de-dag op alle hosts (niet versturen)"}. {"Update plan","Plan voor de opwaardering"}. +{"Update ~p","Opwaarderen van ~p"}. {"Update script","Script voor de opwaardering"}. {"Uptime:","Uptime:"}. {"Use of STARTTLS required","Gebruik van STARTTLS is vereist"}. @@ -357,6 +372,7 @@ {"User JID","JID Gebruiker"}. {"User Management","Gebruikersbeheer"}. {"Username:","Gebruikersnaam:"}. +{"User ~s","Gebruiker ~s"}. {"Users","Gebruikers"}. {"Users Last Activity","Laatste activiteit van gebruikers"}. {"Validate","Bevestigen"}. diff --git a/priv/msgs/nl.po b/priv/msgs/nl.po index 2e1881e3545..2ef3024735e 100644 --- a/priv/msgs/nl.po +++ b/priv/msgs/nl.po @@ -55,6 +55,26 @@ msgstr "CAPTCHA webpagina." msgid "The CAPTCHA is valid." msgstr "De geautomatiseerde Turing-test is geslaagd." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Gebruiker" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Wachtwoord" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -159,7 +179,7 @@ msgid "Show Integral Table" msgstr "Volledige tabel laten zien" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistieken" @@ -183,17 +203,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Geregistreerde gebruikers" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Gebruiker" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Wachtwoord" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -945,7 +954,7 @@ msgstr "Karakterset voor server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Groepsgesprekken" @@ -962,7 +971,7 @@ msgstr "Registratie van een bijnaam op " msgid "Enter nickname you want to register" msgstr "Voer de bijnaam in die u wilt registreren" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Bijnaam" @@ -971,24 +980,24 @@ msgstr "Bijnaam" msgid "ejabberd MUC module" msgstr "ejabberd's MUC module" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Groepschat" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Aantal groepsgesprekken" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Permanente groepsgesprekken" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Geregistreerde gebruikersnamen" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lijst van groepsgesprekken" @@ -1130,7 +1139,7 @@ msgstr "Instellingen van de chatruimte" msgid "Room Occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1138,177 +1147,177 @@ msgstr "" "Alleen moderators en deelnemers mogen het onderwerp van deze chatruimte " "veranderen" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Alleen moderators mogen het onderwerp van deze chatruimte veranderen" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "De Jabber ID ~s is ongeldig" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "De bijnaam ~s bestaat niet in deze chatruimte" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Ongeldige affiliatie: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Ongeldige rol: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Instellingen van chatruimte ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Naam van de chatruimte" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Beschrijving" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Chatruimte blijvend maken" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Chatruimte doorzoekbaar maken" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Deelnemerslijst publiek maken" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Chatruimte beveiligen met een wachtwoord" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Maximum aantal aanwezigen" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Geen limiet" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Jabber ID's kunnen achterhaald worden door" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "moderators" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "iedereen" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Chatruimte enkel toegankelijk maken voor leden" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Chatruimte gemodereerd maken" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Gebruikers standaard instellen als deelnemers" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Sta gebruikers toe het onderwerp te veranderen" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Gebruikers mogen privéberichten verzenden" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Gebruikers mogen privéberichten verzenden aan" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "niemand" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Gebruikers mogen naar andere gebruikers verzoeken verzenden" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Gebruikers mogen uitnodigingen verzenden" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Sta bezoekers toe hun statusbericht in te stellen" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Sta bezoekers toe hun naam te veranderen" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Gebruikers mogen stemaanvragen verzenden" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimale interval tussen stemaanvragen (in seconden)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Chatruimte beveiligen met een geautomatiseerde Turing test" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Zet bericht-archivering aan" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Geen CAPTCHA test voor Jabber IDs" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Logs aanzetten" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "U hebt een client nodig die x:data ondersteunt om deze chatruimte in te " "stellen" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Stemaanvraag" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Keur stemaanvraag goed of af." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "JID Gebruiker" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Stemaanvraag honoreren voor deze persoon?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s nodigt je uit voor het groepsgesprek ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "het wachtwoord is" diff --git a/priv/msgs/no.msg b/priv/msgs/no.msg index 5cc014e8586..81a591ad7e0 100644 --- a/priv/msgs/no.msg +++ b/priv/msgs/no.msg @@ -61,7 +61,6 @@ {"Delete message of the day on all hosts","Slett melding for dagen på alle maskiner"}. {"Delete message of the day","Slett melding for dagen"}. {"Delete Selected","Slett valgte"}. -{"Delete","Slett"}. {"Delete User","Slett Bruker"}. {"Deliver event notifications","Lever begivenhets kunngjøringer"}. {"Deliver payloads with event notifications","Send innhold sammen med kunngjøringer"}. @@ -332,7 +331,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Denne er ufølsom for små og store bokstaver: macbeth er det samme som MacBeth og Macbeth. "}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Denne siden lar deg lage en Jabber konto på denne Jabber serveren. Din JID (Jabber ID) vil være i formatet: brukernavn@server. Vennligst les instruksjonene nøye slik at du fyller ut skjemaet riktig."}. {"This page allows to unregister a Jabber account in this Jabber server.","Denne siden lar deg avregistrere en Jabber konto på denne Jabber serveren."}. -{"This room is not anonymous","Dette rommet er ikke anonymt"}. {"Thursday","torsdag"}. {"Time delay","Tids forsinkelse"}. {"Time","Tid"}. diff --git a/priv/msgs/no.po b/priv/msgs/no.po index 3e83bd90dd4..bf768a914d2 100644 --- a/priv/msgs/no.po +++ b/priv/msgs/no.po @@ -52,6 +52,26 @@ msgstr "CAPTCHA web side" msgid "The CAPTCHA is valid." msgstr "Captchaen er ikke gyldig" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Bruker" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Passord" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -156,7 +176,7 @@ msgid "Show Integral Table" msgstr "Vis Integral Tabell" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistikk" @@ -180,17 +200,6 @@ msgstr "Maskin" msgid "Registered Users" msgstr "Registrerte Brukere" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Bruker" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Passord" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -938,7 +947,7 @@ msgstr "Tekstkoding for server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Samtalerom" @@ -954,7 +963,7 @@ msgstr "Registrer Kallenavn på " msgid "Enter nickname you want to register" msgstr "Skriv inn kallenavnet du ønsker å registrere" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Kallenavn" @@ -963,27 +972,27 @@ msgstr "Kallenavn" msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Samtalerom" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "forlater rommet" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrerte Brukere" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1124,181 +1133,181 @@ msgstr "Rom Konfigurasjon" msgid "Room Occupants" msgstr "Samtalerom Deltakere" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Bare redaktører og deltakere kan endre emnet i dette rommet" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Bare ordstyrer tillates å endre emnet i dette rommet" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Ugyldig Jabber ID ~s" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Kallenavn ~s eksisterer ikke i dette rommet" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Ugyldig rang: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Ugyldig rolle: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Konfigurasjon for rom ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Romtittel" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Rom beskrivelse" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Gjør rommet permanent" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Gjør rommet offentlig søkbart" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Gjør deltakerlisten offentlig" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Passordbeskytt rommet" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Maksimum Antall Deltakere" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Ingen grense" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Presenter ekte Jabber IDer til" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "kun for redaktører" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "hvem som helst" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Gjør rommet tilgjengelig kun for medlemmer" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Gjør rommet redaktørstyrt" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Standard brukere som deltakere" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Tillat brukere å endre emne" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Tillat brukere å sende private meldinger" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Tillat brukere å sende private meldinger til" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "ingen" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Tillat brukere å sende forespørsel til andre brukere" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Tillat brukere å sende invitasjoner" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Tillat besøkende å sende status tekst i " -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Tillat besøkende å endre kallenavn" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Tillat brukere å sende lyd forespørsler" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimums interval mellom lyd forespørsler (i sekunder)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Gjør rommet CAPTCHA beskyttet" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Ekskluder Jabber IDer fra CAPTCHA utfordring" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Slå på logging" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Du trenger en klient som støtter x:data for å " -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Antall deltakere" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Lyd forespørsel" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Enten godkjenn eller forby lyd forespørselen" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Bruker JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Gi lyd til denne personen?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s inviterer deg til rommet ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "passordet er" diff --git a/priv/msgs/pl.msg b/priv/msgs/pl.msg index 46e2f7744cf..73eceee2bb8 100644 --- a/priv/msgs/pl.msg +++ b/priv/msgs/pl.msg @@ -28,6 +28,7 @@ {"April","Kwiecień"}. {"August","Sierpień"}. {"Backup Management","Zarządzanie kopiami zapasowymi"}. +{"Backup of ~p","Kopia zapasowa ~p"}. {"Backup to File at ","Zapisz kopię w pliku na "}. {"Backup","Wykonaj kopie"}. {"Bad format","Błędny format"}. @@ -55,6 +56,7 @@ {"Country","Państwo"}. {"CPU Time:","Czas CPU:"}. {"Database","Baza danych"}. +{"Database Tables at ~p","Tabele bazy na ~p"}. {"Database Tables Configuration at ","Konfiguracja tabel bazy na "}. {"December","Grudzień"}. {"Default users as participants","Domyślni użytkownicy jako uczestnicy"}. @@ -62,7 +64,6 @@ {"Delete message of the day","Usuń wiadomość dnia"}. {"Delete Selected","Usuń zaznaczone"}. {"Delete User","Usuń użytkownika"}. -{"Delete","Usuń"}. {"Deliver event notifications","Dostarczaj powiadomienia o zdarzeniach"}. {"Deliver payloads with event notifications","Dostarczaj zawartość publikacji wraz z powiadomieniami o zdarzeniach"}. {"Description:","Opis:"}. @@ -75,6 +76,7 @@ {"Either approve or decline the voice request.","Zatwierdź lub odrzuć żądanie głosowe"}. {"ejabberd IRC module","Moduł IRC ejabberd"}. {"ejabberd MUC module","Moduł MUC"}. +{"ejabberd Multicast service","Serwis multicast ejabbera"}. {"ejabberd Publish-Subscribe module","Moduł Publish-Subscribe"}. {"ejabberd SOCKS5 Bytestreams module","Moduł SOCKS5 Bytestreams"}. {"ejabberd vCard module","Moduł vCard ejabberd"}. @@ -82,6 +84,7 @@ {"Elements","Elementy"}. {"Email","Email"}. {"Enable logging","Włącz logowanie"}. +{"Enable message archiving","Włącz archiwizowanie rozmów"}. {"Encoding for server ~b","Kodowanie znaków dla serwera ~b"}. {"End User Session","Zakończ sesję uzytkownika"}. {"Enter list of {Module, [Options]}","Wprowadź listę {Moduł, [Opcje]}"}. @@ -97,6 +100,7 @@ {"Error","Błąd"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Przykład: [{\"wroclaw.irc.pl\",\"utf-8\"}, {\"warszawa.irc.pl\", \"iso8859-2\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Pomiń Jabber ID z żądania CAPTCHA"}. +{"Export all tables as SQL queries to a file:","Wyeksportuj wszystkie tabele jako zapytania SQL do pliku:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Eksportuj dane wszystkich użytkowników serwera do plików w formacie PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Eksportuj dane użytkowników z hosta do plików w formacie PIEFXIS (XEP-0227):"}. {"Family Name","Nazwisko"}. @@ -161,6 +165,7 @@ {"Listened Ports at ","Porty nasłuchujące na "}. {"Listened Ports","Porty nasłuchujące"}. {"List of modules to start","Lista modułów do uruchomienia"}. +{"List of rooms","Lista pokoi"}. {"Low level update script","Skrypt aktualizacji niskiego poziomu"}. {"Make participants list public","Upublicznij listę uczestników"}. {"Make room CAPTCHA protected","Pokój zabezpieczony captchą"}. @@ -183,8 +188,11 @@ {"moderators only","tylko moderatorzy"}. {"Modified modules","Zmodyfikowane moduły"}. {"Module","Moduł"}. +{"Modules at ~p","Moduły na ~p"}. {"Modules","Moduły"}. {"Monday","Poniedziałek"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Wieloosobowa rozmowa"}. {"Name","Imię"}. {"Name:","Nazwa:"}. {"Never","Nigdy"}. @@ -197,6 +205,7 @@ {"No Data","Brak danych"}. {"Node ID","ID węzła"}. {"Node not found","Węzeł nie został znaleziony"}. +{"Node ~p","Węzeł ~p"}. {"Nodes","Węzły"}. {"No limit","Bez limitu"}. {"None","Brak"}. @@ -236,6 +245,7 @@ {"Path to File","Scieżka do pliku"}. {"Pending","Oczekuje"}. {"Period: ","Przedział czasu: "}. +{"Permanent rooms","Stałych pokoi"}. {"Persist items to storage","Przechowuj na stałe dane PubSub"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Te opcje kopii zapasowych dotyczą tylko wbudowanej bazy danych typu Mnesia. Jeśli korzystasz z modułu ODBC, musisz wykonać kopie bazy we własnym zakresie."}. @@ -253,6 +263,7 @@ {"Raw","Żródło"}. {"Really delete message of the day?","Na pewno usunąć wiadomość dnia?"}. {"Register a Jabber account","Załóż konto Jabber"}. +{"Registered nicknames","Zarejestrowanych nicków"}. {"Registered Users:","Użytkownicy zarejestrowani:"}. {"Registered Users","Użytkownicy zarejestrowani"}. {"Register","Zarejestruj"}. @@ -329,15 +340,18 @@ {"There was an error changing the password: ","Podczas próby zmiany hasła wystąpił błąd:"}. {"There was an error creating the account: ","Wystąpił błąd podczas tworzenia konta:"}. {"There was an error deleting the account: ","Podczas usuwania konta wystąpił błąd:"}. +{"This IP address is blacklisted in ~s","Ten adres IP został zablokowany w ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Pole nie rozróżnia wielkości liter: słowo Hanna jest takie samo jak hAnna lub haNNa."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Niniejsza strona pozwala na założenie konta Jabber na tym serwerze. Twój JID (Jabber IDentyfikator) będzie miał postać: nazwa_użytkownika@serwer. Przeczytaj dokładnie instrukcję i wypełnij pola."}. {"This page allows to unregister a Jabber account in this Jabber server.","Ta strona pozwala usunąć konto Jabber z tego serwera."}. -{"This room is not anonymous","Ten pokój nie jest anonimowy"}. {"Thursday","Czwartek"}. {"Time","Czas"}. {"Time delay","Opóźnienie"}. {"To","Do"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Zbyt wiele (~p) nieudanych prób logowanie z tego adresu IP (~s). Ten adres zostanie odblokowany o ~s UTC"}. +{"Too many unacked stanzas","Zbyt wiele niepotwierdzonych pakietów"}. {"To ~s","Do ~s"}. +{"Total rooms","Wszystkich pokoi"}. {"Transactions Aborted:","Transakcje anulowane:"}. {"Transactions Committed:","Transakcje zakończone:"}. {"Transactions Logged:","Transakcje zalogowane:"}. @@ -350,6 +364,7 @@ {"Update message of the day (don't send)","Aktualizuj wiadomość dnia (bez wysyłania)"}. {"Update message of the day on all hosts (don't send)","Aktualizuj wiadomość dnia na wszystkich hostach (bez wysyłania)"}. {"Update plan","Plan aktualizacji"}. +{"Update ~p","Uaktualnij ~p"}. {"Update script","Skrypt aktualizacji"}. {"Uptime:","Czas pracy:"}. {"Use of STARTTLS required","Wymagane jest użycie STARTTLS"}. @@ -358,6 +373,7 @@ {"Username:","Nazwa użytkownika:"}. {"Users Last Activity","Ostatnia aktywność użytkowników"}. {"Users","Użytkownicy"}. +{"User ~s","Użytkownik ~s"}. {"User","Użytkownik"}. {"Validate","Potwierdź"}. {"vCard User Search","Wyszukiwanie vCard użytkowników"}. diff --git a/priv/msgs/pl.po b/priv/msgs/pl.po index 961307d32da..900b877ee39 100644 --- a/priv/msgs/pl.po +++ b/priv/msgs/pl.po @@ -57,6 +57,26 @@ msgstr "Strona internetowa CAPTCHA" msgid "The CAPTCHA is valid." msgstr "Captcha jest poprawna." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Użytkownik" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Serwer:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Hasło" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -127,7 +147,8 @@ msgstr "Wirtualne Hosty" msgid "Users" msgstr "Użytkownicy" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 mod_configure.erl:524 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 msgid "Online Users" msgstr "Użytkownicy zalogowani" @@ -159,7 +180,8 @@ msgstr "Pokaż zwykłą tabelę" msgid "Show Integral Table" msgstr "Pokaż tabelę całkowitą" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 mod_muc_admin.erl:246 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statystyki" @@ -183,17 +205,6 @@ msgstr "Host" msgid "Registered Users" msgstr "Użytkownicy zarejestrowani" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 mod_register.erl:262 -#: mod_vcard.erl:490 -msgid "User" -msgstr "Użytkownik" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Hasło" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -945,7 +956,7 @@ msgstr "Kodowanie znaków dla serwera ~b" msgid "Server ~b" msgstr "Serwer ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Pokoje rozmów" @@ -961,8 +972,8 @@ msgstr "Rejestracja nazwy użytkownika na " msgid "Enter nickname you want to register" msgstr "Wprowadz nazwę użytkownika którego chcesz zarejestrować" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 mod_vcard.erl:490 -#: mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 +#: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Nazwa użytkownika" @@ -970,24 +981,24 @@ msgstr "Nazwa użytkownika" msgid "ejabberd MUC module" msgstr "Moduł MUC" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Wieloosobowa rozmowa" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Wszystkich pokoi" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Stałych pokoi" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Zarejestrowanych nicków" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lista pokoi" @@ -1127,181 +1138,181 @@ msgstr "Konfiguracja pokoju" msgid "Room Occupants" msgstr "Lista uczestników" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Tylko moderatorzy i uczestnicy mogą zmienić temat tego pokoju" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Tylko moderatorzy mogą zmienić temat tego pokoju" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s jest niepoprawny" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Nie ma nicka ~s w tym pokoju" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Nieprawidłowa przynależność: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Nieprawidłowa rola: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Konfiguracja pokoju ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Tytuł pokoju" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Opis pokoju" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Utwórz pokój na stałe" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Pozwól wyszukiwać pokój" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Upublicznij listę uczestników" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Pokój zabezpieczony hasłem" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Maksymalna liczba uczestników" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Prawdziwe Jabber ID widoczne dla" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "tylko moderatorzy" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "wszystkich" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Pokój tylko dla członków" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Pokój moderowany" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Domyślni użytkownicy jako uczestnicy" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Pozwól użytkownikom zmieniać temat" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Pozwól użytkownikom wysyłać prywatne wiadomości" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Pozwól użytkownikom wysyłać prywatne wiadomości" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "nikt" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Pozwól użytkownikom pobierać informacje o innych użytkownikach" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Pozwól użytkownikom wysyłać zaproszenia" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Pozwól uczestnikom na wysyłanie statusów opisowych" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Pozwól uczestnikom na zmianę nicka" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Pozwól użytkownikom wysyłać zaproszenia" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimalny odstęp między żądaniami głosowymi (w sekundach)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Pokój zabezpieczony captchą" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Włącz archiwizowanie rozmów" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Pomiń Jabber ID z żądania CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Włącz logowanie" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Potrzebujesz klienta obsługującego x:data aby skonfigurować pokój" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Liczba uczestników" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "prywatny, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Żądanie głosowe" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Zatwierdź lub odrzuć żądanie głosowe" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Użytkownik " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Udzielić głosu tej osobie?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s zaprasza Cię do pokoju ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "hasło to:" diff --git a/priv/msgs/pt-br.msg b/priv/msgs/pt-br.msg index 60aea8d8fa5..62cb4978733 100644 --- a/priv/msgs/pt-br.msg +++ b/priv/msgs/pt-br.msg @@ -19,17 +19,21 @@ {"Allow users to send invites","Permitir a usuários envio de convites"}. {"Allow users to send private messages","Permitir a usuários enviarem mensagens privadas"}. {"Allow visitors to change nickname","Permitir mudança de apelido aos visitantes"}. +{"Allow visitors to send private messages to","Permitir visitantes enviar mensagem privada para"}. {"Allow visitors to send status text in presence updates","Permitir atualizações de status aos visitantes"}. +{"Allow visitors to send voice requests","Permitir aos visitantes o envio de convites"}. {"All Users","Todos os usuários"}. {"Announcements","Anúncios"}. {"anyone","qualquer um"}. {"April","Abril"}. {"August","Agosto"}. {"Backup Management","Gestão de Backup"}. +{"Backup of ~p","Backup de ~p"}. {"Backup","Salvar cópia de segurança"}. {"Backup to File at ","Salvar backup para arquivo em "}. {"Bad format","Formato incorreto"}. {"Birthday","Aniversário"}. +{"CAPTCHA web page","CAPTCHA web page"}. {"Change Password","Mudar senha"}. {"Change User Password","Alterar Senha do Usuário"}. {"Characters not allowed:","Caracteres não aceitos:"}. @@ -52,10 +56,10 @@ {"Country","País"}. {"CPU Time:","Tempo de CPU"}. {"Database","Base de dados"}. +{"Database Tables at ~p","Tabelas do bancod de dados em ~p"}. {"Database Tables Configuration at ","Configuração de Tabelas de Base de dados em "}. {"December","Dezembro"}. {"Default users as participants","Usuários padrões como participantes"}. -{"Delete","Eliminar"}. {"Delete message of the day","Apagar mensagem do dia"}. {"Delete message of the day on all hosts","Apagar a mensagem do dia em todos os hosts"}. {"Delete Selected","Remover os selecionados"}. @@ -64,13 +68,15 @@ {"Deliver payloads with event notifications","Enviar payloads junto com as notificações de eventos"}. {"Description:","Descrição:"}. {"Disc only copy","Somente copia em disco"}. +{"Displayed Groups:","Grupos Exibidos:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","Não revele o seu computador a ninguém, mesmo para o administrador deste servidor Jabber."}. {"Dump Backup to Text File at ","Exportar backup para texto em "}. -{"Dump to Text File","Exportar para arquivo de texto"}. +{"Dump to Text File","Exportar para arquivo texto"}. {"Edit Properties","Editar propriedades"}. {"Either approve or decline the voice request.","Você deve aprovar/desaprovar a requisição de voz."}. {"ejabberd IRC module","Módulo de IRC para ejabberd"}. {"ejabberd MUC module","Módulo de MUC para ejabberd"}. +{"ejabberd Multicast service","ejabberd Multicast service"}. {"ejabberd Publish-Subscribe module","Módulo para Publicar Tópicos do ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Modulo ejabberd SOCKS5 Bytestreams"}. {"ejabberd vCard module","Módulo vCard para ejabberd"}. @@ -78,6 +84,7 @@ {"Elements","Elementos"}. {"Email","Email"}. {"Enable logging","Permitir criação de logs"}. +{"Enable message archiving","Habilitar arquivamento de mensagens"}. {"Encoding for server ~b","Codificação para o servidor ~b"}. {"End User Session","Terminar Sessão do Usuário"}. {"Enter list of {Module, [Options]}","Introduza lista de {módulo, [opções]}"}. @@ -93,6 +100,7 @@ {"Error","Erro"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Exemplo: [{\"irc.teste.net\", \"koi8-r\"}, 6667, \"senha\"}, {\"dominio.foo.net\", \"iso8859-1\", 7000}, {\"irc.servidordeteste.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Excluir IDs Jabber de serem submetidos ao CAPTCHA"}. +{"Export all tables as SQL queries to a file:","Exportar todas as tabelas como SQL para um arquivo:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportar todos os dados de todos os usuários no servidor, para arquivos formato PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportar dados dos usuários em um host, para arquivos PIEFXIS (XEP-0227):"}. {"Family Name","Sobrenome"}. @@ -108,6 +116,7 @@ {"Get User Last Login Time","Obter a Data do Último Login"}. {"Get User Password","Obter Senha do Usuário"}. {"Get User Statistics","Obter Estatísticas do Usuário"}. +{"Grant voice to this person?","Dar 'voice' a esta usuário?"}. {"Group ","Grupo "}. {"Groups","Grupos"}. {"has been banned","foi banido"}. @@ -117,6 +126,7 @@ {"has been kicked","foi removido"}. {" has set the subject to: "," a posto o assunto: "}. {"Host","Máquina"}. +{"If you don't see the CAPTCHA image here, visit the web page.","Se você não conseguir ver o CAPTCHA aqui, visite a web page."}. {"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","Se você deseja especificar portas diferentes, senhas ou codifações para servidores de IRC, complete esta lista com os valores no formato: '{\"servidor IRC\", \"codificação\", porta, \"senha\"}'. Por padrão, este serviço usa a codificação \"~s\", porta \"~p\", e senha em branco (vazia)"}. {"Import Directory","Importar diretório"}. {"Import File","Importar arquivo"}. @@ -125,7 +135,7 @@ {"Import users data from a PIEFXIS file (XEP-0227):","Importar usuários de um arquivo PIEFXIS (XEP-0227): "}. {"Import users data from jabberd14 spool directory:","Importar dados dos usuários de um diretório-fila jabberd14:"}. {"Import Users from Dir at ","Importar usuários a partir do diretório em "}. -{"Import Users From jabberd14 Spool Files","Importar usuários de arquivos jabberd14"}. +{"Import Users From jabberd14 Spool Files","Importar usuários de arquivos jabberd14 (spool files)"}. {"Invalid affiliation: ~s","Afiliação não válida: ~s"}. {"Invalid role: ~s","Cargo (role) é não válido: ~s"}. {"IP addresses","Endereços IP"}. @@ -152,9 +162,10 @@ {"Last month","Último mês"}. {"Last year","Último ano"}. {"leaves the room","Sair da sala"}. -{"Listened Ports at ","Portas ouvintes em "}. +{"Listened Ports at ","Portas abertas em "}. {"Listened Ports","Portas escutadas"}. {"List of modules to start","Listas de módulos para inicializar"}. +{"List of rooms","Lista de salas"}. {"Low level update script","Script de atualização low level"}. {"Make participants list public","Tornar pública a lista de participantes"}. {"Make room CAPTCHA protected","Tornar protegida a senha da sala"}. @@ -168,7 +179,7 @@ {"Max # of items to persist","Máximo # de elementos que persistem"}. {"Max payload size in bytes","Máximo tamanho do payload em bytes"}. {"May","Maio"}. -{"Members:","Miembros:"}. +{"Members:","Membros:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memorize a sua senha, ou escreva-a em um papel e guarde-o em um lugar seguro. Jabber não é uma maneira automatizada para recuperar a sua senha, se você a esquecer eventualmente."}. {"Memory","Memória"}. {"Message body","Corpo da mensagem"}. @@ -177,11 +188,15 @@ {"moderators only","apenas moderadores"}. {"Modified modules","Módulos atualizados"}. {"Module","Módulo"}. +{"Modules at ~p","Módulos em ~p"}. {"Modules","Módulos"}. {"Monday","Segunda"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Chat multi-usuário"}. {"Name:","Nome:"}. {"Name","Nome"}. {"Never","Nunca"}. +{"New Password:","Nova Senha:"}. {"Nickname","Apelido"}. {"Nickname Registration at ","Registro do apelido em "}. {"Nickname ~s does not exist in the room","O nick ~s não existe em la sala"}. @@ -190,6 +205,7 @@ {"No Data","Nenhum dado"}. {"Node ID","ID do Tópico"}. {"Node not found","Nó não encontrado"}. +{"Node ~p","Nó ~p"}. {"Nodes","Nós"}. {"No limit","Ilimitado"}. {"None","Nenhum"}. @@ -206,6 +222,7 @@ {"Offline Messages:","Mensagens offline"}. {"Offline Messages","Mensagens offline"}. {"OK","OK"}. +{"Old Password:","Senha Antiga:"}. {"Online","Conectado"}. {"Online Users","Usuários conectados"}. {"Online Users:","Usuários online"}. @@ -222,11 +239,13 @@ {"Password ~b","Senha ~b"}. {"Password:","Senha:"}. {"Password","Senha"}. +{"Password Verification:","Verificação de Senha"}. {"Password Verification","Verificação de Senha"}. {"Path to Dir","Caminho para o diretório"}. {"Path to File","Caminho do arquivo"}. {"Pending","Pendente"}. {"Period: ","Período: "}. +{"Permanent rooms","Salas permanentes"}. {"Persist items to storage","Persistir elementos ao armazenar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Observe que tais opções farão backup apenas da base de dados Mnesia. Caso você esteja utilizando o modulo ODBC, você precisará fazer backup de sua base de dados SQL separadamente."}. @@ -244,8 +263,10 @@ {"Raw","Intocado"}. {"Really delete message of the day?","Deletar realmente a mensagem do dia?"}. {"Register a Jabber account","Registrar uma conta Jabber"}. +{"Registered nicknames","Usuários registrados"}. {"Registered Users:","Usuários registrados"}. {"Registered Users","Usuários Registrados"}. +{"Register","Registrar"}. {"Registration in mod_irc for ","Registro em mod_irc para "}. {"Remote copy","Copia remota"}. {"Remove All Offline Messages","Remover Todas as Mensagens Offline"}. @@ -256,7 +277,7 @@ {"Restart","Reiniciar"}. {"Restart Service","Reiniciar Serviço"}. {"Restore Backup from File at ","Restaurar backup a partir do arquivo em "}. -{"Restore binary backup after next ejabberd restart (requires less memory):","Restaurar backup binário após próximo reinicialização do ejabberd (requer menos memória):"}. +{"Restore binary backup after next ejabberd restart (requires less memory):","Restaurar backup binário após reinicialização do ejabberd (requer menos memória):"}. {"Restore binary backup immediately:","Restaurar backup binário imediatamente"}. {"Restore plain text backup immediately:","Restaurar backup formato texto imediatamente:"}. {"Restore","Restaurar"}. @@ -281,6 +302,7 @@ {"Send announcement to all users on all hosts","Enviar aviso para todos os usuários em todos os hosts"}. {"September","Setembro"}. {"Server ~b","Servidor ~b"}. +{"Server:","Servidor:"}. {"Set message of the day and send to online users","Definir mensagem do dia e enviar a todos usuários online"}. {"Set message of the day on all hosts and send to online users","Definir mensagem do dia em todos os hosts e enviar para os usuários online"}. {"Shared Roster Groups","Grupos Shared Roster"}. @@ -318,15 +340,18 @@ {"There was an error changing the password: ","Houveram erros ao mudar a senha: "}. {"There was an error creating the account: ","Houveram erras ao criar esta conta: "}. {"There was an error deleting the account: ","Erro ao deletar esta conta: "}. +{"This IP address is blacklisted in ~s","Este endereço IP está bloqueado em ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Não é 'case insensitive': macbeth é o mesmo que MacBeth e ainda Macbeth. "}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Esta pagina aceita criações de novas contas Jabber neste servidor. A sua JID (Identificador Jabber) será da seguinte forma: 'usuário@servidor'. Por favor, leia cuidadosamente as instruções para preencher corretamente os campos."}. {"This page allows to unregister a Jabber account in this Jabber server.","Esta página aceita para deletar uma conta Jabber neste servidor."}. -{"This room is not anonymous","Essa sala não é anônima"}. {"Thursday","Quinta"}. {"Time delay","Intervalo (Tempo)"}. -{"Time","Fecha"}. +{"Time","Tempo"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço serádesbloqueado as ~s UTC"}. +{"Too many unacked stanzas","número excessivo de instâncias sem confirmação"}. {"To","Para"}. {"To ~s","Para ~s"}. +{"Total rooms","Salas no total"}. {"Transactions Aborted:","Transações abortadas:"}. {"Transactions Committed:","Transações salvas:"}. {"Transactions Logged:","Transações de log:"}. @@ -338,12 +363,16 @@ {"Update","Atualizar"}. {"Update message of the day (don't send)","Atualizar mensagem do dia (não enviar)"}. {"Update message of the day on all hosts (don't send)","Atualizar a mensagem do dia em todos os host (não enviar)"}. +{"Update ~p","Atualizar ~p"}. {"Update plan","Plano de Atualização"}. {"Update script","Script de atualização"}. {"Uptime:","Uptime:"}. {"Use of STARTTLS required","É obrigatório uso de STARTTLS"}. +{"User JID","Usuário JID"}. {"User Management","Gerenciamento de Usuários"}. +{"Username:","Usuário:"}. {"Users Last Activity","Ultimas atividades dos usuários"}. +{"User ~s","Usuário ~s"}. {"Users","Usuários"}. {"User","Usuário"}. {"Validate","Validar"}. @@ -354,9 +383,11 @@ {"When to send the last published item","Quando enviar o último tópico publicado"}. {"Whether to allow subscriptions","Permitir subscrições"}. {"You can later change your password using a Jabber client.","Mais tarde você pode alterar a sua senha usando um cliente Jabber."}. +{"You need a client that supports x:data and CAPTCHA to register","Você precisa de um cliente com suporte de x:data para poder registrar o nick"}. +{"You need a client that supports x:data to register the nickname","Você precisa de um cliente com suporte a x:data para registrar o seu apelido"}. {"You need an x:data capable client to configure mod_irc settings","Necessitas um cliente com suporte de x:data para configurar las opções de mod_irc"}. {"You need an x:data capable client to configure room","Necessitas um cliente com suporte de x:data para configurar la sala"}. {"You need an x:data capable client to search","Necessitas um cliente com suporte de x:data para poder buscar"}. {"Your Jabber account was successfully created.","Sua conta jabber foi criada corretamente."}. {"Your Jabber account was successfully deleted.","Sua conta Jabber foi deletada com sucesso."}. -{"Your messages to ~s are being blocked. To unblock them, visit ~s","Suas mensagens para ~s estão bloqueadas. Para desbloquea-las, visite: ~s"}. +{"Your messages to ~s are being blocked. To unblock them, visit ~s","Suas mensagens para ~s estão bloqueadas. Para desbloqueá-las, visite: ~s"}. diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index b81711c85f9..42c521e931c 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -53,6 +53,26 @@ msgstr "CAPTCHA web page" msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é inválido." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Usuário" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Servidor:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Senha" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -157,7 +177,7 @@ msgid "Show Integral Table" msgstr "Mostrar Tabela Integral" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" @@ -181,17 +201,6 @@ msgstr "Máquina" msgid "Registered Users" msgstr "Usuários Registrados" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Usuário" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Senha" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -943,7 +952,7 @@ msgstr "Codificação para o servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salas de Chat" @@ -960,7 +969,7 @@ msgstr "Registro do apelido em " msgid "Enter nickname you want to register" msgstr "Introduza o apelido que quer registrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Apelido" @@ -969,24 +978,24 @@ msgstr "Apelido" msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Chat multi-usuário" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Salas no total" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Salas permanentes" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Usuários registrados" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Lista de salas" @@ -1127,7 +1136,7 @@ msgstr "Configuração de salas" msgid "Room Occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1135,175 +1144,175 @@ msgstr "" "Somente os moderadores e os participamentes podem alterar o assunto desta " "sala" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Somente os moderadores podem alterar o assunto desta sala" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s não es válido" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "O nick ~s não existe em la sala" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiliação não válida: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Cargo (role) é não válido: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Configuração para ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Descrição da Sala" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Tornar sala persistente" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Tornar sala pública possível de ser encontrada" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Tornar pública a lista de participantes" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Tornar protegida a senha da sala" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Número máximo de participantes" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Ilimitado" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Tornar o Jabber ID real visível por" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "apenas moderadores" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "qualquer um" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Tornar sala apenas para membros" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Tornar a sala moderada" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Usuários padrões como participantes" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Permitir a usuários modificar o assunto" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Permitir a usuários enviarem mensagens privadas" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Permitir visitantes enviar mensagem privada para" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "ninguém" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Permitir a usuários pesquisar informações sobre os demais" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Permitir a usuários envio de convites" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Permitir atualizações de status aos visitantes" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Permitir mudança de apelido aos visitantes" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Permitir aos visitantes o envio de convites" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "O intervalo mínimo entre requisições de voz (em segundos)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Tornar protegida a senha da sala" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Habilitar arquivamento de mensagens" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir IDs Jabber de serem submetidos ao CAPTCHA" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Permitir criação de logs" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Necessitas um cliente com suporte de x:data para configurar la sala" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privado, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Requisição de voz" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Você deve aprovar/desaprovar a requisição de voz." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Usuário JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Dar 'voice' a esta usuário?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s convidou você para a sala ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "a senha é" diff --git a/priv/msgs/pt.msg b/priv/msgs/pt.msg index 85e8bf0811d..fe2b45fcdcc 100644 --- a/priv/msgs/pt.msg +++ b/priv/msgs/pt.msg @@ -22,7 +22,6 @@ {"Configuration","Configuração"}. {"Connected Resources:","Recursos conectados:"}. {"Country","País"}. -{"Delete","Eliminar"}. {"Delete Selected","Eliminar os seleccionados"}. {"Disc only copy","Cópia apenas em disco"}. {"Dump Backup to Text File at ","Exporta cópia de segurança para ficheiro de texto em "}. diff --git a/priv/msgs/pt.po b/priv/msgs/pt.po index 8b5572ae5a1..3620b28c98e 100644 --- a/priv/msgs/pt.po +++ b/priv/msgs/pt.po @@ -49,6 +49,26 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Utilizador" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Nunca" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Palavra-chave" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -161,7 +181,7 @@ msgid "Show Integral Table" msgstr "" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" @@ -188,17 +208,6 @@ msgstr "Nome do servidor" msgid "Registered Users" msgstr "Utilizadores registados" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Utilizador" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Palavra-chave" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -989,7 +998,7 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "" @@ -1007,7 +1016,7 @@ msgstr "Registo da alcunha em " msgid "Enter nickname you want to register" msgstr "Introduza a alcunha que quer registar" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Alcunha" @@ -1016,25 +1025,25 @@ msgstr "Alcunha" msgid "ejabberd MUC module" msgstr "Módulo MUC de ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Utilizadores registados" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1178,202 +1187,202 @@ msgstr "Configuração" msgid "Room Occupants" msgstr "" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Só os moderadores e os participantes podem mudar o tópico desta sala" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Só os moderadores podem mudar o tópico desta sala" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s não é válido" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "A alcunha ~s não existe na sala" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiliação inválida: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Papel inválido: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 #, fuzzy msgid "Configuration of room ~s" msgstr "Configuração para " -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 #, fuzzy msgid "Room description" msgstr "Subscrição" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 #, fuzzy msgid "Make room persistent" msgstr "Tornar a sala permanente?" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 #, fuzzy msgid "Make room public searchable" msgstr "Tornar a sala publicamente visível?" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 #, fuzzy msgid "Make participants list public" msgstr "Tornar pública a lista de participantes?" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 #, fuzzy msgid "Make room password protected" msgstr "Proteger a sala com palavra-chave?" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 #, fuzzy msgid "anyone" msgstr "Nenhum" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 #, fuzzy msgid "Make room members-only" msgstr "Tornar a sala exclusiva a membros?" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Tornar a sala moderada" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 #, fuzzy msgid "Default users as participants" msgstr "Os utilizadores são membros por omissão?" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 #, fuzzy msgid "Allow users to change the subject" msgstr "Permitir aos utilizadores mudar o tópico?" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 #, fuzzy msgid "Allow users to send private messages" msgstr "Permitir que os utilizadores enviem mensagens privadas?" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir que os utilizadores enviem mensagens privadas?" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 #, fuzzy msgid "Allow users to query other users" msgstr "Permitir aos utilizadores consultar outros utilizadores?" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 #, fuzzy msgid "Allow users to send invites" msgstr "Permitir que os utilizadores enviem convites?" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Permitir aos utilizadores mudar o tópico?" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir que os utilizadores enviem convites?" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Proteger a sala com palavra-chave?" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 #, fuzzy msgid "Enable logging" msgstr "Guardar históricos?" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "É necessário um cliente com suporte de x:data para configurar a sala" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Utilizador" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 #, fuzzy msgid "the password is" msgstr "Mudar palavra-chave" diff --git a/priv/msgs/ru.msg b/priv/msgs/ru.msg index e5ea42e0bb1..2589a2c0e94 100644 --- a/priv/msgs/ru.msg +++ b/priv/msgs/ru.msg @@ -28,6 +28,7 @@ {"April","апреля"}. {"August","августа"}. {"Backup Management","Управление резервным копированием"}. +{"Backup of ~p","Резервное копирование ~p"}. {"Backup to File at ","Резервное копирование в файл на "}. {"Backup","Резервное копирование"}. {"Bad format","Неправильный формат"}. @@ -54,6 +55,7 @@ {"Connections parameters","Параметры соединения"}. {"Country","Страна"}. {"CPU Time:","Процессорное время:"}. +{"Database Tables at ~p","Таблицы базы данных на ~p"}. {"Database Tables Configuration at ","Конфигурация таблиц базы данных на "}. {"Database","База данных"}. {"December","декабря"}. @@ -62,7 +64,6 @@ {"Delete message of the day","Удалить сообщение дня"}. {"Delete Selected","Удалить выделенные"}. {"Delete User","Удалить пользователя"}. -{"Delete","Удалить"}. {"Deliver event notifications","Доставлять уведомления о событиях"}. {"Deliver payloads with event notifications","Доставлять вместе с уведомлениями o публикациях сами публикации"}. {"Description:","Описание:"}. @@ -75,6 +76,7 @@ {"Either approve or decline the voice request.","Подтвердите или отклоните право голоса."}. {"ejabberd IRC module","ejabberd IRC модуль"}. {"ejabberd MUC module","ejabberd MUC модуль"}. +{"ejabberd Multicast service","ejabberd Multicast сервис"}. {"ejabberd Publish-Subscribe module","Модуль ejabberd Публикации-Подписки"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}. {"ejabberd vCard module","ejabberd vCard модуль"}. @@ -82,6 +84,7 @@ {"Elements","Элементы"}. {"Email","Электронная почта"}. {"Enable logging","Включить журналирование"}. +{"Enable message archiving","Включить хранение сообщений"}. {"Encoding for server ~b","Кодировка сервера ~b"}. {"End User Session","Завершить сеанс пользователя"}. {"Enter list of {Module, [Options]}","Введите список вида {Module, [Options]}"}. @@ -97,6 +100,7 @@ {"Error","Ошибка"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Пример: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Исключить показ капчи для списка Jabber ID"}. +{"Export all tables as SQL queries to a file:","Экспортировать все таблицы в виде SQL запросов в файл:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):"}. {"Family Name","Фамилия"}. @@ -161,6 +165,7 @@ {"Listened Ports at ","Прослушиваемые порты на "}. {"Listened Ports","Прослушиваемые порты"}. {"List of modules to start","Список запускаемых модулей"}. +{"List of rooms","Список комнат"}. {"Low level update script","Низкоуровневый сценарий обновления"}. {"Make participants list public","Сделать список участников видимым всем"}. {"Make room CAPTCHA protected","Сделать комнату защищённой капчей"}. @@ -182,9 +187,12 @@ {"Minimum interval between voice requests (in seconds)","Минимальный интервал между запросами на право голоса"}. {"moderators only","только модераторам"}. {"Modified modules","Изменённые модули"}. +{"Modules at ~p","Модули на ~p"}. {"Modules","Модули"}. {"Module","Модуль"}. {"Monday","Понедельник"}. +{"Multicast","Мультикаст"}. +{"Multi-User Chat","Конференция"}. {"Name:","Название:"}. {"Name","Название"}. {"Never","Никогда"}. @@ -197,6 +205,7 @@ {"No Data","Нет данных"}. {"Node ID","ID узла"}. {"Node not found","Узел не найден"}. +{"Node ~p","Узел ~p"}. {"Nodes","Узлы"}. {"No limit","Не ограничено"}. {"None","Нет"}. @@ -236,6 +245,7 @@ {"Path to File","Путь к файлу"}. {"Pending","Ожидание"}. {"Period: ","Период"}. +{"Permanent rooms","Постоянные комнаты"}. {"Persist items to storage","Сохранять публикации в хранилище"}. {"Ping","Пинг"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Заметьте, что здесь производится резервное копирование только встроенной базы данных Mnesia. Если Вы также используете другое хранилище данных (например с помощью модуля ODBC), то его резервное копирование следует осуществлять отдельно."}. @@ -253,6 +263,7 @@ {"Raw","Необработанный формат"}. {"Really delete message of the day?","Действительно удалить сообщение дня?"}. {"Register a Jabber account","Зарегистрировать Jabber-аккаунт"}. +{"Registered nicknames","Зарегистрированные псевдонимы"}. {"Registered Users:","Зарегистрированные пользователи:"}. {"Registered Users","Зарегистрированные пользователи"}. {"Register","Зарегистрировать"}. @@ -329,14 +340,17 @@ {"There was an error changing the password: ","Ошибка при смене пароля:"}. {"There was an error creating the account: ","Ошибка при создании аккаунта:"}. {"There was an error deleting the account: ","Ошибка при удалении аккаунта:"}. +{"This IP address is blacklisted in ~s","Этот IP адрес находится в чёрном списке ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Регистр не имеет значения: \"маша\" и \"МАША\" будет считаться одним и тем же именем."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Здесь Вы можете создать Jabber-аккаунт на этом Jabber-сервере. Ваш JID (Jabber-идентификатор) будет в виде: \"пользователь@сервер\". Пожалуйста, внимательно читайте инструкции для правильного заполнения полей."}. {"This page allows to unregister a Jabber account in this Jabber server.","Здесь Вы можете удалить Jabber-аккаунт с этого сервера."}. -{"This room is not anonymous","Эта комната не анонимная"}. {"Thursday","Четверг"}. {"Time delay","По истечение"}. {"Time","Время"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Слишком много (~p) неудачных попыток аутентификации с этого IP-адреса (~s). Адрес будет разблокирован в ~s UTC"}. +{"Too many unacked stanzas","Слишком много неподтверждённых пакетов"}. {"To ~s","К ~s"}. +{"Total rooms","Все комнаты"}. {"To","Кому"}. {"Transactions Aborted:","Транзакции отмененные:"}. {"Transactions Committed:","Транзакции завершенные:"}. @@ -349,6 +363,7 @@ {"Update message of the day (don't send)","Обновить сообщение дня (не рассылать)"}. {"Update message of the day on all hosts (don't send)","Обновить сообщение дня на всех виртуальных серверах (не рассылать)"}. {"Update plan","План обновления"}. +{"Update ~p","Обновление ~p"}. {"Update script","Сценарий обновления"}. {"Update","Обновить"}. {"Uptime:","Время работы:"}. @@ -358,6 +373,7 @@ {"Username:","Имя пользователя:"}. {"Users Last Activity","Статистика последнего подключения пользователей"}. {"Users","Пользователи"}. +{"User ~s","Пользователь ~s"}. {"User","Пользователь"}. {"Validate","Утвердить"}. {"vCard User Search","Поиск пользователей по vCard"}. diff --git a/priv/msgs/ru.po b/priv/msgs/ru.po index 5f7fff6d802..b1219472070 100644 --- a/priv/msgs/ru.po +++ b/priv/msgs/ru.po @@ -6,16 +6,37 @@ msgstr "" "PO-Revision-Date: 2015-09-07 15:04+0300\n" "Last-Translator: Evgeniy Khramtsov \n" "Language-Team: Russian \n" +"Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" "X-Language: Russian (русский)\n" "X-Additional-Translator: Konstantin Khomoutov\n" "X-Additional-Translator: Sergei Golovan\n" "X-Generator: Lokalize 1.0\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" -"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +msgid "Use of STARTTLS required" +msgstr "Вы обязаны использовать STARTTLS" + +#: ejabberd_c2s.erl:626 +msgid "No resource provided" +msgstr "Не указан ресурс" + +#: ejabberd_c2s.erl:1401 +msgid "Replaced by new connection" +msgstr "Заменено новым соединением" + +#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 +#: mod_muc_log.erl:477 +msgid "has been kicked" +msgstr "выгнали из комнаты" + +#: ejabberd_c2s.erl:2490 +msgid "Too many unacked stanzas" +msgstr "Слишком много неподтверждённых пакетов" #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" @@ -38,10 +59,142 @@ msgstr "Ссылка на капчу" msgid "The CAPTCHA is valid." msgstr "Проверка капчи прошла успешно." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Пользователь" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Сервер:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Пароль" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + +#: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 +#: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 +msgid "Unauthorized" +msgstr "Не авторизован" + #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" msgstr "Web-интерфейс администрирования ejabberd" +#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +msgid "Administration" +msgstr "Администрирование" + +#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: mod_configure.erl:532 +msgid "Access Control Lists" +msgstr "Списки управления доступом" + +#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 +#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 +#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 +#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 +#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 +#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 +#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 +#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +msgid "Submitted" +msgstr "Отправлено" + +#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 +#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 +#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 +#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 +#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 +#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +msgid "Bad format" +msgstr "Неправильный формат" + +#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 +#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 +#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +msgid "Submit" +msgstr "Отправить" + +#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +msgid "Raw" +msgstr "Необработанный формат" + +#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 +#: mod_shared_roster.erl:1180 +msgid "Delete Selected" +msgstr "Удалить выделенные" + +#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: mod_configure.erl:533 +msgid "Access Rules" +msgstr "Правила доступа" + +#: ejabberd_web_admin.erl:849 +msgid "~s access rule configuration" +msgstr "Конфигурация правила доступа ~s" + +#: ejabberd_web_admin.erl:867 +msgid "Virtual Hosts" +msgstr "Виртуальные хосты" + +#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +msgid "Users" +msgstr "Пользователи" + +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: mod_configure.erl:524 +msgid "Online Users" +msgstr "Подключённые пользователи" + +#: ejabberd_web_admin.erl:907 +msgid "Users Last Activity" +msgstr "Статистика последнего подключения пользователей" + +#: ejabberd_web_admin.erl:911 +msgid "Period: " +msgstr "Период" + +#: ejabberd_web_admin.erl:924 +msgid "Last month" +msgstr "За последний месяц" + +#: ejabberd_web_admin.erl:925 +msgid "Last year" +msgstr "За последний год" + +#: ejabberd_web_admin.erl:927 +msgid "All activity" +msgstr "Вся статистика" + +#: ejabberd_web_admin.erl:930 +msgid "Show Ordinary Table" +msgstr "Показать обычную таблицу" + +#: ejabberd_web_admin.erl:933 +msgid "Show Integral Table" +msgstr "Показать интегральную таблицу" + +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: mod_muc_admin.erl:247 +msgid "Statistics" +msgstr "Статистика" + +#: ejabberd_web_admin.erl:950 +msgid "Not Found" +msgstr "Не Найдено" + +#: ejabberd_web_admin.erl:963 +msgid "Node not found" +msgstr "Узел не найден" + #: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 msgid "Add New" msgstr "Добавить" @@ -54,31 +207,6 @@ msgstr "Хост" msgid "Registered Users" msgstr "Зарегистрированные пользователи" -#: ejabberd_web_admin.erl:1275 mod_configure.erl:524 -msgid "Online Users" -msgstr "Подключённые пользователи" - -#: ejabberd_web_admin.erl:1329 ejabberd_web_admin.erl:1614 mod_offline.erl:787 -#: mod_roster.erl:1494 mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 -msgid "Submitted" -msgstr "Отправлено" - -#: ejabberd_web_admin.erl:1330 ejabberd_web_admin.erl:1615 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 -msgid "Bad format" -msgstr "Неправильный формат" - -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Пользователь" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Пароль" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -107,6 +235,7 @@ msgid "Registered Users:" msgstr "Зарегистрированные пользователи:" #: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 +#: ejabberd_web_admin.erl:2125 msgid "Online Users:" msgstr "Подключённые пользователи:" @@ -119,7 +248,7 @@ msgid "Outgoing s2s Servers:" msgstr "Исходящие s2s-серверы:" #: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 msgid "None" msgstr "Нет" @@ -161,6 +290,201 @@ msgstr "Работающие узлы" msgid "Stopped Nodes" msgstr "Остановленные узлы" +#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +msgid "Node ~p" +msgstr "Узел ~p" + +#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +msgid "Database" +msgstr "База данных" + +#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +msgid "Backup" +msgstr "Резервное копирование" + +#: ejabberd_web_admin.erl:1783 +msgid "Listened Ports" +msgstr "Прослушиваемые порты" + +#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +msgid "Update" +msgstr "Обновить" + +#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 +#: ejabberd_web_admin.erl:2551 +msgid "Restart" +msgstr "Перезапустить" + +#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 +#: ejabberd_web_admin.erl:2555 +msgid "Stop" +msgstr "Остановить" + +#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +msgid "Modules" +msgstr "Модули" + +#: ejabberd_web_admin.erl:1804 +msgid "RPC Call Error" +msgstr "Ошибка вызова RPC" + +#: ejabberd_web_admin.erl:1855 +msgid "Database Tables at ~p" +msgstr "Таблицы базы данных на ~p" + +#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +msgid "Name" +msgstr "Название" + +#: ejabberd_web_admin.erl:1866 +msgid "Storage Type" +msgstr "Тип таблицы" + +#: ejabberd_web_admin.erl:1867 +msgid "Elements" +msgstr "Элементы" + +#: ejabberd_web_admin.erl:1868 +msgid "Memory" +msgstr "Память" + +#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +msgid "Error" +msgstr "Ошибка" + +#: ejabberd_web_admin.erl:1893 +msgid "Backup of ~p" +msgstr "Резервное копирование ~p" + +#: ejabberd_web_admin.erl:1897 +msgid "" +"Please note that these options will only backup the builtin Mnesia database. " +"If you are using the ODBC module, you also need to backup your SQL database " +"separately." +msgstr "" +"Заметьте, что здесь производится резервное копирование только встроенной " +"базы данных Mnesia. Если Вы также используете другое хранилище данных " +"(например с помощью модуля ODBC), то его резервное копирование следует " +"осуществлять отдельно." + +#: ejabberd_web_admin.erl:1907 +msgid "Store binary backup:" +msgstr "Сохранить бинарную резервную копию:" + +#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 +#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 +#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 +#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 +#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 +#: ejabberd_web_admin.erl:2032 +msgid "OK" +msgstr "Продолжить" + +#: ejabberd_web_admin.erl:1917 +msgid "Restore binary backup immediately:" +msgstr "Восстановить из бинарной резервной копии немедленно:" + +#: ejabberd_web_admin.erl:1927 +msgid "" +"Restore binary backup after next ejabberd restart (requires less memory):" +msgstr "" +"Восстановить из бинарной резервной копии при следующем запуске (требует " +"меньше памяти):" + +#: ejabberd_web_admin.erl:1937 +msgid "Store plain text backup:" +msgstr "Сохранить текстовую резервную копию:" + +#: ejabberd_web_admin.erl:1947 +msgid "Restore plain text backup immediately:" +msgstr "Восстановить из текстовой резервной копии немедленно:" + +#: ejabberd_web_admin.erl:1957 +msgid "Import users data from a PIEFXIS file (XEP-0227):" +msgstr "Импорт пользовательских данных из файла формата PIEFXIS (XEP-0227):" + +#: ejabberd_web_admin.erl:1970 +msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" +msgstr "" +"Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-0227):" + +#: ejabberd_web_admin.erl:1982 +msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" +msgstr "" +"Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):" + +#: ejabberd_web_admin.erl:1998 +msgid "Export all tables as SQL queries to a file:" +msgstr "Экспортировать все таблицы в виде SQL запросов в файл:" + +#: ejabberd_web_admin.erl:2014 +msgid "Import user data from jabberd14 spool file:" +msgstr "Импорт пользовательских данных из буферного файла jabberd14:" + +#: ejabberd_web_admin.erl:2025 +msgid "Import users data from jabberd14 spool directory:" +msgstr "Импорт пользовательских данных из буферной директории jabberd14:" + +#: ejabberd_web_admin.erl:2053 +msgid "Listened Ports at " +msgstr "Прослушиваемые порты на " + +#: ejabberd_web_admin.erl:2082 +msgid "Modules at ~p" +msgstr "Модули на ~p" + +#: ejabberd_web_admin.erl:2113 +msgid "Statistics of ~p" +msgstr "статистика узла ~p" + +#: ejabberd_web_admin.erl:2117 +msgid "Uptime:" +msgstr "Время работы:" + +#: ejabberd_web_admin.erl:2121 +msgid "CPU Time:" +msgstr "Процессорное время:" + +#: ejabberd_web_admin.erl:2129 +msgid "Transactions Committed:" +msgstr "Транзакции завершенные:" + +#: ejabberd_web_admin.erl:2133 +msgid "Transactions Aborted:" +msgstr "Транзакции отмененные:" + +#: ejabberd_web_admin.erl:2137 +msgid "Transactions Restarted:" +msgstr "Транзакции перезапущенные:" + +#: ejabberd_web_admin.erl:2141 +msgid "Transactions Logged:" +msgstr "Транзакции запротоколированные:" + +#: ejabberd_web_admin.erl:2181 +msgid "Update ~p" +msgstr "Обновление ~p" + +#: ejabberd_web_admin.erl:2192 +msgid "Update plan" +msgstr "План обновления" + +#: ejabberd_web_admin.erl:2193 +msgid "Modified modules" +msgstr "Изменённые модули" + +#: ejabberd_web_admin.erl:2194 +msgid "Update script" +msgstr "Сценарий обновления" + +#: ejabberd_web_admin.erl:2195 +msgid "Low level update script" +msgstr "Низкоуровневый сценарий обновления" + +#: ejabberd_web_admin.erl:2196 +msgid "Script check" +msgstr "Проверка сценария" + #: ejabberd_web_admin.erl:2376 msgid "IP" msgstr "IP" @@ -181,14 +505,6 @@ msgstr "Модуль" msgid "Options" msgstr "Параметры" -#: ejabberd_web_admin.erl:2407 ejabberd_web_admin.erl:2551 -msgid "Restart" -msgstr "Перезапустить" - -#: ejabberd_web_admin.erl:2411 ejabberd_web_admin.erl:2555 -msgid "Stop" -msgstr "Остановить" - #: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 msgid "Start" msgstr "Запустить" @@ -274,10 +590,6 @@ msgstr "Удалить сообщение дня со всех виртуаль msgid "Configuration" msgstr "Конфигурация" -#: mod_configure.erl:150 mod_configure.erl:611 -msgid "Database" -msgstr "База данных" - #: mod_configure.erl:153 mod_configure.erl:636 msgid "Start Modules" msgstr "Запуск модулей" @@ -286,10 +598,6 @@ msgstr "Запуск модулей" msgid "Stop Modules" msgstr "Остановка модулей" -#: mod_configure.erl:159 mod_configure.erl:648 -msgid "Backup" -msgstr "Резервное копирование" - #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "Восстановление из резервной копии" @@ -347,14 +655,6 @@ msgstr "Получить количество зарегистрированны msgid "Get Number of Online Users" msgstr "Получить количество подключённых пользователей" -#: mod_configure.erl:196 mod_configure.erl:532 -msgid "Access Control Lists" -msgstr "Списки управления доступом" - -#: mod_configure.erl:198 mod_configure.erl:533 -msgid "Access Rules" -msgstr "Правила доступа" - #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "Управление пользователями" @@ -367,10 +667,6 @@ msgstr "Все пользователи" msgid "Outgoing s2s Connections" msgstr "Исходящие s2s-соединения" -#: mod_configure.erl:613 mod_configure.erl:626 -msgid "Modules" -msgstr "Модули" - #: mod_configure.erl:615 msgid "Backup Management" msgstr "Управление резервным копированием" @@ -516,10 +812,6 @@ msgstr "Количество зарегистрированных пользов msgid "Number of online users" msgstr "Количество подключённых пользователей" -#: mod_configure.erl:1854 mod_muc_log.erl:474 mod_muc_log.erl:477 -msgid "has been kicked" -msgstr "выгнали из комнаты" - #: mod_configure.erl:1937 msgid "Last login" msgstr "Время последнего подключения" @@ -666,6 +958,10 @@ msgstr "Кодировка сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" +#: mod_muc.erl:797 mod_muc_admin.erl:321 +msgid "Chatrooms" +msgstr "Комнаты" + #: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" msgstr "Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент" @@ -678,7 +974,7 @@ msgstr "Регистрация псевдонима на " msgid "Enter nickname you want to register" msgstr "Введите псевдоним, который Вы хотели бы зарегистрировать" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдоним" @@ -687,35 +983,27 @@ msgstr "Псевдоним" msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "Конференция" -#: mod_muc_admin.erl:246 -msgid "Statistics" -msgstr "Статистика" - -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 msgid "Total rooms" msgstr "Все комнаты" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 msgid "Permanent rooms" msgstr "Постоянные комнаты" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 msgid "Registered nicknames" msgstr "Зарегистрированные псевдонимы" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "Список комнат" -#: mod_muc_admin.erl:320 -msgid "Chatrooms" -msgstr "Комнаты" - #: mod_muc_log.erl:445 mod_muc_log.erl:454 msgid "Chatroom configuration modified" msgstr "Конфигурация комнаты изменилась" @@ -852,182 +1140,182 @@ msgstr "Конфигурация комнаты" msgid "Room Occupants" msgstr "Участники комнаты" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Только модераторы и участники могут изменять тему в этой комнате" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Только модераторы могут изменять тему в этой комнате" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s недопустимый" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Псевдоним ~s в комнате отсутствует" -#: mod_muc_room.erl:2788 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Недопустимый ранг: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Недопустимая роль: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Конфигурация комнаты ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Название комнаты" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Описание комнаты" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Сделать комнату постоянной" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Сделать комнату видимой всем" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Сделать список участников видимым всем" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Сделать комнату защищённой паролем" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Максимальное количество участников" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Не ограничено" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Сделать реальные Jabber ID участников видимыми" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "только модераторам" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "всем участникам" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Комната только для зарегистрированных участников" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Сделать комнату модерируемой" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Сделать пользователей участниками по умолчанию" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Разрешить пользователям изменять тему" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Разрешить приватные сообщения" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Разрешить посетителям посылать приватные сообщения" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "никто" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Разрешить iq-запросы к пользователям" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Разрешить пользователям посылать приглашения" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Разрешить посетителям вставлять текcт статуса в сообщения о присутствии" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Разрешить посетителям изменять псевдоним" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Разрешить посетителям запрашивать право голоса" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Минимальный интервал между запросами на право голоса" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Сделать комнату защищённой капчей" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "Включить хранение сообщений" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Исключить показ капчи для списка Jabber ID" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Включить журналирование" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Чтобы сконфигурировать комнату, требуется x:data-совместимый клиент" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Число присутствующих" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "приватная, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Запрос на право голоса" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Подтвердите или отклоните право голоса." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "JID пользователя" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Предоставить голос?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s приглашает вас в комнату ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "пароль:" @@ -1059,10 +1347,6 @@ msgstr "Кому" msgid "Packet" msgstr "Пакет" -#: mod_offline.erl:809 mod_shared_roster.erl:1180 -msgid "Delete Selected" -msgstr "Удалить выделенные" - #: mod_offline.erl:977 msgid "Offline Messages:" msgstr "Офлайновые сообщения:" @@ -1356,10 +1640,6 @@ msgstr "Видимые группы:" msgid "Group " msgstr "Группа " -#: mod_shared_roster.erl:1274 -msgid "Submit" -msgstr "Отправить" - #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" msgstr "Erlang Jabber Server" @@ -1400,10 +1680,6 @@ msgstr "Полное имя" msgid "Middle Name" msgstr "Отчество" -#: mod_vcard.erl:490 mod_vcard.erl:616 -msgid "Name" -msgstr "Название" - #: mod_vcard.erl:490 mod_vcard.erl:626 msgid "Organization Name" msgstr "Название организации" @@ -1436,190 +1712,6 @@ msgstr "Результаты поиска в " msgid "Fill in fields to search for any matching Jabber User" msgstr "Заполните форму для поиска пользователя Jabber" -#~ msgid "Use of STARTTLS required" -#~ msgstr "Вы обязаны использовать STARTTLS" - -#~ msgid "No resource provided" -#~ msgstr "Не указан ресурс" - -#~ msgid "Replaced by new connection" -#~ msgstr "Заменено новым соединением" - -#~ msgid "Too many unacked stanzas" -#~ msgstr "Слишком много неподтверждённых пакетов" - -#~ msgid "Unauthorized" -#~ msgstr "Не авторизован" - -#~ msgid "Administration" -#~ msgstr "Администрирование" - -#~ msgid "Raw" -#~ msgstr "Необработанный формат" - -#~ msgid "~s access rule configuration" -#~ msgstr "Конфигурация правила доступа ~s" - -#~ msgid "Virtual Hosts" -#~ msgstr "Виртуальные хосты" - -#~ msgid "Users" -#~ msgstr "Пользователи" - -#~ msgid "Users Last Activity" -#~ msgstr "Статистика последнего подключения пользователей" - -#~ msgid "Period: " -#~ msgstr "Период" - -#~ msgid "Last month" -#~ msgstr "За последний месяц" - -#~ msgid "Last year" -#~ msgstr "За последний год" - -#~ msgid "All activity" -#~ msgstr "Вся статистика" - -#~ msgid "Show Ordinary Table" -#~ msgstr "Показать обычную таблицу" - -#~ msgid "Show Integral Table" -#~ msgstr "Показать интегральную таблицу" - -#~ msgid "Not Found" -#~ msgstr "Не Найдено" - -#~ msgid "Node not found" -#~ msgstr "Узел не найден" - -#~ msgid "Node ~p" -#~ msgstr "Узел ~p" - -#~ msgid "Listened Ports" -#~ msgstr "Прослушиваемые порты" - -#~ msgid "Update" -#~ msgstr "Обновить" - -#~ msgid "RPC Call Error" -#~ msgstr "Ошибка вызова RPC" - -#~ msgid "Database Tables at ~p" -#~ msgstr "Таблицы базы данных на ~p" - -#~ msgid "Storage Type" -#~ msgstr "Тип таблицы" - -#~ msgid "Elements" -#~ msgstr "Элементы" - -#~ msgid "Memory" -#~ msgstr "Память" - -#~ msgid "Error" -#~ msgstr "Ошибка" - -#~ msgid "Backup of ~p" -#~ msgstr "Резервное копирование ~p" - -#~ msgid "" -#~ "Please note that these options will only backup the builtin Mnesia " -#~ "database. If you are using the ODBC module, you also need to backup your " -#~ "SQL database separately." -#~ msgstr "" -#~ "Заметьте, что здесь производится резервное копирование только встроенной " -#~ "базы данных Mnesia. Если Вы также используете другое хранилище данных " -#~ "(например с помощью модуля ODBC), то его резервное копирование следует " -#~ "осуществлять отдельно." - -#~ msgid "Store binary backup:" -#~ msgstr "Сохранить бинарную резервную копию:" - -#~ msgid "OK" -#~ msgstr "Продолжить" - -#~ msgid "Restore binary backup immediately:" -#~ msgstr "Восстановить из бинарной резервной копии немедленно:" - -#~ msgid "" -#~ "Restore binary backup after next ejabberd restart (requires less memory):" -#~ msgstr "" -#~ "Восстановить из бинарной резервной копии при следующем запуске (требует " -#~ "меньше памяти):" - -#~ msgid "Store plain text backup:" -#~ msgstr "Сохранить текстовую резервную копию:" - -#~ msgid "Restore plain text backup immediately:" -#~ msgstr "Восстановить из текстовой резервной копии немедленно:" - -#~ msgid "Import users data from a PIEFXIS file (XEP-0227):" -#~ msgstr "Импорт пользовательских данных из файла формата PIEFXIS (XEP-0227):" - -#~ msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" -#~ msgstr "" -#~ "Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-" -#~ "0227):" - -#~ msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" -#~ msgstr "" -#~ "Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):" - -#~ msgid "Export all tables as SQL queries to a file:" -#~ msgstr "Экспортировать все таблицы в виде SQL запросов в файл:" - -#~ msgid "Import user data from jabberd14 spool file:" -#~ msgstr "Импорт пользовательских данных из буферного файла jabberd14:" - -#~ msgid "Import users data from jabberd14 spool directory:" -#~ msgstr "Импорт пользовательских данных из буферной директории jabberd14:" - -#~ msgid "Listened Ports at " -#~ msgstr "Прослушиваемые порты на " - -#~ msgid "Modules at ~p" -#~ msgstr "Модули на ~p" - -#~ msgid "Statistics of ~p" -#~ msgstr "статистика узла ~p" - -#~ msgid "Uptime:" -#~ msgstr "Время работы:" - -#~ msgid "CPU Time:" -#~ msgstr "Процессорное время:" - -#~ msgid "Transactions Committed:" -#~ msgstr "Транзакции завершенные:" - -#~ msgid "Transactions Aborted:" -#~ msgstr "Транзакции отмененные:" - -#~ msgid "Transactions Restarted:" -#~ msgstr "Транзакции перезапущенные:" - -#~ msgid "Transactions Logged:" -#~ msgstr "Транзакции запротоколированные:" - -#~ msgid "Update ~p" -#~ msgstr "Обновление ~p" - -#~ msgid "Update plan" -#~ msgstr "План обновления" - -#~ msgid "Modified modules" -#~ msgstr "Изменённые модули" - -#~ msgid "Update script" -#~ msgstr "Сценарий обновления" - -#~ msgid "Low level update script" -#~ msgstr "Низкоуровневый сценарий обновления" - -#~ msgid "Script check" -#~ msgstr "Проверка сценария" - #~ msgid "Delete" #~ msgstr "Удалить" diff --git a/priv/msgs/sk.msg b/priv/msgs/sk.msg index 5c75e704e8d..ef10413126a 100644 --- a/priv/msgs/sk.msg +++ b/priv/msgs/sk.msg @@ -62,7 +62,6 @@ {"Delete message of the day","Zmazať správu dňa"}. {"Delete Selected","Zmazať vybrané"}. {"Delete User","Vymazať užívateľa"}. -{"Delete","Zmazať"}. {"Deliver event notifications","Doručiť oznamy o udalosti"}. {"Deliver payloads with event notifications","Doručiť náklad s upozornením na udalosť"}. {"Description:","Popis:"}. @@ -331,7 +330,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Veľké a malé písmená sa nerozlišujú: macbeth je to isté ako MacBeth a Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Táto stránka umožňuje refistrovať Jabber účet na tomto serveri. Vaše JID (Jabber IDentifikátor) bude vo formáte: užívateľ@server. Pozorne sledujte inštrukcie, aby ste údaje vypnili správne."}. {"This page allows to unregister a Jabber account in this Jabber server.","Na tejto stránke si môžete zrušiť Jabber účet registrovaný na tomto serveri."}. -{"This room is not anonymous","Táto miestnosť nie je anonymná"}. {"Thursday","Štvrtok"}. {"Time","Čas"}. {"Time delay","Časový posun"}. diff --git a/priv/msgs/sk.po b/priv/msgs/sk.po index 39d9a21d0a1..03ce8f3b5cb 100644 --- a/priv/msgs/sk.po +++ b/priv/msgs/sk.po @@ -53,6 +53,26 @@ msgstr "Webová stránka CAPTCHA" msgid "The CAPTCHA is valid." msgstr "Platná CAPTCHA." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Užívateľ" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server ~b" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Heslo" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -157,7 +177,7 @@ msgid "Show Integral Table" msgstr "Zobraziť kompletnú tabuľku" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Štatistiky" @@ -181,17 +201,6 @@ msgstr "Server" msgid "Registered Users" msgstr "Registrovaní používatelia" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Užívateľ" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Heslo" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -943,7 +952,7 @@ msgstr "Kódovanie pre server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Diskusné miestnosti" @@ -959,7 +968,7 @@ msgstr "Registrácia prezývky na " msgid "Enter nickname you want to register" msgstr "Zadajte prezývku, ktorú chcete registrovať" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Prezývka" @@ -968,27 +977,27 @@ msgstr "Prezývka" msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Diskusné miestnosti" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "odišiel(a) z miestnosti" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrovaní používatelia" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1128,181 +1137,181 @@ msgstr "Nastavenia miestnosti" msgid "Room Occupants" msgstr "Ľudí v miestnosti" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Len moderátori a zúčastnený majú povolené meniť tému tejto miestnosti" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Len moderátori majú povolené meniť tému miestnosti" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s je neplatné" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Prezývka ~s v miestnosti neexistuje" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Neplatné priradenie: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Neplatná rola: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Konfigurácia miestnosti ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Názov miestnosti" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Popis miestnosti" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Nastaviť miestnosť ako trvalú" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Nastaviť miestnosť ako verejne prehľadávateľnú" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Nastaviť zoznam zúčastnených ako verejný" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Chrániť miestnosť heslom" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Počet účastníkov" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Zobrazovať skutočné Jabber ID" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "moderátorom" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "všetkým" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Nastaviť miestnosť len pre členov" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Nastaviť miestnosť ako moderovanú" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Užívatelia sú implicitne členmi" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Povoliť užívateľom meniť tému" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Povoliť užívateľom odosielať súkromné správy" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Povoliť užívateľom odosielať súkromné správy" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "nikto" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Povoliť užívateľom dotazovať sa informácie o iných užívateľoch" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Povoliť používateľom posielanie pozvánok" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Návštevníci môžu posielať textové informácie v stavových správach" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Návštevníci môžu meniť prezývky" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Povoliť používateľom posielanie pozvánok" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimum interval between voice requests (in seconds)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Chrániť miestnosť systémom CAPTCHA" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Nepoužívať CAPTCHA pre nasledujúce Jabber ID" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Zapnúť zaznamenávanie histórie" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Na konfiguráciu miestnosti potrebujete klienta podporujúceho x:data" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Počet zúčastnených" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "súkromná, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Žiadosť o Voice" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Povolte alebo zamietnite žiadosť o Voice." -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Používateľ " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Prideltiť Voice tejto osobe?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s Vás pozýva do miestnosti ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "heslo je" diff --git a/priv/msgs/sv.msg b/priv/msgs/sv.msg index a0bf3e978be..2eb56b41679 100644 --- a/priv/msgs/sv.msg +++ b/priv/msgs/sv.msg @@ -53,7 +53,6 @@ {"Delete message of the day on all hosts","Ta bort dagens meddelande på alla värdar"}. {"Delete message of the day","Ta bort dagens meddelande"}. {"Delete Selected","Tabort valda"}. -{"Delete","Ta bort"}. {"Delete User","Ta bort användare"}. {"Deliver event notifications","Skicka eventnotifikation"}. {"Deliver payloads with event notifications","Skicka innehåll tillsammans med notifikationer"}. @@ -293,7 +292,6 @@ {"Sunday","Söndag"}. {"The CAPTCHA is valid.","Din CAPTCHA är godkänd."}. {"the password is","Lösenordet är"}. -{"This room is not anonymous","Detta rum är inte anonymt"}. {"Thursday","Torsdag"}. {"Time delay","Tidsförsening"}. {"Time","Tid"}. diff --git a/priv/msgs/sv.po b/priv/msgs/sv.po index a42582ddf8a..cfb28dab4ce 100644 --- a/priv/msgs/sv.po +++ b/priv/msgs/sv.po @@ -53,6 +53,26 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "Din CAPTCHA är godkänd." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Användarnamn" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Server ~b" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Lösenord" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -157,7 +177,7 @@ msgid "Show Integral Table" msgstr "Visa kumulativ tabell" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistik" @@ -181,17 +201,6 @@ msgstr "Server" msgid "Registered Users" msgstr "Registrerade användare" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Användarnamn" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Lösenord" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -939,7 +948,7 @@ msgstr "Encoding för server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Chattrum" @@ -956,7 +965,7 @@ msgstr "Registrera smeknamn på " msgid "Enter nickname you want to register" msgstr "Skriv in smeknamnet du vill registrera" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Smeknamn" @@ -965,27 +974,27 @@ msgstr "Smeknamn" msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Chattrum" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "lämnar rummet" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Registrerade användare" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1129,7 +1138,7 @@ msgstr "Rumkonfiguration" msgid "Room Occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1137,181 +1146,181 @@ msgstr "" "Endast moderatorer och deltagare har tillåtelse att ändra ämnet i det här " "rummet" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Endast moderatorer får ändra ämnet i det här rummet" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Otillåtet Jabber ID ~s" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Smeknamnet ~s existerar inte i det här rummet" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Ogiltlig rang: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Ogiltlig roll: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Konfiguration för ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Rumstitel" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 #, fuzzy msgid "Room description" msgstr "Beskrivning:" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Gör rummet permanent" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Gör rummet publikt sökbart" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Gör deltagarlistan publik" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Gör losenorden i rummet publika" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Maximalt antal av användare" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Ingen gräns" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Nuvarande äkta Jabber IDs till" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "endast moderatorer" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "Vemsomhelst" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Gör om rummet till endast medlemmar" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Gör rummet modererat" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Gör om användare till deltagare" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Tillåt användare att byta ämne" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Tillåt användare att skicka privata meddelanden" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Tillåt användare att skicka privata meddelanden" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Tillåt användare att söka efter andra användare" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Tillåt användare att skicka inbjudningar" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "Tillåt gäster att skicka statustext som uppdatering" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Tillåt gäster att kunna ändra smeknamn" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Tillåt användare att skicka inbjudningar" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Gör losenorden i rummet publika" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Möjliggör login" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "Du behöver en klient som stödjer x:data för att konfiguera detta rum" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Användare " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s bjöd in dig till rummet ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "Lösenordet är" diff --git a/priv/msgs/th.msg b/priv/msgs/th.msg index 17989e31e8c..18acbef4acb 100644 --- a/priv/msgs/th.msg +++ b/priv/msgs/th.msg @@ -44,7 +44,6 @@ {"Database Tables Configuration at ","การกำหนดค่าตารางฐานข้อมูลที่"}. {"December","ธันวาคม"}. {"Default users as participants","ผู้ใช้เริ่มต้นเป็นผู้เข้าร่วม"}. -{"Delete","ลบ"}. {"Delete message of the day","ลบข้อความของวัน"}. {"Delete message of the day on all hosts","ลบข้อความของวันบนโฮสต์ทั้งหมด"}. {"Delete Selected","ลบข้อความที่เลือก"}. @@ -251,7 +250,6 @@ {"Subscription","การสมัครสมาชิก"}. {"Sunday","วันอาทิตย์"}. {"the password is","รหัสผ่านคือ"}. -{"This room is not anonymous","ห้องนี้ไม่ปิดบังชื่อ"}. {"Thursday","วันพฤหัสบดี"}. {"Time","เวลา"}. {"Time delay","การหน่วงเวลา"}. diff --git a/priv/msgs/th.po b/priv/msgs/th.po index 6f2f5db865f..d988554c482 100644 --- a/priv/msgs/th.po +++ b/priv/msgs/th.po @@ -49,6 +49,26 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "ผู้ใช้" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "ไม่เคย" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "รหัสผ่าน" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -154,7 +174,7 @@ msgid "Show Integral Table" msgstr "แสดงตารางรวม" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "สถิติ" @@ -179,17 +199,6 @@ msgstr "โฮสต์" msgid "Registered Users" msgstr "ผู้ใช้ที่ลงทะเบียน" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "ผู้ใช้" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "รหัสผ่าน" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -943,7 +952,7 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "ห้องสนทนา" @@ -960,7 +969,7 @@ msgstr "การลงทะเบียนชื่อเล่นที่ " msgid "Enter nickname you want to register" msgstr "ป้อนชื่อเล่นที่คุณต้องการลงทะเบียน" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "ชื่อเล่น" @@ -969,27 +978,27 @@ msgstr "ชื่อเล่น" msgid "ejabberd MUC module" msgstr "ejabberd MUC module" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "ห้องสนทนา" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "ออกจากห้อง" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "ผู้ใช้ที่ลงทะเบียน" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1134,193 +1143,193 @@ msgstr "การกำหนดค่าห้องสนทนา" msgid "Room Occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "ผู้ดูแลการสนทนาและผู้เข้าร่วมเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s ไม่ถูกต้อง" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "ไม่มีชื่อเล่น ~s อยู่ในห้องนี้" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "การเข้าร่วมที่ไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "บทบาทไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 #, fuzzy msgid "Configuration of room ~s" msgstr "การกำหนดค่าสำหรับ " -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "ชื่อห้อง" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 #, fuzzy msgid "Room description" msgstr "รายละเอียด:" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "สร้างเป็นห้องถาวร" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "สร้างเป็นห้องที่บุคคลทั่วไปสามารถค้นหาได้" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "สร้างรายการผู้เข้าร่วมสำหรับใช้งานโดยบุคคลทั่วไป" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "สร้างห้องที่มีการป้องกันด้วยรหัสผ่าน" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "จำนวนผู้ครอบครองห้องสูงสุด" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "ไม่จำกัด" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "แสดง Jabber IDs ที่ถูกต้องแก่" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "สำหรับผู้ดูแลการสนทนาเท่านั้น" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "ทุกคน" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "สร้างห้องสำหรับสมาชิกเท่านั้น" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 #, fuzzy msgid "Make room moderated" msgstr "สร้างเป็นห้องถาวร" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "ผู้ใช้เริ่มต้นเป็นผู้เข้าร่วม" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 #, fuzzy msgid "Allow users to change the subject" msgstr "อนุญาตให้ผู้ใช้เปลี่ยนหัวข้อได้" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "อนุญาตให้ผู้ใช้ถามคำถามกับผู้ใช้คนอื่นๆ ได้" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to change nickname" msgstr "อนุญาตให้ผู้ใช้เปลี่ยนหัวข้อได้" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "สร้างห้องที่มีการป้องกันด้วยรหัสผ่าน" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "เปิดใช้งานการบันทึก" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดค่าห้องสนทนา " -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "ส่วนตัว, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "ผู้ใช้" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s เชิญคุณเข้าร่วมสนทนาในห้อง ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "รหัสผ่านคือ" diff --git a/priv/msgs/tr.msg b/priv/msgs/tr.msg index df2db867521..dd4927eec31 100644 --- a/priv/msgs/tr.msg +++ b/priv/msgs/tr.msg @@ -61,7 +61,6 @@ {"Delete message of the day","Günün mesajını sil"}. {"Delete message of the day on all hosts","Tüm sunuculardaki günün mesajını sil"}. {"Delete Selected","Seçilenleri Sil"}. -{"Delete","Sil"}. {"Delete User","Kullanıcıyı Sil"}. {"Deliver event notifications","Olay uyarıları gönderilsin"}. {"Deliver payloads with event notifications","Yükleri (payload) olay uyarıları ile beraber gönder"}. @@ -332,7 +331,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Burada büyük küçük harfi yapılmaz: macbeth ile MacBeth ve Macbeth aynıdır."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Bu sayfa bu Jabber sunucusunda bir Jabber hesabı oluşturulmasına olanak tanıyor. Sizin JID'iniz (Jabber Tanımlayıcısı) şu biçemde olacaktır: kullanici_adi@sunucu. Lütfen alanları doğru doldurabilmek için yönergeleri dikkatle okuyunuz."}. {"This page allows to unregister a Jabber account in this Jabber server.","Bu sayfa bu Jabber sunucusundan bir Jabber hesabının kaydını silmeye olanak tanıyor."}. -{"This room is not anonymous","Bu oda anonim değil"}. {"Thursday","Perşembe"}. {"Time delay","Zaman gecikmesi"}. {"Time","Zaman"}. diff --git a/priv/msgs/tr.po b/priv/msgs/tr.po index 84a638baa6f..1c976864a13 100644 --- a/priv/msgs/tr.po +++ b/priv/msgs/tr.po @@ -57,6 +57,26 @@ msgstr "CAPTCHA web sayfası" msgid "The CAPTCHA is valid." msgstr "İnsan doğrulaması (captcha) geçerli." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Kullanıcı" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Sunucu:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Parola" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -161,7 +181,7 @@ msgid "Show Integral Table" msgstr "Önemli Tabloyu Göster" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "İstatistikler" @@ -185,17 +205,6 @@ msgstr "Sunucu" msgid "Registered Users" msgstr "Kayıtlı Kullanıcılar" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Kullanıcı" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Parola" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -951,7 +960,7 @@ msgstr "Sunucu için kodlama ~b" msgid "Server ~b" msgstr "Sunucu ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Sohbet Odaları" @@ -969,7 +978,7 @@ msgstr "Takma İsim Kaydı : " msgid "Enter nickname you want to register" msgstr "Kaydettirmek istediğiniz takma ismi giriniz" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Takma isim" @@ -978,27 +987,27 @@ msgstr "Takma isim" msgid "ejabberd MUC module" msgstr "ejabberd MUC modülü" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Sohbet Odaları" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "odadan ayrıldı" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Kayıtlı Kullanıcılar" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1138,7 +1147,7 @@ msgstr "Oda Ayarları" msgid "Room Occupants" msgstr "Oda Sakini Sayısı" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1146,178 +1155,178 @@ msgstr "" "Sadece moderatörlerin ve katılımcıların bu odanın konusunu değiştirmesine " "izin veriliyor" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Sadece moderatörlerin bu odanın konusunu değiştirmesine izin veriliyor" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s geçersiz" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "~s takma ismi odada yok" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Geçersiz ilişki: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Geçersiz rol: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "~s odasının ayarları" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Oda başlığı" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Oda tanımı" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Odayı kalıcı hale getir" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Odayı herkes tarafından aranabilir hale getir" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Katılımcı listesini herkese açık hale getir" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Odayı parola korumalı hale getir" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Odada En Fazla Bulunabilecek Kişi Sayısı" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Sınırsız" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Gerçek Jabber ID'lerini göster :" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "sadece moderatörler" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "herkes" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Odayı sadece üyelere açık hale getir" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Odayı moderasyonlu hale getir" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Kullanıcılar öntanımlı olarak katılımcı olsun" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Kullanıcıların konu değiştirmesine izin ver" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Kullanıcıların özel mesaj göndermelerine izin ver" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "Ziyaretçilerin özel mesaj göndermelerine izin ver" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "hiç kimse" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Kullanıcıların diğer kullanıcıları sorgulamalarına izin ver" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Kullanıcıların davetiye göndermelerine izin ver" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Ziyaretçilerin varlık (presence) güncellemelerinde durum metni " "göndermelerine izin ver" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Ziyaretçilerin takma isim değiştirmelerine izin ver" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "Ziyaretçilerin ses isteğine göndermelerine izin ver" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ses istekleri arasında olabilecek en az aralık (saniye olarak)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Odayı insan doğrulaması (captcha) korumalı hale getir" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA doğrulamasını şu Jabber ID'ler için yapma" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Kayıt tutma özelliğini aç" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "Odayı ayarlamak için x:data becerisine sahip bir istemciye gereksinimiz var" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Oda sakini sayısı" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "özel" -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "Ses isteği" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "Ses isteğini kabul edin ya da reddedin" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "Kullanıcı JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "Bu kişiye ses verelim mi?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s sizi ~s odasına davet ediyor" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "parola :" diff --git a/priv/msgs/uk.msg b/priv/msgs/uk.msg index f6f9553e76c..48abe548073 100644 --- a/priv/msgs/uk.msg +++ b/priv/msgs/uk.msg @@ -60,7 +60,6 @@ {"Delete message of the day","Видалити повідомлення дня"}. {"Delete Selected","Видалити виділені"}. {"Delete User","Видалити Користувача"}. -{"Delete","Видалити"}. {"Deliver event notifications","Доставляти сповіщення про події"}. {"Deliver payloads with event notifications","Доставляти разом з повідомленнями про публікації самі публікації"}. {"Description:","Опис:"}. @@ -326,7 +325,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Регістр не має значення: \"МАША\" та \"маша\" буде сприйматися як одне й те саме ім'я."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Тут ви можете зареєструвати обліковий запис Jabber на цьому сервері. Ваш JID (ідентифікатор Jabber) матиме вигляд \"користувач@сервер\". Щоб вірно заповнити поля нижче, будь ласка, уважно читайте інструкції до них."}. {"This page allows to unregister a Jabber account in this Jabber server.","Ця сторінка дозволяє видалити свій акаунт з Jabber-сервера."}. -{"This room is not anonymous","Ця кімната не анонімна"}. {"Thursday","Четвер"}. {"Time delay","Час затримки"}. {"Time","Час"}. diff --git a/priv/msgs/uk.po b/priv/msgs/uk.po index d9f8b91395f..8b39ac64a61 100644 --- a/priv/msgs/uk.po +++ b/priv/msgs/uk.po @@ -55,6 +55,26 @@ msgstr "Адреса капчі" msgid "The CAPTCHA is valid." msgstr "Перевірку капчею закінчено успішно" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Користувач" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Сервер:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Пароль" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -159,7 +179,7 @@ msgid "Show Integral Table" msgstr "Показати інтегральну таблицю" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Статистика" @@ -183,17 +203,6 @@ msgstr "Хост" msgid "Registered Users" msgstr "Зареєстровані користувачі" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Користувач" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Пароль" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -949,7 +958,7 @@ msgstr "Кодування для сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Кімнати" @@ -967,7 +976,7 @@ msgstr "Реєстрація псевдоніма на " msgid "Enter nickname you want to register" msgstr "Введіть псевдонім, який ви хочете зареєструвати" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдонім" @@ -976,27 +985,27 @@ msgstr "Псевдонім" msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Кімнати" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "вийшов(ла) з кімнати" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Зареєстровані користувачі" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1136,187 +1145,187 @@ msgstr "Конфігурація кімнати" msgid "Room Occupants" msgstr "Учасники кімнати" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Тільки модератори та учасники можуть змінювати тему в цій кімнаті" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s недопустимий" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Псевдонім ~s в кімнаті відсутній" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Недопустимий ранг: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Недопустима роль: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "Конфігурація кімнати ~s" -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Назва кімнати" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "Опис кімнати" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Зробити кімнату постійною" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Зробити кімнату видимою всім" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Зробити список учасників видимим всім" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Зробити кімнату захищеною паролем" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Максимальна кількість учасників" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Без обмежень" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Зробити реальні Jabber ID учасників видимими" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "тільки модераторам" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "всім учасникам" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Кімната тільки для зареєтрованых учасників" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Зробити кімнату модерованою" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Зробити користувачів учасниками за замовчуванням" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "Дозволити користувачам змінювати тему" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Дозволити приватні повідомлення" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Дозволити приватні повідомлення" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Дозволити iq-запити до користувачів" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Дозволити користувачам надсилати запрошення" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Дозволити відвідувачам відсилати текст статусу в оновленнях присутності" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Дозволити відвідувачам змінювати псевдонім" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Дозволити користувачам надсилати запрошення" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "Зробити кімнату захищеною капчею" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Пропускати ці Jabber ID без CAPTCHA-запиту" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Включити журнал роботи" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "Для конфігурування кімнати потрібно використовувати клієнт з підтримкою x:" "data" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Кількість присутніх" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "приватна, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Користувач " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s запрошує вас до кімнати ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "пароль:" diff --git a/priv/msgs/vi.msg b/priv/msgs/vi.msg index bacc0a5412b..4edeb1baf60 100644 --- a/priv/msgs/vi.msg +++ b/priv/msgs/vi.msg @@ -48,7 +48,6 @@ {"Delete message of the day","Xóa thư trong ngày"}. {"Delete Selected","Tùy chọn Xóa được Chọn"}. {"Delete User","Xóa Người Sử Dụng"}. -{"Delete","Xóa"}. {"Deliver event notifications","Đưa ra các thông báo sự kiện"}. {"Deliver payloads with event notifications","Đưa ra thông tin dung lượng với các thông báo sự kiện"}. {"Description:","Miêu tả:"}. @@ -251,7 +250,6 @@ {"Subscription","Đăng ký"}. {"Sunday","Chủ Nhật"}. {"the password is","mật khẩu là"}. -{"This room is not anonymous","Phòng này không nặc danh"}. {"Thursday","Thứ Năm"}. {"Time delay","Thời gian trì hoãn"}. {"Time","Thời Gian"}. diff --git a/priv/msgs/vi.po b/priv/msgs/vi.po index dad52d6484d..e8101eac9c7 100644 --- a/priv/msgs/vi.po +++ b/priv/msgs/vi.po @@ -49,6 +49,26 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Người sử dụng" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Không bao giờ" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Mật Khẩu" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -154,7 +174,7 @@ msgid "Show Integral Table" msgstr "Hiển Thị Bảng Đầy Đủ" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Số liệu thống kê" @@ -179,17 +199,6 @@ msgstr "Máy chủ" msgid "Registered Users" msgstr "Người Sử Dụng Đã Đăng Ký" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Người sử dụng" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Mật Khẩu" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -954,7 +963,7 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Phòng trò chuyện" @@ -973,7 +982,7 @@ msgstr "Đăng Ký Bí Danh tại" msgid "Enter nickname you want to register" msgstr "Nhập bí danh bạn muốn đăng ký" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Bí danh" @@ -982,27 +991,27 @@ msgstr "Bí danh" msgid "ejabberd MUC module" msgstr "Môdun ejabberd MUC Bản quyền" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Phòng trò chuyện" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "rời khỏi phòng này" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Người Sử Dụng Đã Đăng Ký" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1147,7 +1156,7 @@ msgstr "Cấu Hình Phòng" msgid "Room Occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " @@ -1156,188 +1165,188 @@ msgstr "" "Chỉ có những người điều phối và những người tham gia được phép thay đổi chủ " "đề trong phòng này" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s không hợp lệ" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Bí danh ~s không tồn tại trong phòng này" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Tư cách không hợp lệ: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Vai trò không hợp lệ: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 #, fuzzy msgid "Configuration of room ~s" msgstr "Cấu hình cho " -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Tên phòng" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 #, fuzzy msgid "Room description" msgstr "Miêu tả:" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Tạo phòng bền vững" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Tạo phòng có thể tìm kiếm công khai" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Tạo danh sách người tham dự công khai" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Tạo phòng được bảo vệ bằng mật khẩu" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Số Lượng Người Tham Dự Tối Đa" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Không giới hạn" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Jabber ID thực tế hiện hành đến" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "nhà điều phối duy nhất" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "bất kỳ ai" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Tạo phòng chỉ cho phép tư cách thành viên tham gia" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 #, fuzzy msgid "Make room moderated" msgstr "Tạo phòng bền vững" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Người sử dụng mặc định là người tham dự" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 #, fuzzy msgid "Allow users to change the subject" msgstr "Cho phép người sử dụng thay đổi chủ đề" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Cho phép người sử dụng hỏi người sử dụng khác" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Cho phép người sử dụng gửi lời mời" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Cho phép người sử dụng thay đổi chủ đề" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Cho phép người sử dụng gửi lời mời" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Tạo phòng được bảo vệ bằng mật khẩu" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Cho phép ghi nhật ký" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định " "cấu hình phòng họp" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "riêng," -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Người sử dụng " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s mời bạn vào phòng ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "mật khẩu là" diff --git a/priv/msgs/wa.msg b/priv/msgs/wa.msg index d915b6aeeac..8fee456c687 100644 --- a/priv/msgs/wa.msg +++ b/priv/msgs/wa.msg @@ -47,7 +47,6 @@ {"Database Tables Configuration at ","Apontiaedje des tåves del båze di dnêyes so "}. {"December","decimbe"}. {"Default users as participants","Les uzeus sont des pårticipants come prémetowe dujhance"}. -{"Delete","Disfacer"}. {"Delete message of the day","Disfacer l' messaedje do djoû"}. {"Delete message of the day on all hosts","Disfacer l' messaedje do djoû so tos les lodjoes"}. {"Delete Selected","Disfacer les elemints tchoezis"}. @@ -260,7 +259,6 @@ {"Subscription","Abounmimnt"}. {"Sunday","dimegne"}. {"the password is","li scret est"}. -{"This room is not anonymous","Cisse såle ci n' est nén anonime"}. {"Thursday","djudi"}. {"Time","Date"}. {"Time delay","Tårdjaedje"}. diff --git a/priv/msgs/wa.po b/priv/msgs/wa.po index 7f424fd4cbb..ae42f0b269e 100644 --- a/priv/msgs/wa.po +++ b/priv/msgs/wa.po @@ -49,6 +49,26 @@ msgstr "" msgid "The CAPTCHA is valid." msgstr "" +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "Uzeu" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "Måy" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "Sicret" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -153,7 +173,7 @@ msgid "Show Integral Table" msgstr "Mostrer totå" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Sitatistikes" @@ -178,17 +198,6 @@ msgstr "Sierveu" msgid "Registered Users" msgstr "Uzeus edjistrés" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "Uzeu" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "Sicret" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -952,7 +961,7 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Såles di berdelaedje" @@ -970,7 +979,7 @@ msgstr "Edjîstraedje di metou no amon " msgid "Enter nickname you want to register" msgstr "Dinez l' metou no ki vos vloz edjîstrer" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "Metou no" @@ -979,27 +988,27 @@ msgstr "Metou no" msgid "ejabberd MUC module" msgstr "Module MUC (såles di berdelaedje) po ejabberd" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "Såles di berdelaedje" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "cwite li såle" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "Uzeus edjistrés" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1145,7 +1154,7 @@ msgstr "Apontiaedje del såle" msgid "Room Occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " @@ -1154,185 +1163,185 @@ msgstr "" "Seulmint les moderateus et les pårticipants polèt candjî l' sudjet dins " "cisse såle ci" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Li Jabber ID ~s n' est nén valide" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "Li metou no ~s n' egzistêye nén dins l' såle" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "Afiyaedje nén valide: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "Role nén valide: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 #, fuzzy msgid "Configuration of room ~s" msgstr "Apontiaedje po " -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "Tite del såle" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 #, fuzzy msgid "Room description" msgstr "Discrijhaedje:" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "Rinde li såle permaninte" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "Rinde li såle di berdelaedje cweråve publicmint" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "Rinde publike li djivêye des pårticipants" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "Rinde li såle di berdelaedje protedjeye pa scret" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "Nombe macsimom di prezints" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "Pont d' limite" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "Mostrer les vraiys Jabber IDs a" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "les moderateus seulmint" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "tot l' minme kî" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "Rinde li såle di berdelaedje ristrindowe ås mimbes seulmint" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "Rinde li såle di berdelaedje moderêye" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "Les uzeus sont des pårticipants come prémetowe dujhance" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 #, fuzzy msgid "Allow users to change the subject" msgstr "Les uzeus polèt candjî l' tite" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "Les uzeus polèt evoyî des messaedjes privés" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Les uzeus polèt evoyî des messaedjes privés" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "Les uzeus polèt cweri ls ôtes uzeus" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "Les uzeus polèt evoyî priyaedjes" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permete ki les viziteus evoyexhe des tecse d' estat dins leus messaedjes di " "prezince" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "Permete ki les viziteus candjexhe leus metous nos" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Les uzeus polèt evoyî priyaedjes" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Rinde li såle di berdelaedje protedjeye pa scret" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "Mete en alaedje li djournå" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "I vs fåt on cliyint ki sopoite x:data por vos poleur apontyî l' såle" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 #, fuzzy msgid "User JID" msgstr "Uzeu " -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s vos preye sol såle ~s" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "li scret est" diff --git a/priv/msgs/zh.msg b/priv/msgs/zh.msg index 62bd900e6ed..131b84f7065 100644 --- a/priv/msgs/zh.msg +++ b/priv/msgs/zh.msg @@ -62,7 +62,6 @@ {"Delete message of the day","删除每日消息"}. {"Delete Selected","删除已选内容"}. {"Delete User","删除用户"}. -{"Delete","删除"}. {"Deliver event notifications","传递事件通知"}. {"Deliver payloads with event notifications","用事件通告传输有效负载"}. {"Description:","描述:"}. @@ -332,7 +331,6 @@ {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","此处不区分大小写: macbeth 与 MacBeth 和 Macbeth 是一样的."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","本页面允许在此服务器上创建 Jabber 帐户. 你的 JID (Jabber ID) 的形式如下: 用户名@服务器. 请仔细阅读说明并正确填写相应字段."}. {"This page allows to unregister a Jabber account in this Jabber server.","此页面允许在此 Jabber 服务器上注销 Jabber 帐户"}. -{"This room is not anonymous","此房间不是匿名房间"}. {"Thursday","星期四"}. {"Time delay","时间延迟"}. {"Time","时间"}. diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index 0438b2e4d92..a1bd3d9ff88 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -50,6 +50,26 @@ msgstr "验证码网页" msgid "The CAPTCHA is valid." msgstr "验证码有效." +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 +#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +msgid "User" +msgstr "用户" + +#: ejabberd_oauth.erl:256 +#, fuzzy +msgid "Server" +msgstr "服务器:" + +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 +#: mod_muc_room.erl:3377 mod_register.erl:272 +msgid "Password" +msgstr "密码" + +#: ejabberd_oauth.erl:267 +msgid "Accept" +msgstr "" + #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" @@ -154,7 +174,7 @@ msgid "Show Integral Table" msgstr "显示完整列表" #: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:246 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "统计" @@ -178,17 +198,6 @@ msgstr "主机" msgid "Registered Users" msgstr "注册用户" -#: ejabberd_web_admin.erl:1338 ejabberd_web_admin.erl:1393 -#: mod_register.erl:262 mod_vcard.erl:490 -msgid "User" -msgstr "用户" - -#: ejabberd_web_admin.erl:1343 mod_configure.erl:1398 mod_configure.erl:1485 -#: mod_configure.erl:1889 mod_configure.erl:2124 mod_muc_room.erl:3376 -#: mod_register.erl:272 -msgid "Password" -msgstr "密码" - #: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" @@ -930,7 +939,7 @@ msgstr "服务器 ~b 的编码" msgid "Server ~b" msgstr "服务器 ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:320 +#: mod_muc.erl:797 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "聊天室" @@ -946,7 +955,7 @@ msgstr "昵称注册于 " msgid "Enter nickname you want to register" msgstr "请输入您想要注册的昵称" -#: mod_muc.erl:1014 mod_muc_room.erl:4264 mod_roster.erl:1436 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 #: mod_vcard.erl:490 mod_vcard.erl:621 msgid "Nickname" msgstr "昵称" @@ -955,27 +964,27 @@ msgstr "昵称" msgid "ejabberd MUC module" msgstr "ejabberd MUC 模块" -#: mod_muc_admin.erl:230 mod_muc_admin.erl:233 mod_muc_admin.erl:245 -#: mod_muc_admin.erl:319 +#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 +#: mod_muc_admin.erl:320 msgid "Multi-User Chat" msgstr "" -#: mod_muc_admin.erl:248 +#: mod_muc_admin.erl:249 #, fuzzy msgid "Total rooms" msgstr "聊天室" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:250 #, fuzzy msgid "Permanent rooms" msgstr "离开房间" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:251 #, fuzzy msgid "Registered nicknames" msgstr "注册用户" -#: mod_muc_admin.erl:253 +#: mod_muc_admin.erl:254 msgid "List of rooms" msgstr "" @@ -1115,181 +1124,181 @@ msgstr "房间配置" msgid "Room Occupants" msgstr "房间人数" -#: mod_muc_room.erl:997 +#: mod_muc_room.erl:998 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "只有主持人和参与人可以在此房间里更改主题" -#: mod_muc_room.erl:1002 +#: mod_muc_room.erl:1003 msgid "Only moderators are allowed to change the subject in this room" msgstr "只有主持人可以在此房间里更改主题" -#: mod_muc_room.erl:2751 +#: mod_muc_room.erl:2752 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s 无效" -#: mod_muc_room.erl:2765 +#: mod_muc_room.erl:2766 msgid "Nickname ~s does not exist in the room" msgstr "昵称 ~s 不在该房间" -#: mod_muc_room.erl:2788 mod_muc_room.erl:3168 +#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 msgid "Invalid affiliation: ~s" msgstr "无效加入: ~s" -#: mod_muc_room.erl:2839 +#: mod_muc_room.erl:2840 msgid "Invalid role: ~s" msgstr "无效角色: ~s" -#: mod_muc_room.erl:3341 +#: mod_muc_room.erl:3342 msgid "Configuration of room ~s" msgstr "房间 ~s 的配置 " -#: mod_muc_room.erl:3352 +#: mod_muc_room.erl:3353 msgid "Room title" msgstr "房间标题" -#: mod_muc_room.erl:3354 mod_muc_room.erl:4101 +#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 msgid "Room description" msgstr "房间描述" -#: mod_muc_room.erl:3362 +#: mod_muc_room.erl:3363 msgid "Make room persistent" msgstr "永久保存该房间" -#: mod_muc_room.erl:3368 +#: mod_muc_room.erl:3369 msgid "Make room public searchable" msgstr "使房间可被公开搜索" -#: mod_muc_room.erl:3371 +#: mod_muc_room.erl:3372 msgid "Make participants list public" msgstr "公开参与人列表" -#: mod_muc_room.erl:3373 +#: mod_muc_room.erl:3374 msgid "Make room password protected" msgstr "进入此房间需要密码" -#: mod_muc_room.erl:3387 +#: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" msgstr "允许的与会人最大数" -#: mod_muc_room.erl:3399 +#: mod_muc_room.erl:3400 msgid "No limit" msgstr "不限" -#: mod_muc_room.erl:3429 +#: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" msgstr "将真实 Jabber ID 显示给" -#: mod_muc_room.erl:3443 mod_muc_room.erl:3506 +#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" msgstr "仅主持人" -#: mod_muc_room.erl:3453 mod_muc_room.erl:3516 +#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 msgid "anyone" msgstr "任何人" -#: mod_muc_room.erl:3459 +#: mod_muc_room.erl:3460 msgid "Make room members-only" msgstr "设置房间只接收会员" -#: mod_muc_room.erl:3462 +#: mod_muc_room.erl:3463 msgid "Make room moderated" msgstr "设置房间只接收主持人" -#: mod_muc_room.erl:3465 +#: mod_muc_room.erl:3466 msgid "Default users as participants" msgstr "用户默认被视为参与人" -#: mod_muc_room.erl:3468 +#: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "允许用户更改主题" -#: mod_muc_room.erl:3471 +#: mod_muc_room.erl:3472 msgid "Allow users to send private messages" msgstr "允许用户发送私聊消息" -#: mod_muc_room.erl:3479 +#: mod_muc_room.erl:3480 msgid "Allow visitors to send private messages to" msgstr "允许访客发送私聊消息至" -#: mod_muc_room.erl:3497 +#: mod_muc_room.erl:3498 msgid "nobody" msgstr "没有人" -#: mod_muc_room.erl:3522 +#: mod_muc_room.erl:3523 msgid "Allow users to query other users" msgstr "允许用户查询其它用户" -#: mod_muc_room.erl:3525 +#: mod_muc_room.erl:3526 msgid "Allow users to send invites" msgstr "允许用户发送邀请" -#: mod_muc_room.erl:3528 +#: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" msgstr "更新在线状态时允许用户发送状态文本" -#: mod_muc_room.erl:3532 +#: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" msgstr "允许用户更改昵称" -#: mod_muc_room.erl:3535 +#: mod_muc_room.erl:3536 msgid "Allow visitors to send voice requests" msgstr "允许访客发送声音请求" -#: mod_muc_room.erl:3538 +#: mod_muc_room.erl:3539 msgid "Minimum interval between voice requests (in seconds)" msgstr "声音请求的最小间隔(以秒为单位)" -#: mod_muc_room.erl:3545 +#: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" msgstr "保护房间验证码" -#: mod_muc_room.erl:3552 +#: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3558 +#: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "从验证码挑战中排除 Jabber ID" -#: mod_muc_room.erl:3567 +#: mod_muc_room.erl:3568 msgid "Enable logging" msgstr "启用服务器端聊天记录" -#: mod_muc_room.erl:3577 +#: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" msgstr "您需要一个兼容 x:data 的客户端来配置房间" -#: mod_muc_room.erl:4103 +#: mod_muc_room.erl:4104 msgid "Number of occupants" msgstr "驻留人数" -#: mod_muc_room.erl:4173 +#: mod_muc_room.erl:4174 msgid "private, " msgstr "保密, " -#: mod_muc_room.erl:4237 +#: mod_muc_room.erl:4238 msgid "Voice request" msgstr "声音请求" -#: mod_muc_room.erl:4242 +#: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." msgstr "接受或拒绝声音请求" -#: mod_muc_room.erl:4262 +#: mod_muc_room.erl:4263 msgid "User JID" msgstr "用户 JID" -#: mod_muc_room.erl:4266 +#: mod_muc_room.erl:4267 msgid "Grant voice to this person?" msgstr "为此人授权声音?" -#: mod_muc_room.erl:4409 +#: mod_muc_room.erl:4410 msgid "~s invites you to the room ~s" msgstr "~s 邀请你到 ~s 房间" -#: mod_muc_room.erl:4421 +#: mod_muc_room.erl:4422 msgid "the password is" msgstr "密码是" From 3fc1d8ca9a0c7d6f96c750c068061b68c84673bd Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 29 Sep 2015 14:21:57 +0200 Subject: [PATCH 276/695] Set version 15.09 for mix --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 09a6cc62536..1285148969c 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.07.0", + version: "15.09.0", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", From 704844fd2a1e98fae4efb63583aa5e7ca662ce9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 29 Sep 2015 15:33:49 +0200 Subject: [PATCH 277/695] Temporary switch to fork of oauth2 that compiles with r18 --- rebar.config.script | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config.script b/rebar.config.script index 64f0f63637b..633433c197b 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -63,7 +63,7 @@ Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}, - {oauth2, ".*", {git, "https://github.com/IvanMartinez/oauth2.git"}}, + {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], ConfigureCmd = fun(Pkg, Flags) -> From b63c51c245066654e912315664087dc759d59637 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Tue, 29 Sep 2015 13:18:49 -0500 Subject: [PATCH 278/695] Add additional package information for hex.pm --- mix.exs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mix.exs b/mix.exs index 1285148969c..b71c7e25565 100644 --- a/mix.exs +++ b/mix.exs @@ -10,6 +10,7 @@ defmodule Ejabberd.Mixfile do compilers: [:asn1] ++ Mix.compilers, erlc_options: erlc_options, erlc_paths: ["asn1", "src"], + package: package, deps: deps] end @@ -45,6 +46,12 @@ defmodule Ejabberd.Mixfile do {:eredis, git: "https://github.com/wooga/eredis"}, {:exrm, "~> 0.19.2"} ] + + defp package do + [licenses: ["GPLv2"], + links: %{"Site" => "https://www.ejabberd.im", + "Documentation" => "http://docs.ejabberd.im", + "Source" => "https://github.com/processone/ejabberd"}] end end From 6b81a1ed90fb98a8158cdd2f6b51b7d659b4c802 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Tue, 29 Sep 2015 13:19:35 -0500 Subject: [PATCH 279/695] clean up whitespace --- mix.exs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/mix.exs b/mix.exs index b71c7e25565..a708df675f0 100644 --- a/mix.exs +++ b/mix.exs @@ -20,32 +20,31 @@ defmodule Ejabberd.Mixfile do included_applications: [:p1_logger,:p1_yaml,:p1_tls,:p1_xml,:p1_stringprep,:p1_zlib,:p1_cache_tab,:mnesia,:p1_utils, :p1_iconv,:esip,:p1_stun,:ehyperloglog,:p1_mysql,:p1_pgsql,:eredis]] end - + defp erlc_options do # Use our own includes + includes from all dependencies includes = ["include"] ++ Path.wildcard(Path.join("..", "/*/include")) [:debug_info] ++ Enum.map(includes, fn(path) -> {:i, path} end) end - + defp deps do - [ - {:p1_xml, git: "https://github.com/processone/xml"}, - {:p1_logger, git: "https://github.com/processone/p1_logger"}, - {:p1_yaml, git: "https://github.com/processone/p1_yaml"}, - {:p1_tls, git: "https://github.com/processone/tls"}, - {:p1_stringprep, git: "https://github.com/processone/stringprep"}, - {:p1_zlib, git: "https://github.com/processone/zlib"}, - {:p1_cache_tab, git: "https://github.com/processone/cache_tab"}, - {:p1_utils, git: "https://github.com/processone/p1_utils"}, - {:p1_iconv, git: "https://github.com/processone/eiconv"}, - {:esip, git: "https://github.com/processone/p1_sip"}, - {:p1_stun, git: "https://github.com/processone/stun"}, - {:ehyperloglog, git: "https://github.com/vaxelfel/eHyperLogLog"}, - {:p1_mysql, git: "https://github.com/processone/mysql"}, - {:p1_pgsql, git: "https://github.com/processone/pgsql"}, - {:eredis, git: "https://github.com/wooga/eredis"}, - {:exrm, "~> 0.19.2"} - ] + [{:p1_xml, git: "https://github.com/processone/xml"}, + {:p1_logger, git: "https://github.com/processone/p1_logger"}, + {:p1_yaml, git: "https://github.com/processone/p1_yaml"}, + {:p1_tls, git: "https://github.com/processone/tls"}, + {:p1_stringprep, git: "https://github.com/processone/stringprep"}, + {:p1_zlib, git: "https://github.com/processone/zlib"}, + {:p1_cache_tab, git: "https://github.com/processone/cache_tab"}, + {:p1_utils, git: "https://github.com/processone/p1_utils"}, + {:p1_iconv, git: "https://github.com/processone/eiconv"}, + {:esip, git: "https://github.com/processone/p1_sip"}, + {:p1_stun, git: "https://github.com/processone/stun"}, + {:ehyperloglog, git: "https://github.com/vaxelfel/eHyperLogLog"}, + {:p1_mysql, git: "https://github.com/processone/mysql"}, + {:p1_pgsql, git: "https://github.com/processone/pgsql"}, + {:eredis, git: "https://github.com/wooga/eredis"}, + {:exrm, "~> 0.19.2"}] + end defp package do [licenses: ["GPLv2"], From 59b6a46f82c0173bae6646845c41b38b7fd43858 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Tue, 29 Sep 2015 13:21:35 -0500 Subject: [PATCH 280/695] Ignore mnesiadb and _build --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index eb54d51e697..b4950e01ef8 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ XmppAddr.hrl /logs/ /priv/sql /rel/ejabberd +/_build +/mnesiadb From 9c82f160e5565b0cbd3b942979004bc4b50559b2 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Tue, 29 Sep 2015 14:08:39 -0500 Subject: [PATCH 281/695] Use lowecase directory name for lib/ejabberd --- lib/{Ejabberd => ejabberd}/hooks.ex | 0 lib/{Ejabberd => ejabberd}/logger.ex | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename lib/{Ejabberd => ejabberd}/hooks.ex (100%) rename lib/{Ejabberd => ejabberd}/logger.ex (100%) diff --git a/lib/Ejabberd/hooks.ex b/lib/ejabberd/hooks.ex similarity index 100% rename from lib/Ejabberd/hooks.ex rename to lib/ejabberd/hooks.ex diff --git a/lib/Ejabberd/logger.ex b/lib/ejabberd/logger.ex similarity index 100% rename from lib/Ejabberd/logger.ex rename to lib/ejabberd/logger.ex From 67d3b50598897bcdf7982580baa99dab968e20bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 1 Oct 2015 14:33:39 +0200 Subject: [PATCH 282/695] Switch macros resolving in config files to be global instead of per file --- src/ejabberd_config.erl | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index c3355591351..0ff1706ae93 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -120,7 +120,12 @@ read_file(File) -> {include_modules_configs, true}]). read_file(File, Opts) -> - Terms = get_plain_terms_file(File, Opts), + Terms1 = get_plain_terms_file(File, Opts), + Terms_macros = case proplists:get_bool(replace_macros, Opts) of + true -> replace_macros(Terms1); + false -> Terms1 + end, + Terms = transform_terms(Terms_macros), State = lists:foldl(fun search_hosts/2, #state{}, Terms), {Head, Tail} = lists:partition( fun({host_config, _}) -> false; @@ -209,16 +214,11 @@ get_plain_terms_file(File1, Opts) -> [] end, BinTerms = BinTerms1 ++ [{include_config_file, list_to_binary(V)} || V <- ModInc], - BinTerms2 = case proplists:get_bool(replace_macros, Opts) of - true -> replace_macros(BinTerms); - false -> BinTerms - end, - BinTerms3 = transform_terms(BinTerms2), case proplists:get_bool(include_files, Opts) of true -> - include_config_files(BinTerms3); + include_config_files(BinTerms); false -> - BinTerms3 + BinTerms end; {error, Reason} -> ?ERROR_MSG(Reason, []), @@ -373,8 +373,18 @@ exit_or_halt(ExitText) -> get_config_option_key(Name, Val) -> if Name == listen -> - [{Key, _, _}] = ejabberd_listener:validate_cfg([Val]), - Key; + lists:foldl( + fun({port, Port}, {_, IP, T, Mod}) -> + {Port, IP, T, Mod}; + ({ip, IP}, {Port, _, T, Mod}) -> + {Port, IP, T, Mod}; + ({transport, T}, {Port, IP, _, Mod}) -> + {Port, IP, T, Mod}; + ({module, Mod}, {Port, IP, T, _}) -> + {Port, IP, T, Mod}; + (_, Res) -> + Res + end, {5222, {0,0,0,0}, tcp, ejabberd_c2s}, Val); is_tuple(Val) -> element(1, Val); true -> From 24fa95fd60b139d17417aad932c89cf72f28c938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 1 Oct 2015 21:09:03 +0200 Subject: [PATCH 283/695] Fix problem with --auth in ejabberd_ctl:process2/2 --- src/ejabberd_ctl.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 8b6f1852079..dd258833c65 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -209,7 +209,7 @@ process(Args) -> %% @spec (Args::[string()], AccessCommands) -> {String::string(), Code::integer()} process2(["--auth", User, Server, Pass | Args], AccessCommands) -> - process2(Args, {list_to_binary(User), list_to_binary(Server), list_to_binary(Pass)}, AccessCommands); + process2(Args, {list_to_binary(User), list_to_binary(Server), list_to_binary(Pass), true}, AccessCommands); process2(Args, AccessCommands) -> process2(Args, admin, AccessCommands). From 41d65f8fe2f02381f293ec178b494f91536e3ca1 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Fri, 2 Oct 2015 10:40:55 +0200 Subject: [PATCH 284/695] We want oauth2 to be supported as default in Elixir environment --- mix.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index a708df675f0..16732c53efe 100644 --- a/mix.exs +++ b/mix.exs @@ -18,7 +18,7 @@ defmodule Ejabberd.Mixfile do [mod: {:ejabberd_app, []}, applications: [:ssl], included_applications: [:p1_logger,:p1_yaml,:p1_tls,:p1_xml,:p1_stringprep,:p1_zlib,:p1_cache_tab,:mnesia,:p1_utils, - :p1_iconv,:esip,:p1_stun,:ehyperloglog,:p1_mysql,:p1_pgsql,:eredis]] + :p1_iconv,:esip,:p1_stun,:ehyperloglog,:p1_mysql,:p1_pgsql,:eredis,:oauth2,:xmlrpc]] end defp erlc_options do @@ -43,6 +43,8 @@ defmodule Ejabberd.Mixfile do {:p1_mysql, git: "https://github.com/processone/mysql"}, {:p1_pgsql, git: "https://github.com/processone/pgsql"}, {:eredis, git: "https://github.com/wooga/eredis"}, + {:oauth2, git: "https://github.com/prefiks/oauth2.git"}, + {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git"}, {:exrm, "~> 0.19.2"}] end From c7750689e83ec59bf52475316b76a06ba42226cd Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 20 Aug 2015 19:15:16 +0300 Subject: [PATCH 285/695] Fix force_update_presence --- src/ejabberd_c2s.erl | 4 ++-- src/ejabberd_sm.erl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 2c06fef05fc..cb4bc02c9f2 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1741,8 +1741,8 @@ handle_info({route_xmlstreamelement, El}, _StateName, StateData) -> {next_state, NStateName, NStateData, _Timeout} = session_established({xmlstreamelement, El}, StateData), fsm_next_state(NStateName, NStateData); -handle_info({force_update_presence, LUser}, StateName, - #state{user = LUser, server = LServer} = StateData) -> +handle_info({force_update_presence, LUser, LServer}, StateName, + #state{jid = #jid{luser = LUser, lserver = LServer}} = StateData) -> NewStateData = case StateData#state.pres_last of #xmlel{name = <<"presence">>} -> PresenceEl = diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index cfaf24dfa45..58e2f3c65d0 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -741,7 +741,7 @@ force_update_presence({LUser, LServer}) -> Mod = get_sm_backend(), Ss = Mod:get_sessions(LUser, LServer), lists:foreach(fun (#session{sid = {_, Pid}}) -> - Pid ! {force_update_presence, LUser} + Pid ! {force_update_presence, LUser, LServer} end, Ss). From 6378c673df75ad05932e9029d3ccc965df43c810 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 12 Aug 2015 16:58:56 +0300 Subject: [PATCH 286/695] Avoid MAM dups when routing to multiple resources --- src/mod_mam.erl | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 3e3e0873de3..0c85e7016c5 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -157,11 +157,12 @@ remove_user(LUser, LServer, odbc) -> LServer, [<<"delete from archive_prefs where username='">>, SUser, <<"';">>]). -user_receive_packet(Pkt, C2SState, JID, Peer, _To) -> +user_receive_packet(Pkt, C2SState, JID, Peer, To) -> LUser = JID#jid.luser, LServer = JID#jid.lserver, + IsBareCopy = is_bare_copy(JID, To), case should_archive(Pkt) of - true -> + true when not IsBareCopy -> NewPkt = strip_my_archived_tag(Pkt, LServer), case store_msg(C2SState, NewPkt, LUser, LServer, Peer, recv) of {ok, ID} -> @@ -178,7 +179,7 @@ user_receive_packet(Pkt, C2SState, JID, Peer, _To) -> _ -> NewPkt end; - false -> + _ -> Pkt end. @@ -726,6 +727,38 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, Pkt2 = jlib:replace_from(jlib:jid_replace_resource(JidRequestor, Nick), Pkt1), jlib:remove_attr(<<"to">>, Pkt2). +is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> + PrioRes = ejabberd_sm:get_user_present_resources(U, S), + MaxRes = case catch lists:max(PrioRes) of + {_Prio, Res} when is_binary(Res) -> + Res; + _ -> + undefined + end, + IsBareTo = case To of + #jid{lresource = <<"">>} -> + true; + #jid{lresource = LRes} -> + %% Unavailable resources are handled like bare JIDs. + lists:keyfind(LRes, 2, PrioRes) =:= false + end, + case {IsBareTo, R} of + {true, MaxRes} -> + ?DEBUG("Recipient of message to bare JID has top priority: ~s@~s/~s", + [U, S, R]), + false; + {true, _R} -> + %% The message was sent to our bare JID, and we currently have + %% multiple resources with the same highest priority, so the session + %% manager routes the message to each of them. We store the message + %% only from the resource where R equals MaxRes. + ?DEBUG("Additional recipient of message to bare JID: ~s@~s/~s", + [U, S, R]), + true; + {false, _R} -> + false + end. + send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> QID = xml:get_tag_attr_s(<<"queryid">>, SubEl), NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), From 83dd79a6a78c8ac5c5a73143caa1a23c3a0a7f6e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 6 Oct 2015 11:06:04 +0200 Subject: [PATCH 287/695] Remove unused dependency --- mix.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/mix.exs b/mix.exs index 16732c53efe..d45b3289cc6 100644 --- a/mix.exs +++ b/mix.exs @@ -39,7 +39,6 @@ defmodule Ejabberd.Mixfile do {:p1_iconv, git: "https://github.com/processone/eiconv"}, {:esip, git: "https://github.com/processone/p1_sip"}, {:p1_stun, git: "https://github.com/processone/stun"}, - {:ehyperloglog, git: "https://github.com/vaxelfel/eHyperLogLog"}, {:p1_mysql, git: "https://github.com/processone/mysql"}, {:p1_pgsql, git: "https://github.com/processone/pgsql"}, {:eredis, git: "https://github.com/wooga/eredis"}, From 6aeb9dcb38921249cdfe453baeadcd03298d5d6e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 7 Oct 2015 00:06:58 +0200 Subject: [PATCH 288/695] cosmetic cleanup --- include/ejabberd_http.hrl | 9 +- include/mod_offline.hrl | 11 + src/acl.erl | 39 +- src/ejabberd_admin.erl | 4 +- src/ejabberd_auth.erl | 5 +- src/ejabberd_auth_external.erl | 1 - src/ejabberd_c2s.erl | 756 ++++++++++++++---------------- src/ejabberd_captcha.erl | 42 +- src/ejabberd_cluster.erl | 53 +++ src/ejabberd_commands.erl | 12 +- src/ejabberd_config.erl | 2 +- src/ejabberd_ctl.erl | 7 +- src/ejabberd_frontend_socket.erl | 51 +- src/ejabberd_hooks.erl | 7 +- src/ejabberd_http.erl | 78 ++- src/ejabberd_http_bind.erl | 155 +++--- src/ejabberd_local.erl | 54 +-- src/ejabberd_logger.erl | 1 - src/ejabberd_odbc.erl | 33 +- src/ejabberd_piefxis.erl | 25 +- src/ejabberd_receiver.erl | 69 +-- src/ejabberd_riak.erl | 2 + src/ejabberd_router.erl | 3 +- src/ejabberd_router_multicast.erl | 18 + src/ejabberd_s2s.erl | 71 +-- src/ejabberd_s2s_in.erl | 38 -- src/ejabberd_s2s_out.erl | 49 +- src/ejabberd_sm.erl | 62 +-- src/ejabberd_sm_redis.erl | 3 +- src/ejabberd_socket.erl | 11 +- src/ejabberd_system_monitor.erl | 19 +- src/ejabberd_update.erl | 25 +- src/ejabberd_web_admin.erl | 82 ++-- src/eldap.erl | 79 +--- src/gen_iq_handler.erl | 115 ++--- src/mod_carboncopy.erl | 32 +- src/mod_configure.erl | 21 +- src/mod_fail2ban.erl | 2 +- src/mod_irc.erl | 2 - src/mod_mam.erl | 532 ++++++++++----------- src/mod_muc.erl | 183 +++----- src/mod_muc_admin.erl | 1 - src/mod_muc_log.erl | 93 +--- src/mod_muc_room.erl | 76 +-- src/mod_multicast.erl | 75 +-- src/mod_offline.erl | 66 ++- src/mod_privacy.erl | 22 +- src/mod_proxy65_sm.erl | 5 +- src/mod_pubsub.erl | 18 +- src/mod_register.erl | 2 + src/mod_roster.erl | 1 - src/mod_shared_roster.erl | 27 +- src/mod_shared_roster_ldap.erl | 9 +- src/mod_sip.erl | 2 +- src/mod_sip_proxy.erl | 2 +- src/mod_sip_registrar.erl | 2 +- src/mod_stats.erl | 14 +- src/node_pep.erl | 3 +- src/node_pep_odbc.erl | 3 +- 59 files changed, 1276 insertions(+), 1908 deletions(-) create mode 100644 include/mod_offline.hrl create mode 100644 src/ejabberd_cluster.erl diff --git a/include/ejabberd_http.hrl b/include/ejabberd_http.hrl index 404427d7f22..7e3d40ee196 100644 --- a/include/ejabberd_http.hrl +++ b/include/ejabberd_http.hrl @@ -19,7 +19,7 @@ %%%---------------------------------------------------------------------- -record(request, - {method, % :: method(), + {method :: method(), path = [] :: [binary()], q = [] :: [{binary() | nokey, binary()}], us = {<<>>, <<>>} :: {binary(), binary()}, @@ -30,11 +30,10 @@ ip :: {inet:ip_address(), inet:port_number()}, host = <<"">> :: binary(), port = 5280 :: inet:port_number(), - tp = http, % :: protocol(), opts = [] :: list(), + tp = http :: protocol(), headers = [] :: [{atom() | binary(), binary()}]}). - -record(ws, {socket :: inet:socket() | p1_tls:tls_socket(), sockmod = gen_tcp :: gen_tcp | p1_tls, @@ -47,3 +46,7 @@ q = [] :: [{binary() | nokey, binary()}], buf :: binary(), http_opts = [] :: list()}). + +-type method() :: 'GET' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'PUT' | 'POST' | 'TRACE'. +-type protocol() :: http | https. +-type http_request() :: #request{}. diff --git a/include/mod_offline.hrl b/include/mod_offline.hrl new file mode 100644 index 00000000000..c4c70604a7e --- /dev/null +++ b/include/mod_offline.hrl @@ -0,0 +1,11 @@ +-record(offline_msg, + {us = {<<"">>, <<"">>} :: {binary(), binary()}, + timestamp = now() :: erlang:timestamp() | '_', + expire = now() :: erlang:timestamp() | never | '_', + from = #jid{} :: jid() | '_', + to = #jid{} :: jid() | '_', + packet = #xmlel{} :: xmlel() | '_'}). + +-record(state, + {host = <<"">> :: binary(), + access_max_offline_messages}). diff --git a/src/acl.erl b/src/acl.erl index 021e4e2d43a..d56292680b8 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -98,7 +98,7 @@ to_record(Host, ACLName, ACLSpec) -> -spec add(binary(), aclname(), aclspec()) -> ok | {error, any()}. add(Host, ACLName, ACLSpec) -> - {ResL, BadNodes} = rpc:multicall(mnesia:system_info(running_db_nodes), + {ResL, BadNodes} = ejabberd_cluster:multicall( ?MODULE, add_local, [Host, ACLName, ACLSpec]), case lists:keyfind(aborted, 1, ResL) of @@ -125,7 +125,7 @@ add_local(Host, ACLName, ACLSpec) -> -spec add_list(binary(), [acl()], boolean()) -> ok | {error, any()}. add_list(Host, ACLs, Clear) -> - {ResL, BadNodes} = rpc:multicall(mnesia:system_info(running_db_nodes), + {ResL, BadNodes} = ejabberd_cluster:multicall( ?MODULE, add_list_local, [Host, ACLs, Clear]), case lists:keyfind(aborted, 1, ResL) of @@ -167,16 +167,12 @@ add_list_local(Host, ACLs, Clear) -> access_name(), [access_rule()]) -> ok | {error, any()}. add_access(Host, Access, Rules) -> - case mnesia:transaction( - fun() -> - mnesia:write( - #access{name = {Access, Host}, - rules = Rules}) - end) of - {atomic, ok} -> - ok; - Err -> - {error, Err} + Obj = #access{name = {Access, Host}, rules = Rules}, + case mnesia:transaction(fun() -> mnesia:write(Obj) end) of + {atomic, ok} -> + ok; + Err -> + {error, Err} end. -spec load_from_config() -> ok. @@ -239,8 +235,7 @@ normalize_spec(Spec) -> {server_regexp, SR} -> {server_regexp, b(SR)}; {server_glob, S} -> {server_glob, b(S)}; {resource_glob, R} -> {resource_glob, b(R)}; - {ip, {Net, Mask}} -> - {ip, {Net, Mask}}; + {ip, {Net, Mask}} -> {ip, {Net, Mask}}; {ip, S} -> case parse_ip_netmask(b(S)) of {ok, Net, Mask} -> @@ -294,17 +289,15 @@ match_acl(none, _JID, _Host) -> match_acl(ACL, IP, Host) when tuple_size(IP) == 4; tuple_size(IP) == 8 -> lists:any( - fun(#acl{aclspec = {ip, {Net, Mask}}}) -> + fun({ip, {Net, Mask}}) -> is_ip_match(IP, Net, Mask); (_) -> false - end, - ets:lookup(acl, {ACL, Host}) ++ - ets:lookup(acl, {ACL, global})); + end, get_aclspecs(ACL, Host)); match_acl(ACL, JID, Host) -> {User, Server, Resource} = jlib:jid_tolower(JID), lists:any( - fun(#acl{aclspec = Spec}) -> + fun(Spec) -> case Spec of all -> true; {user, {U, S}} -> U == User andalso S == Server; @@ -350,7 +343,13 @@ match_acl(ACL, JID, Host) -> false end end, - ets:lookup(acl, {ACL, Host}) ++ + get_aclspecs(ACL, Host)). + +get_aclspecs(ACL, Host) -> + lists:flatmap( + fun(#acl{aclspec = Specs}) -> + Specs + end, ets:lookup(acl, {ACL, Host}) ++ ets:lookup(acl, {ACL, global})). is_regexp_match(String, RegExp) -> diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index dc4c10c8701..2068f10c873 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -462,7 +462,7 @@ restore_mnesia(Path) -> %% Mnesia database restore %% This function is called from ejabberd_ctl, ejabberd_web_admin and -%% mod_configure/adhoc +%% mod_configure/adhoc restore(Path) -> mnesia:restore(Path, [{keep_tables,keep_tables()}, {default_op, skip_tables}]). @@ -477,7 +477,7 @@ keep_tables() -> %% Returns the list of modules tables in use, according to the list of actually %% loaded modules -keep_modules_tables() -> +keep_modules_tables() -> lists:map(fun(Module) -> module_tables(Module) end, gen_mod:loaded_modules(?MYNAME)). diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 03c117b6c65..6fb3caa000f 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -77,7 +77,7 @@ -callback get_password_s(binary(), binary()) -> binary() | {binary(), binary(), binary(), integer()}. start() -> -%% This is only executed by ejabberd_c2s for non-SASL auth client + %% This is only executed by ejabberd_c2s for non-SASL auth client lists:foreach(fun (Host) -> lists:foreach(fun (M) -> M:start(Host) end, auth_modules(Host)) @@ -187,7 +187,8 @@ try_register(User, Server, Password) -> case is_user_exists(User, Server) of true -> {atomic, exists}; false -> - case lists:member(jlib:nameprep(Server), ?MYHOSTS) of + LServer = jlib:nameprep(Server), + case lists:member(LServer, ?MYHOSTS) of true -> Res = lists:foldl(fun (_M, {atomic, ok} = Res) -> Res; (M, _) -> diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 4d11507ee97..cc3a781cef4 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -281,7 +281,6 @@ is_fresh_enough(TimeStampLast, CacheTime) -> get_last_access(User, Server) -> case ejabberd_sm:get_user_resources(User, Server) of [] -> -%% _US = {User, Server}, case get_last_info(User, Server) of mod_last_required -> mod_last_required; not_found -> never; diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index cb4bc02c9f2..c82f1a34c93 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -203,8 +203,9 @@ start(SockData, Opts) -> ?SUPERVISOR_START. start_link(SockData, Opts) -> - ?GEN_FSM:start_link(ejabberd_c2s, [SockData, Opts], - fsm_limit_opts(Opts) ++ ?FSMOPTS). + (?GEN_FSM):start_link(ejabberd_c2s, + [SockData, Opts], + fsm_limit_opts(Opts) ++ ?FSMOPTS). socket_type() -> xml_stream. @@ -256,13 +257,6 @@ stop(FsmRef) -> (?GEN_FSM):send_event(FsmRef, closed). %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, StateName, StateData} | -%% {ok, StateName, StateData, Timeout} | -%% ignore | -%% {stop, StopReason} -%%---------------------------------------------------------------------- init([{SockMod, Socket}, Opts]) -> Access = case lists:keysearch(access, 1, Opts) of {value, {_, A}} -> A; @@ -350,36 +344,29 @@ get_subscribed(FsmRef) -> (?GEN_FSM):sync_send_all_state_event(FsmRef, get_subscribed, 1000). -%%---------------------------------------------------------------------- -%% Func: StateName/2 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- - wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> DefaultLang = ?MYLANG, case xml:get_attr_s(<<"xmlns:stream">>, Attrs) of ?NS_STREAM -> - Server = - case StateData#state.server of - <<"">> -> - jlib:nameprep(xml:get_attr_s(<<"to">>, Attrs)); - S -> S - end, + Server = + case StateData#state.server of + <<"">> -> + jlib:nameprep(xml:get_attr_s(<<"to">>, Attrs)); + S -> S + end, Lang = case xml:get_attr_s(<<"xml:lang">>, Attrs) of - Lang1 when byte_size(Lang1) =< 35 -> - %% As stated in BCP47, 4.4.1: - %% Protocols or specifications that - %% specify limited buffer sizes for - %% language tags MUST allow for - %% language tags of at least 35 characters. - Lang1; - _ -> - %% Do not store long language tag to - %% avoid possible DoS/flood attacks - <<"">> - end, + Lang1 when byte_size(Lang1) =< 35 -> + %% As stated in BCP47, 4.4.1: + %% Protocols or specifications that + %% specify limited buffer sizes for + %% language tags MUST allow for + %% language tags of at least 35 characters. + Lang1; + _ -> + %% Do not store long language tag to + %% avoid possible DoS/flood attacks + <<"">> + end, IsBlacklistedIP = is_ip_blacklisted(StateData#state.ip, Lang), case lists:member(Server, ?MYHOSTS) of true when IsBlacklistedIP == false -> @@ -392,168 +379,162 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> TLS = StateData#state.tls, TLSEnabled = StateData#state.tls_enabled, TLSRequired = StateData#state.tls_required, - SASLState = - cyrsasl:server_new( - <<"jabber">>, Server, <<"">>, [], - fun(U) -> - ejabberd_auth:get_password_with_authmodule( - U, Server) - end, - fun(U, P) -> - ejabberd_auth:check_password_with_authmodule( - U, Server, P) - end, - fun(U, P, D, DG) -> - ejabberd_auth:check_password_with_authmodule( - U, Server, P, D, DG) - end), + SASLState = cyrsasl:server_new( + <<"jabber">>, Server, <<"">>, [], + fun (U) -> + ejabberd_auth:get_password_with_authmodule( + U, Server) + end, + fun (U, P) -> + ejabberd_auth:check_password_with_authmodule( + U, Server, P) + end, + fun (U, P, D, DG) -> + ejabberd_auth:check_password_with_authmodule( + U, Server, P, D, DG) + end), Mechs = case TLSEnabled or not TLSRequired of - true -> - Ms = lists:map(fun (S) -> - #xmlel{name = <<"mechanism">>, - attrs = [], - children = [{xmlcdata, S}]} - end, - cyrsasl:listmech(Server)), - [#xmlel{name = <<"mechanisms">>, - attrs = [{<<"xmlns">>, ?NS_SASL}], - children = Ms}]; - false -> - [] - end, + true -> + Ms = lists:map(fun (S) -> + #xmlel{name = <<"mechanism">>, + attrs = [], + children = [{xmlcdata, S}]} + end, + cyrsasl:listmech(Server)), + [#xmlel{name = <<"mechanisms">>, + attrs = [{<<"xmlns">>, ?NS_SASL}], + children = Ms}]; + false -> + [] + end, SockMod = - (StateData#state.sockmod):get_sockmod( - StateData#state.socket), + (StateData#state.sockmod):get_sockmod(StateData#state.socket), Zlib = StateData#state.zlib, - CompressFeature = - case Zlib andalso - ((SockMod == gen_tcp) orelse - (SockMod == p1_tls)) of - true -> - [#xmlel{name = <<"compression">>, - attrs = [{<<"xmlns">>, ?NS_FEATURE_COMPRESS}], - children = [#xmlel{name = <<"method">>, - attrs = [], - children = [{xmlcdata, <<"zlib">>}]}]}]; - _ -> - [] - end, + CompressFeature = case Zlib andalso + ((SockMod == gen_tcp) orelse (SockMod == p1_tls)) of + true -> + [#xmlel{name = <<"compression">>, + attrs = [{<<"xmlns">>, ?NS_FEATURE_COMPRESS}], + children = [#xmlel{name = <<"method">>, + attrs = [], + children = [{xmlcdata, <<"zlib">>}]}]}]; + _ -> + [] + end, TLSFeature = case (TLS == true) andalso - (TLSEnabled == false) andalso - (SockMod == gen_tcp) of - true -> - case TLSRequired of - true -> - [#xmlel{name = <<"starttls">>, - attrs = [{<<"xmlns">>, ?NS_TLS}], - children = [#xmlel{name = <<"required">>, - attrs = [], - children = []}]}]; - _ -> - [#xmlel{name = <<"starttls">>, - attrs = [{<<"xmlns">>, ?NS_TLS}], - children = []}] - end; - false -> - [] - end, + (TLSEnabled == false) andalso + (SockMod == gen_tcp) of + true -> + case TLSRequired of + true -> + [#xmlel{name = <<"starttls">>, + attrs = [{<<"xmlns">>, ?NS_TLS}], + children = [#xmlel{name = <<"required">>, + attrs = [], + children = []}]}]; + _ -> + [#xmlel{name = <<"starttls">>, + attrs = [{<<"xmlns">>, ?NS_TLS}], + children = []}] + end; + false -> + [] + end, StreamFeatures1 = TLSFeature ++ CompressFeature ++ Mechs, StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features, - Server, StreamFeatures1, [Server]), + Server, StreamFeatures1, [Server]), send_element(StateData, - #xmlel{name = <<"stream:features">>, - attrs = [], - children = - StreamFeatures}), + #xmlel{name = <<"stream:features">>, + attrs = [], + children = StreamFeatures}), fsm_next_state(wait_for_feature_request, - StateData#state{ - server = Server, - sasl_state = SASLState, - lang = Lang}); + StateData#state{server = Server, + sasl_state = SASLState, + lang = Lang}); _ -> case StateData#state.resource of - <<"">> -> - RosterVersioningFeature = - ejabberd_hooks:run_fold(roster_get_versioning_feature, - Server, [], - [Server]), - StreamManagementFeature = - case stream_mgmt_enabled(StateData) of - true -> - [#xmlel{name = <<"sm">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGMT_2}], - children = []}, - #xmlel{name = <<"sm">>, - attrs = [{<<"xmlns">>, ?NS_STREAM_MGMT_3}], - children = []}]; - false -> - [] + <<"">> -> + RosterVersioningFeature = + ejabberd_hooks:run_fold(roster_get_versioning_feature, + Server, [], + [Server]), + StreamManagementFeature = + case stream_mgmt_enabled(StateData) of + true -> + [#xmlel{name = <<"sm">>, + attrs = [{<<"xmlns">>, ?NS_STREAM_MGMT_2}], + children = []}, + #xmlel{name = <<"sm">>, + attrs = [{<<"xmlns">>, ?NS_STREAM_MGMT_3}], + children = []}]; + false -> + [] end, - StreamFeatures1 = [#xmlel{name = <<"bind">>, - attrs = [{<<"xmlns">>, ?NS_BIND}], - children = []}, - #xmlel{name = <<"session">>, - attrs = [{<<"xmlns">>, ?NS_SESSION}], - children = []}] - ++ - RosterVersioningFeature ++ - StreamManagementFeature ++ - ejabberd_hooks:run_fold(c2s_post_auth_features, - Server, [], [Server]), - StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features, - Server, StreamFeatures1, [Server]), - send_element(StateData, - #xmlel{name = <<"stream:features">>, - attrs = [], - children = StreamFeatures}), - fsm_next_state(wait_for_bind, - StateData#state{server = Server, lang = Lang}); - _ -> - send_element(StateData, - #xmlel{name = <<"stream:features">>, - attrs = [], - children = []}), - fsm_next_state(wait_for_session, - StateData#state{server = Server, lang = Lang}) + StreamFeatures1 = [#xmlel{name = <<"bind">>, + attrs = [{<<"xmlns">>, ?NS_BIND}], + children = []}, + #xmlel{name = <<"session">>, + attrs = [{<<"xmlns">>, ?NS_SESSION}], + children = []}] + ++ + RosterVersioningFeature ++ + StreamManagementFeature ++ + ejabberd_hooks:run_fold(c2s_post_auth_features, + Server, [], [Server]), + StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features, + Server, StreamFeatures1, [Server]), + send_element(StateData, + #xmlel{name = <<"stream:features">>, + attrs = [], + children = StreamFeatures}), + fsm_next_state(wait_for_bind, + StateData#state{server = Server, lang = Lang}); + _ -> + send_element(StateData, + #xmlel{name = <<"stream:features">>, + attrs = [], + children = []}), + fsm_next_state(wait_for_session, + StateData#state{server = Server, lang = Lang}) end end; - _ -> - send_header(StateData, Server, <<"">>, DefaultLang), - if not StateData#state.tls_enabled and - StateData#state.tls_required -> - send_element(StateData, + _ -> + send_header(StateData, Server, <<"">>, DefaultLang), + if not StateData#state.tls_enabled and + StateData#state.tls_required -> + send_element(StateData, ?POLICY_VIOLATION_ERR(Lang, - <<"Use of STARTTLS required">>)), - send_trailer(StateData), - {stop, normal, StateData}; - true -> - fsm_next_state(wait_for_auth, + <<"Use of STARTTLS required">>)), + send_trailer(StateData), + {stop, normal, StateData}; + true -> + fsm_next_state(wait_for_auth, StateData#state{server = Server, - lang = Lang}) - end + lang = Lang}) + end + end; + true -> + IP = StateData#state.ip, + {true, LogReason, ReasonT} = IsBlacklistedIP, + ?INFO_MSG("Connection attempt from blacklisted IP ~s: ~s", + [jlib:ip_to_list(IP), LogReason]), + send_header(StateData, Server, <<"">>, DefaultLang), + send_element(StateData, ?POLICY_VIOLATION_ERR(Lang, ReasonT)), + send_trailer(StateData), + {stop, normal, StateData}; + _ -> + send_header(StateData, ?MYNAME, <<"">>, DefaultLang), + send_element(StateData, ?HOST_UNKNOWN_ERR), + send_trailer(StateData), + {stop, normal, StateData} end; - true -> - IP = StateData#state.ip, - {true, LogReason, ReasonT} = IsBlacklistedIP, - ?INFO_MSG("Connection attempt from blacklisted IP ~s: ~s", - [jlib:ip_to_list(IP), LogReason]), - send_header(StateData, Server, <<"">>, DefaultLang), - send_element(StateData, ?POLICY_VIOLATION_ERR(Lang, ReasonT)), - send_trailer(StateData), - {stop, normal, StateData}; _ -> send_header(StateData, ?MYNAME, <<"">>, DefaultLang), - send_element(StateData, ?HOST_UNKNOWN_ERR), + send_element(StateData, ?INVALID_NS_ERR), send_trailer(StateData), {stop, normal, StateData} - end; - _ -> - send_header(StateData, ?MYNAME, <<"">>, DefaultLang), - send_element(StateData, ?INVALID_NS_ERR), - send_trailer(StateData), - {stop, normal, StateData} end; wait_for_stream(timeout, StateData) -> {stop, normal, StateData}; @@ -574,151 +555,148 @@ wait_for_stream(closed, StateData) -> {stop, normal, StateData}. wait_for_auth({xmlstreamelement, #xmlel{name = Name} = El}, StateData) - when ?IS_STREAM_MGMT_TAG(Name) -> + when ?IS_STREAM_MGMT_TAG(Name) -> fsm_next_state(wait_for_auth, dispatch_stream_mgmt(El, StateData)); wait_for_auth({xmlstreamelement, El}, StateData) -> case is_auth_packet(El) of - {auth, _ID, get, {U, _, _, _}} -> - #xmlel{name = Name, attrs = Attrs} = - jlib:make_result_iq_reply(El), - case U of - <<"">> -> UCdata = []; - _ -> UCdata = [{xmlcdata, U}] - end, - Res = case - ejabberd_auth:plain_password_required(StateData#state.server) - of - false -> - #xmlel{name = Name, attrs = Attrs, - children = - [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, ?NS_AUTH}], - children = - [#xmlel{name = <<"username">>, - attrs = [], - children = UCdata}, - #xmlel{name = <<"password">>, - attrs = [], children = []}, - #xmlel{name = <<"digest">>, - attrs = [], children = []}, - #xmlel{name = <<"resource">>, - attrs = [], - children = []}]}]}; - true -> - #xmlel{name = Name, attrs = Attrs, - children = - [#xmlel{name = <<"query">>, - attrs = [{<<"xmlns">>, ?NS_AUTH}], - children = - [#xmlel{name = <<"username">>, - attrs = [], - children = UCdata}, - #xmlel{name = <<"password">>, - attrs = [], children = []}, - #xmlel{name = <<"resource">>, - attrs = [], - children = []}]}]} - end, - send_element(StateData, Res), - fsm_next_state(wait_for_auth, StateData); - {auth, _ID, set, {_U, _P, _D, <<"">>}} -> - Err = jlib:make_error_reply(El, - ?ERR_AUTH_NO_RESOURCE_PROVIDED((StateData#state.lang))), - send_element(StateData, Err), - fsm_next_state(wait_for_auth, StateData); - {auth, _ID, set, {U, P, D, R}} -> - JID = jlib:make_jid(U, StateData#state.server, R), - case JID /= error andalso - acl:match_rule(StateData#state.server, - StateData#state.access, JID) - == allow - of - true -> - DGen = fun (PW) -> - p1_sha:sha(<<(StateData#state.streamid)/binary, PW/binary>>) - end, - case ejabberd_auth:check_password_with_authmodule(U, - StateData#state.server, - P, D, DGen) + {auth, _ID, get, {U, _, _, _}} -> + #xmlel{name = Name, attrs = Attrs} = jlib:make_result_iq_reply(El), + case U of + <<"">> -> UCdata = []; + _ -> UCdata = [{xmlcdata, U}] + end, + Res = case + ejabberd_auth:plain_password_required(StateData#state.server) + of + false -> + #xmlel{name = Name, attrs = Attrs, + children = + [#xmlel{name = <<"query">>, + attrs = [{<<"xmlns">>, ?NS_AUTH}], + children = + [#xmlel{name = <<"username">>, + attrs = [], + children = UCdata}, + #xmlel{name = <<"password">>, + attrs = [], children = []}, + #xmlel{name = <<"digest">>, + attrs = [], children = []}, + #xmlel{name = <<"resource">>, + attrs = [], + children = []}]}]}; + true -> + #xmlel{name = Name, attrs = Attrs, + children = + [#xmlel{name = <<"query">>, + attrs = [{<<"xmlns">>, ?NS_AUTH}], + children = + [#xmlel{name = <<"username">>, + attrs = [], + children = UCdata}, + #xmlel{name = <<"password">>, + attrs = [], children = []}, + #xmlel{name = <<"resource">>, + attrs = [], + children = []}]}]} + end, + send_element(StateData, Res), + fsm_next_state(wait_for_auth, StateData); + {auth, _ID, set, {_U, _P, _D, <<"">>}} -> + Err = jlib:make_error_reply(El, + ?ERR_AUTH_NO_RESOURCE_PROVIDED((StateData#state.lang))), + send_element(StateData, Err), + fsm_next_state(wait_for_auth, StateData); + {auth, _ID, set, {U, P, D, R}} -> + JID = jlib:make_jid(U, StateData#state.server, R), + case JID /= error andalso + acl:match_rule(StateData#state.server, + StateData#state.access, JID) + == allow + of + true -> + DGen = fun (PW) -> + p1_sha:sha(<<(StateData#state.streamid)/binary, PW/binary>>) + end, + case ejabberd_auth:check_password_with_authmodule(U, + StateData#state.server, + P, D, DGen) of - {true, AuthModule} -> - ?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s", - [StateData#state.socket, - jlib:jid_to_string(JID), AuthModule, - ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), - ejabberd_hooks:run(c2s_auth_result, StateData#state.server, - [true, U, StateData#state.server, - StateData#state.ip]), - Conn = get_conn_type(StateData), - Info = [{ip, StateData#state.ip}, {conn, Conn}, + {true, AuthModule} -> + ?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s", + [StateData#state.socket, + jlib:jid_to_string(JID), AuthModule, + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), + ejabberd_hooks:run(c2s_auth_result, StateData#state.server, + [true, U, StateData#state.server, + StateData#state.ip]), + Conn = get_conn_type(StateData), + Info = [{ip, StateData#state.ip}, {conn, Conn}, {auth_module, AuthModule}], - Res = jlib:make_result_iq_reply( - El#xmlel{children = []}), - send_element(StateData, Res), - ejabberd_sm:open_session(StateData#state.sid, U, - StateData#state.server, R, - Info), - change_shaper(StateData, JID), - {Fs, Ts} = - ejabberd_hooks:run_fold(roster_get_subscription_lists, - StateData#state.server, - {[], []}, - [U, - StateData#state.server]), - LJID = - jlib:jid_tolower(jlib:jid_remove_resource(JID)), - Fs1 = [LJID | Fs], - Ts1 = [LJID | Ts], - PrivList = ejabberd_hooks:run_fold(privacy_get_user_list, - StateData#state.server, - #userlist{}, - [U, StateData#state.server]), - NewStateData = StateData#state{user = U, - resource = R, - jid = JID, - conn = Conn, - auth_module = AuthModule, - pres_f = (?SETS):from_list(Fs1), - pres_t = (?SETS):from_list(Ts1), - privacy_list = PrivList}, - fsm_next_state(session_established, NewStateData); - _ -> - ?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s", - [StateData#state.socket, - jlib:jid_to_string(JID), - ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), - ejabberd_hooks:run(c2s_auth_result, StateData#state.server, - [false, U, StateData#state.server, - StateData#state.ip]), - Err = jlib:make_error_reply(El, ?ERR_NOT_AUTHORIZED), - send_element(StateData, Err), - fsm_next_state(wait_for_auth, StateData) - end; - _ -> - if JID == error -> - ?INFO_MSG("(~w) Forbidden legacy authentication " - "for username '~s' with resource '~s'", - [StateData#state.socket, U, R]), - Err = jlib:make_error_reply(El, ?ERR_JID_MALFORMED), - send_element(StateData, Err), - fsm_next_state(wait_for_auth, StateData); - true -> - ?INFO_MSG("(~w) Forbidden legacy authentication " - "for ~s from ~s", - [StateData#state.socket, - jlib:jid_to_string(JID), - ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), - ejabberd_hooks:run(c2s_auth_result, StateData#state.server, - [false, U, StateData#state.server, - StateData#state.ip]), - Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), - send_element(StateData, Err), - fsm_next_state(wait_for_auth, StateData) - end - end; - _ -> - process_unauthenticated_stanza(StateData, El), - fsm_next_state(wait_for_auth, StateData) + Res = jlib:make_result_iq_reply( + El#xmlel{children = []}), + send_element(StateData, Res), + ejabberd_sm:open_session(StateData#state.sid, U, + StateData#state.server, R, + Info), + change_shaper(StateData, JID), + {Fs, Ts} = + ejabberd_hooks:run_fold(roster_get_subscription_lists, + StateData#state.server, + {[], []}, + [U, StateData#state.server]), + LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + Fs1 = [LJID | Fs], + Ts1 = [LJID | Ts], + PrivList = ejabberd_hooks:run_fold(privacy_get_user_list, + StateData#state.server, + #userlist{}, + [U, StateData#state.server]), + NewStateData = StateData#state{user = U, + resource = R, + jid = JID, + conn = Conn, + auth_module = AuthModule, + pres_f = (?SETS):from_list(Fs1), + pres_t = (?SETS):from_list(Ts1), + privacy_list = PrivList}, + fsm_next_state(session_established, NewStateData); + _ -> + ?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s", + [StateData#state.socket, + jlib:jid_to_string(JID), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), + ejabberd_hooks:run(c2s_auth_result, StateData#state.server, + [false, U, StateData#state.server, + StateData#state.ip]), + Err = jlib:make_error_reply(El, ?ERR_NOT_AUTHORIZED), + send_element(StateData, Err), + fsm_next_state(wait_for_auth, StateData) + end; + _ -> + if JID == error -> + ?INFO_MSG("(~w) Forbidden legacy authentication " + "for username '~s' with resource '~s'", + [StateData#state.socket, U, R]), + Err = jlib:make_error_reply(El, ?ERR_JID_MALFORMED), + send_element(StateData, Err), + fsm_next_state(wait_for_auth, StateData); + true -> + ?INFO_MSG("(~w) Forbidden legacy authentication " + "for ~s from ~s", + [StateData#state.socket, + jlib:jid_to_string(JID), + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), + ejabberd_hooks:run(c2s_auth_result, StateData#state.server, + [false, U, StateData#state.server, + StateData#state.ip]), + Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), + send_element(StateData, Err), + fsm_next_state(wait_for_auth, StateData) + end + end; + _ -> + process_unauthenticated_stanza(StateData, El), + fsm_next_state(wait_for_auth, StateData) end; wait_for_auth(timeout, StateData) -> {stop, normal, StateData}; @@ -786,10 +764,10 @@ wait_for_feature_request({xmlstreamelement, El}, fsm_next_state(wait_for_sasl_response, StateData#state{sasl_state = NewSASLState}); {error, Error, Username} -> - ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s", - [StateData#state.socket, - Username, StateData#state.server, - ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), + ?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s", + [StateData#state.socket, + Username, StateData#state.server, + ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, Username, StateData#state.server, StateData#state.ip]), @@ -1121,46 +1099,45 @@ wait_for_session({xmlstreamelement, El}, StateData) -> R = NewStateData#state.resource, JID = NewStateData#state.jid, case acl:match_rule(NewStateData#state.server, - NewStateData#state.access, JID) of + NewStateData#state.access, JID) of allow -> ?INFO_MSG("(~w) Opened session for ~s", - [NewStateData#state.socket, - jlib:jid_to_string(JID)]), + [NewStateData#state.socket, jlib:jid_to_string(JID)]), Res = jlib:make_result_iq_reply(El#xmlel{children = []}), NewState = send_stanza(NewStateData, Res), change_shaper(NewState, JID), {Fs, Ts} = ejabberd_hooks:run_fold( - roster_get_subscription_lists, - NewState#state.server, - {[], []}, - [U, NewState#state.server]), + roster_get_subscription_lists, + NewState#state.server, + {[], []}, + [U, NewState#state.server]), LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), Fs1 = [LJID | Fs], Ts1 = [LJID | Ts], PrivList = ejabberd_hooks:run_fold( - privacy_get_user_list, NewState#state.server, - #userlist{}, - [U, NewState#state.server]), + privacy_get_user_list, + NewState#state.server, + #userlist{}, + [U, NewState#state.server]), Conn = get_conn_type(NewState), Info = [{ip, NewState#state.ip}, {conn, Conn}, {auth_module, NewState#state.auth_module}], ejabberd_sm:open_session( - NewState#state.sid, U, NewState#state.server, R, Info), - UpdatedStateData = - NewState#state{ - conn = Conn, - pres_f = ?SETS:from_list(Fs1), - pres_t = ?SETS:from_list(Ts1), - privacy_list = PrivList}, + NewState#state.sid, U, NewState#state.server, R, Info), + UpdatedStateData = + NewState#state{ + conn = Conn, + pres_f = ?SETS:from_list(Fs1), + pres_t = ?SETS:from_list(Ts1), + privacy_list = PrivList}, fsm_next_state_pack(session_established, - UpdatedStateData); + UpdatedStateData); _ -> ejabberd_hooks:run(forbidden_session_hook, - NewStateData#state.server, [JID]), + NewStateData#state.server, [JID]), ?INFO_MSG("(~w) Forbidden session for ~s", - [NewStateData#state.socket, - jlib:jid_to_string(JID)]), + [NewStateData#state.socket, jlib:jid_to_string(JID)]), Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), send_element(NewStateData, Err), fsm_next_state(wait_for_session, NewStateData) @@ -1168,7 +1145,6 @@ wait_for_session({xmlstreamelement, El}, StateData) -> _ -> fsm_next_state(wait_for_session, NewStateData) end; - wait_for_session(timeout, StateData) -> {stop, normal, StateData}; wait_for_session({xmlstreamend, _Name}, StateData) -> @@ -1230,8 +1206,7 @@ session_established(closed, #state{mgmt_state = active} = StateData) -> session_established(closed, StateData) -> {stop, normal, StateData}. -%% Process packets sent by user (coming from user on c2s XMPP -%% connection) +%% Process packets sent by user (coming from user on c2s XMPP connection) session_established2(El, StateData) -> #xmlel{name = Name, attrs = Attrs} = El, NewStateData = update_num_stanzas_in(StateData, El), @@ -1323,37 +1298,9 @@ wait_for_resume(Event, StateData) -> ?DEBUG("Ignoring event while waiting for resumption: ~p", [Event]), fsm_next_state(wait_for_resume, StateData). -%%---------------------------------------------------------------------- -%% Func: StateName/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- -%state_name(Event, From, StateData) -> -% Reply = ok, -% {reply, Reply, state_name, StateData}. - -%%---------------------------------------------------------------------- -%% Func: handle_event/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_event(_Event, StateName, StateData) -> fsm_next_state(StateName, StateData). -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- handle_sync_event({get_presence}, _From, StateName, StateData) -> User = StateData#state.user, @@ -1386,12 +1333,6 @@ handle_sync_event(_Event, _From, StateName, code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), ejabberd_hooks:run(c2s_loop_debug, [Text]), @@ -1446,7 +1387,8 @@ handle_info({route, _From, _To, {broadcast, Data}}, jlib:jid_remove_resource(StateData#state.jid), StateData#state.jid, jlib:iq_to_xml(PrivPushIQ)), - NewState = send_stanza(StateData, PrivPushEl), + NewState = send_stanza( + StateData, PrivPushEl), fsm_next_state(StateName, NewState#state{privacy_list = NewPL}) end; @@ -1682,7 +1624,8 @@ handle_info({route, From, To, From, To, Packet, in) of - allow -> {true, Attrs, StateData}; + allow -> + {true, Attrs, StateData}; deny -> case xml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; @@ -1700,14 +1643,14 @@ handle_info({route, From, To, end, if Pass -> Attrs2 = - jlib:replace_from_to_attrs(jlib:jid_to_string(From), - jlib:jid_to_string(To), NewAttrs), + jlib:replace_from_to_attrs(jlib:jid_to_string(From), + jlib:jid_to_string(To), NewAttrs), FixedPacket0 = #xmlel{name = Name, attrs = Attrs2, children = Els}, FixedPacket = ejabberd_hooks:run_fold( - user_receive_packet, - NewState#state.server, - FixedPacket0, - [NewState, NewState#state.jid, From, To]), + user_receive_packet, + NewState#state.server, + FixedPacket0, + [NewState, NewState#state.jid, From, To]), SentStateData = send_packet(NewState, FixedPacket), ejabberd_hooks:run(c2s_loop_debug, [{route, From, To, Packet}]), fsm_next_state(StateName, SentStateData); @@ -1798,23 +1741,11 @@ handle_info(Info, StateName, StateData) -> ?ERROR_MSG("Unexpected info: ~p", [Info]), fsm_next_state(StateName, StateData). - -%%---------------------------------------------------------------------- -%% Func: print_state/1 -%% Purpose: Prepare the state to be printed on error log -%% Returns: State to print -%%---------------------------------------------------------------------- print_state(State = #state{pres_t = T, pres_f = F, pres_a = A}) -> - State#state{pres_t = {pres_t, ?SETS:size(T)}, - pres_f = {pres_f, ?SETS:size(F)}, - pres_a = {pres_a, ?SETS:size(A)} - }. - -%%---------------------------------------------------------------------- -%% Func: terminate/3 -%% Purpose: Shutdown the fsm -%% Returns: any -%%---------------------------------------------------------------------- + State#state{pres_t = {pres_t, (?SETS):size(T)}, + pres_f = {pres_f, (?SETS):size(F)}, + pres_a = {pres_a, (?SETS):size(A)}}. + terminate(_Reason, StateName, StateData) -> case StateData#state.mgmt_state of resumed -> @@ -1986,7 +1917,7 @@ is_auth_packet(El) -> #iq{id = ID, type = Type, xmlns = ?NS_AUTH, sub_el = SubEl} -> #xmlel{children = Els} = SubEl, {auth, ID, Type, - get_auth_tags(Els, <<"">>, <<"">>, <<"">>, <<"">>)}; + get_auth_tags(Els, <<"">>, <<"">>, <<"">>, <<"">>)}; _ -> false end. @@ -2042,12 +1973,11 @@ process_presence_probe(From, To, StateData) -> undefined -> ok; _ -> - Cond = ?SETS:is_element(LFrom, StateData#state.pres_f) - orelse - ((LFrom /= LBFrom) andalso - ?SETS:is_element(LBFrom, StateData#state.pres_f)), - if - Cond -> + Cond = ((?SETS):is_element(LFrom, StateData#state.pres_f) + orelse + ((LFrom /= LBFrom) andalso + (?SETS):is_element(LBFrom, StateData#state.pres_f))), + if Cond -> %% To is the one sending the presence (the probe target) Packet = jlib:add_delay_info(StateData#state.pres_last, To, StateData#state.pres_timestamp), @@ -2283,11 +2213,11 @@ roster_change(IJID, ISubscription, StateData) -> OldIsFrom = (?SETS):is_element(LIJID, StateData#state.pres_f), FSet = if IsFrom -> (?SETS):add_element(LIJID, StateData#state.pres_f); - not IsFrom -> remove_element(LIJID, StateData#state.pres_f) + true -> remove_element(LIJID, StateData#state.pres_f) end, TSet = if IsTo -> (?SETS):add_element(LIJID, StateData#state.pres_t); - not IsTo -> remove_element(LIJID, StateData#state.pres_t) + true -> remove_element(LIJID, StateData#state.pres_t) end, case StateData#state.pres_last of undefined -> @@ -2543,12 +2473,12 @@ check_from(El, FromJID) -> #jid{} -> if (JID#jid.luser == FromJID#jid.luser) and - (JID#jid.lserver == FromJID#jid.lserver) and - (JID#jid.lresource == FromJID#jid.lresource) -> + (JID#jid.lserver == FromJID#jid.lserver) and + (JID#jid.lresource == FromJID#jid.lresource) -> El; (JID#jid.luser == FromJID#jid.luser) and - (JID#jid.lserver == FromJID#jid.lserver) and - (JID#jid.lresource == <<"">>) -> + (JID#jid.lserver == FromJID#jid.lserver) and + (JID#jid.lresource == <<"">>) -> El; true -> 'invalid-from' diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 8a1de2ede8d..8815c43678e 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -75,13 +75,6 @@ tref :: reference(), args :: any()}). -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). @@ -276,12 +269,6 @@ create_captcha_x(SID, To, Lang, Limiter, HeadEls, Err -> Err end. -%% @spec (Id::string(), Lang::string()) -> {FormEl, {ImgEl, TextEl, IdEl, KeyEl}} | captcha_not_found -%% where FormEl = xmlelement() -%% ImgEl = xmlelement() -%% TextEl = xmlelement() -%% IdEl = xmlelement() -%% KeyEl = xmlelement() -spec build_captcha_html(binary(), binary()) -> captcha_not_found | {xmlel(), {xmlel(), xmlel(), @@ -330,12 +317,6 @@ build_captcha_html(Id, Lang) -> _ -> captcha_not_found end. -%% @spec (Id::string(), ProvidedKey::string()) -> captcha_valid | captcha_non_valid | captcha_not_found --spec check_captcha(binary(), binary()) -> captcha_not_found | - captcha_valid | - captcha_non_valid. - - -spec process_reply(xmlel()) -> ok | {error, bad_match | not_found | malformed}. process_reply(#xmlel{} = El) -> @@ -405,9 +386,6 @@ process(_Handlers, process(_Handlers, _Request) -> ejabberd_web:error(not_found). -%%==================================================================== -%% gen_server callbacks -%%==================================================================== init([]) -> mnesia:delete_table(captcha), ets:new(captcha, @@ -454,16 +432,6 @@ terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- -%%% Internal functions -%%-------------------------------------------------------------------- -%%-------------------------------------------------------------------- -%% Function: create_image() -> {ok, Type, Key, Image} | {error, Reason} -%% Type = "image/png" | "image/jpeg" | "image/gif" -%% Key = string() -%% Image = binary() -%% Reason = atom() -%%-------------------------------------------------------------------- create_image() -> create_image(undefined). create_image(Limiter) -> @@ -596,12 +564,6 @@ is_limited(Limiter) -> end end. -%%-------------------------------------------------------------------- -%% Function: cmd(Cmd) -> Data | {error, Reason} -%% Cmd = string() -%% Data = binary() -%% Description: os:cmd/1 replacement -%%-------------------------------------------------------------------- -define(CMD_TIMEOUT, 5000). -define(MAX_FILE_SIZE, 64 * 1024). @@ -663,6 +625,10 @@ lookup_captcha(Id) -> _ -> {error, enoent} end. +-spec check_captcha(binary(), binary()) -> captcha_not_found | + captcha_valid | + captcha_non_valid. + check_captcha(Id, ProvidedKey) -> case ets:lookup(captcha, Id) of [#captcha{pid = Pid, args = Args, key = ValidKey, diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl new file mode 100644 index 00000000000..5c3a0fc5b9f --- /dev/null +++ b/src/ejabberd_cluster.erl @@ -0,0 +1,53 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_cluster.erl +%%% Author : Christophe Romain +%%% Purpose : Ejabberd clustering management +%%% Created : 7 Oct 2015 by Christophe Romain +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-module(ejabberd_cluster). + +%% API +-export([get_nodes/0, call/4, multicall/3, multicall/4]). + +-include("ejabberd.hrl"). +-include("logger.hrl"). + +-spec get_nodes() -> [node()]. + +get_nodes() -> + mnesia:system_info(running_db_nodes). + +-spec call(node(), module(), atom(), [any()]) -> any(). + +call(Node, Module, Function, Args) -> + rpc:call(Node, Module, Function, Args, 5000). + +-spec multicall(module(), atom(), [any()]) -> {list(), [node()]}. + +multicall(Module, Function, Args) -> + multicall(get_nodes(), Module, Function, Args). + +-spec multicall([node()], module(), atom(), list()) -> {list(), [node()]}. + +multicall(Nodes, Module, Function, Args) -> + rpc:multicall(Nodes, Module, Function, Args, 5000). + diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index 34297e006b4..c5026328602 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -326,7 +326,7 @@ execute_command(Name, Arguments) -> ) -> any(). %% @spec (AccessCommands, Auth, Name::atom(), Arguments) -> ResultTerm | {error, Error} -%% where +%% where %% AccessCommands = [{Access, CommandNames, Arguments}] %% Auth = {User::string(), Server::string(), Password::string(), Admin::boolean()} %% | noauth @@ -414,7 +414,7 @@ get_tags_commands() -> %% ----------------------------- %% @spec (AccessCommands, Auth, Method, Command, Arguments) -> ok -%% where +%% where %% AccessCommands = [ {Access, CommandNames, Arguments} ] %% Auth = {User::string(), Server::string(), Password::string()} | noauth %% Method = atom() @@ -479,8 +479,8 @@ check_auth(Command, {User, Server, {oauth, Token}, _}) -> check_auth(_Command, {User, Server, Password, _}) when is_binary(Password) -> %% Check the account exists and password is valid case ejabberd_auth:check_password(User, Server, Password) of - true -> {ok, User, Server}; - _ -> throw({error, invalid_account_data}) + true -> {ok, User, Server}; + _ -> throw({error, invalid_account_data}) end. check_access(Command, all, _) @@ -528,9 +528,9 @@ check_access_arguments(Command, ArgumentRestrictions, Arguments) -> tag_arguments(ArgsDefs, Args) -> lists:zipwith( - fun({ArgName, _ArgType}, ArgValue) -> + fun({ArgName, _ArgType}, ArgValue) -> {ArgName, ArgValue} - end, + end, ArgsDefs, Args). diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 0ff1706ae93..8f3795cd36a 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -192,7 +192,6 @@ env_binary_to_list(Application, Parameter) -> %% Returns a list of plain terms, %% in which the options 'include_config_file' were parsed %% and the terms in those files were included. -%% @spec(string()) -> [term()] %% @spec(iolist()) -> [term()] get_plain_terms_file(File) -> get_plain_terms_file(File, [{include_files, true}]). @@ -844,6 +843,7 @@ replace_module(mod_roster_odbc) -> {mod_roster, odbc}; replace_module(mod_shared_roster_odbc) -> {mod_shared_roster, odbc}; replace_module(mod_vcard_odbc) -> {mod_vcard, odbc}; replace_module(mod_vcard_xupdate_odbc) -> {mod_vcard_xupdate, odbc}; +replace_module(mod_pubsub_odbc) -> {mod_pubsub, odbc}; replace_module(Module) -> case is_elixir_module(Module) of true -> expand_elixir_module(Module); diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index dd258833c65..70e17b4133d 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -80,7 +80,7 @@ start() -> end end, Node = list_to_atom(SNode1), - Status = case rpc:call(Node, ?MODULE, process, [Args]) of + Status = case ejabberd_cluster:call(Node, ?MODULE, process, [Args]) of {badrpc, Reason} -> print("Failed RPC connection to the node ~p: ~p~n", [Node, Reason]), @@ -392,7 +392,10 @@ format_result(ElementsTuple, {_Name, {tuple, ElementsDef}}) -> fun({Element, ElementDef}) -> ["\t" | format_result(Element, ElementDef)] end, - ElementsAndDef)]. + ElementsAndDef)]; + +format_result(404, {_Name, _}) -> + make_status(not_found). make_status(ok) -> ?STATUS_SUCCESS; make_status(true) -> ?STATUS_SUCCESS; diff --git a/src/ejabberd_frontend_socket.erl b/src/ejabberd_frontend_socket.erl index b169572b32b..ad227b039e4 100644 --- a/src/ejabberd_frontend_socket.erl +++ b/src/ejabberd_frontend_socket.erl @@ -58,10 +58,6 @@ %%==================================================================== %% API %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- start_link(Module, SockMod, Socket, Opts, Receiver) -> gen_server:start_link(?MODULE, [Module, SockMod, Socket, Opts, Receiver], []). @@ -137,18 +133,10 @@ peername(_FsmRef) -> %%gen_server:call(FsmRef, peername). {ok, {{0, 0, 0, 0}, 0}}. - %%==================================================================== %% gen_server callbacks %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([Module, SockMod, Socket, Opts, Receiver]) -> Node = ejabberd_node_groups:get_closest_node(backend), {SockMod2, Socket2} = check_starttls(SockMod, Socket, Receiver, Opts), @@ -159,15 +147,6 @@ init([Module, SockMod, Socket, Opts, Receiver]) -> socket = Socket2, receiver = Receiver}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call({starttls, TLSOpts}, _From, State) -> {ok, TLSSocket} = p1_tls:tcp_to_tls(State#state.socket, TLSOpts), ejabberd_receiver:starttls(State#state.receiver, TLSSocket), @@ -184,7 +163,6 @@ handle_call({starttls, TLSOpts, Data}, _From, State) -> {reply, Reply, State#state{socket = TLSSocket, sockmod = p1_tls}, ?HIBERNATE_TIMEOUT}; - handle_call({compress, Data}, _From, State) -> {ok, ZlibSocket} = ejabberd_receiver:compress(State#state.receiver, Data), @@ -238,21 +216,9 @@ handle_call(peername, _From, State) -> handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info(timeout, State) -> proc_lib:hibernate(gen_server, enter_loop, [?MODULE, [], State]), @@ -260,31 +226,16 @@ handle_info(timeout, State) -> handle_info(_Info, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. -%%-------------------------------------------------------------------- -%%% Internal functions -%%-------------------------------------------------------------------- check_starttls(SockMod, Socket, Receiver, Opts) -> TLSEnabled = proplists:get_bool(tls, Opts), TLSOpts = lists:filter(fun({certfile, _}) -> true; (_) -> false end, Opts), - if - TLSEnabled -> + if TLSEnabled -> {ok, TLSSocket} = p1_tls:tcp_to_tls(Socket, TLSOpts), ejabberd_receiver:starttls(Receiver, TLSSocket), {p1_tls, TLSSocket}; diff --git a/src/ejabberd_hooks.erl b/src/ejabberd_hooks.erl index d136ba70564..dd03e4ca48e 100644 --- a/src/ejabberd_hooks.erl +++ b/src/ejabberd_hooks.erl @@ -58,9 +58,6 @@ -include("logger.hrl"). -%% Timeout of 5 seconds in calls to distributed hooks --define(TIMEOUT_DISTRIBUTED_HOOK, 5000). - -record(state, {}). -type local_hook() :: { Seq :: integer(), Module :: atom(), Function :: atom()}. -type distributed_hook() :: { Seq :: integer(), Node :: atom(), Module :: atom(), Function :: atom()}. @@ -310,7 +307,7 @@ run1([], _Hook, _Args) -> %% It is not attempted again in case of failure. Next hook will be executed run1([{_Seq, Node, Module, Function} | Ls], Hook, Args) -> %% MR: Should we have a safe rpc, like we have a safe apply or is bad_rpc enough ? - case rpc:call(Node, Module, Function, Args, ?TIMEOUT_DISTRIBUTED_HOOK) of + case ejabberd_cluster:call(Node, Module, Function, Args) of timeout -> ?ERROR_MSG("Timeout on RPC to ~p~nrunning hook: ~p", [Node, {Hook, Args}]), @@ -344,7 +341,7 @@ run1([{_Seq, Module, Function} | Ls], Hook, Args) -> run_fold1([], _Hook, Val, _Args) -> Val; run_fold1([{_Seq, Node, Module, Function} | Ls], Hook, Val, Args) -> - case rpc:call(Node, Module, Function, [Val | Args], ?TIMEOUT_DISTRIBUTED_HOOK) of + case ejabberd_cluster:call(Node, Module, Function, [Val | Args]) of {badrpc, Reason} -> ?ERROR_MSG("Bad RPC error to ~p: ~p~nrunning hook: ~p", [Node, Reason, {Hook, Args}]), diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 4c647ab5807..d2649846bf0 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -166,7 +166,8 @@ init({SockMod, Socket}, Opts) -> {error, _} -> State end. -become_controller(_Pid) -> ok. +become_controller(_Pid) -> + ok. socket_type() -> raw. @@ -201,22 +202,20 @@ parse_headers(#state{request_method = Method, trail = Data} = State) -> PktType = case Method of - undefined -> http_bin; - _ -> httph_bin - end, + undefined -> http_bin; + _ -> httph_bin + end, case erlang:decode_packet(PktType, Data, []) of - {ok, Pkt, Rest} -> - NewState = process_header(State#state{trail = Rest}, {ok, Pkt}), + {ok, Pkt, Rest} -> + NewState = process_header(State#state{trail = Rest}, {ok, Pkt}), case NewState#state.end_of_request of - true -> - ok; - _ -> - parse_headers(NewState) + true -> ok; + _ -> parse_headers(NewState) end; - {more, _} -> - receive_headers(State#state{trail = Data}); - _ -> - ok + {more, _} -> + receive_headers(State#state{trail = Data}); + _ -> + ok end. process_header(State, Data) -> @@ -266,10 +265,8 @@ process_header(State, Data) -> State#state{request_host = Host, request_headers = add_header(Name, Host, State)}; {ok, {http_header, _, Name, _, Value}} when is_binary(Name) -> - State#state{request_headers = - add_header(normalize_header_name(Name), - Value, - State)}; + State#state{request_headers = + add_header(normalize_header_name(Name), Value, State)}; {ok, {http_header, _, Name, _, Value}} -> State#state{request_headers = add_header(Name, Value, State)}; @@ -322,14 +319,6 @@ get_host_really_served(Default, Provided) -> false -> Default end. -%% @spec (SockMod, HostPort) -> {Host::string(), Port::integer(), TP} -%% where -%% SockMod = gen_tcp | tls -%% HostPort = string() -%% TP = http | https -%% @doc Given a socket and hostport header, return data of transfer protocol. -%% Note that HostPort can be a string of a host like "example.org", -%% or a string of a host and port like "example.org:5280". get_transfer_protocol(SockMod, HostPort) -> [Host | PortList] = str:tokens(HostPort, <<":">>), case {SockMod, PortList} of @@ -416,17 +405,17 @@ extract_path_query(_State) -> false. process_request(#state{request_method = Method, - request_auth = Auth, - request_lang = Lang, - sockmod = SockMod, - socket = Socket, - options = Options, - request_host = Host, - request_port = Port, - request_tp = TP, - request_headers = RequestHeaders, - request_handlers = RequestHandlers, - trail = Trail} = State) -> + request_auth = Auth, + request_lang = Lang, + sockmod = SockMod, + socket = Socket, + options = Options, + request_host = Host, + request_port = Port, + request_tp = TP, + request_headers = RequestHeaders, + request_handlers = RequestHandlers, + trail = Trail} = State) -> case extract_path_query(State) of false -> make_bad_request(State); @@ -476,7 +465,6 @@ process_request(#state{request_method = Method, end. make_bad_request(State) -> -%% Support for X-Forwarded-From make_xhtml_output(State, 400, [], ejabberd_web:make_xhtml([#xmlel{name = <<"h1">>, attrs = [], @@ -532,13 +520,13 @@ recv_data(State, Len, Acc) -> make_xhtml_output(State, Status, Headers, XHTML) -> Data = case lists:member(html, Headers) of - true -> - iolist_to_binary([?HTML_DOCTYPE, - xml:element_to_binary(XHTML)]); - _ -> - iolist_to_binary([?XHTML_DOCTYPE, - xml:element_to_binary(XHTML)]) - end, + true -> + iolist_to_binary([?HTML_DOCTYPE, + xml:element_to_binary(XHTML)]); + _ -> + iolist_to_binary([?XHTML_DOCTYPE, + xml:element_to_binary(XHTML)]) + end, Headers1 = case lists:keysearch(<<"Content-Type">>, 1, Headers) of diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index 42be5256132..de3eb70dbb5 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -1,11 +1,27 @@ %%%---------------------------------------------------------------------- %%% File : ejabberd_http_bind.erl %%% Author : Stefan Strigler -%%% Purpose : Implements XMPP over BOSH (XEP-0206) (formerly known as -%%% HTTP Binding) +%%% Purpose : Implements XMPP over BOSH (XEP-0206) %%% Created : 21 Sep 2005 by Stefan Strigler %%% Modified: may 2009 by Mickael Remond, Alexey Schepin -%%% Id : $Id: ejabberd_http_bind.erl 953 2009-05-07 10:40:40Z alexey $ +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% %%%---------------------------------------------------------------------- -module(ejabberd_http_bind). @@ -78,7 +94,7 @@ wait_timer, ctime = 0, timer, - pause=0, + pause = 0, unprocessed_req_list = [], % list of request that have been delayed for proper reordering: {Request, PID} req_list = [], % list of requests (cache) max_inactivity, @@ -132,19 +148,15 @@ -define(PROCESS_DELAY_MAX, 1000). -%% Line copied from mod_http_bind.erl -define(PROCNAME_MHB, ejabberd_mod_http_bind). -%%%---------------------------------------------------------------------- -%%% API -%%%---------------------------------------------------------------------- -%% TODO: If compile with no supervisor option, start the session without -%% supervisor start(XMPPDomain, Sid, Key, IP, HOpts) -> ?DEBUG("Starting session", []), SupervisorProc = gen_mod:get_module_proc(XMPPDomain, ?PROCNAME_MHB), - case catch supervisor:start_child(SupervisorProc, [Sid, Key, IP, HOpts]) of - {ok, Pid} -> {ok, Pid}; + case catch supervisor:start_child(SupervisorProc, + [Sid, Key, IP, HOpts]) + of + {ok, Pid} -> {ok, Pid}; _ -> check_bind_module(XMPPDomain), {error, "Cannot start HTTP bind session"} end. @@ -222,7 +234,7 @@ process_request(Data, IP, HOpts) -> XmppDomain -> NXmppDomain = jlib:nameprep(XmppDomain), Sid = p1_sha:sha(term_to_binary({now(), make_ref()})), - case start(NXmppDomain, Sid, <<"">>, IP, HOpts) of + case start(NXmppDomain, Sid, <<"">>, IP, HOpts) of {error, _} -> {500, ?HEADER, <<" {updated, undefined}. %% Open a database connection to MySQL mysql_connect(Server, Port, DB, Username, Password) -> case p1_mysql_conn:start(binary_to_list(Server), Port, - binary_to_list(Username), binary_to_list(Password), - binary_to_list(DB), fun log/3) + binary_to_list(Username), + binary_to_list(Password), + binary_to_list(DB), fun log/3) of - {ok, Ref} -> - p1_mysql_conn:fetch(Ref, [<<"set names 'utf8';">>], - self()), - {ok, Ref}; - Err -> Err + {ok, Ref} -> + p1_mysql_conn:fetch( + Ref, [<<"set names 'utf8';">>], self()), + {ok, Ref}; + Err -> Err end. %% Convert MySQL query result to Erlang ODBC result formalism @@ -706,7 +703,7 @@ db_opts(Host) -> [odbc, <<"DSN=", Host/binary, ";UID=", Username/binary, ";PWD=", Pass/binary>>]; _ -> - [Type, Server, Port, DB, User, Pass] + [Type, Server, Port, DB, User, Pass] end end. diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 3b29aeefe5a..c5e6a443627 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -5,7 +5,6 @@ %%% Created : 17 Jul 2008 by Pablo Polvorin %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2012, Evgeniy Khramtsov %%% @doc %%% %%% @@ -714,31 +713,9 @@ make_xinclude(Fn) -> Base = filename:basename(Fn), io_lib:format("", [Base]). -%%%================================== -%%%% Export user -%% @spec (Fd, Username::string(), Host::string()) -> ok -%% @doc Extract user information and print it. -%% @spec (Username::string(), Host::string()) -> string() -%% @spec (InfoName::atom(), Username::string(), Host::string()) -> string() -%%%================================== -%%%% Interface with ejabberd offline storage -%% Copied from mod_offline.erl and customized -%%%================================== -%%%% Interface with ejabberd private storage -%%%================================== -%%%% Disk file access -%% @spec () -> string() -%% @spec (Dir::string(), FnT::string()) -> string() -%% @spec (FnT::string(), Host::string()) -> FnH::string() -%% @doc Make the filename for the host. -%% Example: ``("20080804-231550", "jabber.example.org") -> "20080804-231550_jabber_example_org.xml"'' -%% @spec (Fn::string()) -> {ok, Fd} -%% @spec (Fd) -> ok -%% @spec (Fd, String::string()) -> ok print(Fd, String) -> -%%%================================== -%%% vim: set filetype=erlang tabstop=8 foldmarker=%%%%,%%%= foldmethod=marker: file:write(Fd, String). opt_type(auth_password_format) -> fun (X) -> X end; opt_type(_) -> [auth_password_format]. + diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 9652e526802..cd7c1d31adc 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -58,13 +58,6 @@ -define(HIBERNATE_TIMEOUT, 90000). -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- -spec start_link(inet:socket(), atom(), shaper:shaper(), non_neg_integer() | infinity) -> ignore | {error, any()} | @@ -76,10 +69,6 @@ start_link(Socket, SockMod, Shaper, MaxStanzaSize) -> -spec start(inet:socket(), atom(), shaper:shaper()) -> undefined | pid(). -%%-------------------------------------------------------------------- -%% Function: start() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- start(Socket, SockMod, Shaper) -> start(Socket, SockMod, Shaper, infinity). @@ -127,13 +116,6 @@ close(Pid) -> %% gen_server callbacks %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([Socket, SockMod, Shaper, MaxStanzaSize]) -> ShaperState = shaper:new(Shaper), Timeout = case SockMod of @@ -145,15 +127,6 @@ init([Socket, SockMod, Shaper, MaxStanzaSize]) -> shaper_state = ShaperState, max_stanza_size = MaxStanzaSize, timeout = Timeout}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call({starttls, TLSSocket}, _From, #state{xml_stream_state = XMLStreamState, c2s_pid = C2SPid, @@ -163,15 +136,15 @@ handle_call({starttls, TLSSocket}, _From, undefined -> XMLStreamState; _ -> - xml_stream:new(C2SPid, - MaxStanzaSize) + xml_stream:new(C2SPid, MaxStanzaSize) end, NewState = State#state{socket = TLSSocket, sock_mod = p1_tls, xml_stream_state = NewXMLStreamState}, case p1_tls:recv_data(TLSSocket, <<"">>) of {ok, TLSData} -> - {reply, ok, process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT}; + {reply, ok, + process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT}; {error, _Reason} -> {stop, normal, ok, NewState} end; @@ -186,24 +159,23 @@ handle_call({compress, Data}, _From, true -> ok end, close_stream(XMLStreamState), - NewXMLStreamState = xml_stream:new(C2SPid, - MaxStanzaSize), + NewXMLStreamState = xml_stream:new(C2SPid, MaxStanzaSize), NewState = State#state{socket = ZlibSocket, sock_mod = ezlib, xml_stream_state = NewXMLStreamState}, case ezlib:recv_data(ZlibSocket, <<"">>) of {ok, ZlibData} -> - {reply, {ok, ZlibSocket}, - process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT}; - {error, _Reason} -> {stop, normal, ok, NewState} + {reply, {ok, ZlibSocket}, + process_data(ZlibData, NewState), ?HIBERNATE_TIMEOUT}; + {error, _Reason} -> + {stop, normal, ok, NewState} end; handle_call(reset_stream, _From, #state{xml_stream_state = XMLStreamState, c2s_pid = C2SPid, max_stanza_size = MaxStanzaSize} = State) -> close_stream(XMLStreamState), - NewXMLStreamState = xml_stream:new(C2SPid, - MaxStanzaSize), + NewXMLStreamState = xml_stream:new(C2SPid, MaxStanzaSize), Reply = ok, {reply, Reply, State#state{xml_stream_state = NewXMLStreamState}, @@ -218,12 +190,6 @@ handle_call({become_controller, C2SPid}, _From, State) -> handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State, ?HIBERNATE_TIMEOUT}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast({change_shaper, Shaper}, State) -> NewShaperState = shaper:new(Shaper), {noreply, State#state{shaper_state = NewShaperState}, @@ -232,12 +198,6 @@ handle_cast(close, State) -> {stop, normal, State}; handle_cast(_Msg, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info({Tag, _TCPSocket, Data}, #state{socket = Socket, sock_mod = SockMod} = State) when (Tag == tcp) or (Tag == ssl) or @@ -285,13 +245,6 @@ handle_info(timeout, State) -> handle_info(_Info, State) -> {noreply, State, ?HIBERNATE_TIMEOUT}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, #state{xml_stream_state = XMLStreamState, c2s_pid = C2SPid} = @@ -304,10 +257,6 @@ terminate(_Reason, catch (State#state.sock_mod):close(State#state.socket), ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- diff --git a/src/ejabberd_riak.erl b/src/ejabberd_riak.erl index c8084674fab..7f89775e0a8 100644 --- a/src/ejabberd_riak.erl +++ b/src/ejabberd_riak.erl @@ -6,6 +6,8 @@ %%% Created : 29 Dec 2011 by Alexey Shchepin %%% @copyright (C) 2002-2015 ProcessOne %%% +%%% ejabberd, Copyright (C) 2002-2015 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 diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 6a56a22eae2..53ac7fb4cbf 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -226,7 +226,8 @@ dirty_get_all_domains() -> init([]) -> update_tables(), mnesia:create_table(route, - [{ram_copies, [node()]}, {type, bag}, + [{ram_copies, [node()]}, + {type, bag}, {attributes, record_info(fields, route)}]), mnesia:add_table_copy(route, node(), ram_copies), mnesia:subscribe({table, route, simple}), diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index 373d92272d1..226a3492759 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -3,6 +3,24 @@ %%% Author : Badlop %%% Purpose : Multicast router %%% Created : 11 Aug 2007 by Badlop +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% %%%---------------------------------------------------------------------- -module(ejabberd_router_multicast). diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index b5604eb7c7e..9923eb121f5 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -85,13 +85,6 @@ -type temporarily_blocked() :: #temporarily_blocked{}. -%%==================================================================== -%% API -%%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). @@ -162,7 +155,7 @@ remove_connection(FromTo, Pid, Key) -> have_connection(FromTo) -> case catch mnesia:dirty_read(s2s, FromTo) of - [_] -> + [_] -> true; _ -> false @@ -251,51 +244,26 @@ check_peer_certificate(SockMod, Sock, Peer) -> %% gen_server callbacks %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([]) -> update_tables(), - mnesia:create_table(s2s, [{ram_copies, [node()]}, {type, bag}, - {attributes, record_info(fields, s2s)}]), + mnesia:create_table(s2s, + [{ram_copies, [node()]}, + {type, bag}, + {attributes, record_info(fields, s2s)}]), mnesia:add_table_copy(s2s, node(), ram_copies), mnesia:subscribe(system), ejabberd_commands:register_commands(commands()), - mnesia:create_table(temporarily_blocked, [{ram_copies, [node()]}, {attributes, record_info(fields, temporarily_blocked)}]), + mnesia:create_table(temporarily_blocked, + [{ram_copies, [node()]}, + {attributes, record_info(fields, temporarily_blocked)}]), {ok, #state{}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call(_Request, _From, State) -> - Reply = ok, - {reply, Reply, State}. + {reply, ok, State}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info({mnesia_system_event, {mnesia_down, Node}}, State) -> clean_table_from_bad_node(Node), {noreply, State}; @@ -309,27 +277,17 @@ handle_info({route, From, To, Packet}, State) -> {noreply, State}; handle_info(_Info, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, _State) -> ejabberd_commands:unregister_commands(commands()), ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- + clean_table_from_bad_node(Node) -> F = fun() -> Es = mnesia:select( @@ -520,7 +478,8 @@ parent_domains(Domain) -> end, [], lists:reverse(str:tokens(Domain, <<".">>))). -send_element(Pid, El) -> Pid ! {send_element, El}. +send_element(Pid, El) -> + Pid ! {send_element, El}. %%%---------------------------------------------------------------------- %%% ejabberd commands @@ -566,10 +525,8 @@ update_tables() -> {'EXIT', _} -> ok end, case lists:member(local_s2s, mnesia:system_info(tables)) of - true -> - mnesia:delete_table(local_s2s); - false -> - ok + true -> mnesia:delete_table(local_s2s); + false -> ok end. %% Check if host is in blacklist or white list diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 99a313ef6b1..d840c315877 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -111,9 +111,6 @@ -define(INVALID_XML_ERR, xml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). -%%%---------------------------------------------------------------------- -%%% API -%%%---------------------------------------------------------------------- start(SockData, Opts) -> ?SUPERVISOR_START. start_link(SockData, Opts) -> @@ -126,13 +123,6 @@ socket_type() -> xml_stream. %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, StateName, StateData} | -%% {ok, StateName, StateData, Timeout} | -%% ignore | -%% {stop, StopReason} -%%---------------------------------------------------------------------- init([{SockMod, Socket}, Opts]) -> ?DEBUG("started: ~p", [{SockMod, Socket}]), Shaper = case lists:keysearch(shaper, 1, Opts) of @@ -567,20 +557,8 @@ stream_established(closed, StateData) -> % Reply = ok, % {reply, Reply, state_name, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_event/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Returns: The associated StateData for this connection -%% {reply, Reply, NextStateName, NextStateData} -%% Reply = {state_infos, [{InfoName::atom(), InfoValue::any()] -%%---------------------------------------------------------------------- handle_sync_event(get_state_infos, _From, StateName, StateData) -> @@ -621,12 +599,6 @@ handle_sync_event(_Event, _From, StateName, code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), {next_state, StateName, StateData}; @@ -636,11 +608,6 @@ handle_info({timeout, Timer, _}, _StateName, handle_info(_, StateName, StateData) -> {next_state, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: terminate/3 -%% Purpose: Shutdown the fsm -%% Returns: any -%%---------------------------------------------------------------------- terminate(Reason, _StateName, StateData) -> ?DEBUG("terminated: ~p", [Reason]), case Reason of @@ -661,11 +628,6 @@ get_external_hosts(StateData) -> || {{D, _}, established} <- dict:to_list(Connections)] end. -%%---------------------------------------------------------------------- -%% Func: print_state/1 -%% Purpose: Prepare the state to be printed on error log -%% Returns: State to print -%%---------------------------------------------------------------------- print_state(State) -> State. %%%---------------------------------------------------------------------- diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 65a60c40298..bc815166ff8 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -37,7 +37,7 @@ start_connection/1, terminate_if_waiting_delay/2, stop_connection/1, - transform_options/1]). + transform_options/1]). -export([init/1, open_socket/2, wait_for_stream/2, wait_for_validation/2, wait_for_features/2, @@ -141,13 +141,6 @@ stop_connection(Pid) -> p1_fsm:send_event(Pid, closed). %%% Callback functions from p1_fsm %%%---------------------------------------------------------------------- -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, StateName, StateData} | -%% {ok, StateName, StateData, Timeout} | -%% ignore | -%% {stop, StopReason} -%%---------------------------------------------------------------------- init([From, Server, Type]) -> process_flag(trap_exit, true), ?DEBUG("started: ~p", [{From, Server, Type}]), @@ -222,12 +215,6 @@ init([From, Server, Type]) -> tls_options = TLSOpts, queue = queue:new(), myname = From, server = Server, new = New, verify = Verify, timer = Timer}}. -%%---------------------------------------------------------------------- -%% Func: StateName/2 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- open_socket(init, StateData) -> log_s2s_out(StateData#state.new, StateData#state.myname, StateData#state.server, StateData#state.tls), @@ -292,8 +279,6 @@ open_socket(timeout, StateData) -> open_socket(_, StateData) -> {next_state, open_socket, StateData}. -%%---------------------------------------------------------------------- -%% IPv4 open_socket1({_, _, _, _} = Addr, Port) -> open_socket2(inet, Addr, Port); %% IPv6 @@ -872,19 +857,7 @@ stream_established(closed, StateData) -> %% Reply = ok, %% {reply, Reply, state_name, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_event/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_event(_Event, StateName, StateData) -> -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Returns: The associated StateData for this connection -%% {reply, Reply, NextStateName, NextStateData} -%% Reply = {state_infos, [{InfoName::atom(), InfoValue::any()] -%%---------------------------------------------------------------------- {next_state, StateName, StateData, get_timeout_interval(StateName)}. @@ -933,12 +906,6 @@ handle_sync_event(_Event, _From, StateName, code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_info({send_text, Text}, StateName, StateData) -> send_text(StateData, Text), cancel_timer(StateData#state.timer), @@ -995,11 +962,6 @@ handle_info(_, StateName, StateData) -> {next_state, StateName, StateData, get_timeout_interval(StateName)}. -%%---------------------------------------------------------------------- -%% Func: terminate/3 -%% Purpose: Shutdown the fsm -%% Returns: any -%%---------------------------------------------------------------------- terminate(Reason, StateName, StateData) -> ?DEBUG("terminated: ~p", [{Reason, StateName}]), case StateData#state.new of @@ -1018,11 +980,6 @@ terminate(Reason, StateName, StateData) -> end, ok. -%%---------------------------------------------------------------------- -%% Func: print_state/1 -%% Purpose: Prepare the state to be printed on error log -%% Returns: State to print -%%---------------------------------------------------------------------- print_state(State) -> State. %%%---------------------------------------------------------------------- @@ -1328,10 +1285,6 @@ wait_before_reconnect(StateData) -> D1 -> lists:min([D1 * 2, get_max_retry_delay()]) end, Timer = erlang:start_timer(Delay, self(), []), -%% @doc Get the maximum allowed delay for retry to reconnect (in miliseconds). -%% The default value is 5 minutes. -%% The option {s2s_max_retry_delay, Seconds} can be used (in seconds). -%% @spec () -> integer() {next_state, wait_before_retry, StateData#state{timer = Timer, delay_to_retry = Delay, queue = queue:new()}}. diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 58e2f3c65d0..772f075ec4a 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -95,10 +95,6 @@ %%==================================================================== %% API %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- -export_type([sid/0]). start() -> @@ -107,8 +103,7 @@ start() -> supervisor:start_child(ejabberd_sup, ChildSpec). start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], - []). + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). -spec route(jid(), jid(), xmlel() | broadcast()) -> ok. @@ -149,6 +144,9 @@ close_session(SID, User, Server, Resource) -> ejabberd_hooks:run(sm_remove_connection_hook, JID#jid.lserver, [SID, JID, Info]). +-spec check_in_subscription(any(), binary(), binary(), + any(), any(), any()) -> any(). + check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) -> case ejabberd_auth:is_user_exists(User, Server) of true -> Acc; @@ -268,6 +266,8 @@ dirty_get_sessions_list() -> Mod = get_sm_backend(), [S#session.usr || S <- Mod:get_sessions()]. +-spec dirty_get_my_sessions_list() -> [#session{}]. + dirty_get_my_sessions_list() -> Mod = get_sm_backend(), [S || S <- Mod:get_sessions(), node(element(2, S#session.sid)) == node()]. @@ -285,20 +285,20 @@ get_all_pids() -> Mod = get_sm_backend(), [element(2, S#session.sid) || S <- Mod:get_sessions()]. +-spec get_vh_session_number(binary()) -> non_neg_integer(). + get_vh_session_number(Server) -> LServer = jlib:nameprep(Server), Mod = get_sm_backend(), length(Mod:get_sessions(LServer)). register_iq_handler(Host, XMLNS, Module, Fun) -> - ejabberd_sm ! - {register_iq_handler, Host, XMLNS, Module, Fun}. + ejabberd_sm ! {register_iq_handler, Host, XMLNS, Module, Fun}. -spec register_iq_handler(binary(), binary(), atom(), atom(), list()) -> any(). register_iq_handler(Host, XMLNS, Module, Fun, Opts) -> - ejabberd_sm ! - {register_iq_handler, Host, XMLNS, Module, Fun, Opts}. + ejabberd_sm ! {register_iq_handler, Host, XMLNS, Module, Fun, Opts}. -spec unregister_iq_handler(binary(), binary()) -> any(). @@ -310,13 +310,6 @@ unregister_iq_handler(Host, XMLNS) -> %% gen_server callbacks %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([]) -> Mod = get_sm_backend(), Mod:init(), @@ -333,32 +326,11 @@ init([]) -> ejabberd_commands:register_commands(commands()), {ok, #state{}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info({route, From, To, Packet}, State) -> case catch do_route(From, To, Packet) of {'EXIT', Reason} -> @@ -388,27 +360,19 @@ handle_info({unregister_iq_handler, Host, XMLNS}, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, _State) -> ejabberd_commands:unregister_commands(commands()), ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- +-spec set_session(sid(), binary(), binary(), binary(), + prio(), info()) -> ok. + set_session(SID, User, Server, Resource, Priority, Info) -> LUser = jlib:nodeprep(User), LServer = jlib:nameprep(Server), diff --git a/src/ejabberd_sm_redis.erl b/src/ejabberd_sm_redis.erl index a92845b81c2..1a3ce5ab8cf 100644 --- a/src/ejabberd_sm_redis.erl +++ b/src/ejabberd_sm_redis.erl @@ -131,7 +131,8 @@ get_sessions(LUser, LServer) -> [] end. --spec get_sessions(binary(), binary(), binary()) -> [#session{}]. +-spec get_sessions(binary(), binary(), binary()) -> + [#session{}]. get_sessions(LUser, LServer, LResource) -> USKey = us_to_key({LUser, LServer}), case eredis:q(?PROCNAME, ["HGETALL", USKey]) of diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index 29c7774e4a2..3ebd4cc2342 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -67,15 +67,12 @@ -export_type([socket_state/0, sockmod/0]). --spec start(atom(), sockmod(), socket(), [{atom(), any()}]) -> any(). %%==================================================================== %% API %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: -%% Description: -%%-------------------------------------------------------------------- +-spec start(atom(), sockmod(), socket(), [{atom(), any()}]) -> any(). + start(Module, SockMod, Socket, Opts) -> case Module:socket_type() of xml_stream -> @@ -241,7 +238,3 @@ peername(#socket_state{sockmod = SockMod, _ -> SockMod:peername(Socket) end. -%%==================================================================== -%% Internal functions -%%==================================================================== -%==================================================================== diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index fe8c1d2bbbb..cfe97a73e4b 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -32,7 +32,7 @@ -behaviour(gen_server). %% API --export([start_link/0, process_command/3, +-export([start_link/0, process_command/3, register_hook/1, process_remote_command/1]). -export([init/1, handle_call/3, handle_cast/2, @@ -85,6 +85,10 @@ process_command(From, To, Packet) -> _ -> ok end. +register_hook(Host) -> + ejabberd_hooks:add(local_send_to_resource_hook, Host, + ?MODULE, process_command, 50). + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -100,11 +104,7 @@ init(Opts) -> LH = proplists:get_value(large_heap, Opts), process_flag(priority, high), erlang:system_monitor(self(), [{large_heap, LH}]), - lists:foreach(fun (Host) -> - ejabberd_hooks:add(local_send_to_resource_hook, Host, - ?MODULE, process_command, 50) - end, - ?MYHOSTS), + lists:foreach(fun register_hook/1, ?MYHOSTS), {ok, #state{}}. %%-------------------------------------------------------------------- @@ -245,8 +245,9 @@ s2s_out_info(Pid) -> [<<"Process type: s2s_out">>, case FromTo of [{From, To}] -> - list_to_binary(io_lib:format("\nS2S connection: from ~s to ~s", - [From, To])); + <<"\n", + (io_lib:format("S2S connection: from ~s to ~s", + [From, To]))/binary>>; _ -> <<"">> end, check_send_queue(Pid), <<"\n">>, @@ -310,7 +311,7 @@ help() -> "\n setlh ">>. remote_command(Node, Args, From, To) -> - Message = case rpc:call(Node, ?MODULE, + Message = case ejabberd_cluster:call(Node, ?MODULE, process_remote_command, [Args]) of {badrpc, Reason} -> diff --git a/src/ejabberd_update.erl b/src/ejabberd_update.erl index afcb6222541..aebcbd2254d 100644 --- a/src/ejabberd_update.erl +++ b/src/ejabberd_update.erl @@ -67,9 +67,6 @@ update(ModulesToUpdate) -> {error, Reason} end. -%% OTP R14B03 and older provided release_handler_1:eval_script/3 -%% But OTP R14B04 and newer provide release_handler_1:eval_script/5 -%% Dialyzer reports a call to missing function; don't worry. eval_script(Script, Apps, LibDirs) -> release_handler_1:eval_script(Script, Apps, LibDirs, [], []). @@ -138,17 +135,17 @@ build_script(Dir, UpdatedBeams) -> LowLevelScript, [{ejabberd, "", filename:join(Dir, "..")}]), Check1 = case Check of - {ok, []} -> - ?DEBUG("script: ~p~n", [Script]), - ?DEBUG("low level script: ~p~n", [LowLevelScript]), - ?DEBUG("check: ~p~n", [Check]), - ok; - _ -> - ?ERROR_MSG("script: ~p~n", [Script]), - ?ERROR_MSG("low level script: ~p~n", [LowLevelScript]), - ?ERROR_MSG("check: ~p~n", [Check]), - error - end, + {ok, []} -> + ?DEBUG("script: ~p~n", [Script]), + ?DEBUG("low level script: ~p~n", [LowLevelScript]), + ?DEBUG("check: ~p~n", [Check]), + ok; + _ -> + ?ERROR_MSG("script: ~p~n", [Script]), + ?ERROR_MSG("low level script: ~p~n", [LowLevelScript]), + ?ERROR_MSG("check: ~p~n", [Check]), + error + end, {Script, LowLevelScript, Check1}. %% Copied from Erlang/OTP file: lib/sasl/src/systools.hrl diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 7df7ee090d7..c2a93e433e4 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1062,8 +1062,9 @@ term_to_string(T) -> %% @spec (T::any(), Cols::integer()) -> {NumLines::integer(), Paragraph::string()} term_to_paragraph(T, Cols) -> - Paragraph = list_to_binary(erl_prettypr:format(erl_syntax:abstract(T), - [{paper, Cols}])), + P1 = erl_syntax:abstract(T), + P2 = erl_prettypr:format(P1, [{paper, Cols}]), + Paragraph = list_to_binary(P2), FieldList = ejabberd_regexp:split(Paragraph, <<"\n">>), NumLines = length(FieldList), {NumLines, Paragraph}. @@ -1799,7 +1800,7 @@ get_node(Host, Node, [], _Query, Lang) -> <<"Modules">>)])] ++ MenuItems2))]; get_node(global, Node, [<<"db">>], Query, Lang) -> - case rpc:call(Node, mnesia, system_info, [tables]) of + case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of {badrpc, _Reason} -> [?XCT(<<"h1">>, <<"RPC Call Error">>)]; Tables -> @@ -1811,7 +1812,7 @@ get_node(global, Node, [<<"db">>], Query, Lang) -> Rows = lists:map(fun (Table) -> STable = iolist_to_binary(atom_to_list(Table)), - TInfo = case rpc:call(Node, mnesia, + TInfo = case ejabberd_cluster:call(Node, mnesia, table_info, [Table, all]) of @@ -2031,7 +2032,7 @@ get_node(global, Node, [<<"backup">>], Query, Lang) -> [?INPUTT(<<"submit">>, <<"import_dir">>, <<"OK">>)])])])])])]; get_node(global, Node, [<<"ports">>], Query, Lang) -> - Ports = rpc:call(Node, ejabberd_config, + Ports = ejabberd_cluster:call(Node, ejabberd_config, get_local_option, [listen, {ejabberd_listener, validate_cfg}, []]), @@ -2045,7 +2046,7 @@ get_node(global, Node, [<<"ports">>], Query, Lang) -> {error, iolist_to_binary(io_lib:format("~p", [Reason]))}; _ -> nothing end, - NewPorts = lists:sort(rpc:call(Node, ejabberd_config, + NewPorts = lists:sort(ejabberd_cluster:call(Node, ejabberd_config, get_local_option, [listen, {ejabberd_listener, validate_cfg}, @@ -2068,7 +2069,7 @@ get_node(global, Node, [<<"ports">>], Query, Lang) -> [node_ports_to_xhtml(NewPorts, Lang)])]; get_node(Host, Node, [<<"modules">>], Query, Lang) when is_binary(Host) -> - Modules = rpc:call(Node, gen_mod, + Modules = ejabberd_cluster:call(Node, gen_mod, loaded_modules_with_opts, [Host]), Res = case catch node_modules_parse_query(Host, Node, Modules, Query) @@ -2077,7 +2078,7 @@ get_node(Host, Node, [<<"modules">>], Query, Lang) {'EXIT', Reason} -> ?INFO_MSG("~p~n", [Reason]), error; _ -> nothing end, - NewModules = lists:sort(rpc:call(Node, gen_mod, + NewModules = lists:sort(ejabberd_cluster:call(Node, gen_mod, loaded_modules_with_opts, [Host])), H1String = list_to_binary(io_lib:format(?T(<<"Modules at ~p">>), [Node])), (?H1GL(H1String, <<"modules-overview">>, @@ -2093,21 +2094,21 @@ get_node(Host, Node, [<<"modules">>], Query, Lang) [{<<"action">>, <<"">>}, {<<"method">>, <<"post">>}], [node_modules_to_xhtml(NewModules, Lang)])]; get_node(global, Node, [<<"stats">>], _Query, Lang) -> - UpTime = rpc:call(Node, erlang, statistics, + UpTime = ejabberd_cluster:call(Node, erlang, statistics, [wall_clock]), UpTimeS = list_to_binary(io_lib:format("~.3f", [element(1, UpTime) / 1000])), - CPUTime = rpc:call(Node, erlang, statistics, [runtime]), + CPUTime = ejabberd_cluster:call(Node, erlang, statistics, [runtime]), CPUTimeS = list_to_binary(io_lib:format("~.3f", [element(1, CPUTime) / 1000])), OnlineUsers = mnesia:table_info(session, size), - TransactionsCommitted = rpc:call(Node, mnesia, + TransactionsCommitted = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_commits]), - TransactionsAborted = rpc:call(Node, mnesia, + TransactionsAborted = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_failures]), - TransactionsRestarted = rpc:call(Node, mnesia, + TransactionsRestarted = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_restarts]), - TransactionsLogged = rpc:call(Node, mnesia, system_info, + TransactionsLogged = ejabberd_cluster:call(Node, mnesia, system_info, [transaction_log_writes]), [?XC(<<"h1">>, list_to_binary(io_lib:format(?T(<<"Statistics of ~p">>), [Node]))), @@ -2142,12 +2143,12 @@ get_node(global, Node, [<<"stats">>], _Query, Lang) -> ?XAC(<<"td">>, [{<<"class">>, <<"alignright">>}], (pretty_string_int(TransactionsLogged)))])])])]; get_node(global, Node, [<<"update">>], Query, Lang) -> - rpc:call(Node, code, purge, [ejabberd_update]), + ejabberd_cluster:call(Node, code, purge, [ejabberd_update]), Res = node_update_parse_query(Node, Query), - rpc:call(Node, code, load_file, [ejabberd_update]), + ejabberd_cluster:call(Node, code, load_file, [ejabberd_update]), {ok, _Dir, UpdatedBeams, Script, LowLevelScript, Check} = - rpc:call(Node, ejabberd_update, update_info, []), + ejabberd_cluster:call(Node, ejabberd_update, update_info, []), Mods = case UpdatedBeams of [] -> ?CT(<<"None">>); _ -> @@ -2216,14 +2217,14 @@ get_node(Host, Node, NPath, Query, Lang) -> node_parse_query(Node, Query) -> case lists:keysearch(<<"restart">>, 1, Query) of {value, _} -> - case rpc:call(Node, init, restart, []) of + case ejabberd_cluster:call(Node, init, restart, []) of {badrpc, _Reason} -> error; _ -> ok end; _ -> case lists:keysearch(<<"stop">>, 1, Query) of {value, _} -> - case rpc:call(Node, init, stop, []) of + case ejabberd_cluster:call(Node, init, stop, []) of {badrpc, _Reason} -> error; _ -> ok end; @@ -2307,35 +2308,35 @@ node_backup_parse_query(Node, Query) -> {value, {_, Path}} -> Res = case Action of <<"store">> -> - rpc:call(Node, mnesia, backup, + ejabberd_cluster:call(Node, mnesia, backup, [binary_to_list(Path)]); <<"restore">> -> - rpc:call(Node, ejabberd_admin, + ejabberd_cluster:call(Node, ejabberd_admin, restore, [Path]); <<"fallback">> -> - rpc:call(Node, mnesia, + ejabberd_cluster:call(Node, mnesia, install_fallback, [binary_to_list(Path)]); <<"dump">> -> - rpc:call(Node, ejabberd_admin, + ejabberd_cluster:call(Node, ejabberd_admin, dump_to_textfile, [Path]); <<"load">> -> - rpc:call(Node, mnesia, + ejabberd_cluster:call(Node, mnesia, load_textfile, [binary_to_list(Path)]); <<"import_piefxis_file">> -> - rpc:call(Node, ejabberd_piefxis, + ejabberd_cluster:call(Node, ejabberd_piefxis, import_file, [Path]); <<"export_piefxis_dir">> -> - rpc:call(Node, ejabberd_piefxis, + ejabberd_cluster:call(Node, ejabberd_piefxis, export_server, [Path]); <<"export_piefxis_host_dir">> -> {value, {_, Host}} = lists:keysearch(<>, 1, Query), - rpc:call(Node, ejabberd_piefxis, + ejabberd_cluster:call(Node, ejabberd_piefxis, export_host, [Path, Host]); <<"export_sql_file">> -> @@ -2343,13 +2344,13 @@ node_backup_parse_query(Node, Query) -> lists:keysearch(<>, 1, Query), - rpc:call(Node, ejd2odbc, + ejabberd_cluster:call(Node, ejd2odbc, export, [Host, Path]); <<"import_file">> -> - rpc:call(Node, ejabberd_admin, + ejabberd_cluster:call(Node, ejabberd_admin, import_file, [Path]); <<"import_dir">> -> - rpc:call(Node, ejabberd_admin, + ejabberd_cluster:call(Node, ejabberd_admin, import_dir, [Path]) end, case Res of @@ -2474,10 +2475,10 @@ node_ports_parse_query(Node, Ports, Query) -> {ok, Tokens, _} = erl_scan:string(binary_to_list(SOpts) ++ "."), {ok, Opts} = erl_parse:parse_term(Tokens), - rpc:call(Node, ejabberd_listener, + ejabberd_cluster:call(Node, ejabberd_listener, delete_listener, [PortIpNetp2, Module1]), - R = rpc:call(Node, ejabberd_listener, + R = ejabberd_cluster:call(Node, ejabberd_listener, add_listener, [PortIpNetp2, Module, Opts]), throw({is_added, R}); @@ -2487,7 +2488,7 @@ node_ports_parse_query(Node, Ports, Query) -> 1, Query) of {value, _} -> - rpc:call(Node, ejabberd_listener, + ejabberd_cluster:call(Node, ejabberd_listener, delete_listener, [PortIpNetp, Module1]), throw(submitted); @@ -2520,7 +2521,7 @@ node_ports_parse_query(Node, Ports, Query) -> {Port2, _SPort, IP2, _SIP, _SSPort, NetProt2, OptsClean} = get_port_data({Port2, STIP2, NetProt2}, Opts), - R = rpc:call(Node, ejabberd_listener, add_listener, + R = ejabberd_cluster:call(Node, ejabberd_listener, add_listener, [{Port2, IP2, NetProt2}, Module, OptsClean]), throw({is_added, R}); _ -> ok @@ -2579,9 +2580,9 @@ node_modules_parse_query(Host, Node, Modules, Query) -> {ok, Tokens, _} = erl_scan:string(binary_to_list(<>)), {ok, Opts} = erl_parse:parse_term(Tokens), - rpc:call(Node, gen_mod, stop_module, + ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]), - rpc:call(Node, gen_mod, start_module, + ejabberd_cluster:call(Node, gen_mod, start_module, [Host, Module, Opts]), throw(submitted); _ -> @@ -2589,7 +2590,7 @@ node_modules_parse_query(Host, Node, Modules, Query) -> 1, Query) of {value, _} -> - rpc:call(Node, gen_mod, stop_module, + ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]), throw(submitted); _ -> ok @@ -2605,7 +2606,7 @@ node_modules_parse_query(Host, Node, Modules, Query) -> Module = jlib:binary_to_atom(SModule), {ok, Tokens, _} = erl_scan:string(binary_to_list(<>)), {ok, Opts} = erl_parse:parse_term(Tokens), - rpc:call(Node, gen_mod, start_module, + ejabberd_cluster:call(Node, gen_mod, start_module, [Host, Module, Opts]), throw(submitted); _ -> ok @@ -2618,7 +2619,7 @@ node_update_parse_query(Node, Query) -> proplists:get_all_values(<<"selected">>, Query), ModulesToUpdate = [jlib:binary_to_atom(M) || M <- ModulesToUpdateStrings], - case rpc:call(Node, ejabberd_update, update, + case ejabberd_cluster:call(Node, ejabberd_update, update, [ModulesToUpdate]) of {ok, _} -> ok; @@ -2893,7 +2894,8 @@ make_menu_item(item, 3, URI, Name, Lang) -> %%%================================== -%%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: opt_type(access) -> fun (V) -> V end; opt_type(_) -> [access]. + +%%% vim: set foldmethod=marker foldmarker=%%%%,%%%=: diff --git a/src/eldap.erl b/src/eldap.erl index dbd561afd14..f48b2d84076 100644 --- a/src/eldap.erl +++ b/src/eldap.erl @@ -629,27 +629,10 @@ init([Hosts, Port, Rootdn, Passwd, Opts]) -> id = 0, dict = dict:new(), req_q = queue:new()}, 0}. -%%---------------------------------------------------------------------- -%% Func: StateName/2 -%% Called when gen_fsm:send_event/2,3 is invoked (async) -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- connecting(timeout, S) -> {ok, NextState, NewS} = connect_bind(S), {next_state, NextState, NewS}. -%%---------------------------------------------------------------------- -%% Func: StateName/3 -%% Called when gen_fsm:sync_send_event/2,3 is invoked. -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- connecting(Event, From, S) -> Q = queue:in({Event, From}, S#eldap.req_q), {next_state, connecting, S#eldap{req_q = Q}}. @@ -678,34 +661,15 @@ handle_event(close, _StateName, S) -> handle_event(_Event, StateName, S) -> {next_state, StateName, S}. -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Called when gen_fsm:sync_send_all_state_event/2,3 is invoked -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- handle_sync_event(_Event, _From, StateName, S) -> {reply, {StateName, S}, StateName, S}. -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- - %% %% Packets arriving in various states %% handle_info({Tag, _Socket, Data}, connecting, S) when Tag == tcp; Tag == ssl -> - ?DEBUG("tcp packet received when disconnected!~n~p", - [Data]), + ?DEBUG("tcp packet received when disconnected!~n~p", [Data]), {next_state, connecting, S}; handle_info({Tag, _Socket, Data}, wait_bind_response, S) when Tag == tcp; Tag == ssl -> @@ -724,8 +688,7 @@ handle_info({Tag, _Socket, Data}, wait_bind_response, S) {next_state, connecting, close_and_retry(S)} end; handle_info({Tag, _Socket, Data}, StateName, S) - when (StateName == active orelse - StateName == active_bind) + when (StateName == active orelse StateName == active_bind) andalso (Tag == tcp orelse Tag == ssl) -> case catch recvd_packet(Data, S) of {response, Response, RequestType} -> @@ -766,8 +729,7 @@ handle_info({timeout, Timer, {cmd_timeout, Id}}, handle_info({timeout, retry_connect}, connecting, S) -> {ok, NextState, NewS} = connect_bind(S), {next_state, NextState, NewS}; -handle_info({timeout, _Timer, bind_timeout}, - wait_bind_response, S) -> +handle_info({timeout, _Timer, bind_timeout}, wait_bind_response, S) -> {next_state, connecting, close_and_retry(S)}; %% %% Make sure we don't fill the message queue with rubbish @@ -825,16 +787,14 @@ send_command(Command, From, S) -> Message = #'LDAPMessage'{messageID = Id, protocolOp = {Name, Request}}, ?DEBUG("~p~n", [{Name, ejabberd_config:may_hide_data(Request)}]), - {ok, Bytes} = 'ELDAPv3':encode('LDAPMessage', - Message), + {ok, Bytes} = 'ELDAPv3':encode('LDAPMessage', Message), case (S#eldap.sockmod):send(S#eldap.fd, Bytes) of ok -> - Timer = erlang:start_timer(?CMD_TIMEOUT, self(), - {cmd_timeout, Id}), - New_dict = dict:store(Id, - [{Timer, Command, From, Name}], S#eldap.dict), - {ok, S#eldap{id = Id, dict = New_dict}}; - Error -> Error + Timer = erlang:start_timer(?CMD_TIMEOUT, self(), {cmd_timeout, Id}), + New_dict = dict:store(Id, [{Timer, Command, From, Name}], S#eldap.dict), + {ok, S#eldap{id = Id, dict = New_dict}}; + Error -> + Error end. gen_req({search, A}) -> @@ -1148,8 +1108,7 @@ bind_request(Socket, S) -> Message = #'LDAPMessage'{messageID = Id, protocolOp = {bindRequest, Req}}, ?DEBUG("Bind Request Message:~p~n", [ejabberd_config:may_hide_data(Message)]), - {ok, Bytes} = 'ELDAPv3':encode('LDAPMessage', - Message), + {ok, Bytes} = 'ELDAPv3':encode('LDAPMessage', Message), case (S#eldap.sockmod):send(Socket, Bytes) of ok -> {ok, S#eldap{id = Id}}; Error -> Error @@ -1162,24 +1121,6 @@ next_host(Host, Hosts) -> % Find next in turn next_host(Host, Hosts, Hosts). -%%% -------------------------------------------------------------------- -%%% Verify the input data -%%% -------------------------------------------------------------------- -%%% -------------------------------------------------------------------- -%%% Get and Validate the initial configuration -%%% -------------------------------------------------------------------- -%% get_atom(Key, List) -> -%% case lists:keysearch(Key, 1, List) of -%% {value, {Key, Value}} when is_atom(Value) -> -%% Value; -%% {value, {Key, _Value}} -> -%% throw({error, "Bad Value in Config for " ++ atom_to_list(Key)}); -%% false -> -%% throw({error, "No Entry in Config for " ++ atom_to_list(Key)}) -%% end. -%%% -------------------------------------------------------------------- -%%% Other Stuff -%%% -------------------------------------------------------------------- next_host(Host, [Host], Hosts) -> hd(Hosts); % Wrap back to first next_host(Host, [Host | Tail], _Hosts) -> diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index c015b893953..2b712aadc42 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -44,9 +44,9 @@ -record(state, {host, module, function}). -%%-type component() :: ejabberd_sm | ejabberd_local. +-type component() :: ejabberd_sm | ejabberd_local. -type type() :: no_queue | one_queue | pos_integer() | parallel. -%%-type opts() :: no_queue | {one_queue, pid()} | {queues, [pid()]} | parallel. +-type opts() :: no_queue | {one_queue, pid()} | {queues, [pid()]} | parallel. %%==================================================================== %% API @@ -62,33 +62,37 @@ start_link(Host, Module, Function) -> add_iq_handler(Component, Host, NS, Module, Function, Type) -> case Type of - no_queue -> - Component:register_iq_handler(Host, NS, Module, - Function, no_queue); - one_queue -> - {ok, Pid} = supervisor:start_child(ejabberd_iq_sup, - [Host, Module, Function]), - Component:register_iq_handler(Host, NS, Module, - Function, {one_queue, Pid}); - N when is_integer(N) -> - Pids = lists:map(fun (_) -> - {ok, Pid} = - supervisor:start_child(ejabberd_iq_sup, - [Host, Module, - Function]), - Pid - end, - lists:seq(1, N)), - Component:register_iq_handler(Host, NS, Module, - Function, {queues, Pids}); - parallel -> - Component:register_iq_handler(Host, NS, Module, - Function, parallel) + no_queue -> + Component:register_iq_handler(Host, NS, Module, + Function, no_queue); + one_queue -> + {ok, Pid} = supervisor:start_child(ejabberd_iq_sup, + [Host, Module, Function]), + Component:register_iq_handler(Host, NS, Module, + Function, {one_queue, Pid}); + N when is_integer(N) -> + Pids = lists:map(fun (_) -> + {ok, Pid} = + supervisor:start_child(ejabberd_iq_sup, + [Host, Module, + Function]), + Pid + end, + lists:seq(1, N)), + Component:register_iq_handler(Host, NS, Module, + Function, {queues, Pids}); + parallel -> + Component:register_iq_handler(Host, NS, Module, + Function, parallel) end. +-spec remove_iq_handler(component(), binary(), binary()) -> any(). + remove_iq_handler(Component, Host, NS) -> Component:unregister_iq_handler(Host, NS). +-spec stop_iq_handler(atom(), atom(), [pid()]) -> any(). + stop_iq_handler(_Module, _Function, Opts) -> case Opts of {one_queue, Pid} -> gen_server:call(Pid, stop); @@ -100,21 +104,25 @@ stop_iq_handler(_Module, _Function, Opts) -> _ -> ok end. +-spec handle(binary(), atom(), atom(), opts(), jid(), jid(), iq()) -> any(). + handle(Host, Module, Function, Opts, From, To, IQ) -> case Opts of - no_queue -> - process_iq(Host, Module, Function, From, To, IQ); - {one_queue, Pid} -> Pid ! {process_iq, From, To, IQ}; - {queues, Pids} -> - Pid = lists:nth(erlang:phash(now(), length(Pids)), - Pids), - Pid ! {process_iq, From, To, IQ}; - parallel -> - spawn(?MODULE, process_iq, + no_queue -> + process_iq(Host, Module, Function, From, To, IQ); + {one_queue, Pid} -> + Pid ! {process_iq, From, To, IQ}; + {queues, Pids} -> + Pid = lists:nth(erlang:phash(now(), length(Pids)), Pids), + Pid ! {process_iq, From, To, IQ}; + parallel -> + spawn(?MODULE, process_iq, [Host, Module, Function, From, To, IQ]); - _ -> todo + _ -> todo end. +-spec process_iq(binary(), atom(), atom(), jid(), jid(), iq()) -> any(). + process_iq(_Host, Module, Function, From, To, IQ) -> case catch Module:Function(From, To, IQ) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); @@ -146,44 +154,16 @@ transform_module_options(Opts) -> %% gen_server callbacks %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([Host, Module, Function]) -> {ok, #state{host = Host, module = Module, function = Function}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call(stop, _From, State) -> Reply = ok, {stop, normal, Reply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info({process_iq, From, To, IQ}, #state{host = Host, module = Module, function = Function} = @@ -192,19 +172,8 @@ handle_info({process_iq, From, To, IQ}, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 42c77f15023..8fc2ca79e6a 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -25,6 +25,7 @@ %%% %%%---------------------------------------------------------------------- -module (mod_carboncopy). + -author ('ecestari@process-one.net'). -protocol({xep, 280, '0.8'}). @@ -112,7 +113,7 @@ iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children ?INFO_MSG("carbons disabled for user ~s@~s/~s", [U,S,R]), disable(S, U, R) end, - case Result of + case Result of ok -> ?DEBUG("carbons IQ result: ok", []), IQ#iq{type=result, sub_el=[]}; @@ -129,9 +130,8 @@ user_send_packet(Packet, _C2SState, From, To) -> user_receive_packet(Packet, _C2SState, JID, _From, To) -> check_and_forward(JID, To, Packet, received). - -% verifier si le trafic est local -% Modified from original version: + +% Modified from original version: % - registered to the user_send_packet hook, to be called only once even for multicast % - do not support "private" message mode, and do not modify the original packet in any way % - we also replicate "read" notifications @@ -145,8 +145,8 @@ check_and_forward(JID, To, Packet, Direction)-> send_copies(JID, To, Packet, Direction), Packet; true -> - %% stop the hook chain, we don't want mod_logdb to register - %% this message (duplicate) + %% stop the hook chain, we don't want logging modules to duplicates + %% this message {stop, Packet} end; _ -> @@ -156,7 +156,7 @@ check_and_forward(JID, To, Packet, Direction)-> remove_connection(User, Server, Resource, _Status)-> disable(Server, User, Resource), ok. - + %%% Internal %% Direction = received | sent @@ -208,31 +208,31 @@ send_copies(JID, To, Packet, Direction)-> ok. build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_2) -> - #xmlel{name = <<"message">>, + #xmlel{name = <<"message">>, attrs = [{<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, message_type(Packet)}, {<<"from">>, jlib:jid_to_string(Sender)}, {<<"to">>, jlib:jid_to_string(Dest)}], - children = [ - #xmlel{name = list_to_binary(atom_to_list(Direction)), + children = [ + #xmlel{name = list_to_binary(atom_to_list(Direction)), attrs = [{<<"xmlns">>, ?NS_CARBONS_2}], children = [ - #xmlel{name = <<"forwarded">>, + #xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}], children = [ complete_packet(JID, Packet, Direction)]} ]} ]}; build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_1) -> - #xmlel{name = <<"message">>, + #xmlel{name = <<"message">>, attrs = [{<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, message_type(Packet)}, {<<"from">>, jlib:jid_to_string(Sender)}, {<<"to">>, jlib:jid_to_string(Dest)}], - children = [ - #xmlel{name = list_to_binary(atom_to_list(Direction)), + children = [ + #xmlel{name = list_to_binary(atom_to_list(Direction)), attrs = [{<<"xmlns">>, ?NS_CARBONS_1}]}, - #xmlel{name = <<"forwarded">>, + #xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}], children = [complete_packet(JID, Packet, Direction)]} ]}. @@ -285,7 +285,7 @@ has_non_empty_body(Packet) -> xml:get_subtag_cdata(Packet, <<"body">>) =/= <<"">>. %% list {resource, cc_version} with carbons enabled for given user and host -list(User, Server)-> +list(User, Server) -> mnesia:dirty_select(?TABLE, [{#carboncopy{us = {User, Server}, resource = '$2', version = '$3'}, [], [{{'$2','$3'}}]}]). diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 6b07c9840e5..3803ba1c96a 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -985,7 +985,7 @@ get_form(_Host, [<<"running nodes">>, ENode, <<"DB">>], case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> - case rpc:call(Node, mnesia, system_info, [tables]) of + case ejabberd_cluster:call(Node, mnesia, system_info, [tables]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; Tables -> @@ -1007,7 +1007,7 @@ get_form(_Host, [<<"running nodes">>, ENode, <<"DB">>], ?T(Lang, <<"Choose storage type of tables">>)}]} | lists:map(fun (Table) -> - case rpc:call(Node, mnesia, + case ejabberd_cluster:call(Node, mnesia, table_info, [Table, storage_type]) @@ -1028,7 +1028,7 @@ get_form(Host, case search_running_node(ENode) of false -> {error, ?ERR_ITEM_NOT_FOUND}; Node -> - case rpc:call(Node, gen_mod, loaded_modules, [Host]) of + case ejabberd_cluster:call(Node, gen_mod, loaded_modules, [Host]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; Modules -> @@ -1607,7 +1607,7 @@ set_form(_From, Host, case Vals of [<<"1">>] -> Module = jlib:binary_to_atom(Var), - rpc:call(Node, gen_mod, stop_module, + ejabberd_cluster:call(Node, gen_mod, stop_module, [Host, Module]); _ -> ok end @@ -1634,7 +1634,7 @@ set_form(_From, Host, case erl_parse:parse_term(Tokens) of {ok, Modules} -> lists:foreach(fun ({Module, Args}) -> - rpc:call(Node, gen_mod, + ejabberd_cluster:call(Node, gen_mod, start_module, [Host, Module, Args]) end, @@ -1656,7 +1656,7 @@ set_form(_From, _Host, case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> - case rpc:call(Node, mnesia, backup, [String]) of + case ejabberd_cluster:call(Node, mnesia, backup, [String]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; @@ -1675,7 +1675,7 @@ set_form(_From, _Host, case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> - case rpc:call(Node, ejabberd_admin, restore, [String]) + case ejabberd_cluster:call(Node, ejabberd_admin, restore, [String]) of {badrpc, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; @@ -1695,7 +1695,7 @@ set_form(_From, _Host, case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> - case rpc:call(Node, ejabberd_admin, dump_to_textfile, + case ejabberd_cluster:call(Node, ejabberd_admin, dump_to_textfile, [String]) of {badrpc, _Reason} -> @@ -1715,7 +1715,7 @@ set_form(_From, _Host, case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> - rpc:call(Node, jd2ejd, import_file, [String]), + ejabberd_cluster:call(Node, jd2ejd, import_file, [String]), {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end @@ -1729,7 +1729,7 @@ set_form(_From, _Host, case lists:keysearch(<<"path">>, 1, XData) of false -> {error, ?ERR_BAD_REQUEST}; {value, {_, [String]}} -> - rpc:call(Node, jd2ejd, import_dir, [String]), + ejabberd_cluster:call(Node, jd2ejd, import_dir, [String]), {result, []}; _ -> {error, ?ERR_BAD_REQUEST} end @@ -1912,7 +1912,6 @@ set_form(From, Host, Server) of [] -> -%% _US = {User, Server}, case get_last_info(User, Server) of not_found -> ?T(Lang, <<"Never">>); {ok, Timestamp, _Status} -> diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 67b705d9a0b..abfd1273fba 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -1,11 +1,11 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2014, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 15 Aug 2014 by Evgeny Khramtsov %%% +%%% %%% ejabberd, Copyright (C) 2014-2015 ProcessOne %%% %%% This program is free software; you can redistribute it and/or diff --git a/src/mod_irc.erl b/src/mod_irc.erl index 25511848306..31fb317076a 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -784,8 +784,6 @@ set_form(ServerHost, Host, From, [], _Lang, XData) -> set_form(_ServerHost, _Host, _, _, _Lang, _XData) -> {error, ?ERR_SERVICE_UNAVAILABLE}. -%% Host = "irc.example.com" -%% ServerHost = "example.com" get_connection_params(Host, From, IRCServer) -> [_ | HostTail] = str:tokens(Host, <<".">>), ServerHost = str:join(HostTail, <<".">>), diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 0c85e7016c5..7781cff9a5e 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -43,27 +43,27 @@ -include("mod_muc_room.hrl"). -record(archive_msg, - {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', - id = <<>> :: binary() | '_', - timestamp = now() :: erlang:timestamp() | '_' | '$1', - peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', - bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', + {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', + id = <<>> :: binary() | '_', + timestamp = now() :: erlang:timestamp() | '_' | '$1', + peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', + bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', packet = #xmlel{} :: xmlel() | '_', nick = <<"">> :: binary(), type = chat :: chat | groupchat}). -record(archive_prefs, - {us = {<<"">>, <<"">>} :: {binary(), binary()}, - default = never :: never | always | roster, - always = [] :: [ljid()], - never = [] :: [ljid()]}). + {us = {<<"">>, <<"">>} :: {binary(), binary()}, + default = never :: never | always | roster, + always = [] :: [ljid()], + never = [] :: [ljid()]}). %%%=================================================================== %%% API %%%=================================================================== start(Host, Opts) -> IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, - one_queue), + one_queue), DBType = gen_mod:db_type(Host, Opts), init_db(DBType, Host), init_cache(DBType, Opts), @@ -80,9 +80,9 @@ start(Host, Opts) -> gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MAM_1, ?MODULE, process_iq_v0_3, IQDisc), ejabberd_hooks:add(user_receive_packet, Host, ?MODULE, - user_receive_packet, 500), + user_receive_packet, 500), ejabberd_hooks:add(user_send_packet, Host, ?MODULE, - user_send_packet, 500), + user_send_packet, 500), ejabberd_hooks:add(muc_filter_message, Host, ?MODULE, muc_filter_message, 50), ejabberd_hooks:add(muc_process_iq, Host, ?MODULE, @@ -95,21 +95,21 @@ start(Host, Opts) -> init_db(mnesia, _Host) -> mnesia:create_table(archive_msg, - [{disc_only_copies, [node()]}, - {type, bag}, - {attributes, record_info(fields, archive_msg)}]), + [{disc_only_copies, [node()]}, + {type, bag}, + {attributes, record_info(fields, archive_msg)}]), mnesia:create_table(archive_prefs, - [{disc_only_copies, [node()]}, - {attributes, record_info(fields, archive_prefs)}]); + [{disc_only_copies, [node()]}, + {attributes, record_info(fields, archive_prefs)}]); init_db(_, _) -> ok. init_cache(_DBType, Opts) -> MaxSize = gen_mod:get_opt(cache_size, Opts, - fun(I) when is_integer(I), I>0 -> I end, - 1000), + fun(I) when is_integer(I), I>0 -> I end, + 1000), LifeTime = gen_mod:get_opt(cache_life_time, Opts, - fun(I) when is_integer(I), I>0 -> I end, + fun(I) when is_integer(I), I>0 -> I end, timer:hours(1) div 1000), cache_tab:new(archive_prefs, [{max_size, MaxSize}, {life_time, LifeTime}]). @@ -144,9 +144,9 @@ remove_user(User, Server) -> remove_user(LUser, LServer, mnesia) -> US = {LUser, LServer}, F = fun () -> - mnesia:delete({archive_msg, US}), - mnesia:delete({archive_prefs, US}) - end, + mnesia:delete({archive_msg, US}), + mnesia:delete({archive_prefs, US}) + end, mnesia:transaction(F); remove_user(LUser, LServer, odbc) -> SUser = ejabberd_odbc:escape(LUser), @@ -162,25 +162,25 @@ user_receive_packet(Pkt, C2SState, JID, Peer, To) -> LServer = JID#jid.lserver, IsBareCopy = is_bare_copy(JID, To), case should_archive(Pkt) of - true when not IsBareCopy -> - NewPkt = strip_my_archived_tag(Pkt, LServer), + true when not IsBareCopy -> + NewPkt = strip_my_archived_tag(Pkt, LServer), case store_msg(C2SState, NewPkt, LUser, LServer, Peer, recv) of - {ok, ID} -> - Archived = #xmlel{name = <<"archived">>, - attrs = [{<<"by">>, LServer}, - {<<"xmlns">>, ?NS_MAM_TMP}, - {<<"id">>, ID}]}, + {ok, ID} -> + Archived = #xmlel{name = <<"archived">>, + attrs = [{<<"by">>, LServer}, + {<<"xmlns">>, ?NS_MAM_TMP}, + {<<"id">>, ID}]}, StanzaID = #xmlel{name = <<"stanza-id">>, attrs = [{<<"by">>, LServer}, - {<<"xmlns">>, ?NS_SID_0}, - {<<"id">>, ID}]}, + {<<"xmlns">>, ?NS_SID_0}, + {<<"id">>, ID}]}, NewEls = [Archived, StanzaID|NewPkt#xmlel.children], - NewPkt#xmlel{children = NewEls}; - _ -> - NewPkt - end; - _ -> - Pkt + NewPkt#xmlel{children = NewEls}; + _ -> + NewPkt + end; + _ -> + Pkt end. user_send_packet(Pkt, C2SState, JID, Peer) -> @@ -188,12 +188,12 @@ user_send_packet(Pkt, C2SState, JID, Peer) -> LServer = JID#jid.lserver, case should_archive(Pkt) of true -> - NewPkt = strip_my_archived_tag(Pkt, LServer), + NewPkt = strip_my_archived_tag(Pkt, LServer), store_msg(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), LUser, LServer, Peer, send), - NewPkt; - false -> - Pkt + NewPkt; + false -> + Pkt end. muc_filter_message(Pkt, #state{config = Config} = MUCState, @@ -218,23 +218,23 @@ muc_filter_message(Pkt, #state{config = Config} = MUCState, % Query archive v0.2 process_iq_v0_2(#jid{lserver = LServer} = From, - #jid{lserver = LServer} = To, - #iq{type = get, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> + #jid{lserver = LServer} = To, + #iq{type = get, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> Fs = lists:flatmap( - fun(#xmlel{name = <<"start">>} = El) -> - [{<<"start">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"end">>} = El) -> - [{<<"end">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"with">>} = El) -> - [{<<"with">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"withroom">>} = El) -> - [{<<"withroom">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"withtext">>} = El) -> - [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"set">>}) -> - [{<<"set">>, SubEl}]; - (_) -> - [] + fun (#xmlel{name = <<"start">>} = El) -> + [{<<"start">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"end">>} = El) -> + [{<<"end">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"with">>} = El) -> + [{<<"with">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"withroom">>} = El) -> + [{<<"withroom">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"withtext">>} = El) -> + [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"set">>}) -> + [{<<"set">>, SubEl}]; + (_) -> + [] end, SubEl#xmlel.children), process_iq(LServer, From, To, IQ, SubEl, Fs, chat); process_iq_v0_2(From, To, IQ) -> @@ -242,8 +242,8 @@ process_iq_v0_2(From, To, IQ) -> % Query archive v0.3 process_iq_v0_3(#jid{lserver = LServer} = From, - #jid{lserver = LServer} = To, - #iq{type = set, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> + #jid{lserver = LServer} = To, + #iq{type = set, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> process_iq(LServer, From, To, IQ, SubEl, get_xdata_fields(SubEl), chat); process_iq_v0_3(From, To, IQ) -> process_iq(From, To, IQ). @@ -266,15 +266,15 @@ muc_process_iq(IQ, _MUCState, _From, _To) -> get_xdata_fields(SubEl) -> case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), - xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of - {#xmlel{} = XData, false} -> - jlib:parse_xdata_submit(XData); - {#xmlel{} = XData, #xmlel{}} -> - [{<<"set">>, SubEl} | jlib:parse_xdata_submit(XData)]; - {false, #xmlel{}} -> - [{<<"set">>, SubEl}]; - {false, false} -> - [] + xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of + {#xmlel{} = XData, false} -> + jlib:parse_xdata_submit(XData); + {#xmlel{} = XData, #xmlel{}} -> + [{<<"set">>, SubEl} | jlib:parse_xdata_submit(XData)]; + {false, #xmlel{}} -> + [{<<"set">>, SubEl}]; + {false, false} -> + [] end. %%%=================================================================== @@ -283,32 +283,32 @@ get_xdata_fields(SubEl) -> % Preference setting (both v0.2 & v0.3) process_iq(#jid{luser = LUser, lserver = LServer}, - #jid{lserver = LServer}, - #iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> + #jid{lserver = LServer}, + #iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> try {case xml:get_tag_attr_s(<<"default">>, SubEl) of - <<"always">> -> always; - <<"never">> -> never; - <<"roster">> -> roster - end, - lists:foldl( - fun(#xmlel{name = <<"always">>, children = Els}, {A, N}) -> - {get_jids(Els) ++ A, N}; - (#xmlel{name = <<"never">>, children = Els}, {A, N}) -> - {A, get_jids(Els) ++ N}; - (_, {A, N}) -> - {A, N} - end, {[], []}, SubEl#xmlel.children)} of - {Default, {Always, Never}} -> - case write_prefs(LUser, LServer, LServer, Default, - lists:usort(Always), lists:usort(Never)) of - ok -> - IQ#iq{type = result, sub_el = []}; - _Err -> - IQ#iq{type = error, - sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} - end + <<"always">> -> always; + <<"never">> -> never; + <<"roster">> -> roster + end, + lists:foldl( + fun(#xmlel{name = <<"always">>, children = Els}, {A, N}) -> + {get_jids(Els) ++ A, N}; + (#xmlel{name = <<"never">>, children = Els}, {A, N}) -> + {A, get_jids(Els) ++ N}; + (_, {A, N}) -> + {A, N} + end, {[], []}, SubEl#xmlel.children)} of + {Default, {Always, Never}} -> + case write_prefs(LUser, LServer, LServer, Default, + lists:usort(Always), lists:usort(Never)) of + ok -> + IQ#iq{type = result, sub_el = []}; + _Err -> + IQ#iq{type = error, + sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} + end catch _:_ -> - IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} + IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end; process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. @@ -344,64 +344,64 @@ process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> should_archive(#xmlel{name = <<"message">>} = Pkt) -> case {xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs), - xml:get_subtag_cdata(Pkt, <<"body">>)} of - {<<"error">>, _} -> - false; - {<<"groupchat">>, _} -> + xml:get_subtag_cdata(Pkt, <<"body">>)} of + {<<"error">>, _} -> + false; + {<<"groupchat">>, _} -> false; - {_, <<>>} -> - %% Empty body - false; - _ -> - true + {_, <<>>} -> + %% Empty body + false; + _ -> + true end; should_archive(#xmlel{}) -> false. strip_my_archived_tag(Pkt, LServer) -> NewEls = lists:filter( - fun(#xmlel{name = Tag, attrs = Attrs}) - when Tag == <<"archived">>; Tag == <<"stanza-id">> -> - case catch jlib:nameprep( - xml:get_attr_s( - <<"by">>, Attrs)) of - LServer -> - false; - _ -> - true - end; - (_) -> - true - end, Pkt#xmlel.children), + fun(#xmlel{name = Tag, attrs = Attrs}) + when Tag == <<"archived">>; Tag == <<"stanza-id">> -> + case catch jlib:nameprep( + xml:get_attr_s( + <<"by">>, Attrs)) of + LServer -> + false; + _ -> + true + end; + (_) -> + true + end, Pkt#xmlel.children), Pkt#xmlel{children = NewEls}. should_archive_peer(C2SState, - #archive_prefs{default = Default, - always = Always, - never = Never}, - Peer) -> + #archive_prefs{default = Default, + always = Always, + never = Never}, + Peer) -> LPeer = jlib:jid_tolower(Peer), case lists:member(LPeer, Always) of - true -> - true; - false -> - case lists:member(LPeer, Never) of - true -> - false; - false -> - case Default of - always -> true; - never -> false; - roster -> - case ejabberd_c2s:get_subscription( - LPeer, C2SState) of - both -> true; - from -> true; - to -> true; - _ -> false - end - end - end + true -> + true; + false -> + case lists:member(LPeer, Never) of + true -> + false; + false -> + case Default of + always -> true; + never -> false; + roster -> + case ejabberd_c2s:get_subscription( + LPeer, C2SState) of + both -> true; + from -> true; + to -> true; + _ -> false + end + end + end end. should_archive_muc(_MUCState, _Peer) -> @@ -411,12 +411,12 @@ should_archive_muc(_MUCState, _Peer) -> store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> Prefs = get_prefs(LUser, LServer), case should_archive_peer(C2SState, Prefs, Peer) of - true -> + true -> US = {LUser, LServer}, store(Pkt, LServer, US, chat, Peer, <<"">>, Dir, - gen_mod:db_type(LServer, ?MODULE)); - false -> - pass + gen_mod:db_type(LServer, ?MODULE)); + false -> + pass end. store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> @@ -436,17 +436,17 @@ store(Pkt, _, {LUser, LServer}, Type, Peer, Nick, _Dir, mnesia) -> ID = jlib:integer_to_binary(now_to_usec(TS)), case mnesia:dirty_write( #archive_msg{us = {LUser, LServer}, - id = ID, - timestamp = TS, - peer = LPeer, - bare_peer = {PUser, PServer, <<>>}, + id = ID, + timestamp = TS, + peer = LPeer, + bare_peer = {PUser, PServer, <<>>}, type = Type, nick = Nick, - packet = Pkt}) of - ok -> - {ok, ID}; - Err -> - Err + packet = Pkt}) of + ok -> + {ok, ID}; + Err -> + Err end; store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> TSinteger = now_to_usec(now()), @@ -456,28 +456,28 @@ store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> groupchat -> jlib:jid_to_string({LUser, LHost, <<>>}) end, BarePeer = jlib:jid_to_string( - jlib:jid_tolower( - jlib:jid_remove_resource(Peer))), + jlib:jid_tolower( + jlib:jid_remove_resource(Peer))), LPeer = jlib:jid_to_string( - jlib:jid_tolower(Peer)), + jlib:jid_tolower(Peer)), XML = xml:element_to_binary(Pkt), Body = xml:get_subtag_cdata(Pkt, <<"body">>), case ejabberd_odbc:sql_query( - LServer, - [<<"insert into archive (username, timestamp, " - "peer, bare_peer, xml, txt, kind, nick) values (">>, - <<"'">>, ejabberd_odbc:escape(SUser), <<"', ">>, - <<"'">>, TS, <<"', ">>, - <<"'">>, ejabberd_odbc:escape(LPeer), <<"', ">>, - <<"'">>, ejabberd_odbc:escape(BarePeer), <<"', ">>, - <<"'">>, ejabberd_odbc:escape(XML), <<"', ">>, - <<"'">>, ejabberd_odbc:escape(Body), <<"', ">>, - <<"'">>, jlib:atom_to_binary(Type), <<"', ">>, - <<"'">>, ejabberd_odbc:escape(Nick), <<"');">>]) of - {updated, _} -> - {ok, ID}; - Err -> - Err + LServer, + [<<"insert into archive (username, timestamp, " + "peer, bare_peer, xml, txt, kind, nick) values (">>, + <<"'">>, ejabberd_odbc:escape(SUser), <<"', ">>, + <<"'">>, TS, <<"', ">>, + <<"'">>, ejabberd_odbc:escape(LPeer), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(BarePeer), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(XML), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(Body), <<"', ">>, + <<"'">>, jlib:atom_to_binary(Type), <<"', ">>, + <<"'">>, ejabberd_odbc:escape(Nick), <<"');">>]) of + {updated, _} -> + {ok, ID}; + Err -> + Err end. write_prefs(LUser, LServer, Host, Default, Always, Never) -> @@ -486,9 +486,9 @@ write_prefs(LUser, LServer, Host, Default, Always, Never) -> DB -> DB end, Prefs = #archive_prefs{us = {LUser, LServer}, - default = Default, - always = Always, - never = Never}, + default = Default, + always = Always, + never = Never}, cache_tab:dirty_insert( archive_prefs, {LUser, LServer}, Prefs, fun() -> write_prefs(LUser, LServer, Prefs, DBType) end). @@ -496,21 +496,21 @@ write_prefs(LUser, LServer, Host, Default, Always, Never) -> write_prefs(_LUser, _LServer, Prefs, mnesia) -> mnesia:dirty_write(Prefs); write_prefs(LUser, _LServer, #archive_prefs{default = Default, - never = Never, - always = Always}, - {odbc, Host}) -> + never = Never, + always = Always}, + {odbc, Host}) -> SUser = ejabberd_odbc:escape(LUser), SDefault = erlang:atom_to_binary(Default, utf8), SAlways = ejabberd_odbc:encode_term(Always), SNever = ejabberd_odbc:encode_term(Never), case update(Host, <<"archive_prefs">>, - [<<"username">>, <<"def">>, <<"always">>, <<"never">>], - [SUser, SDefault, SAlways, SNever], - [<<"username='">>, SUser, <<"'">>]) of - {updated, _} -> - ok; - Err -> - Err + [<<"username">>, <<"def">>, <<"always">>, <<"never">>], + [SUser, SDefault, SAlways, SNever], + [<<"username='">>, SUser, <<"'">>]) of + {updated, _} -> + ok; + Err -> + Err end. get_prefs(LUser, LServer) -> @@ -520,24 +520,24 @@ get_prefs(LUser, LServer) -> DBType) end), case Res of - {ok, Prefs} -> - Prefs; - error -> - Default = gen_mod:get_module_opt( - LServer, ?MODULE, default, - fun(always) -> always; - (never) -> never; - (roster) -> roster - end, never), - #archive_prefs{us = {LUser, LServer}, default = Default} + {ok, Prefs} -> + Prefs; + error -> + Default = gen_mod:get_module_opt( + LServer, ?MODULE, default, + fun(always) -> always; + (never) -> never; + (roster) -> roster + end, never), + #archive_prefs{us = {LUser, LServer}, default = Default} end. get_prefs(LUser, LServer, mnesia) -> case mnesia:dirty_read(archive_prefs, {LUser, LServer}) of - [Prefs] -> - {ok, Prefs}; - _ -> - error + [Prefs] -> + {ok, Prefs}; + _ -> + error end; get_prefs(LUser, LServer, odbc) -> case ejabberd_odbc:sql_query( @@ -545,16 +545,16 @@ get_prefs(LUser, LServer, odbc) -> [<<"select def, always, never from archive_prefs ">>, <<"where username='">>, ejabberd_odbc:escape(LUser), <<"';">>]) of - {selected, _, [[SDefault, SAlways, SNever]]} -> - Default = erlang:binary_to_existing_atom(SDefault, utf8), - Always = ejabberd_odbc:decode_term(SAlways), - Never = ejabberd_odbc:decode_term(SNever), - {ok, #archive_prefs{us = {LUser, LServer}, - default = Default, - always = Always, - never = Never}}; - _ -> - error + {selected, _, [[SDefault, SAlways, SNever]]} -> + Default = erlang:binary_to_existing_atom(SDefault, utf8), + Always = ejabberd_odbc:decode_term(SAlways), + Never = ejabberd_odbc:decode_term(SNever), + {ok, #archive_prefs{us = {LUser, LServer}, + default = Default, + always = Always, + never = Never}}; + _ -> + error end. select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType) -> @@ -578,7 +578,7 @@ select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> {room, {_, _, <<"">>} = WithJID} -> select(LServer, jlib:make_jid(WithJID), Start, End, WithJID, RSM, MsgType, DBType); - _ -> + _ -> select(LServer, From, Start, End, With, RSM, MsgType, DBType) end; @@ -631,8 +631,8 @@ select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor, Count = length(Msgs), {lists:map( fun(Msg) -> - {Msg#archive_msg.id, - jlib:binary_to_integer(Msg#archive_msg.id), + {Msg#archive_msg.id, + jlib:binary_to_integer(Msg#archive_msg.id), msg_to_el(Msg, MsgType, JidRequestor)} end, FilteredMsgs), IsComplete, Count}; select(LServer, #jid{luser = LUser} = JidRequestor, @@ -650,8 +650,8 @@ select(LServer, #jid{luser = LUser} = JidRequestor, % the client did not specify a limit using RSM then the server % should return a policy-violation error to the client. case {ejabberd_odbc:sql_query(Host, Query), - ejabberd_odbc:sql_query(Host, CountQuery)} of - {{selected, _, Res}, {selected, _, [[Count]]}} -> + ejabberd_odbc:sql_query(Host, CountQuery)} of + {{selected, _, Res}, {selected, _, [[Count]]}} -> {Max, Direction} = case RSM of #rsm_in{max = M, direction = D} -> {M, D}; _ -> {undefined, undefined} @@ -666,24 +666,24 @@ select(LServer, #jid{luser = LUser} = JidRequestor, true -> {Res, true} end, - {lists:map( + {lists:map( fun([TS, XML, PeerBin, Kind, Nick]) -> - #xmlel{} = El = xml_stream:parse_element(XML), - Now = usec_to_now(jlib:binary_to_integer(TS)), - PeerJid = jlib:jid_tolower(jlib:string_to_jid(PeerBin)), + #xmlel{} = El = xml_stream:parse_element(XML), + Now = usec_to_now(jlib:binary_to_integer(TS)), + PeerJid = jlib:jid_tolower(jlib:string_to_jid(PeerBin)), T = if Kind /= <<"">> -> jlib:binary_to_atom(Kind); true -> chat end, - {TS, jlib:binary_to_integer(TS), - msg_to_el(#archive_msg{timestamp = Now, + {TS, jlib:binary_to_integer(TS), + msg_to_el(#archive_msg{timestamp = Now, packet = El, type = T, nick = Nick, peer = PeerJid}, MsgType, JidRequestor)} - end, Res1), IsComplete, jlib:binary_to_integer(Count)}; + end, Res1), IsComplete, jlib:binary_to_integer(Count)}; _ -> {[], false, 0} end. @@ -693,12 +693,12 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, Delay = jlib:now_to_utc_string(TS), Pkt = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick), #xmlel{name = <<"forwarded">>, - attrs = [{<<"xmlns">>, ?NS_FORWARD}], - children = [#xmlel{name = <<"delay">>, - attrs = [{<<"xmlns">>, ?NS_DELAY}, - {<<"stamp">>, Delay}]}, - xml:replace_tag_attr( - <<"xmlns">>, <<"jabber:client">>, Pkt)]}. + attrs = [{<<"xmlns">>, ?NS_FORWARD}], + children = [#xmlel{name = <<"delay">>, + attrs = [{<<"xmlns">>, ?NS_DELAY}, + {<<"stamp">>, Delay}]}, + xml:replace_tag_attr( + <<"xmlns">>, <<"jabber:client">>, Pkt)]}. maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of @@ -864,42 +864,42 @@ match_rsm(_Now, _) -> make_matchspec(LUser, LServer, Start, End, {_, _, <<>>} = With) -> ets:fun2ms( fun(#archive_msg{timestamp = TS, - us = US, - bare_peer = BPeer} = Msg) - when Start =< TS, End >= TS, - US == {LUser, LServer}, - BPeer == With -> - Msg + us = US, + bare_peer = BPeer} = Msg) + when Start =< TS, End >= TS, + US == {LUser, LServer}, + BPeer == With -> + Msg end); make_matchspec(LUser, LServer, Start, End, {_, _, _} = With) -> ets:fun2ms( fun(#archive_msg{timestamp = TS, - us = US, - peer = Peer} = Msg) - when Start =< TS, End >= TS, - US == {LUser, LServer}, - Peer == With -> - Msg + us = US, + peer = Peer} = Msg) + when Start =< TS, End >= TS, + US == {LUser, LServer}, + Peer == With -> + Msg end); make_matchspec(LUser, LServer, Start, End, none) -> ets:fun2ms( fun(#archive_msg{timestamp = TS, - us = US, - peer = Peer} = Msg) - when Start =< TS, End >= TS, - US == {LUser, LServer} -> - Msg + us = US, + peer = Peer} = Msg) + when Start =< TS, End >= TS, + US == {LUser, LServer} -> + Msg end). make_sql_query(User, _LServer, Start, End, With, RSM) -> {Max, Direction, ID} = case RSM of - #rsm_in{} -> - {RSM#rsm_in.max, - RSM#rsm_in.direction, - RSM#rsm_in.id}; - none -> - {none, none, <<>>} - end, + #rsm_in{} -> + {RSM#rsm_in.max, + RSM#rsm_in.direction, + RSM#rsm_in.id}; + none -> + {none, none, <<>>} + end, LimitClause = if is_integer(Max), Max >= 0 -> [<<" limit ">>, jlib:integer_to_binary(Max+1)]; true -> @@ -936,19 +936,19 @@ make_sql_query(User, _LServer, Start, End, With, RSM) -> [] end, StartClause = case Start of - {_, _, _} -> - [<<" and timestamp >= ">>, - jlib:integer_to_binary(now_to_usec(Start))]; - _ -> - [] - end, + {_, _, _} -> + [<<" and timestamp >= ">>, + jlib:integer_to_binary(now_to_usec(Start))]; + _ -> + [] + end, EndClause = case End of - {_, _, _} -> - [<<" and timestamp <= ">>, - jlib:integer_to_binary(now_to_usec(End))]; - _ -> - [] - end, + {_, _, _} -> + [<<" and timestamp <= ">>, + jlib:integer_to_binary(now_to_usec(End))]; + _ -> + [] + end, SUser = ejabberd_odbc:escape(User), Query = [<<"SELECT timestamp, xml, peer, kind, nick" @@ -991,11 +991,11 @@ datetime_to_now(DateTime, USecs) -> get_jids(Els) -> lists:flatmap( fun(#xmlel{name = <<"jid">>} = El) -> - J = jlib:string_to_jid(xml:get_tag_cdata(El)), - [jlib:jid_tolower(jlib:jid_remove_resource(J)), - jlib:jid_tolower(J)]; - (_) -> - [] + J = jlib:string_to_jid(xml:get_tag_cdata(El)), + [jlib:jid_tolower(jlib:jid_remove_resource(J)), + jlib:jid_tolower(J)]; + (_) -> + [] end, Els). update(LServer, Table, Fields, Vals, Where) -> diff --git a/src/mod_muc.erl b/src/mod_muc.erl index e68472a29e3..18b123fa432 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -42,12 +42,12 @@ restore_room/3, forget_room/3, create_room/5, - shutdown_rooms/1, + shutdown_rooms/1, process_iq_disco_items/4, broadcast_service_message/2, - export/1, - import/1, - import/3, + export/1, + import/1, + import/3, can_use_nick/4]). -export([init/1, handle_call/3, handle_cast/2, @@ -85,10 +85,6 @@ %%==================================================================== %% API %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:start_link({local, Proc}, ?MODULE, @@ -295,13 +291,6 @@ can_use_nick(LServer, Host, JID, Nick, odbc) -> %% gen_server callbacks %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([Host, Opts]) -> MyHost = gen_mod:get_opt_host(Host, Opts, <<"conference.@HOST@">>), @@ -390,8 +379,7 @@ init([Host, Opts]) -> ejabberd_router:register_route(MyHost), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, - HistorySize, - RoomShaper), + HistorySize, RoomShaper), {ok, #state{host = MyHost, server_host = Host, access = {Access, AccessCreate, AccessAdmin, AccessPersistent}, @@ -399,15 +387,6 @@ init([Host, Opts]) -> history_size = HistorySize, room_shaper = RoomShaper}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call(stop, _From, State) -> {stop, normal, ok, State}; handle_call({create, Room, From, Nick, Opts}, _From, @@ -428,20 +407,8 @@ handle_call({create, Room, From, Nick, Opts}, _From, register_room(Host, Room, Pid), {reply, ok, State}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info({route, From, To, Packet}, #state{host = Host, server_host = ServerHost, access = Access, default_room_opts = DefRoomOpts, @@ -468,21 +435,10 @@ handle_info({mnesia_system_event, {mnesia_down, Node}}, State) -> {noreply, State}; handle_info(_Info, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, State) -> ejabberd_router:unregister_route(State#state.host), ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- @@ -508,13 +464,13 @@ do_route(Host, ServerHost, Access, HistorySize, RoomShaper, case acl:match_rule(ServerHost, AccessRoute, From) of allow -> do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, - From, To, Packet, DefRoomOpts); + From, To, Packet, DefRoomOpts); _ -> #xmlel{attrs = Attrs} = Packet, Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Access denied by service policy">>, Err = jlib:make_error_reply(Packet, - ?ERRT_FORBIDDEN(Lang, ErrText)), + ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route_error(To, From, Err, Packet) end. @@ -645,26 +601,23 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, <<"error">> -> ok; <<"result">> -> ok; _ -> - Err = jlib:make_error_reply( - Packet, ?ERR_ITEM_NOT_FOUND), - ejabberd_router:route(To, From, Err) - end - end; - _ -> + Err = jlib:make_error_reply(Packet, + ?ERR_ITEM_NOT_FOUND), + ejabberd_router:route(To, From, Err) + end + end; + _ -> case mnesia:dirty_read(muc_online_room, {Room, Host}) of [] -> Type = xml:get_attr_s(<<"type">>, Attrs), case {Name, Type} of {<<"presence">>, <<"">>} -> case check_user_can_create_room(ServerHost, - AccessCreate, From, - Room) of + AccessCreate, From, Room) of true -> - {ok, Pid} = start_new_room( - Host, ServerHost, Access, - Room, HistorySize, - RoomShaper, From, - Nick, DefRoomOpts), + {ok, Pid} = start_new_room(Host, ServerHost, Access, + Room, HistorySize, + RoomShaper, From, Nick, DefRoomOpts), register_room(Host, Room, Pid), mod_muc_room:route(Pid, From, Nick, Packet), ok; @@ -676,19 +629,18 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, ejabberd_router:route(To, From, Err) end; _ -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), - ErrText = <<"Conference room does not exist">>, - Err = jlib:make_error_reply(Packet, - ?ERRT_ITEM_NOT_FOUND(Lang, - ErrText)), - ejabberd_router:route(To, From, Err) - end; - [R] -> - Pid = R#muc_online_room.pid, - ?DEBUG("MUC: send to process ~p~n", [Pid]), - mod_muc_room:route(Pid, From, Nick, Packet), - ok - end + Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + ErrText = <<"Conference room does not exist">>, + Err = jlib:make_error_reply(Packet, + ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), + ejabberd_router:route(To, From, Err) + end; + [R] -> + Pid = R#muc_online_room.pid, + ?DEBUG("MUC: send to process ~p~n", [Pid]), + mod_muc_room:route(Pid, From, Nick, Packet), + ok + end end. check_user_can_create_room(ServerHost, AccessCreate, @@ -743,48 +695,43 @@ get_rooms(LServer, Host, odbc) -> Err -> ?ERROR_MSG("failed to get rooms: ~p", [Err]), [] end. -load_permanent_rooms(Host, ServerHost, Access, HistorySize, RoomShaper) -> +load_permanent_rooms(Host, ServerHost, Access, + HistorySize, RoomShaper) -> lists:foreach( fun(R) -> - {Room, Host} = R#muc_room.name_host, - case mnesia:dirty_read(muc_online_room, {Room, Host}) of - [] -> - {ok, Pid} = mod_muc_room:start( - Host, - ServerHost, - Access, - Room, - HistorySize, - RoomShaper, - R#muc_room.opts), - register_room(Host, Room, Pid); - _ -> - ok - end - end, get_rooms(ServerHost, Host)). + {Room, Host} = R#muc_room.name_host, + case mnesia:dirty_read(muc_online_room, {Room, Host}) of + [] -> + {ok, Pid} = mod_muc_room:start(Host, + ServerHost, Access, Room, + HistorySize, RoomShaper, + R#muc_room.opts), + register_room(Host, Room, Pid); + _ -> ok + end + end, + get_rooms(ServerHost, Host)). start_new_room(Host, ServerHost, Access, Room, - HistorySize, RoomShaper, From, - Nick, DefRoomOpts) -> + HistorySize, RoomShaper, From, + Nick, DefRoomOpts) -> case restore_room(ServerHost, Host, Room) of - error -> + error -> ?DEBUG("MUC: open new room '~s'~n", [Room]), - mod_muc_room:start(Host, ServerHost, Access, - Room, HistorySize, - RoomShaper, From, - Nick, DefRoomOpts); - Opts -> + mod_muc_room:start(Host, ServerHost, Access, Room, + HistorySize, RoomShaper, + From, Nick, DefRoomOpts); + Opts -> ?DEBUG("MUC: restore room '~s'~n", [Room]), - mod_muc_room:start(Host, ServerHost, Access, - Room, HistorySize, - RoomShaper, Opts) + mod_muc_room:start(Host, ServerHost, Access, Room, + HistorySize, RoomShaper, Opts) end. register_room(Host, Room, Pid) -> F = fun() -> - mnesia:write(#muc_online_room{name_host = {Room, Host}, - pid = Pid}) - end, + mnesia:write(#muc_online_room{name_host = {Room, Host}, + pid = Pid}) + end, mnesia:transaction(F). @@ -840,7 +787,6 @@ iq_disco_items(Host, From, Lang, none) -> _ -> false end end, get_vh_rooms(Host)); - iq_disco_items(Host, From, Lang, Rsm) -> {Rooms, RsmO} = get_vh_rooms(Host, Rsm), RsmOut = jlib:rsm_encode(RsmO), @@ -920,13 +866,6 @@ get_room_pos(Desired, [_ | Rooms], HeadPosition) -> flush() -> receive _ -> flush() after 0 -> ok end. -define(XFIELD(Type, Label, Var, Val), -%% @doc Get a pseudo unique Room Name. The Room Name is generated as a hash of -%% the requester JID, the local time and a random salt. -%% -%% "pseudo" because we don't verify that there is not a room -%% with the returned Name already created, nor mark the generated Name -%% as "already used". But in practice, it is unique enough. See -%% http://xmpp.org/extensions/xep-0045.html#createroom-unique #xmlel{name = <<"field">>, attrs = [{<<"type">>, Type}, @@ -1177,13 +1116,12 @@ iq_get_vcard(Lang) -> <<"ejabberd MUC module">>))/binary, "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. - broadcast_service_message(Host, Msg) -> lists:foreach( - fun(#muc_online_room{pid = Pid}) -> - gen_fsm:send_all_state_event( - Pid, {service_message, Msg}) - end, get_vh_rooms(Host)). + fun(#muc_online_room{pid = Pid}) -> + gen_fsm:send_all_state_event( + Pid, {service_message, Msg}) + end, get_vh_rooms(Host)). get_vh_rooms(Host) -> @@ -1349,8 +1287,7 @@ import(_LServer) -> [{<<"select name, host, opts from muc_room;">>, fun([Name, RoomHost, SOpts]) -> Opts = opts_to_binary(ejabberd_odbc:decode_term(SOpts)), - #muc_room{name_host = {Name, RoomHost}, - opts = Opts} + #muc_room{name_host = {Name, RoomHost}, opts = Opts} end}, {<<"select jid, host, nick from muc_registered;">>, fun([J, RoomHost, Nick]) -> diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 923428b3fba..b11b5ae2c55 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -411,7 +411,6 @@ create_room(Name, Host, ServerHost) -> AcCreate = gen_mod:get_module_opt(ServerHost, mod_muc, access_create, fun(X) -> X end, all), AcAdmin = gen_mod:get_module_opt(ServerHost, mod_muc, access_admin, fun(X) -> X end, none), AcPer = gen_mod:get_module_opt(ServerHost, mod_muc, access_persistent, fun(X) -> X end, all), - _PersistHistory = gen_mod:get_module_opt(ServerHost, mod_muc, persist_history, fun(X) -> X end, false), HistorySize = gen_mod:get_module_opt(ServerHost, mod_muc, history_size, fun(X) -> X end, 20), RoomShaper = gen_mod:get_module_opt(ServerHost, mod_muc, room_shaper, fun(X) -> X end, none), diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 65e604ba41d..a5242824d00 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -76,23 +76,14 @@ %%==================================================================== %% API %%==================================================================== -%%-------------------------------------------------------------------- -%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} -%% Description: Starts the server -%%-------------------------------------------------------------------- start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). start(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - ChildSpec = - {Proc, - {?MODULE, start_link, [Host, Opts]}, - temporary, - 1000, - worker, - [?MODULE]}, + ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, + temporary, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> @@ -123,19 +114,11 @@ transform_module_options(Opts) -> %%==================================================================== %% gen_server callbacks %%==================================================================== - -%%-------------------------------------------------------------------- -%% Function: init(Args) -> {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%% Description: Initiates the server -%%-------------------------------------------------------------------- init([Host, Opts]) -> OutDir = gen_mod:get_opt(outdir, Opts, fun iolist_to_binary/1, <<"www/muc">>), - DirType = gen_mod:get_opt(dirtype, Opts, + DirType = gen_mod:get_opt(dirtype, Opts, fun(subdirs) -> subdirs; (plain) -> plain end, subdirs), @@ -181,31 +164,17 @@ init([Host, Opts]) -> {ok, #logstate{host = Host, out_dir = OutDir, dir_type = DirType, dir_name = DirName, - file_format = FileFormat, file_permissions = FilePermissions, css_file = CSSFile, + file_format = FileFormat, css_file = CSSFile, + file_permissions = FilePermissions, access = AccessLog, lang = Lang, timezone = Timezone, spam_prevention = NoFollow, top_link = Top_link}}. -%%-------------------------------------------------------------------- -%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | -%% {stop, Reason, State} -%% Description: Handling call messages -%%-------------------------------------------------------------------- handle_call({check_access_log, ServerHost, FromJID}, _From, State) -> Reply = acl:match_rule(ServerHost, State#logstate.access, FromJID), {reply, Reply, State}; handle_call(stop, _From, State) -> {stop, normal, ok, State}. -%%-------------------------------------------------------------------- -%% Function: handle_cast(Msg, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling cast messages -%%-------------------------------------------------------------------- handle_cast({add_to_log, Type, Data, Room, Opts}, State) -> case catch add_to_log2(Type, Data, Room, Opts, State) of {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); @@ -214,27 +183,10 @@ handle_cast({add_to_log, Type, Data, Room, Opts}, State) -> {noreply, State}; handle_cast(_Msg, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: handle_info(Info, State) -> {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} -%% Description: Handling all non call/cast messages -%%-------------------------------------------------------------------- handle_info(_Info, State) -> {noreply, State}. -%%-------------------------------------------------------------------- -%% Function: terminate(Reason, State) -> void() -%% Description: This function is called by a gen_server when it is about to -%% terminate. It should be the opposite of Module:init/1 and do any necessary -%% cleaning up. When it returns, the gen_server terminates with Reason. -%% The return value is ignored. -%%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. -%%-------------------------------------------------------------------- -%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} -%% Description: Convert process state when code is changed -%%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- @@ -242,19 +194,19 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- add_to_log2(text, {Nick, Packet}, Room, Opts, State) -> case has_no_permanent_store_hint(Packet) of - false -> - case {xml:get_subtag(Packet, <<"subject">>), - xml:get_subtag(Packet, <<"body">>)} - of - {false, false} -> ok; - {false, SubEl} -> - Message = {body, xml:get_tag_cdata(SubEl)}, - add_message_to_log(Nick, Message, Room, Opts, State); - {SubEl, _} -> - Message = {subject, xml:get_tag_cdata(SubEl)}, - add_message_to_log(Nick, Message, Room, Opts, State) - end; - true -> ok + false -> + case {xml:get_subtag(Packet, <<"subject">>), + xml:get_subtag(Packet, <<"body">>)} + of + {false, false} -> ok; + {false, SubEl} -> + Message = {body, xml:get_tag_cdata(SubEl)}, + add_message_to_log(Nick, Message, Room, Opts, State); + {SubEl, _} -> + Message = {subject, xml:get_tag_cdata(SubEl)}, + add_message_to_log(Nick, Message, Room, Opts, State) + end; + true -> ok end; add_to_log2(roomconfig_change, _Occupants, Room, Opts, State) -> @@ -349,7 +301,6 @@ close_previous_log(Fn, Images_dir, FileFormat) -> write_last_lines(_, _, plaintext) -> ok; write_last_lines(F, Images_dir, _FileFormat) -> -%% list_to_integer/2 was introduced in OTP R14 fw(F, <<"
    ">>). set_filemode(Fn, {FileMode, FileGroup}) -> - ok = file:change_mode(Fn, list_to_integer(integer_to_list(FileMode), 8)), + ok = file:change_mode(Fn, list_to_integer(integer_to_list(FileMode), 8)), ok = file:change_group(Fn, FileGroup). htmlize_nick(Nick1, html) -> @@ -1163,10 +1114,7 @@ roomoccupants_to_string(Users, _FileFormat) -> Users1 /= []], iolist_to_binary([<<"
    ">>, Res, <<"
    ">>]). -%% Users = [{JID, Nick, Role}] group_by_role(Users) -> -%% Role = atom() -%% Users = [{JID, Nick}] {Ms, Ps, Vs, Ns} = lists:foldl(fun ({JID, Nick, moderator}, {Mod, Par, Vis, Non}) -> @@ -1238,7 +1186,8 @@ get_room_state(RoomPid) -> get_state), R. -get_proc_name(Host) -> gen_mod:get_module_proc(Host, ?PROCNAME). +get_proc_name(Host) -> + gen_mod:get_module_proc(Host, ?PROCNAME). calc_hour_offset(TimeHere) -> TimeZero = calendar:now_to_universal_time(now()), diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 39e045d9e64..cf26bdea1f1 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -112,23 +112,17 @@ start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts) -> %%% Callback functions from gen_fsm %%%---------------------------------------------------------------------- -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, StateName, StateData} | -%% {ok, StateName, StateData, Timeout} | -%% ignore | -%% {stop, StopReason} -%%---------------------------------------------------------------------- -init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, _Nick, DefRoomOpts]) -> +init([Host, ServerHost, Access, Room, HistorySize, + RoomShaper, Creator, _Nick, DefRoomOpts]) -> process_flag(trap_exit, true), Shaper = shaper:new(RoomShaper), State = set_affiliation(Creator, owner, - #state{host = Host, server_host = ServerHost, - access = Access, room = Room, - history = lqueue_new(HistorySize), - jid = jlib:make_jid(Room, Host, <<"">>), - just_created = true, - room_shaper = Shaper}), + #state{host = Host, server_host = ServerHost, + access = Access, room = Room, + history = lqueue_new(HistorySize), + jid = jlib:make_jid(Room, Host, <<"">>), + just_created = true, + room_shaper = Shaper}), State1 = set_opts(DefRoomOpts, State), if (State1#state.config)#config.persistent -> mod_muc:store_room(State1#state.server_host, @@ -137,7 +131,7 @@ init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, _Nick, D make_opts(State1)); true -> ok end, - ?INFO_MSG("Created MUC room ~s@~s by ~s", + ?INFO_MSG("Created MUC room ~s@~s by ~s", [Room, Host, jlib:jid_to_string(Creator)]), add_to_log(room_existence, created, State1), add_to_log(room_existence, started, State1), @@ -155,12 +149,6 @@ init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts]) -> add_to_log(room_existence, started, State), {ok, normal_state, State}. -%%---------------------------------------------------------------------- -%% Func: StateName/2 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- normal_state({route, From, <<"">>, #xmlel{name = <<"message">>, attrs = Attrs, children = Els} = @@ -688,12 +676,6 @@ normal_state({route, From, ToNick, normal_state(_Event, StateData) -> {next_state, normal_state, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_event/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_event({service_message, Msg}, _StateName, StateData) -> MessagePkt = #xmlel{name = <<"message">>, @@ -742,15 +724,6 @@ handle_event({set_affiliations, Affiliations}, handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_sync_event/4 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {reply, Reply, NextStateName, NextStateData} | -%% {reply, Reply, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} | -%% {stop, Reason, Reply, NewStateData} -%%---------------------------------------------------------------------- handle_sync_event({get_disco_item, JID, Lang}, _From, StateName, StateData) -> Reply = get_roomdesc_reply(JID, StateData, get_roomdesc_tail(StateData, Lang)), @@ -779,12 +752,6 @@ handle_sync_event(_Event, _From, StateName, code_change(_OldVsn, StateName, StateData, _Extra) -> {ok, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: handle_info/3 -%% Returns: {next_state, NextStateName, NextStateData} | -%% {next_state, NextStateName, NextStateData, Timeout} | -%% {stop, Reason, NewStateData} -%%---------------------------------------------------------------------- handle_info({process_user_presence, From}, normal_state = _StateName, StateData) -> RoomQueueEmpty = queue:is_empty(StateData#state.room_queue), RoomQueue = queue:in({presence, From}, StateData#state.room_queue), @@ -864,11 +831,6 @@ handle_info(shutdown, _StateName, StateData) -> handle_info(_Info, StateName, StateData) -> {next_state, StateName, StateData}. -%%---------------------------------------------------------------------- -%% Func: terminate/3 -%% Purpose: Shutdown the fsm -%% Returns: any -%%---------------------------------------------------------------------- terminate(Reason, _StateName, StateData) -> ?INFO_MSG("Stopping MUC room ~s@~s", [StateData#state.room, StateData#state.host]), @@ -979,7 +941,7 @@ process_groupchat_message(From, StateData#state.server_host, StateData#state.users, NewPacket), - NewStateData2 = case has_body_or_subject(Packet) of + NewStateData2 = case has_body_or_subject(NewPacket) of true -> add_message_to_history(FromNick, From, NewPacket, @@ -1808,9 +1770,9 @@ is_nick_change(JID, Nick, StateData) -> nick_collision(User, Nick, StateData) -> UserOfNick = find_jid_by_nick(Nick, StateData), - UserOfNick /= false andalso + (UserOfNick /= false andalso jlib:jid_remove_resource(jlib:jid_tolower(UserOfNick)) - /= jlib:jid_remove_resource(jlib:jid_tolower(User)). + /= jlib:jid_remove_resource(jlib:jid_tolower(User))). add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, @@ -4412,7 +4374,6 @@ check_invitation(From, Els, Lang, StateData) -> jlib:jid_to_string({StateData#state.room, StateData#state.host, <<"">>})]), - case (StateData#state.config)#config.password_protected of @@ -4561,6 +4522,13 @@ tab_count_user(JID) -> element_size(El) -> byte_size(xml:element_to_binary(El)). +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Multicast + +send_multiple(From, Server, Users, Packet) -> + JIDs = [ User#user.jid || {_, User} <- ?DICT:to_list(Users)], + ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Detect messange stanzas that don't have meaninful content @@ -4571,9 +4539,3 @@ has_body_or_subject(Packet) -> (_) -> true end, Packet#xmlel.children). -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Multicast - -send_multiple(From, Server, Users, Packet) -> - JIDs = [ User#user.jid || {_, User} <- ?DICT:to_list(Users)], - ejabberd_router_multicast:route_multicast(From, Server, JIDs, Packet). diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 0abf4215c61..ad7514c1ae9 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -3,6 +3,24 @@ %%% Author : Badlop %%% Purpose : Extended Stanza Addressing (XEP-0033) support %%% Created : 29 May 2007 by Badlop +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% %%%---------------------------------------------------------------------- -module(mod_multicast). @@ -713,8 +731,7 @@ process_iqreply_error(From, LServiceS, _Packet) -> %%% Check protocol support: Receive response: Disco %%%------------------------- -process_iqreply_result(From, LServiceS, Packet, - State) -> +process_iqreply_result(From, LServiceS, Packet, State) -> #xmlel{name = <<"query">>, attrs = Attrs2, children = Els2} = xml:get_subtag(Packet, <<"query">>), @@ -741,37 +758,35 @@ process_discoinfo_result(From, LServiceS, Els, process_discoinfo_result2(From, FromS, LServiceS, Els, Waiter) -> - Multicast_support = lists:any(fun (XML) -> - case XML of - #xmlel{name = <<"feature">>, - attrs = Attrs} -> - (?NS_ADDRESS) == - xml:get_attr_s(<<"var">>, - Attrs); - _ -> false - end - end, - Els), + Multicast_support = + lists:any( + fun(XML) -> + case XML of + #xmlel{name = <<"feature">>, attrs = Attrs} -> + (?NS_ADDRESS) == xml:get_attr_s(<<"var">>, Attrs); + _ -> false + end + end, + Els), Group = Waiter#waiter.group, RServer = Group#group.server, case Multicast_support of - true -> - SenderT = sender_type(From), - RLimits = get_limits_xml(Els, SenderT), - add_response(RServer, - {multicast_supported, FromS, RLimits}), - FromM = Waiter#waiter.sender, - DestsM = Group#group.dests, - PacketM = Waiter#waiter.packet, - AAttrsM = Waiter#waiter.aattrs, - AddressesM = Waiter#waiter.addresses, - RServiceM = FromS, - route_packet_multicast(FromM, RServiceM, PacketM, - AAttrsM, DestsM, AddressesM, RLimits), - delo_waiter(Waiter); - false -> - case FromS of - RServer -> + true -> + SenderT = sender_type(From), + RLimits = get_limits_xml(Els, SenderT), + add_response(RServer, {multicast_supported, FromS, RLimits}), + FromM = Waiter#waiter.sender, + DestsM = Group#group.dests, + PacketM = Waiter#waiter.packet, + AAttrsM = Waiter#waiter.aattrs, + AddressesM = Waiter#waiter.addresses, + RServiceM = FromS, + route_packet_multicast(FromM, RServiceM, PacketM, + AAttrsM, DestsM, AddressesM, RLimits), + delo_waiter(Waiter); + false -> + case FromS of + RServer -> send_query_items(FromS, LServiceS), delo_waiter(Waiter), add_waiter(Waiter#waiter{awaiting = diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 5165c8e6884..bcd65b21b47 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -39,7 +39,7 @@ -export([count_offline_messages/2]). -export([start/2, - start_link/2, + start_link/2, stop/1, store_packet/3, resend_offline_messages/2, @@ -48,11 +48,11 @@ remove_expired_messages/1, remove_old_messages/2, remove_user/2, - import/1, - import/3, - export/1, + import/1, + import/3, + export/1, get_queue_length/2, - get_offline_els/2, + get_offline_els/2, webadmin_page/3, webadmin_user/4, webadmin_user_parse_query/5]). @@ -70,17 +70,7 @@ -include("ejabberd_web_admin.hrl"). --record(offline_msg, - {us = {<<"">>, <<"">>} :: {binary(), binary()}, - timestamp = now() :: erlang:timestamp() | '_', - expire = now() :: erlang:timestamp() | never | '_', - from = #jid{} :: jid() | '_', - to = #jid{} :: jid() | '_', - packet = #xmlel{} :: xmlel() | '_'}). - --record(state, - {host = <<"">> :: binary(), - access_max_offline_messages}). +-include("mod_offline.hrl"). -define(PROCNAME, ejabberd_offline). @@ -138,8 +128,11 @@ init([Host, Opts]) -> ejabberd_hooks:add(webadmin_user, Host, ?MODULE, webadmin_user, 50), ejabberd_hooks:add(webadmin_user_parse_query, Host, - ?MODULE, webadmin_user_parse_query, 50), - AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, fun(A) -> A end, max_user_offline_messages), + ?MODULE, webadmin_user_parse_query, 50), + AccessMaxOfflineMsgs = + gen_mod:get_opt(access_max_user_messages, Opts, + fun(A) when is_atom(A) -> A end, + max_user_offline_messages), {ok, #state{host = Host, access_max_offline_messages = AccessMaxOfflineMsgs}}. @@ -253,7 +246,6 @@ store_offline_msg(Host, {User, _}, Msgs, Len, MaxOfflineMsgs, end, Msgs) end. -%% Function copied from ejabberd_sm.erl: get_max_user_messages(AccessRule, {User, Server}, Host) -> case acl:match_rule( Host, AccessRule, jlib:make_jid(User, Server, <<"">>)) of @@ -308,24 +300,24 @@ need_to_store(LServer, Packet) -> store_packet(From, To, Packet) -> case need_to_store(To#jid.lserver, Packet) of true -> - case has_no_store_hint(Packet) of - false -> - case check_event(From, To, Packet) of - true -> - #jid{luser = LUser, lserver = LServer} = To, - TimeStamp = now(), - #xmlel{children = Els} = Packet, - Expire = find_x_expire(TimeStamp, Els), - gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) ! - #offline_msg{us = {LUser, LServer}, - timestamp = TimeStamp, expire = Expire, - from = From, to = To, packet = Packet}, - stop; - _ -> ok - end; - _ -> ok - end; - false -> ok + case has_no_store_hint(Packet) of + false -> + case check_event(From, To, Packet) of + true -> + #jid{luser = LUser, lserver = LServer} = To, + TimeStamp = now(), + #xmlel{children = Els} = Packet, + Expire = find_x_expire(TimeStamp, Els), + gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) ! + #offline_msg{us = {LUser, LServer}, + timestamp = TimeStamp, expire = Expire, + from = From, to = To, packet = Packet}, + stop; + _ -> ok + end; + _ -> ok + end; + false -> ok end. has_no_store_hint(Packet) -> diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 81ea3dfcfe9..6ab559c90ed 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -584,11 +584,10 @@ process_list_set(LUser, LServer, {value, Name}, Els) -> ejabberd_sm:route(jlib:make_jid(LUser, LServer, <<"">>), jlib:make_jid(LUser, LServer, <<"">>), - {broadcast, - {privacy_list, - #userlist{name = Name, - list = []}, - Name}}), + {broadcast, {privacy_list, + #userlist{name = Name, + list = []}, + Name}}), {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end; @@ -601,12 +600,11 @@ process_list_set(LUser, LServer, {value, Name}, Els) -> ejabberd_sm:route(jlib:make_jid(LUser, LServer, <<"">>), jlib:make_jid(LUser, LServer, <<"">>), - {broadcast, - {privacy_list, - #userlist{name = Name, - list = List, - needdb = NeedDb}, - Name}}), + {broadcast, {privacy_list, + #userlist{name = Name, + list = List, + needdb = NeedDb}, + Name}}), {result, []}; _ -> {error, ?ERR_INTERNAL_SERVER_ERROR} end @@ -1166,7 +1164,7 @@ update_table() -> end. export(Server) -> - case ejabberd_odbc:sql_query(jlib:nameprep(Server), + case catch ejabberd_odbc:sql_query(jlib:nameprep(Server), [<<"select id from privacy_list order by " "id desc limit 1;">>]) of {selected, [<<"id">>], [[I]]} -> diff --git a/src/mod_proxy65_sm.erl b/src/mod_proxy65_sm.erl index ce997154e91..f120f828b94 100644 --- a/src/mod_proxy65_sm.erl +++ b/src/mod_proxy65_sm.erl @@ -64,8 +64,9 @@ start_link(Host, Opts) -> []). init([Opts]) -> - mnesia:create_table(bytestream, [{ram_copies, [node()]}, - {attributes, record_info(fields, bytestream)}]), + mnesia:create_table(bytestream, + [{ram_copies, [node()]}, + {attributes, record_info(fields, bytestream)}]), mnesia:add_table_copy(bytestream, node(), ram_copies), MaxConnections = gen_mod:get_opt(max_connections, Opts, fun(I) when is_integer(I), I>0 -> diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index b4e936020f4..6470f0fb5fb 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3480,10 +3480,9 @@ subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> NodeOptions = Node#pubsub_node.options, lists:foldl(fun({LJID, SubID, SubOptions}, {JIDs, Recipients}) -> case is_to_deliver(LJID, NotifyType, Depth, NodeOptions, SubOptions) of - true -> - %% If is to deliver : + true -> case state_can_deliver(LJID, SubOptions) of - [] -> {JIDs, Recipients}; + [] -> {JIDs, Recipients}; JIDsToDeliver -> lists:foldl( fun(JIDToDeliver, {JIDsAcc, RecipientsAcc}) -> @@ -3494,11 +3493,14 @@ subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> %% - add the Jid to JIDs list co-accumulator ; %% - create a tuple of the Jid, Nidx, and SubID (as list), %% and add the tuple to the Recipients list co-accumulator - {[JIDToDeliver | JIDsAcc], [{JIDToDeliver, NodeName, [SubID]} | RecipientsAcc]}; + {[JIDToDeliver | JIDsAcc], + [{JIDToDeliver, NodeName, [SubID]} + | RecipientsAcc]}; true -> %% - if the JIDs co-accumulator contains the Jid %% get the tuple containing the Jid from the Recipient list co-accumulator - {_, {JIDToDeliver, NodeName1, SubIDs}} = lists:keysearch(JIDToDeliver, 1, RecipientsAcc), + {_, {JIDToDeliver, NodeName1, SubIDs}} = + lists:keysearch(JIDToDeliver, 1, RecipientsAcc), %% delete the tuple from the Recipients list % v1 : Recipients1 = lists:keydelete(LJID, 1, Recipients), % v2 : Recipients1 = lists:keyreplace(LJID, 1, Recipients, {LJID, Nidx1, [SubID | SubIDs]}), @@ -3507,7 +3509,11 @@ subscribed_nodes_by_jid(NotifyType, SubsByDepth) -> % v1.1 : {JIDs, lists:append(Recipients1, [{LJID, Nidx1, lists:append(SubIDs, [SubID])}])} % v1.2 : {JIDs, [{LJID, Nidx1, [SubID | SubIDs]} | Recipients1]} % v2: {JIDs, Recipients1} - {JIDsAcc, lists:keyreplace(JIDToDeliver, 1, RecipientsAcc, {JIDToDeliver, NodeName1, [SubID | SubIDs]})} + {JIDsAcc, + lists:keyreplace(JIDToDeliver, 1, + RecipientsAcc, + {JIDToDeliver, NodeName1, + [SubID | SubIDs]})} end end, {JIDs, Recipients}, JIDsToDeliver) end; diff --git a/src/mod_register.erl b/src/mod_register.erl index bb2a8fbe97f..f9ffa9c50cf 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -408,6 +408,8 @@ try_register(User, Server, Password, SourceRaw, Lang) -> {error, ?ERR_JID_MALFORMED}; {error, not_allowed} -> {error, ?ERR_NOT_ALLOWED}; + {error, too_many_users} -> + {error, ?ERR_NOT_ALLOWED}; {error, _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR} end diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 31fbeb1d26e..0677605acd6 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -1005,7 +1005,6 @@ send_unsubscription_to_rosteritems(LUser, LServer) -> end, RosterItems). -%% @spec (From::jid(), Item::roster()) -> ok send_unsubscribing_presence(From, Item) -> IsTo = case Item#roster.subscription of both -> true; diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 83ecade91ef..96cda6e3cca 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -98,9 +98,6 @@ start(Host, Opts) -> ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50). -%%ejabberd_hooks:add(remove_user, Host, -%% ?MODULE, remove_user, 50), - stop(Host) -> ejabberd_hooks:delete(webadmin_menu_host, Host, ?MODULE, webadmin_menu, 70), @@ -126,12 +123,11 @@ stop(Host) -> register_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), -%%ejabberd_hooks:delete(remove_user, Host, -%% ?MODULE, remove_user, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, - 50).%%ejabberd_hooks:delete(remove_user, Host, - %% ?MODULE, remove_user, 50), + 50). + %%ejabberd_hooks:delete(remove_user, Host, + %% ?MODULE, remove_user, 50), get_user_roster(Items, US) -> {U, S} = US, @@ -622,7 +618,6 @@ get_group_users(Host1, Group1) -> get_group_users(Host, Group, GroupOpts) -> case proplists:get_value(all_users, GroupOpts, false) of -%% @spec (Host::string(), Group::string()) -> [{User::string(), Server::string()}] true -> ejabberd_auth:get_vh_registered_users(Host); false -> [] end @@ -675,25 +670,22 @@ get_group_name(Host1, Group1) -> %% Get list of names of groups that have @all@/@online@/etc in the memberlist get_special_users_groups(Host) -> -%% Get list of names of groups that have @online@ in the memberlist lists:filter(fun (Group) -> get_group_opt(Host, Group, all_users, false) orelse get_group_opt(Host, Group, online_users, false) end, list_groups(Host)). +%% Get list of names of groups that have @online@ in the memberlist get_special_users_groups_online(Host) -> -%% Given two lists of groupnames and their options, -%% return the list of displayed groups to the second list lists:filter(fun (Group) -> get_group_opt(Host, Group, online_users, false) end, list_groups(Host)). +%% Given two lists of groupnames and their options, +%% return the list of displayed groups to the second list displayed_groups(GroupsOpts, SelectedGroupsOpts) -> -%% Given a list of group names with options, -%% for those that have @all@ in memberlist, -%% get the list of groups displayed DisplayedGroups = lists:usort(lists:flatmap(fun ({_Group, Opts}) -> [G @@ -712,6 +704,9 @@ displayed_groups(GroupsOpts, SelectedGroupsOpts) -> lists:member(disabled, proplists:get_value(G, GroupsOpts, []))]. +%% Given a list of group names with options, +%% for those that have @all@ in memberlist, +%% get the list of groups displayed get_special_displayed_groups(GroupsOpts) -> Groups = lists:filter(fun ({_Group, Opts}) -> proplists:get_value(all_users, Opts, false) @@ -825,7 +820,7 @@ is_user_in_group(US, Group, Host, odbc) -> %% @spec (Host::string(), {User::string(), Server::string()}, Group::string()) -> {atomic, ok} add_user_to_group(Host, US, Group) -> {LUser, LServer} = US, - case ejabberd_regexp:run(LUser, <<"^@.+@$">>) of + case ejabberd_regexp:run(LUser, <<"^@.+@\$">>) of match -> GroupOpts = (?MODULE):get_group_opts(Host, Group), MoreGroupOpts = case LUser of @@ -884,7 +879,7 @@ push_displayed_to_user(LUser, LServer, Host, Subscription, DisplayedGroups) -> remove_user_from_group(Host, US, Group) -> {LUser, LServer} = US, - case ejabberd_regexp:run(LUser, <<"^@.+@$">>) of + case ejabberd_regexp:run(LUser, <<"^@.+@\$">>) of match -> GroupOpts = (?MODULE):get_group_opts(Host, Group), NewGroupOpts = case LUser of diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 653c83ee254..2a3d8ee1155 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -275,16 +275,9 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -%% For a given user, map all his shared roster contacts to groups they are -%% members of. Skip the user himself iff SkipUS is true. + get_user_to_groups_map({_, Server} = US, SkipUS) -> DisplayedGroups = get_user_displayed_groups(US), -%% Pass given FilterParseArgs to eldap_filter:parse, and if successful, run and -%% return the resulting filter, retrieving given AttributesList. Return the -%% result entries. On any error silently return an empty list of results. -%% -%% Eldap server ID and base DN for the query are both retrieved from the State -%% record. lists:foldl(fun (Group, Dict1) -> GroupName = get_group_name(Server, Group), lists:foldl(fun (Contact, Dict) -> diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 4827e0c3b14..1e4044b1520 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -1,11 +1,11 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2014, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 21 Apr 2014 by Evgeny Khramtsov %%% +%%% %%% ejabberd, Copyright (C) 2014-2015 ProcessOne %%% %%% This program is free software; you can redistribute it and/or diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index 1dcf264ede6..a0dff125625 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -1,11 +1,11 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2014, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 21 Apr 2014 by Evgeny Khramtsov %%% +%%% %%% ejabberd, Copyright (C) 2014-2015 ProcessOne %%% %%% This program is free software; you can redistribute it and/or diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl index 58ffa5029c1..f6b3103b78a 100644 --- a/src/mod_sip_registrar.erl +++ b/src/mod_sip_registrar.erl @@ -1,11 +1,11 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2014, Evgeny Khramtsov %%% @doc %%% %%% @end %%% Created : 23 Apr 2014 by Evgeny Khramtsov %%% +%%% %%% ejabberd, Copyright (C) 2014-2015 ProcessOne %%% %%% This program is free software; you can redistribute it and/or diff --git a/src/mod_stats.erl b/src/mod_stats.erl index ce97dbdf09b..2604f1bb500 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -175,7 +175,7 @@ get_local_stat(_Server, _, Name) -> get_node_stat(Node, Name) when Name == <<"time/uptime">> -> - case catch rpc:call(Node, erlang, statistics, + case catch ejabberd_cluster:call(Node, erlang, statistics, [wall_clock]) of {badrpc, _Reason} -> @@ -188,7 +188,7 @@ get_node_stat(Node, Name) end; get_node_stat(Node, Name) when Name == <<"time/cputime">> -> - case catch rpc:call(Node, erlang, statistics, [runtime]) + case catch ejabberd_cluster:call(Node, erlang, statistics, [runtime]) of {badrpc, _Reason} -> ?STATERR(<<"500">>, <<"Internal Server Error">>); @@ -200,7 +200,7 @@ get_node_stat(Node, Name) end; get_node_stat(Node, Name) when Name == <<"users/online">> -> - case catch rpc:call(Node, ejabberd_sm, + case catch ejabberd_cluster:call(Node, ejabberd_sm, dirty_get_my_sessions_list, []) of {badrpc, _Reason} -> @@ -211,7 +211,7 @@ get_node_stat(Node, Name) end; get_node_stat(Node, Name) when Name == <<"transactions/committed">> -> - case catch rpc:call(Node, mnesia, system_info, + case catch ejabberd_cluster:call(Node, mnesia, system_info, [transaction_commits]) of {badrpc, _Reason} -> @@ -222,7 +222,7 @@ get_node_stat(Node, Name) end; get_node_stat(Node, Name) when Name == <<"transactions/aborted">> -> - case catch rpc:call(Node, mnesia, system_info, + case catch ejabberd_cluster:call(Node, mnesia, system_info, [transaction_failures]) of {badrpc, _Reason} -> @@ -233,7 +233,7 @@ get_node_stat(Node, Name) end; get_node_stat(Node, Name) when Name == <<"transactions/restarted">> -> - case catch rpc:call(Node, mnesia, system_info, + case catch ejabberd_cluster:call(Node, mnesia, system_info, [transaction_restarts]) of {badrpc, _Reason} -> @@ -244,7 +244,7 @@ get_node_stat(Node, Name) end; get_node_stat(Node, Name) when Name == <<"transactions/logged">> -> - case catch rpc:call(Node, mnesia, system_info, + case catch ejabberd_cluster:call(Node, mnesia, system_info, [transaction_log_writes]) of {badrpc, _Reason} -> diff --git a/src/node_pep.erl b/src/node_pep.erl index b219f6449f6..15877b07331 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -54,7 +54,8 @@ init(Host, ServerHost, Opts) -> ok. terminate(Host, ServerHost) -> - node_flat:terminate(Host, ServerHost), ok. + node_flat:terminate(Host, ServerHost), + ok. options() -> [{deliver_payloads, true}, diff --git a/src/node_pep_odbc.erl b/src/node_pep_odbc.erl index 39ea8f0b766..8df25c9b1e0 100644 --- a/src/node_pep_odbc.erl +++ b/src/node_pep_odbc.erl @@ -55,7 +55,8 @@ init(Host, ServerHost, Opts) -> ok. terminate(Host, ServerHost) -> - node_flat_odbc:terminate(Host, ServerHost), ok. + node_flat_odbc:terminate(Host, ServerHost), + ok. options() -> [{odbc, true}, {rsm, true} | node_pep:options()]. From 6a23cad45485f540b14af92b29b75b18038614eb Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 7 Oct 2015 00:19:32 +0200 Subject: [PATCH 289/695] Revert "Fix compilation on Erlang R15B" This reverts commit a5d6044448ad651581db47b33c6991e8ef32eb61. --- src/ejabberd_auth_odbc.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index 45ff4d7786c..de9114037e4 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -83,7 +83,7 @@ check_password(User, Server, Password) -> #scram{storedkey = StoredKey, serverkey = ServerKey, salt = Salt, - iterationcount = jlib:binary_to_integer( + iterationcount = binary_to_integer( IterationCount)}, is_password_scram_valid(Password, Scram); {selected, [<<"password">>, <<"serverkey">>, @@ -168,7 +168,7 @@ set_password(User, Server, Password) -> ejabberd_odbc:escape(Scram#scram.storedkey), ejabberd_odbc:escape(Scram#scram.serverkey), ejabberd_odbc:escape(Scram#scram.salt), - jlib:integer_to_binary(Scram#scram.iterationcount) + integer_to_binary(Scram#scram.iterationcount) ) of {atomic, ok} -> ok; @@ -204,7 +204,7 @@ try_register(User, Server, Password) -> ejabberd_odbc:escape(Scram#scram.storedkey), ejabberd_odbc:escape(Scram#scram.serverkey), ejabberd_odbc:escape(Scram#scram.salt), - jlib:integer_to_binary(Scram#scram.iterationcount) + integer_to_binary(Scram#scram.iterationcount) ) of {updated, 1} -> {atomic, ok}; _ -> {atomic, exists} @@ -278,7 +278,7 @@ get_password(User, Server) -> {jlib:decode_base64(StoredKey), jlib:decode_base64(ServerKey), jlib:decode_base64(Salt), - jlib:binary_to_integer(IterationCount)}; + binary_to_integer(IterationCount)}; _ -> false end; false -> @@ -439,7 +439,7 @@ convert_to_scram(Server) -> case ejabberd_odbc:sql_query_t( [<<"select username, password from users where " "iterationcount=0 limit ">>, - jlib:integer_to_binary(?BATCH_SIZE), + integer_to_binary(?BATCH_SIZE), <<";">>]) of {selected, [<<"username">>, <<"password">>], []} -> ok; @@ -453,7 +453,7 @@ convert_to_scram(Server) -> ejabberd_odbc:escape(Scram#scram.storedkey), ejabberd_odbc:escape(Scram#scram.serverkey), ejabberd_odbc:escape(Scram#scram.salt), - jlib:integer_to_binary(Scram#scram.iterationcount) + integer_to_binary(Scram#scram.iterationcount) ) end, Rs), continue; From f938c2a5e2265f4c0a18eb8b6d5dd8a8249f39b2 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 7 Oct 2015 00:19:42 +0200 Subject: [PATCH 290/695] Revert "Avoid crypto:hmac/3 call for R15B compatibility" This reverts commit 31e356c126cd5b967df9e7b560ce63f2b3b1529b. --- src/scram.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/scram.erl b/src/scram.erl index 8c79352107c..3069be4666c 100644 --- a/src/scram.erl +++ b/src/scram.erl @@ -86,6 +86,4 @@ hi_round(Password, UPrev, IterationCount) -> IterationCount - 1)))). sha_mac(Key, Data) -> - Context1 = crypto:hmac_init(sha, Key), - Context2 = crypto:hmac_update(Context1, Data), - crypto:hmac_final(Context2). + crypto:hmac(sha, Key, Data). From 653105a44fa0eda50b62d5b9c9e8d6dffdcfaea7 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 7 Oct 2015 15:12:15 +0200 Subject: [PATCH 291/695] Fix acl issue from cleanup --- src/acl.erl | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/acl.erl b/src/acl.erl index d56292680b8..f69472d7283 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -289,7 +289,7 @@ match_acl(none, _JID, _Host) -> match_acl(ACL, IP, Host) when tuple_size(IP) == 4; tuple_size(IP) == 8 -> lists:any( - fun({ip, {Net, Mask}}) -> + fun(#acl{aclspec = {ip, {Net, Mask}}}) -> is_ip_match(IP, Net, Mask); (_) -> false @@ -297,7 +297,7 @@ match_acl(ACL, IP, Host) when tuple_size(IP) == 4; match_acl(ACL, JID, Host) -> {User, Server, Resource} = jlib:jid_tolower(JID), lists:any( - fun(Spec) -> + fun(#acl{aclspec = Spec}) -> case Spec of all -> true; {user, {U, S}} -> U == User andalso S == Server; @@ -346,11 +346,7 @@ match_acl(ACL, JID, Host) -> get_aclspecs(ACL, Host)). get_aclspecs(ACL, Host) -> - lists:flatmap( - fun(#acl{aclspec = Specs}) -> - Specs - end, ets:lookup(acl, {ACL, Host}) ++ - ets:lookup(acl, {ACL, global})). + ets:lookup(acl, {ACL, Host}) ++ ets:lookup(acl, {ACL, global}). is_regexp_match(String, RegExp) -> case ejabberd_regexp:run(String, RegExp) of From 880114a909afdbff9100e1e6630042ff9c3b83ac Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 7 Oct 2015 16:14:45 +0200 Subject: [PATCH 292/695] Enforce get_allowed_items_call --- src/mod_pubsub.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 6470f0fb5fb..2482197fe0c 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -2450,7 +2450,7 @@ get_item(Host, Node, ItemId) -> get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) -> case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, none) of - {result, {I, none}} -> {result, I}; + {result, {Items, _RSM}} -> {result, Items}; Error -> Error end. get_allowed_items_call(Host, Nidx, From, Type, Options, Owners, RSM) -> From 6d25db660014856d2e4006cf5475aba0a0dd0f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 7 Oct 2015 16:44:49 +0200 Subject: [PATCH 293/695] Handler module shouldn't be used for differentiating listeners when merging configs --- src/ejabberd_config.erl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 8f3795cd36a..6245179e5e1 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -373,17 +373,15 @@ exit_or_halt(ExitText) -> get_config_option_key(Name, Val) -> if Name == listen -> lists:foldl( - fun({port, Port}, {_, IP, T, Mod}) -> - {Port, IP, T, Mod}; - ({ip, IP}, {Port, _, T, Mod}) -> - {Port, IP, T, Mod}; - ({transport, T}, {Port, IP, _, Mod}) -> - {Port, IP, T, Mod}; - ({module, Mod}, {Port, IP, T, _}) -> - {Port, IP, T, Mod}; + fun({port, Port}, {_, IP, T}) -> + {Port, IP, T}; + ({ip, IP}, {Port, _, T}) -> + {Port, IP, T}; + ({transport, T}, {Port, IP, _}) -> + {Port, IP, T}; (_, Res) -> Res - end, {5222, {0,0,0,0}, tcp, ejabberd_c2s}, Val); + end, {5222, {0,0,0,0}, tcp}, Val); is_tuple(Val) -> element(1, Val); true -> From b5ac0db895ba978ad40583d1484e12d9475d70e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 8 Oct 2015 13:07:00 +0200 Subject: [PATCH 294/695] Be able to merge old style configs with {listen,...} --- src/ejabberd_config.erl | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 6245179e5e1..8553b777258 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -372,16 +372,27 @@ exit_or_halt(ExitText) -> get_config_option_key(Name, Val) -> if Name == listen -> - lists:foldl( - fun({port, Port}, {_, IP, T}) -> - {Port, IP, T}; - ({ip, IP}, {Port, _, T}) -> - {Port, IP, T}; - ({transport, T}, {Port, IP, _}) -> - {Port, IP, T}; - (_, Res) -> - Res - end, {5222, {0,0,0,0}, tcp}, Val); + case Val of + {{Port, IP, Trans}, _Mod, _Opts} -> + {Port, IP, Trans}; + {{Port, Trans}, _Mod, _Opts} when Trans == tcp; Trans == udp -> + {Port, {0,0,0,0}, Trans}; + {{Port, IP}, _Mod, _Opts} -> + {Port, IP, tcp}; + {Port, _Mod, _Opts} -> + {Port, {0,0,0,0}, tcp}; + V when is_list(V) -> + lists:foldl( + fun({port, Port}, {_, IP, T}) -> + {Port, IP, T}; + ({ip, IP}, {Port, _, T}) -> + {Port, IP, T}; + ({transport, T}, {Port, IP, _}) -> + {Port, IP, T}; + (_, Res) -> + Res + end, {5222, {0,0,0,0}, tcp}, Val) + end; is_tuple(Val) -> element(1, Val); true -> @@ -397,7 +408,6 @@ maps_to_lists(IMap) -> [{Name, Val} | Res] end, [], IMap). - merge_configs(Terms, ResMap) -> lists:foldl(fun({Name, Val}, Map) when is_list(Val) -> Old = maps:get(Name, Map, #{}), From 87273619a67a04f7e21a143a920f45798041f086 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 11 Oct 2015 19:42:53 +0300 Subject: [PATCH 295/695] Advertise MAM (XEP-0313) v0.4 support in room disco --- src/mod_muc.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 18b123fa432..05148f8e43d 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -760,7 +760,9 @@ iq_disco_info(ServerHost, Lang) -> case gen_mod:is_loaded(ServerHost, mod_mam) of true -> [#xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_MAM_0}]}]; + attrs = [{<<"var">>, ?NS_MAM_0}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_MAM_1}]}]; false -> [] end. From 1578f17eff8d9d8802c99c6a3432b1874408ecb1 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 12 Oct 2015 10:41:07 +0200 Subject: [PATCH 296/695] Remove obsolete sasl init --- ejabberdctl.template | 2 -- 1 file changed, 2 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 04ede34718a..ea29fa28910 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -104,7 +104,6 @@ if [ "{{release}}" != "true" ] ; then fi fi EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log -SASL_LOG_PATH=$LOGS_DIR/erlang.log DATETIME=`date "+%Y%m%d-%H%M%S"` ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump ERL_INETRC=$ETC_DIR/inetrc @@ -180,7 +179,6 @@ start() $KERNEL_OPTS \ $EJABBERD_OPTS \ -s ejabberd \ - -sasl sasl_error_logger \\{file,\\\"$SASL_LOG_PATH\\\"\\} \ $ERLANG_OPTS $ARGS \"$@\"" } From 4fce1a17d7c38108da1cb431aa9e2ffa72c7f0c8 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 12 Oct 2015 20:53:52 +0300 Subject: [PATCH 297/695] Fix cyrsasl_oauth:mech_new call --- src/cyrsasl_oauth.erl | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/cyrsasl_oauth.erl b/src/cyrsasl_oauth.erl index fc5a9c6cf48..8d23a31857e 100644 --- a/src/cyrsasl_oauth.erl +++ b/src/cyrsasl_oauth.erl @@ -27,11 +27,11 @@ -author('alexey@process-one.net'). --export([start/1, stop/0, mech_new/6, mech_step/2, parse/1]). +-export([start/1, stop/0, mech_new/4, mech_step/2, parse/1]). -behaviour(cyrsasl). --record(state, {host, is_user_exists}). +-record(state, {host}). start(_Opts) -> cyrsasl:register_mechanism(<<"X-OAUTH2">>, ?MODULE, plain), @@ -39,25 +39,20 @@ start(_Opts) -> stop() -> ok. -mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest, - IsUserExists, _ClientCertFile) -> - {ok, #state{host = Host, is_user_exists = IsUserExists}}. +mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest) -> + {ok, #state{host = Host}}. mech_step(State, ClientIn) -> case prepare(ClientIn) of [AuthzId, User, Token] -> - case (State#state.is_user_exists)(User) of + case ejabberd_oauth:check_token( + User, State#state.host, <<"sasl_auth">>, Token) of true -> - case ejabberd_oauth:check_token( - User, State#state.host, <<"sasl_auth">>, Token) of - true -> - {ok, - [{username, User}, {authzid, AuthzId}, - {auth_module, ejabberd_oauth}]}; - false -> - {error, <<"not-authorized">>, User} - end; - _ -> {error, <<"not-authorized">>, User} + {ok, + [{username, User}, {authzid, AuthzId}, + {auth_module, ejabberd_oauth}]}; + false -> + {error, <<"not-authorized">>, User} end; _ -> {error, <<"bad-protocol">>} end. From 25f95d695443153bd8df65f650d760e5f8b8da2b Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Wed, 14 Oct 2015 22:49:47 -0500 Subject: [PATCH 298/695] This dependency was removed in 83dd79a --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index d45b3289cc6..50134bf36f7 100644 --- a/mix.exs +++ b/mix.exs @@ -18,7 +18,7 @@ defmodule Ejabberd.Mixfile do [mod: {:ejabberd_app, []}, applications: [:ssl], included_applications: [:p1_logger,:p1_yaml,:p1_tls,:p1_xml,:p1_stringprep,:p1_zlib,:p1_cache_tab,:mnesia,:p1_utils, - :p1_iconv,:esip,:p1_stun,:ehyperloglog,:p1_mysql,:p1_pgsql,:eredis,:oauth2,:xmlrpc]] + :p1_iconv,:esip,:p1_stun,:p1_mysql,:p1_pgsql,:eredis,:oauth2,:xmlrpc]] end defp erlc_options do From 98c172aed65e73025491efd10d53b744e58c1f5c Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Wed, 14 Oct 2015 22:50:28 -0500 Subject: [PATCH 299/695] mix.lock should be commited to ensure consistent builds. --- mix.lock | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 mix.lock diff --git a/mix.lock b/mix.lock new file mode 100644 index 00000000000..001e00624cb --- /dev/null +++ b/mix.lock @@ -0,0 +1,24 @@ +%{"bbmustache": {:hex, :bbmustache, "1.0.3"}, + "conform": {:hex, :conform, "0.17.0"}, + "eredis": {:git, "https://github.com/wooga/eredis", "bf12ecb30253c84a2331f4f0d93fd68856fcb9f4", []}, + "erlware_commons": {:hex, :erlware_commons, "0.15.0"}, + "esip": {:git, "https://github.com/processone/p1_sip", "d662d3fe7f6288b444ea321d854de0bd6d40e022", []}, + "exrm": {:hex, :exrm, "0.19.9"}, + "getopt": {:hex, :getopt, "0.8.2"}, + "neotoma": {:hex, :neotoma, "1.7.3"}, + "oauth2": {:git, "https://github.com/prefiks/oauth2.git", "e6da9912e5d8f658e7e868f41a102d085bdbef59", []}, + "p1_cache_tab": {:git, "https://github.com/processone/cache_tab", "f7ea12b0ba962a3d2f9a406d2954cf7de4e27230", []}, + "p1_iconv": {:git, "https://github.com/processone/eiconv", "8b7542b1aaf0a851f335e464956956985af6d9a2", []}, + "p1_logger": {:git, "https://github.com/processone/p1_logger", "3e19507fd5606a73694917158767ecb3f5704e3f", []}, + "p1_mysql": {:git, "https://github.com/processone/mysql", "dfa87da95f8fdb92e270741c2a53f796b682f918", []}, + "p1_pgsql": {:git, "https://github.com/processone/pgsql", "e72c03c60bfcb56bbb5d259342021d9cb3581dac", []}, + "p1_stringprep": {:git, "https://github.com/processone/stringprep", "3c640237a3a7831dc39de6a6d329d3a9af25c579", []}, + "p1_stun": {:git, "https://github.com/processone/stun", "061bdae484268cbf0457ad4797e74b8516df3ad1", []}, + "p1_tls": {:git, "https://github.com/processone/tls", "e56321afd974e9da33da913cd31beebc8e73e75f", []}, + "p1_utils": {:git, "https://github.com/processone/p1_utils", "7aa022f995e3be006224a25405cd431483e7d026", []}, + "p1_xml": {:git, "https://github.com/processone/xml", "403066ea5e0b2cd89e65c3ed1a329789c02c3588", []}, + "p1_yaml": {:git, "https://github.com/processone/p1_yaml", "79f756ba73a235c4d3836ec07b5f7f2b55f49638", []}, + "p1_zlib": {:git, "https://github.com/processone/zlib", "e3d4222b7aae616d7ef2e7e2fa0bbf451516c602", []}, + "providers": {:hex, :providers, "1.4.1"}, + "relx": {:hex, :relx, "3.5.0"}, + "xmlrpc": {:git, "https://github.com/rds13/xmlrpc.git", "42e6e96a0fe7106830274feed915125feb1056f3", []}} From 35c33a8a29bf524bb2fccfbb6aa868d714ed54f5 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Wed, 14 Oct 2015 22:52:27 -0500 Subject: [PATCH 300/695] Improve line lengths; use spaces in between commas. --- mix.exs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 50134bf36f7..fcc2973fa92 100644 --- a/mix.exs +++ b/mix.exs @@ -17,8 +17,10 @@ defmodule Ejabberd.Mixfile do def application do [mod: {:ejabberd_app, []}, applications: [:ssl], - included_applications: [:p1_logger,:p1_yaml,:p1_tls,:p1_xml,:p1_stringprep,:p1_zlib,:p1_cache_tab,:mnesia,:p1_utils, - :p1_iconv,:esip,:p1_stun,:p1_mysql,:p1_pgsql,:eredis,:oauth2,:xmlrpc]] + included_applications: [:p1_logger, :p1_yaml, :p1_tls, :p1_xml, + :p1_stringprep, :p1_zlib, :p1_cache_tab, + :mnesia, :p1_utils, :p1_iconv, :esip, :p1_stun, + :p1_mysql, :p1_pgsql, :eredis, :oauth2, :xmlrpc]] end defp erlc_options do From 7d99484859df7c33a73da92d84b5cb5bd27a244e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 15 Oct 2015 10:07:06 +0200 Subject: [PATCH 301/695] Make KEEPALIVE_QUERY list as this is what sql_query/3 expects --- src/ejabberd_odbc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 620c69fe9bc..f86dcca2e08 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -90,7 +90,7 @@ -define(KEEPALIVE_TIMEOUT, 60000). --define(KEEPALIVE_QUERY, <<"SELECT 1;">>). +-define(KEEPALIVE_QUERY, [<<"SELECT 1;">>]). %%-define(DBGFSM, true). From 70606667c60bfc3196defe86056a5eb77841dfd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 15 Oct 2015 15:08:45 +0200 Subject: [PATCH 302/695] Use OTP directory structure for 'make install' --- Makefile.in | 53 ++++++++++++++++++++++---------------------- ejabberdctl.template | 13 ++--------- 2 files changed, 28 insertions(+), 38 deletions(-) diff --git a/Makefile.in b/Makefile.in index f7b30d4689e..c5f2b2d0f9f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -109,9 +109,33 @@ spec: $(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \ 'case xml_gen:compile("tools/xmpp_codec.spec") of ok -> halt(0); _ -> halt(1) end.' -DLLs := $(wildcard deps/*/priv/*.so) $(wildcard deps/*/priv/lib/*.so) +TO_DEST=$(foreach path,$(1),$(if $(filter deps/%,$(path)),$(patsubst deps/%,$(DESTDIR)/lib/%,$(path)),$(patsubst %,$(DESTDIR)/lib/ejabberd/%,$(path)))) +FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path))) +FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w)))) -install: all +DEPS_FILES:=$(call FILES_WILDCARD,deps/*/ebin/*.beam deps/*/ebin/*.app deps/*/priv/* deps/*/priv/lib/* deps/*/priv/bin/* deps/*/include/*.hrl) +DEPS_FILES_FILTERED:=$(filter-out %/epam,$(DEPS_FILES)) +DEPS_DIRS:=$(sort deps/ $(wildcard deps/*) $(dir $(DEPS_FILES))) + +MAIN_FILES:=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/*.app priv/msgs/*.msg priv/lib/* include/*.hrl)) +MAIN_DIRS:=$(sort $(dir $(MAIN_FILES))) + +define COPY_template = +$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) + $(INSTALL) -m 644 $(1) $(call TO_DEST,$(1)) +endef + +$(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,$(file)))) + +$(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS)): + $(INSTALL) -d $@ + +$(call TO_DEST,deps/p1_pam/priv/bin/epam): $(DESTDIR)/lib/%: deps/% $(call TO_DEST,deps/p1_pam/priv/bin/) + $(INSTALL) -m 750 $(O_USER) $< $@ + +copy-files: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES)) + +install: all copy-files # # Configuration files $(INSTALL) -d -m 750 $(G_USER) $(ETCDIR) @@ -146,41 +170,16 @@ install: all -e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \ > ejabberd.init chmod 755 ejabberd.init - # - # Binary Erlang files - $(INSTALL) -d $(BEAMDIR) - $(INSTALL) -m 644 ebin/*.app $(BEAMDIR) - $(INSTALL) -m 644 ebin/*.beam $(BEAMDIR) - $(INSTALL) -m 644 deps/*/ebin/*.app $(BEAMDIR) - $(INSTALL) -m 644 deps/*/ebin/*.beam $(BEAMDIR) # Install Elixir and Elixir dependancies -$(INSTALL) -m 644 deps/*/lib/*/ebin/*.app $(BEAMDIR) -$(INSTALL) -m 644 deps/*/lib/*/ebin/*.beam $(BEAMDIR) rm -f $(BEAMDIR)/configure.beam # - # ejabberd header files - $(INSTALL) -d $(INCLUDEDIR) - $(INSTALL) -m 644 include/*.hrl $(INCLUDEDIR) - $(INSTALL) -m 644 deps/*/include/*.hrl $(INCLUDEDIR) - # # Binary C programs $(INSTALL) -d $(PBINDIR) $(INSTALL) -m 750 $(O_USER) tools/captcha.sh $(PBINDIR) $(INSTALL) -m 750 $(O_USER) tools/joincluster $(PBINDIR) $(INSTALL) -m 750 $(O_USER) tools/leavecluster $(PBINDIR) - [ -f deps/p1_pam/priv/bin/epam ] \ - && $(INSTALL) -m 750 $(O_USER) deps/p1_pam/priv/bin/epam $(PBINDIR) \ - || true - # - # Binary system libraries - $(INSTALL) -d $(SODIR) - $(INSTALL) -m 644 $(DLLs) $(SODIR) - [ -f $(SODIR)/jiffy.so ] && (cd $(PRIVDIR); ln -s lib/jiffy.so; true) || true - [ -f $(SODIR)/sqlite3_drv.so ] && (cd $(PRIVDIR); ln -s lib/sqlite3_drv.so; true) || true - # - # Translated strings - $(INSTALL) -d $(MSGSDIR) - $(INSTALL) -m 644 priv/msgs/*.msg $(MSGSDIR) # # Copy lite.sql [ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR) || true diff --git a/ejabberdctl.template b/ejabberdctl.template index ea29fa28910..f90f71e5345 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -15,6 +15,7 @@ ERL={{erl}} IEX={{bindir}}/iex EPMD={{bindir}}/epmd INSTALLUSER={{installuser}} +ERL_LIBS={{libdir}} # check the proper system user is used if defined if [ "$INSTALLUSER" != "" ] ; then @@ -87,21 +88,12 @@ if [ "{{release}}" != "true" ] ; then if [ "$EJABBERDDIR" = "" ] ; then EJABBERDDIR={{libdir}}/ejabberd fi - if [ "$EJABBERD_EBIN_PATH" = "" ] ; then - EJABBERD_EBIN_PATH=$EJABBERDDIR/ebin - fi if [ "$EJABBERD_PRIV_PATH" = "" ] ; then EJABBERD_PRIV_PATH=$EJABBERDDIR/priv fi if [ "$EJABBERD_BIN_PATH" = "" ] ; then EJABBERD_BIN_PATH=$EJABBERD_PRIV_PATH/bin fi - if [ "$EJABBERD_SO_PATH" = "" ] ; then - EJABBERD_SO_PATH=$EJABBERD_PRIV_PATH/lib - fi - if [ "$EJABBERD_MSGS_PATH" = "" ] ; then - EJABBERD_MSGS_PATH=$EJABBERD_PRIV_PATH/msgs - fi fi EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log DATETIME=`date "+%Y%m%d-%H%M%S"` @@ -154,9 +146,7 @@ cd $SPOOL_DIR # export global variables export EJABBERD_CONFIG_PATH -export EJABBERD_MSGS_PATH export EJABBERD_LOG_PATH -export EJABBERD_SO_PATH export EJABBERD_BIN_PATH export EJABBERD_DOC_PATH export EJABBERD_PID_PATH @@ -166,6 +156,7 @@ export ERL_INETRC export ERL_MAX_PORTS export ERL_MAX_ETS_TABLES export CONTRIB_MODULES_PATH +export ERL_LIBS # start server start() From 53bd0ee818c154cd0fb3da531f1275ac41b23b03 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 17 Oct 2015 22:07:29 +0200 Subject: [PATCH 303/695] ejabberd_c2s: Close socket when waiting for resume Make sure the socket is closed when mod_ping calls ejabberd_c2s:stop/1 for an XEP-0198 session. --- src/ejabberd_c2s.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index c82f1a34c93..f48f44add71 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1202,6 +1202,7 @@ session_established({xmlstreamerror, _}, StateData) -> send_trailer(StateData), {stop, normal, StateData}; session_established(closed, #state{mgmt_state = active} = StateData) -> + catch (StateData#state.sockmod):close(StateData#state.socket), fsm_next_state(wait_for_resume, StateData); session_established(closed, StateData) -> {stop, normal, StateData}. From 5e467b96a1a19b72bf0d851926f2598d643e5a33 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 17 Oct 2015 23:15:31 +0200 Subject: [PATCH 304/695] ejabberd_c2s: Let stop/1 close XEP-0198 sessions The stop/1 function now terminates stream management sessions immediately, just as it does for other sessions. The new ejabberd_c2s:close/1 function can be used to close the socket without terminating the stream management session, like stop/1 did before. --- src/ejabberd_c2s.erl | 19 ++++++++++++++++++- src/mod_ping.erl | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f48f44add71..69b46523845 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -43,6 +43,7 @@ -export([start/2, stop/1, start_link/2, + close/1, send_text/2, send_element/2, socket_type/0, @@ -251,7 +252,9 @@ send_filtered(FsmRef, Feature, From, To, Packet) -> broadcast(FsmRef, Type, From, Packet) -> FsmRef ! {broadcast, Type, From, Packet}. -stop(FsmRef) -> (?GEN_FSM):send_event(FsmRef, closed). +stop(FsmRef) -> (?GEN_FSM):send_event(FsmRef, stop). + +close(FsmRef) -> (?GEN_FSM):send_event(FsmRef, closed). %%%---------------------------------------------------------------------- %%% Callback functions from gen_fsm @@ -552,6 +555,8 @@ wait_for_stream({xmlstreamerror, _}, StateData) -> send_trailer(StateData), {stop, normal, StateData}; wait_for_stream(closed, StateData) -> + {stop, normal, StateData}; +wait_for_stream(stop, StateData) -> {stop, normal, StateData}. wait_for_auth({xmlstreamelement, #xmlel{name = Name} = El}, StateData) @@ -707,6 +712,8 @@ wait_for_auth({xmlstreamerror, _}, StateData) -> send_trailer(StateData), {stop, normal, StateData}; wait_for_auth(closed, StateData) -> + {stop, normal, StateData}; +wait_for_auth(stop, StateData) -> {stop, normal, StateData}. wait_for_feature_request({xmlstreamelement, #xmlel{name = Name} = El}, @@ -869,6 +876,8 @@ wait_for_feature_request({xmlstreamerror, _}, send_trailer(StateData), {stop, normal, StateData}; wait_for_feature_request(closed, StateData) -> + {stop, normal, StateData}; +wait_for_feature_request(stop, StateData) -> {stop, normal, StateData}. wait_for_sasl_response({xmlstreamelement, #xmlel{name = Name} = El}, StateData) @@ -980,6 +989,8 @@ wait_for_sasl_response({xmlstreamerror, _}, send_trailer(StateData), {stop, normal, StateData}; wait_for_sasl_response(closed, StateData) -> + {stop, normal, StateData}; +wait_for_sasl_response(stop, StateData) -> {stop, normal, StateData}. resource_conflict_action(U, S, R) -> @@ -1086,6 +1097,8 @@ wait_for_bind({xmlstreamerror, _}, StateData) -> send_trailer(StateData), {stop, normal, StateData}; wait_for_bind(closed, StateData) -> + {stop, normal, StateData}; +wait_for_bind(stop, StateData) -> {stop, normal, StateData}. wait_for_session({xmlstreamelement, #xmlel{name = Name} = El}, StateData) @@ -1154,6 +1167,8 @@ wait_for_session({xmlstreamerror, _}, StateData) -> send_trailer(StateData), {stop, normal, StateData}; wait_for_session(closed, StateData) -> + {stop, normal, StateData}; +wait_for_session(stop, StateData) -> {stop, normal, StateData}. session_established({xmlstreamelement, #xmlel{name = Name} = El}, StateData) @@ -1205,6 +1220,8 @@ session_established(closed, #state{mgmt_state = active} = StateData) -> catch (StateData#state.sockmod):close(StateData#state.socket), fsm_next_state(wait_for_resume, StateData); session_established(closed, StateData) -> + {stop, normal, StateData}; +session_established(stop, StateData) -> {stop, normal, StateData}. %% Process packets sent by user (coming from user on c2s XMPP connection) diff --git a/src/mod_ping.erl b/src/mod_ping.erl index 7d030685cd0..b4e1041d552 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -169,7 +169,7 @@ handle_cast({iq_pong, JID, timeout}, State) -> JID, case ejabberd_sm:get_session_pid(User, Server, Resource) of - Pid when is_pid(Pid) -> ejabberd_c2s:stop(Pid); + Pid when is_pid(Pid) -> ejabberd_c2s:close(Pid); _ -> ok end; _ -> ok From 28e28e926ab84b99b1eedd232f5f392380e5d32f Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 18 Oct 2015 01:14:48 +0200 Subject: [PATCH 305/695] ejabberd_listener: Fix ETS update on port reuse --- src/ejabberd_listener.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 8660cc2f8af..0bea9c97b73 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -186,8 +186,8 @@ init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) -> listen_tcp(PortIP, Module, SockOpts, Port, IPS) -> case ets:lookup(listen_sockets, PortIP) of [{PortIP, ListenSocket}] -> - ?INFO_MSG("Reusing listening port for ~p", [Port]), - ets:delete(listen_sockets, Port), + ?INFO_MSG("Reusing listening port for ~p", [PortIP]), + ets:delete(listen_sockets, PortIP), ListenSocket; _ -> Res = gen_tcp:listen(Port, [binary, From 97a93263c14aec7bfcddf995160c153947f9bfba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 19 Oct 2015 13:46:51 +0200 Subject: [PATCH 306/695] Make install should work even without having DESTDIR set --- Makefile.in | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index c5f2b2d0f9f..57f355cb1dc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -17,6 +17,9 @@ BINDIR = $(DESTDIR)@bindir@ # /sbin/ SBINDIR = $(DESTDIR)@sbindir@ +# /lib/ +LIBDIR = $(DESTDIR)@libdir@ + # /lib/ejabberd/ EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd @@ -109,7 +112,7 @@ spec: $(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \ 'case xml_gen:compile("tools/xmpp_codec.spec") of ok -> halt(0); _ -> halt(1) end.' -TO_DEST=$(foreach path,$(1),$(if $(filter deps/%,$(path)),$(patsubst deps/%,$(DESTDIR)/lib/%,$(path)),$(patsubst %,$(DESTDIR)/lib/ejabberd/%,$(path)))) +TO_DEST=$(foreach path,$(1),$(if $(filter deps/%,$(path)),$(patsubst deps/%,$(LIBDIR)/%,$(path)),$(patsubst %,$(LIBDIR)/ejabberd/%,$(path)))) FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path))) FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w)))) @@ -130,7 +133,7 @@ $(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template, $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS)): $(INSTALL) -d $@ -$(call TO_DEST,deps/p1_pam/priv/bin/epam): $(DESTDIR)/lib/%: deps/% $(call TO_DEST,deps/p1_pam/priv/bin/) +$(call TO_DEST,deps/p1_pam/priv/bin/epam): $(LIBDIR)/%: deps/% $(call TO_DEST,deps/p1_pam/priv/bin/) $(INSTALL) -m 750 $(O_USER) $< $@ copy-files: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES)) From ff4a00b1f3ccf573e2038197444e5f587524f02e Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 19 Oct 2015 14:23:37 +0200 Subject: [PATCH 307/695] Let Travis CI test "make install" --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a60bb3ac27d..5379f848b9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,9 @@ before_script: script: - ./autogen.sh - - ./configure --enable-all --disable-odbc --disable-elixir + - ./configure --prefix=/tmp/ejabberd --enable-all --disable-odbc --disable-elixir + - make + - make install - make xref - ERL_LIBS=$PWD make test - grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log From 06701b126bc704823e5bc4edd0cff578f6229765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 19 Oct 2015 16:38:31 +0200 Subject: [PATCH 308/695] Make COPY_template compatible with gmake 3.8 --- Makefile.in | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index 57f355cb1dc..391d816123d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -123,9 +123,8 @@ DEPS_DIRS:=$(sort deps/ $(wildcard deps/*) $(dir $(DEPS_FILES))) MAIN_FILES:=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/*.app priv/msgs/*.msg priv/lib/* include/*.hrl)) MAIN_DIRS:=$(sort $(dir $(MAIN_FILES))) -define COPY_template = -$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) - $(INSTALL) -m 644 $(1) $(call TO_DEST,$(1)) +define COPY_template +$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; $$(INSTALL) -m 644 $(1) $(call TO_DEST,$(1)) endef $(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,$(file)))) From 1f2b7e8f207ee43b6cf5ac2d4a3282ac2ae077fc Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 19 Oct 2015 18:50:26 +0300 Subject: [PATCH 309/695] Fix access_commands option handling --- src/ejabberd_commands.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index c5026328602..ba604a07d50 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -491,7 +491,8 @@ check_access(_Command, _Access, admin) -> check_access(_Command, _Access, {_User, _Server, _, true}) -> false; check_access(Command, Access, Auth) - when Command#ejabberd_commands.policy == open; + when Access =/= all; + Command#ejabberd_commands.policy == open; Command#ejabberd_commands.policy == user -> case check_auth(Command, Auth) of {ok, User, Server} -> From 7c1e7e5b5f0342326e38451abe4bc3ca48e3d13c Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 19 Oct 2015 20:16:04 +0300 Subject: [PATCH 310/695] Improve access_commands option backward compatibility --- src/ejabberd_commands.erl | 11 ++++++++--- src/ejabberd_xmlrpc.erl | 7 ++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index ba604a07d50..9f55035dd9e 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -226,6 +226,7 @@ -include("ejabberd.hrl"). -include("logger.hrl"). +-define(POLICY_ACCESS, '$policy'). init() -> ets:new(ejabberd_commands, [named_table, set, public, @@ -483,7 +484,7 @@ check_auth(_Command, {User, Server, Password, _}) when is_binary(Password) -> _ -> throw({error, invalid_account_data}) end. -check_access(Command, all, _) +check_access(Command, ?POLICY_ACCESS, _) when Command#ejabberd_commands.policy == open -> true; check_access(_Command, _Access, admin) -> @@ -491,7 +492,7 @@ check_access(_Command, _Access, admin) -> check_access(_Command, _Access, {_User, _Server, _, true}) -> false; check_access(Command, Access, Auth) - when Access =/= all; + when Access =/= ?POLICY_ACCESS; Command#ejabberd_commands.policy == open; Command#ejabberd_commands.policy == user -> case check_auth(Command, Auth) of @@ -503,6 +504,8 @@ check_access(Command, Access, Auth) check_access(_Command, _Access, _Auth) -> false. +check_access2(?POLICY_ACCESS, _User, _Server) -> + true; check_access2(Access, User, Server) -> %% Check this user has access permission case acl:match_rule(Server, Access, jlib:make_jid(User, Server, <<"">>)) of @@ -536,9 +539,11 @@ tag_arguments(ArgsDefs, Args) -> Args). +get_access_commands(unrestricted) -> + []; get_access_commands(undefined) -> Cmds = get_commands(), - [{all, Cmds, []}]; + [{?POLICY_ACCESS, Cmds, []}]; get_access_commands(AccessCommands) -> AccessCommands. diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index db109920cbd..59a20d92c22 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -197,11 +197,14 @@ socket_type() -> raw. %% ----------------------------- process(_, #request{method = 'POST', data = Data, opts = Opts}) -> AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts, - fun(L) when is_list(L) -> L end, + fun(L) when is_list(L) -> L; + (unrestricted) -> unrestricted + end, undefined), AccessCommands = case AccessCommandsOpts of undefined -> undefined; + unrestricted -> unrestricted; _ -> lists:flatmap( fun({Ac, AcOpts}) -> @@ -537,6 +540,8 @@ make_status(false) -> 1; make_status(error) -> 1; make_status(_) -> 1. +transform_listen_option({access_commands, unrestricted} = Opt, Opts) -> + [Opt | Opts]; transform_listen_option({access_commands, ACOpts}, Opts) -> NewACOpts = lists:map( fun({AName, ACmds, AOpts}) -> From 2d22d6061e2c4d394bddebd7f133a56b356f21fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 20 Oct 2015 15:22:39 +0200 Subject: [PATCH 311/695] Pass {C,CPP,LD}FLAGS used in main ./configure call to invocations from deps --- configure.ac | 3 +++ rebar.config.script | 7 ++++++- vars.config.in | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d30a490d080..c7e7bcd4ad2 100644 --- a/configure.ac +++ b/configure.ac @@ -273,5 +273,8 @@ AC_SUBST(iconv) AC_SUBST(debug) AC_SUBST(lager) AC_SUBST(tools) +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) AC_OUTPUT diff --git a/rebar.config.script b/rebar.config.script index 633433c197b..e0a8923cfc0 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -66,10 +66,15 @@ Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], +CFLags = proplists:get_value(cflags, Cfg, ""), +CPPFLags = proplists:get_value(cppflags, Cfg, ""), +LDFLags = proplists:get_value(ldflags, Cfg, ""), + ConfigureCmd = fun(Pkg, Flags) -> {'get-deps', "sh -c 'cd deps/" ++ Pkg ++ - " && ./configure" ++ Flags ++ "'"} + " && CFLAGS=\""++ CFLags ++"\" CPPFLAGS=\""++ CPPFLags ++"\" LDFLAGS=\""++ LDFLags ++"\"" ++ + " ./configure" ++ Flags ++ "'"} end, XMLFlags = lists:foldl( diff --git a/vars.config.in b/vars.config.in index 2cd5d8e9a6f..69cc516f7ef 100644 --- a/vars.config.in +++ b/vars.config.in @@ -47,6 +47,10 @@ {libdir, "{{release_dir}}/lib"}. {docdir, "{{release_dir}}/doc"}. +{ldflags, "@LDFLAGS@"}. +{cflags, "@CFLAGS@"}. +{cppflags, "@CPPFLAGS@"}. + %% Local Variables: %% mode: erlang %% End: From 8a2fa62cac178a5e15ce7aae3db1af994a4e813a Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Tue, 20 Oct 2015 17:19:31 +0300 Subject: [PATCH 312/695] Remove access_commands 'unrestricted' option, use [] instead. Fix unauthenticated calls to commands with policy=user. --- src/ejabberd_commands.erl | 12 ++++++++---- src/ejabberd_xmlrpc.erl | 7 +------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index 9f55035dd9e..906c8dffc98 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -299,7 +299,8 @@ get_command_format(Name, Auth) -> case Matched of [] -> {error, command_unknown}; - [[Args, Result, user]] when Admin -> + [[Args, Result, user]] when Admin; + Auth == noauth -> {[{user, binary}, {server, binary} | Args], Result}; [[Args, Result, _]] -> {Args, Result} @@ -363,6 +364,9 @@ execute_command2( execute_command2( admin, #ejabberd_commands{policy = user} = Command, Arguments) -> execute_command2(Command, Arguments); +execute_command2( + noauth, #ejabberd_commands{policy = user} = Command, Arguments) -> + execute_command2(Command, Arguments); execute_command2( {User, Server, _, _}, #ejabberd_commands{policy = user} = Command, Arguments) -> execute_command2(Command, [User, Server | Arguments]). @@ -429,7 +433,9 @@ check_access_commands([], _Auth, _Method, _Command, _Arguments) -> check_access_commands(AccessCommands, Auth, Method, Command1, Arguments) -> Command = case {Command1#ejabberd_commands.policy, Auth} of - {user, admin} -> + {user, {_, _, _}} -> + Command1; + {user, _} -> Command1#ejabberd_commands{ args = [{user, binary}, {server, binary} | Command1#ejabberd_commands.args]}; @@ -539,8 +545,6 @@ tag_arguments(ArgsDefs, Args) -> Args). -get_access_commands(unrestricted) -> - []; get_access_commands(undefined) -> Cmds = get_commands(), [{?POLICY_ACCESS, Cmds, []}]; diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 59a20d92c22..db109920cbd 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -197,14 +197,11 @@ socket_type() -> raw. %% ----------------------------- process(_, #request{method = 'POST', data = Data, opts = Opts}) -> AccessCommandsOpts = gen_mod:get_opt(access_commands, Opts, - fun(L) when is_list(L) -> L; - (unrestricted) -> unrestricted - end, + fun(L) when is_list(L) -> L end, undefined), AccessCommands = case AccessCommandsOpts of undefined -> undefined; - unrestricted -> unrestricted; _ -> lists:flatmap( fun({Ac, AcOpts}) -> @@ -540,8 +537,6 @@ make_status(false) -> 1; make_status(error) -> 1; make_status(_) -> 1. -transform_listen_option({access_commands, unrestricted} = Opt, Opts) -> - [Opt | Opts]; transform_listen_option({access_commands, ACOpts}, Opts) -> NewACOpts = lists:map( fun({AName, ACmds, AOpts}) -> From c62bd0c9119426640f660ee2578e47c81e7bc48f Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 21 Oct 2015 12:51:22 +0200 Subject: [PATCH 313/695] Use homogeneous s2s connections stats (#761) --- src/ejabberd_web_admin.erl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index c2a93e433e4..5374cb0d100 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1478,10 +1478,8 @@ get_stats(global, Lang) -> + Total end, 0, ?MYHOSTS), - S2SConns = ejabberd_s2s:dirty_get_connections(), - S2SConnections = length(S2SConns), - S2SServers = length(lists:usort([element(2, C) - || C <- S2SConns])), + OutS2SNumber = ejabberd_s2s:outgoing_s2s_number(), + InS2SNumber = ejabberd_s2s:incoming_s2s_number(), [?XAE(<<"table">>, [], [?XE(<<"tbody">>, [?XE(<<"tr">>, @@ -1492,10 +1490,10 @@ get_stats(global, Lang) -> ?XC(<<"td">>, (pretty_string_int(OnlineUsers)))]), ?XE(<<"tr">>, [?XCT(<<"td">>, <<"Outgoing s2s Connections:">>), - ?XC(<<"td">>, (pretty_string_int(S2SConnections)))]), + ?XC(<<"td">>, (pretty_string_int(OutS2SNumber)))]), ?XE(<<"tr">>, - [?XCT(<<"td">>, <<"Outgoing s2s Servers:">>), - ?XC(<<"td">>, (pretty_string_int(S2SServers)))])])])]; + [?XCT(<<"td">>, <<"Incoming s2s Connections:">>), + ?XC(<<"td">>, (pretty_string_int(InS2SNumber)))])])])]; get_stats(Host, Lang) -> OnlineUsers = length(ejabberd_sm:get_vh_session_list(Host)), From 92b9fb30e0d0440a30301a2fab0a08854faf4005 Mon Sep 17 00:00:00 2001 From: colm Date: Wed, 21 Oct 2015 23:22:53 +0100 Subject: [PATCH 314/695] Don't send full JID in 'from' of Roster Push (RFC 6121 section 2.1.6). This is a patch by @badlop in the comments of github issue #367 --- src/mod_shared_roster.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 96cda6e3cca..9020e5d3e26 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -1025,7 +1025,7 @@ push_item(User, Server, Item) -> children = [item_to_xml(Item)]}]}), lists:foreach(fun (Resource) -> JID = jlib:make_jid(User, Server, Resource), - ejabberd_router:route(JID, JID, Stanza) + ejabberd_router:route(jlib:jid_remove_resource(JID), JID, Stanza) end, ejabberd_sm:get_user_resources(User, Server)). From efdf5636beae6ee0a8490ac939ed198624f43cd8 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 22 Oct 2015 14:00:17 +0200 Subject: [PATCH 315/695] Add simple metrics module for use with grapherl --- src/mod_metrics.erl | 125 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 src/mod_metrics.erl diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl new file mode 100644 index 00000000000..c3a57c9ea6b --- /dev/null +++ b/src/mod_metrics.erl @@ -0,0 +1,125 @@ +%%%------------------------------------------------------------------- +%%% File : mod_metrics.erl +%%% Author : Christophe Romain +%%% Purpose : Simple metrics handler for runtime statistics +%%% Created : 22 Oct 2015 by Christophe Romain +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%------------------------------------------------------------------- + +-module(mod_metrics). + +-behaviour(ejabberd_config). +-author('christophe.romain@process-one.net'). +-behaviour(gen_mod). + +-include("ejabberd.hrl"). +-include("logger.hrl"). +-include("jlib.hrl"). + +-define(HOOKS, [offline_message_hook, + sm_register_connection_hook, sm_remove_connection_hook, + user_send_packet, user_receive_packet, + s2s_send_packet, s2s_receive_packet, + remove_user, register_user]). + +-export([start/2, stop/1, send_metrics/4]). + +-export([offline_message_hook/3, + sm_register_connection_hook/3, sm_remove_connection_hook/3, + user_send_packet/4, user_receive_packet/5, + s2s_send_packet/3, s2s_receive_packet/3, + remove_user/2, register_user/2]). + +%%==================================================================== +%% API +%%==================================================================== + +start(Host, _Opts) -> + [ejabberd_hooks:add(Hook, Host, ?MODULE, Hook, 20) + || Hook <- ?HOOKS]. + +stop(Host) -> + [ejabberd_hooks:delete(Hook, Host, ?MODULE, Hook, 20) + || Hook <- ?HOOKS]. + +%%==================================================================== +%% Hooks handlers +%%==================================================================== + +offline_message_hook(_From, #jid{lserver=LServer}, _Packet) -> + push(LServer, offline_message). + +sm_register_connection_hook(_SID, #jid{lserver=LServer}, _Info) -> + push(LServer, sm_register_connection). +sm_remove_connection_hook(_SID, #jid{lserver=LServer}, _Info) -> + push(LServer, sm_remove_connection). + +user_send_packet(Packet, _C2SState, #jid{lserver=LServer}, _To) -> + push(LServer, user_send_packet), + Packet. +user_receive_packet(Packet, _C2SState, _JID, _From, #jid{lserver=LServer}) -> + push(LServer, user_receive_packet), + Packet. + +s2s_send_packet(#jid{lserver=LServer}, _To, _Packet) -> + push(LServer, s2s_send_packet). +s2s_receive_packet(_From, #jid{lserver=LServer}, _Packet) -> + push(LServer, s2s_receive_packet). + +remove_user(_User, Server) -> + push(jlib:nameprep(Server), remove_user). +register_user(_User, Server) -> + push(jlib:nameprep(Server), register_user). + +%%==================================================================== +%% metrics push handler +%%==================================================================== + +push(Host, Probe) -> + spawn(?MODULE, send_metrics, [Host, Probe, {127,0,0,1}, 11111]). + +send_metrics(Host, Probe, Peer, Port) -> + % our default metrics handler is https://github.com/processone/grapherl + % grapherl metrics are named first with service domain, then nodename + % and name of the data itself, followed by type timestamp and value + % example => process-one.net/xmpp-1.user_receive_packet:c/1441784958:1 + [_, NodeId] = str:tokens(jlib:atom_to_binary(node()), <<"@">>), + [Node | _] = str:tokens(NodeId, <<".">>), + BaseId = <>, + DateTime = erlang:universaltime(), + UnixTime = calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200, + TS = integer_to_binary(UnixTime), + case gen_udp:open(0) of + {ok, Socket} -> + case Probe of + {Key, Val} -> + BVal = integer_to_binary(Val), + Data = <>, + gen_udp:send(Socket, Peer, Port, Data); + Key -> + Data = <>, + gen_udp:send(Socket, Peer, Port, Data) + end, + gen_udp:close(Socket); + Error -> + ?WARNING_MSG("can not open udp socket to grapherl: ~p", [Error]) + end. From d048d1e619173b6e7fb827110fa7dad219901acb Mon Sep 17 00:00:00 2001 From: colm Date: Thu, 22 Oct 2015 13:48:40 +0100 Subject: [PATCH 316/695] mod_ping: allowed the ping ack timeout (the length of time taken to deem that a ping has not being responded to) configurable. it still defaults to 32 seconds as per the constant IQ_TIMEOUT (in ejabberd_local.erl) this just makes it optionally configurable (in my case I needed to be more trigger happy than 32 seconds) --- src/mod_ping.erl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/mod_ping.erl b/src/mod_ping.erl index b4e1041d552..9964daf0374 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -63,6 +63,7 @@ {host = <<"">>, send_pings = ?DEFAULT_SEND_PINGS :: boolean(), ping_interval = ?DEFAULT_PING_INTERVAL :: non_neg_integer(), + ping_ack_timeout = undefined :: non_neg_integer(), timeout_action = none :: none | kill, timers = (?DICT):new() :: ?TDICT}). @@ -106,6 +107,9 @@ init([Host, Opts]) -> PingInterval = gen_mod:get_opt(ping_interval, Opts, fun(I) when is_integer(I), I>0 -> I end, ?DEFAULT_PING_INTERVAL), + PingAckTimeout = gen_mod:get_opt(ping_ack_timeout, Opts, + fun(I) when is_integer(I), I>0 -> I * 1000 end, + undefined), TimeoutAction = gen_mod:get_opt(timeout_action, Opts, fun(none) -> none; (kill) -> kill @@ -131,6 +135,7 @@ init([Host, Opts]) -> #state{host = Host, send_pings = SendPings, ping_interval = PingInterval, timeout_action = TimeoutAction, + ping_ack_timeout = PingAckTimeout, timers = (?DICT):new()}}. terminate(_Reason, #state{host = Host}) -> @@ -187,7 +192,7 @@ handle_info({timeout, _TRef, {ping, JID}}, State) -> gen_server:cast(Pid, {iq_pong, JID, Response}) end, From = jlib:make_jid(<<"">>, State#state.host, <<"">>), - ejabberd_local:route_iq(From, JID, IQ, F), + ejabberd_local:route_iq(From, JID, IQ, F, State#state.ping_ack_timeout), Timers = add_timer(JID, State#state.ping_interval, State#state.timers), {noreply, State#state{timers = Timers}}; From 2a115a83d2b744632602ba378304384889b38afe Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 23 Oct 2015 17:21:19 +0200 Subject: [PATCH 317/695] Let modules_update_specs report failures (#756) --- src/ext_mod.erl | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 765d38b4f6b..ccc847eebdf 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -36,6 +36,7 @@ config_dir/0, opt_type/1]). -include("ejabberd_commands.hrl"). +-include("logger.hrl"). -define(REPOS, "https://github.com/processone/ejabberd-contrib"). @@ -111,10 +112,19 @@ commands() -> update() -> add_sources(?REPOS), - lists:foreach(fun({Package, Spec}) -> + Res = lists:foldl(fun({Package, Spec}, Acc) -> Path = proplists:get_value(url, Spec, ""), - add_sources(Package, Path) - end, modules_spec(sources_dir(), "*")). + Update = add_sources(Package, Path), + ?INFO_MSG("Update package ~s: ~p", [Package, Update]), + case Update of + ok -> Acc; + Error -> [Error|Acc] + end + end, [], modules_spec(sources_dir(), "*")), + case Res of + [] -> ok; + [Error|_] -> Error + end. available() -> Jungle = modules_spec(sources_dir(), "*/*"), From b2eb9f197afeceb6bde48a2d1f0d5b9408703957 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 23 Oct 2015 18:41:35 +0300 Subject: [PATCH 318/695] Don't crash on certificates without extensions (EJAB-1724) --- src/ejabberd_s2s.erl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 9923eb121f5..40179fe7dd4 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -620,10 +620,15 @@ get_s2s_state(S2sPid) -> [{s2s_pid, S2sPid} | Infos]. get_cert_domains(Cert) -> - {rdnSequence, Subject} = - (Cert#'Certificate'.tbsCertificate)#'TBSCertificate'.subject, - Extensions = - (Cert#'Certificate'.tbsCertificate)#'TBSCertificate'.extensions, + TBSCert = Cert#'Certificate'.tbsCertificate, + Subject = case TBSCert#'TBSCertificate'.subject of + {rdnSequence, Subj} -> lists:flatten(Subj); + _ -> [] + end, + Extensions = case TBSCert#'TBSCertificate'.extensions of + Exts when is_list(Exts) -> Exts; + _ -> [] + end, lists:flatmap(fun (#'AttributeTypeAndValue'{type = ?'id-at-commonName', value = Val}) -> @@ -646,7 +651,7 @@ get_cert_domains(Cert) -> end; (_) -> [] end, - lists:flatten(Subject)) + Subject) ++ lists:flatmap(fun (#'Extension'{extnID = ?'id-ce-subjectAltName', From 137a4ee0877e111c9d7c0bfcaff510a6d5ff81f1 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 26 Oct 2015 14:10:55 +0300 Subject: [PATCH 319/695] Add HTTP File Upload support (XEP-0363) --- include/ns.hrl | 3 + src/mod_http_upload.erl | 949 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 952 insertions(+) create mode 100644 src/mod_http_upload.erl diff --git a/include/ns.hrl b/include/ns.hrl index eb4223d9d3d..644874f2d0d 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -152,4 +152,7 @@ -define(NS_CLIENT_STATE, <<"urn:xmpp:csi:0">>). -define(NS_STREAM_MGMT_2, <<"urn:xmpp:sm:2">>). -define(NS_STREAM_MGMT_3, <<"urn:xmpp:sm:3">>). +-define(NS_HTTP_UPLOAD, <<"urn:xmpp:http:upload">>). +-define(NS_HTTP_UPLOAD_OLD, <<"eu:siacs:conversations:http:upload">>). +-define(NS_THUMBS_1, <<"urn:xmpp:thumbs:1">>). -define(NS_NICK, <<"http://jabber.org/protocol/nick">>). diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl new file mode 100644 index 00000000000..a720e528adf --- /dev/null +++ b/src/mod_http_upload.erl @@ -0,0 +1,949 @@ +%%%------------------------------------------------------------------- +%%% File : mod_http_upload.erl +%%% Author : Holger Weiss +%%% Purpose : HTTP File Upload (XEP-0363) +%%% Created : 20 Aug 2015 by Holger Weiss +%%%------------------------------------------------------------------- + +-module(mod_http_upload). +-author('holger@zedat.fu-berlin.de'). + +-define(GEN_SERVER, gen_server). +-define(SERVICE_REQUEST_TIMEOUT, 5000). % 5 seconds. +-define(SLOT_TIMEOUT, 18000000). % 5 hours. +-define(PROCNAME, ?MODULE). +-define(FORMAT(Error), file:format_error(Error)). +-define(URL_ENC(URL), binary_to_list(ejabberd_http:url_encode(URL))). +-define(ADDR_TO_STR(IP), ejabberd_config:may_hide_data(jlib:ip_to_list(IP))). +-define(STR_TO_INT(Str, B), jlib:binary_to_integer(iolist_to_binary(Str), B)). +-define(DEFAULT_CONTENT_TYPE, <<"application/octet-stream">>). +-define(CONTENT_TYPES, + [{<<".avi">>, <<"video/avi">>}, + {<<".bmp">>, <<"image/bmp">>}, + {<<".bz2">>, <<"application/x-bzip2">>}, + {<<".gif">>, <<"image/gif">>}, + {<<".gz">>, <<"application/x-gzip">>}, + {<<".html">>, <<"text/html">>}, + {<<".jpeg">>, <<"image/jpeg">>}, + {<<".jpg">>, <<"image/jpeg">>}, + {<<".mp3">>, <<"audio/mpeg">>}, + {<<".mp4">>, <<"video/mp4">>}, + {<<".mpeg">>, <<"video/mpeg">>}, + {<<".mpg">>, <<"video/mpeg">>}, + {<<".ogg">>, <<"application/ogg">>}, + {<<".pdf">>, <<"application/pdf">>}, + {<<".png">>, <<"image/png">>}, + {<<".rtf">>, <<"application/rtf">>}, + {<<".svg">>, <<"image/svg+xml">>}, + {<<".tiff">>, <<"image/tiff">>}, + {<<".txt">>, <<"text/plain">>}, + {<<".wav">>, <<"audio/wav">>}, + {<<".webp">>, <<"image/webp">>}, + {<<".xz">>, <<"application/x-xz">>}, + {<<".zip">>, <<"application/zip">>}]). + +-behaviour(?GEN_SERVER). +-behaviour(gen_mod). + +%% gen_mod/supervisor callbacks. +-export([start_link/3, + start/2, + stop/1, + mod_opt_type/1]). + +%% gen_server callbacks. +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). + +%% ejabberd_http callback. +-export([process/2]). + +%% ejabberd_hooks callback. +-export([remove_user/2]). + +%% Utility functions. +-export([get_proc_name/2, + expand_home/1]). + +-include("ejabberd.hrl"). +-include("ejabberd_http.hrl"). +-include("jlib.hrl"). +-include("logger.hrl"). + +-record(state, + {server_host :: binary(), + host :: binary(), + name :: binary(), + access :: atom(), + max_size :: pos_integer() | infinity, + secret_length :: pos_integer(), + jid_in_url :: sha1 | node, + file_mode :: integer() | undefined, + dir_mode :: integer() | undefined, + docroot :: binary(), + put_url :: binary(), + get_url :: binary(), + service_url :: binary() | undefined, + thumbnail :: boolean(), + slots = dict:new() :: term()}). % dict:dict() requires Erlang 17. + +-record(media_info, + {type :: string(), + height :: integer(), + weight :: integer()}). + +-type state() :: #state{}. +-type slot() :: [binary()]. +-type media_info() :: #media_info{}. + +%%-------------------------------------------------------------------- +%% gen_mod/supervisor callbacks. +%%-------------------------------------------------------------------- + +-spec start_link(binary(), atom(), gen_mod:opts()) + -> {ok, pid()} | ignore | {error, _}. + +start_link(ServerHost, Proc, Opts) -> + ?GEN_SERVER:start_link({local, Proc}, ?MODULE, {ServerHost, Opts}, []). + +-spec start(binary(), gen_mod:opts()) -> {ok, _} | {ok, _, _} | {error, _}. + +start(ServerHost, Opts) -> + case gen_mod:get_opt(rm_on_unregister, Opts, + fun(B) when is_boolean(B) -> B end, + true) of + true -> + ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, + remove_user, 50), + ejabberd_hooks:add(anonymous_purge_hook, ServerHost, ?MODULE, + remove_user, 50); + false -> ok + end, + Proc = get_proc_name(ServerHost, ?PROCNAME), + Spec = {Proc, + {?MODULE, start_link, [ServerHost, Proc, Opts]}, + permanent, + 3000, + worker, + [?MODULE]}, + supervisor:start_child(ejabberd_sup, Spec). + +-spec stop(binary()) -> ok. + +stop(ServerHost) -> + case gen_mod:get_module_opt(ServerHost, ?MODULE, rm_on_unregister, + fun(B) when is_boolean(B) -> B end, + true) of + true -> + ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, + remove_user, 50), + ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, ?MODULE, + remove_user, 50); + false -> ok + end, + Proc = get_proc_name(ServerHost, ?PROCNAME), + ok = supervisor:terminate_child(ejabberd_sup, Proc), + ok = supervisor:delete_child(ejabberd_sup, Proc). + +-spec mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()]. + +mod_opt_type(host) -> + fun iolist_to_binary/1; +mod_opt_type(name) -> + fun iolist_to_binary/1; +mod_opt_type(access) -> + fun(A) when is_atom(A) -> A end; +mod_opt_type(max_size) -> + fun(I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end; +mod_opt_type(secret_length) -> + fun(I) when is_integer(I), I >= 8 -> I end; +mod_opt_type(jid_in_url) -> + fun(sha1) -> sha1; + (node) -> node + end; +mod_opt_type(file_mode) -> + fun(Mode) -> ?STR_TO_INT(Mode, 8) end; +mod_opt_type(dir_mode) -> + fun(Mode) -> ?STR_TO_INT(Mode, 8) end; +mod_opt_type(docroot) -> + fun iolist_to_binary/1; +mod_opt_type(put_url) -> + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL + end; +mod_opt_type(get_url) -> + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL + end; +mod_opt_type(service_url) -> + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL + end; +mod_opt_type(custom_headers) -> + fun(Headers) -> + lists:map(fun({K, V}) -> + {iolist_to_binary(K), iolist_to_binary(V)} + end, Headers) + end; +mod_opt_type(rm_on_unregister) -> + fun(B) when is_boolean(B) -> B end; +mod_opt_type(thumbnail) -> + fun(B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [host, name, access, max_size, secret_length, jid_in_url, file_mode, + dir_mode, docroot, put_url, get_url, service_url, custom_headers, + rm_on_unregister, thumbnail]. + +%%-------------------------------------------------------------------- +%% gen_server callbacks. +%%-------------------------------------------------------------------- + +-spec init({binary(), gen_mod:opts()}) -> {ok, state()}. + +init({ServerHost, Opts}) -> + process_flag(trap_exit, true), + Host = gen_mod:get_opt_host(ServerHost, Opts, <<"upload.@HOST@">>), + Name = gen_mod:get_opt(name, Opts, + fun iolist_to_binary/1, + <<"HTTP File Upload">>), + Access = gen_mod:get_opt(access, Opts, + fun(A) when is_atom(A) -> A end, + local), + MaxSize = gen_mod:get_opt(max_size, Opts, + fun(I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end, + 104857600), + SecretLength = gen_mod:get_opt(secret_length, Opts, + fun(I) when is_integer(I), I >= 8 -> I end, + 40), + JIDinURL = gen_mod:get_opt(jid_in_url, Opts, + fun(sha1) -> sha1; + (node) -> node + end, + sha1), + DocRoot = gen_mod:get_opt(docroot, Opts, + fun iolist_to_binary/1, + <<"@HOME@/upload">>), + FileMode = gen_mod:get_opt(file_mode, Opts, + fun(Mode) -> ?STR_TO_INT(Mode, 8) end), + DirMode = gen_mod:get_opt(dir_mode, Opts, + fun(Mode) -> ?STR_TO_INT(Mode, 8) end), + PutURL = gen_mod:get_opt(put_url, Opts, + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL + end, + <<"http://@HOST@:5444">>), + GetURL = gen_mod:get_opt(get_url, Opts, + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL + end, + PutURL), + ServiceURL = gen_mod:get_opt(service_url, Opts, + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL + end), + Thumbnail = gen_mod:get_opt(thumbnail, Opts, + fun(B) when is_boolean(B) -> B end, + true), + case ServiceURL of + undefined -> + ok; + <<"http://", _/binary>> -> + application:start(inets); + <<"https://", _/binary>> -> + application:start(inets), + application:start(crypto), + application:start(asn1), + application:start(public_key), + application:start(ssl) + end, + case DirMode of + undefined -> + ok; + Mode -> + file:change_mode(DocRoot, Mode) + end, + ejabberd_router:register_route(Host), + {ok, #state{server_host = ServerHost, host = Host, name = Name, + access = Access, max_size = MaxSize, + secret_length = SecretLength, jid_in_url = JIDinURL, + file_mode = FileMode, dir_mode = DirMode, + thumbnail = Thumbnail, + docroot = expand_home(str:strip(DocRoot, right, $/)), + put_url = expand_host(str:strip(PutURL, right, $/), ServerHost), + get_url = expand_host(str:strip(GetURL, right, $/), ServerHost), + service_url = ServiceURL}}. + +-spec handle_call(_, {pid(), _}, state()) + -> {reply, {ok, pos_integer(), binary(), + pos_integer() | undefined, + pos_integer() | undefined}, state()} | + {reply, {error, binary()}, state()} | {noreply, state()}. + +handle_call({use_slot, Slot}, _From, #state{file_mode = FileMode, + dir_mode = DirMode, + get_url = GetPrefix, + thumbnail = Thumbnail, + docroot = DocRoot} = State) -> + case get_slot(Slot, State) of + {ok, {Size, Timer}} -> + timer:cancel(Timer), + NewState = del_slot(Slot, State), + Path = str:join([DocRoot | Slot], <<$/>>), + {reply, {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail}, + NewState}; + error -> + {reply, {error, <<"Invalid slot">>}, State} + end; +handle_call(get_docroot, _From, #state{docroot = DocRoot} = State) -> + {reply, {ok, DocRoot}, State}; +handle_call(Request, From, State) -> + ?ERROR_MSG("Got unexpected request from ~p: ~p", [From, Request]), + {noreply, State}. + +-spec handle_cast(_, state()) -> {noreply, state()}. + +handle_cast(Request, State) -> + ?ERROR_MSG("Got unexpected request: ~p", [Request]), + {noreply, State}. + +-spec handle_info(timeout | _, state()) -> {noreply, state()}. + +handle_info({route, From, To, #xmlel{name = <<"iq">>} = Stanza}, State) -> + Request = jlib:iq_query_info(Stanza), + {Reply, NewState} = case process_iq(From, Request, State) of + R when is_record(R, iq) -> + {R, State}; + {R, S} -> + {R, S}; + not_request -> + {none, State} + end, + if Reply /= none -> + ejabberd_router:route(To, From, jlib:iq_to_xml(Reply)); + true -> + ok + end, + {noreply, NewState}; +handle_info({slot_timed_out, Slot}, State) -> + NewState = del_slot(Slot, State), + {noreply, NewState}; +handle_info(Info, State) -> + ?ERROR_MSG("Got unexpected info: ~p", [Info]), + {noreply, State}. + +-spec terminate(normal | shutdown | {shutdown, _} | _, _) -> ok. + +terminate(Reason, #state{server_host = ServerHost, host = Host}) -> + ?DEBUG("Stopping HTTP upload process for ~s: ~p", [ServerHost, Reason]), + ejabberd_router:unregister_route(Host), + ok. + +-spec code_change({down, _} | _, state(), _) -> {ok, state()}. + +code_change(_OldVsn, #state{server_host = ServerHost} = State, _Extra) -> + ?DEBUG("Updating HTTP upload process for ~s", [ServerHost]), + {ok, State}. + +%%-------------------------------------------------------------------- +%% ejabberd_http callback. +%%-------------------------------------------------------------------- + +-spec process([binary()], #request{}) + -> {pos_integer(), [{binary(), binary()}], binary()}. + +process(LocalPath, #request{method = 'PUT', host = Host, ip = IP, + data = Data}) -> + Proc = gen_mod:get_module_proc(Host, ?PROCNAME), + case catch gen_server:call(Proc, {use_slot, LocalPath}) of + {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail} + when byte_size(Data) == Size -> + ?DEBUG("Storing file from ~s for ~s: ~s", + [?ADDR_TO_STR(IP), Host, Path]), + case store_file(Path, Data, FileMode, DirMode, + GetPrefix, LocalPath, Thumbnail) of + ok -> + http_response(Host, 201); + {ok, Headers, OutData} -> + http_response(Host, 201, Headers, OutData); + {error, Error} -> + ?ERROR_MSG("Cannot store file ~s from ~s for ~s: ~p", + [Path, ?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 500) + end; + {ok, Size, Path} -> + ?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B", + [Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]), + http_response(Host, 413); + {error, Error} -> + ?INFO_MSG("Rejecting file from ~s for ~s: ~p", + [?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 403); + Error -> + ?ERROR_MSG("Cannot handle PUT request from ~s for ~s: ~p", + [?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 500) + end; +process(LocalPath, #request{method = Method, host = Host, ip = IP}) + when Method == 'GET'; + Method == 'HEAD' -> + Proc = gen_mod:get_module_proc(Host, ?PROCNAME), + case catch gen_server:call(Proc, get_docroot) of + {ok, DocRoot} -> + Path = str:join([DocRoot | LocalPath], <<$/>>), + case file:read_file(Path) of + {ok, Data} -> + ?INFO_MSG("Serving ~s to ~s", [Path, ?ADDR_TO_STR(IP)]), + FileName = lists:last(LocalPath), + ContentType = guess_content_type(FileName), + Headers1 = case ContentType of + <<"image/", _SubType/binary>> -> []; + <<"text/", _SubType/binary>> -> []; + _ -> + [{<<"Content-Disposition">>, + <<"attachment; filename=", + $", FileName/binary, $">>}] + end, + Headers2 = [{<<"Content-Type">>, ContentType} | Headers1], + http_response(Host, 200, Headers2, Data); + {error, eacces} -> + ?INFO_MSG("Cannot serve ~s to ~s: Permission denied", + [Path, ?ADDR_TO_STR(IP)]), + http_response(Host, 403); + {error, enoent} -> + ?INFO_MSG("Cannot serve ~s to ~s: No such file or directory", + [Path, ?ADDR_TO_STR(IP)]), + http_response(Host, 404); + {error, eisdir} -> + ?INFO_MSG("Cannot serve ~s to ~s: Is a directory", + [Path, ?ADDR_TO_STR(IP)]), + http_response(Host, 404); + {error, Error} -> + ?INFO_MSG("Cannot serve ~s to ~s: ~s", + [Path, ?ADDR_TO_STR(IP), ?FORMAT(Error)]), + http_response(Host, 500) + end; + Error -> + ?ERROR_MSG("Cannot handle ~s request from ~s for ~s: ~p", + [Method, ?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 500) + end; +process(_LocalPath, #request{method = 'OPTIONS', host = Host, ip = IP}) -> + ?DEBUG("Responding to OPTIONS request from ~s for ~s", + [?ADDR_TO_STR(IP), Host]), + http_response(Host, 200); +process(_LocalPath, #request{method = Method, host = Host, ip = IP}) -> + ?DEBUG("Rejecting ~s request from ~s for ~s", + [Method, ?ADDR_TO_STR(IP), Host]), + http_response(Host, 405, [{<<"Allow">>, <<"OPTIONS, HEAD, GET, PUT">>}]). + +%%-------------------------------------------------------------------- +%% Exported utility functions. +%%-------------------------------------------------------------------- + +-spec get_proc_name(binary(), atom()) -> atom(). + +get_proc_name(ServerHost, ModuleName) -> + PutURL = gen_mod:get_module_opt(ServerHost, ?MODULE, put_url, + fun(<<"http://", _/binary>> = URL) -> URL; + (<<"https://", _/binary>> = URL) -> URL; + (_) -> <<"http://@HOST@">> + end, + <<"http://@HOST@">>), + [_, ProcHost | _] = binary:split(expand_host(PutURL, ServerHost), + [<<"http://">>, <<"https://">>, + <<":">>, <<"/">>], [global]), + gen_mod:get_module_proc(ProcHost, ModuleName). + +-spec expand_home(binary()) -> binary(). + +expand_home(Subject) -> + {ok, [[Home]]} = init:get_argument(home), + Parts = binary:split(Subject, <<"@HOME@">>, [global]), + str:join(Parts, list_to_binary(Home)). + +%%-------------------------------------------------------------------- +%% Internal functions. +%%-------------------------------------------------------------------- + +%% XMPP request handling. + +-spec process_iq(jid(), iq_request() | reply | invalid, state()) + -> {iq_reply(), state()} | iq_reply() | not_request. + +process_iq(_From, + #iq{type = get, xmlns = ?NS_DISCO_INFO, lang = Lang} = IQ, + #state{server_host = ServerHost, name = Name}) -> + AddInfo = 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) ++ AddInfo}]}; +process_iq(From, + #iq{type = get, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ, + #state{server_host = ServerHost, access = Access} = State) + when XMLNS == ?NS_HTTP_UPLOAD; + XMLNS == ?NS_HTTP_UPLOAD_OLD -> + case acl:match_rule(ServerHost, Access, From) of + allow -> + case parse_request(SubEl, Lang) of + {ok, File, Size, ContentType} -> + case create_slot(State, From, File, Size, ContentType, Lang) of + {ok, Slot} -> + {ok, Timer} = timer:send_after(?SLOT_TIMEOUT, + {slot_timed_out, Slot}), + NewState = add_slot(Slot, Size, Timer, State), + SlotEl = slot_el(Slot, State, XMLNS), + {IQ#iq{type = result, sub_el = [SlotEl]}, NewState}; + {ok, PutURL, GetURL} -> + SlotEl = slot_el(PutURL, GetURL, XMLNS), + IQ#iq{type = result, sub_el = [SlotEl]}; + {error, Error} -> + IQ#iq{type = error, sub_el = [SubEl, Error]} + end; + {error, Error} -> + ?DEBUG("Cannot parse request from ~s", + [jlib:jid_to_string(From)]), + IQ#iq{type = error, sub_el = [SubEl, Error]} + end; + deny -> + ?DEBUG("Denying HTTP upload slot request from ~s", + [jlib:jid_to_string(From)]), + IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + end; +process_iq(_From, #iq{sub_el = SubEl} = IQ, _State) -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; +process_iq(_From, reply, _State) -> + not_request; +process_iq(_From, invalid, _State) -> + not_request. + +-spec parse_request(xmlel(), binary()) + -> {ok, binary(), pos_integer(), binary()} | {error, xmlel()}. + +parse_request(#xmlel{name = <<"request">>, attrs = Attrs} = Request, Lang) -> + case xml:get_attr(<<"xmlns">>, Attrs) of + {value, XMLNS} when XMLNS == ?NS_HTTP_UPLOAD; + XMLNS == ?NS_HTTP_UPLOAD_OLD -> + case {xml:get_subtag_cdata(Request, <<"filename">>), + xml:get_subtag_cdata(Request, <<"size">>), + xml:get_subtag_cdata(Request, <<"content-type">>)} of + {File, SizeStr, ContentType} when byte_size(File) > 0 -> + case catch jlib:binary_to_integer(SizeStr) of + Size when is_integer(Size), Size > 0 -> + {ok, File, Size, yield_content_type(ContentType)}; + _ -> + Text = <<"Please specify file size.">>, + {error, ?ERRT_BAD_REQUEST(Lang, Text)} + end; + _ -> + Text = <<"Please specify file name.">>, + {error, ?ERRT_BAD_REQUEST(Lang, Text)} + end; + _ -> + {error, ?ERR_BAD_REQUEST} + end; +parse_request(_El, _Lang) -> {error, ?ERR_BAD_REQUEST}. + +-spec create_slot(state(), jid(), binary(), pos_integer(), binary(), binary()) + -> {ok, slot()} | {ok, binary(), binary()} | {error, xmlel()}. + +create_slot(#state{service_url = undefined, max_size = MaxSize}, + JID, File, Size, _ContentType, Lang) when MaxSize /= infinity, + Size > MaxSize -> + Text = <<"File larger than ", (jlib:integer_to_binary(MaxSize))/binary, + " Bytes.">>, + ?INFO_MSG("Rejecting file ~s from ~s (too large: ~B bytes)", + [File, jlib:jid_to_string(JID), Size]), + {error, ?ERRT_NOT_ACCEPTABLE(Lang, Text)}; +create_slot(#state{service_url = undefined, + jid_in_url = JIDinURL, + secret_length = SecretLength, + server_host = ServerHost, + docroot = DocRoot}, + JID, File, Size, _ContentType, Lang) -> + UserStr = make_user_string(JID, JIDinURL), + UserDir = <>, + case ejabberd_hooks:run_fold(http_upload_slot_request, ServerHost, allow, + [JID, UserDir, Size, Lang]) of + allow -> + RandStr = make_rand_string(SecretLength), + FileStr = make_file_string(File), + ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", + [jlib:jid_to_string(JID), File]), + {ok, [UserStr, RandStr, FileStr]}; + deny -> + {error, ?ERR_SERVICE_UNAVAILABLE}; + #xmlel{} = Error -> + {error, Error} + end; +create_slot(#state{service_url = ServiceURL}, + #jid{luser = U, lserver = S} = JID, File, Size, ContentType, + _Lang) -> + Options = [{body_format, binary}, {full_result, false}], + HttpOptions = [{timeout, ?SERVICE_REQUEST_TIMEOUT}], + SizeStr = jlib:integer_to_binary(Size), + GetRequest = binary_to_list(ServiceURL) ++ + "?jid=" ++ ?URL_ENC(jlib:jid_to_string({U, S, <<"">>})) ++ + "&name=" ++ ?URL_ENC(File) ++ + "&size=" ++ ?URL_ENC(SizeStr) ++ + "&content_type=" ++ ?URL_ENC(ContentType), + case httpc:request(get, {GetRequest, []}, HttpOptions, Options) of + {ok, {Code, Body}} when Code >= 200, Code =< 299 -> + case binary:split(Body, <<$\n>>, [global, trim]) of + [<<"http", _/binary>> = PutURL, <<"http", _/binary>> = GetURL] -> + ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", + [jlib:jid_to_string(JID), File]), + {ok, PutURL, GetURL}; + Lines -> + ?ERROR_MSG("Cannot parse data received for ~s from <~s>: ~p", + [jlib:jid_to_string(JID), ServiceURL, Lines]), + {error, ?ERR_SERVICE_UNAVAILABLE} + end; + {ok, {402, _Body}} -> + ?INFO_MSG("Got status code 402 for ~s from <~s>", + [jlib:jid_to_string(JID), ServiceURL]), + {error, ?ERR_RESOURCE_CONSTRAINT}; + {ok, {403, _Body}} -> + ?INFO_MSG("Got status code 403 for ~s from <~s>", + [jlib:jid_to_string(JID), ServiceURL]), + {error, ?ERR_NOT_ALLOWED}; + {ok, {413, _Body}} -> + ?INFO_MSG("Got status code 413 for ~s from <~s>", + [jlib:jid_to_string(JID), ServiceURL]), + {error, ?ERR_NOT_ACCEPTABLE}; + {ok, {Code, _Body}} -> + ?ERROR_MSG("Got unexpected status code for ~s from <~s>: ~B", + [jlib:jid_to_string(JID), ServiceURL, Code]), + {error, ?ERR_SERVICE_UNAVAILABLE}; + {error, Reason} -> + ?ERROR_MSG("Error requesting upload slot for ~s from <~s>: ~p", + [jlib:jid_to_string(JID), ServiceURL, Reason]), + {error, ?ERR_SERVICE_UNAVAILABLE} + end. + +-spec add_slot(slot(), pos_integer(), timer:tref(), state()) -> state(). + +add_slot(Slot, Size, Timer, #state{slots = Slots} = State) -> + NewSlots = dict:store(Slot, {Size, Timer}, Slots), + State#state{slots = NewSlots}. + +-spec get_slot(slot(), state()) -> {ok, {pos_integer(), timer:tref()}} | error. + +get_slot(Slot, #state{slots = Slots}) -> + dict:find(Slot, Slots). + +-spec del_slot(slot(), state()) -> state(). + +del_slot(Slot, #state{slots = Slots} = State) -> + NewSlots = dict:erase(Slot, Slots), + State#state{slots = NewSlots}. + +-spec slot_el(slot() | binary(), state() | binary(), binary()) -> xmlel(). + +slot_el(Slot, #state{put_url = PutPrefix, get_url = GetPrefix}, XMLNS) -> + PutURL = str:join([PutPrefix | Slot], <<$/>>), + GetURL = str:join([GetPrefix | Slot], <<$/>>), + slot_el(PutURL, GetURL, XMLNS); +slot_el(PutURL, GetURL, XMLNS) -> + #xmlel{name = <<"slot">>, + attrs = [{<<"xmlns">>, XMLNS}], + children = [#xmlel{name = <<"put">>, + children = [{xmlcdata, PutURL}]}, + #xmlel{name = <<"get">>, + children = [{xmlcdata, GetURL}]}]}. + +-spec make_user_string(jid(), sha1 | node) -> binary(). + +make_user_string(#jid{luser = U, lserver = S}, sha1) -> + p1_sha:sha(<>); +make_user_string(#jid{luser = U}, node) -> + re:replace(U, <<"[^a-zA-Z0-9_.-]">>, <<$_>>, [global, {return, binary}]). + +-spec make_file_string(binary()) -> binary(). + +make_file_string(File) -> + re:replace(File, <<"[^a-zA-Z0-9_.-]">>, <<$_>>, [global, {return, binary}]). + +-spec make_rand_string(non_neg_integer()) -> binary(). + +make_rand_string(Length) -> + list_to_binary(make_rand_string([], Length)). + +-spec make_rand_string(string(), non_neg_integer()) -> string(). + +make_rand_string(S, 0) -> S; +make_rand_string(S, N) -> make_rand_string([make_rand_char() | S], N - 1). + +-spec make_rand_char() -> char(). + +make_rand_char() -> + map_int_to_char(crypto:rand_uniform(0, 62)). + +-spec map_int_to_char(0..61) -> char(). + +map_int_to_char(N) when N =< 9 -> N + 48; % Digit. +map_int_to_char(N) when N =< 35 -> N + 55; % Upper-case character. +map_int_to_char(N) when N =< 61 -> N + 61. % Lower-case character. + +-spec expand_host(binary(), binary()) -> binary(). + +expand_host(Subject, Host) -> + Parts = binary:split(Subject, <<"@HOST@">>, [global]), + str:join(Parts, Host). + +-spec yield_content_type(binary()) -> binary(). + +yield_content_type(<<"">>) -> ?DEFAULT_CONTENT_TYPE; +yield_content_type(Type) -> Type. + +-spec iq_disco_info(binary(), binary()) -> [xmlel()]. + +iq_disco_info(Lang, Name) -> + [#xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"store">>}, + {<<"type">>, <<"file">>}, + {<<"name">>, translate:translate(Lang, Name)}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_HTTP_UPLOAD}]}, + #xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_HTTP_UPLOAD_OLD}]}]. + +%% HTTP request handling. + +store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> + case do_store_file(Path, Data, FileMode, DirMode) of + ok when Thumbnail -> + case identify(Path) of + {ok, MediaInfo} -> + case convert(Path, MediaInfo) of + pass -> + ok; + {ok, OutPath} -> + [UserDir, RandDir|_] = LocalPath, + FileName = filename:basename(OutPath), + URL = str:join([GetPrefix, UserDir, + RandDir, FileName], <<$/>>), + ThumbEl = thumb_el(OutPath, URL), + {ok, + [{<<"Content-Type">>, + <<"text/xml; charset=utf-8">>}], + xml:element_to_binary(ThumbEl)} + end; + {error, _} -> + ok + end; + ok -> + ok; + Err -> + Err + end. + +-spec do_store_file(file:filename_all(), binary(), integer(), integer()) + -> ok | {error, term()}. + +do_store_file(Path, Data, FileMode, DirMode) -> + try + ok = filelib:ensure_dir(Path), + {ok, Io} = file:open(Path, [write, exclusive, raw]), + Ok = file:write(Io, Data), + ok = file:close(Io), + if is_integer(FileMode) -> + ok = file:change_mode(Path, FileMode); + FileMode == undefined -> + ok + end, + if is_integer(DirMode) -> + RandDir = filename:dirname(Path), + UserDir = filename:dirname(RandDir), + ok = file:change_mode(RandDir, DirMode), + ok = file:change_mode(UserDir, DirMode); + DirMode == undefined -> + ok + end, + ok = Ok % Raise an exception if file:write/2 failed. + catch + _:{badmatch, {error, Error}} -> + {error, ?FORMAT(Error)}; + _:Error -> + {error, Error} + end. + +-spec guess_content_type(binary()) -> binary(). + +guess_content_type(FileName) -> + mod_http_fileserver:content_type(FileName, + ?DEFAULT_CONTENT_TYPE, + ?CONTENT_TYPES). + +-spec http_response(binary(), 100..599) + -> {pos_integer(), [{binary(), binary()}], binary()}. + +http_response(Host, Code) -> + http_response(Host, Code, []). + +-spec http_response(binary(), 100..599, [{binary(), binary()}]) + -> {pos_integer(), [{binary(), binary()}], binary()}. + +http_response(Host, Code, ExtraHeaders) -> + Message = <<(code_to_message(Code))/binary, $\n>>, + http_response(Host, Code, ExtraHeaders, Message). + +-spec http_response(binary(), 100..599, [{binary(), binary()}], binary()) + -> {pos_integer(), [{binary(), binary()}], binary()}. + +http_response(Host, Code, ExtraHeaders, Body) -> + ServerHeader = {<<"Server">>, <<"ejabberd ", (?VERSION)/binary>>}, + CustomHeaders = + gen_mod:get_module_opt(Host, ?MODULE, custom_headers, + fun(Headers) -> + lists:map(fun({K, V}) -> + {iolist_to_binary(K), + iolist_to_binary(V)} + end, Headers) + end, + []), + Headers = case proplists:is_defined(<<"Content-Type">>, ExtraHeaders) of + true -> + [ServerHeader | ExtraHeaders]; + false -> + [ServerHeader, {<<"Content-Type">>, <<"text/plain">>} | + ExtraHeaders] + end ++ CustomHeaders, + {Code, Headers, Body}. + +-spec code_to_message(100..599) -> binary(). + +code_to_message(201) -> <<"Upload successful.">>; +code_to_message(403) -> <<"Forbidden.">>; +code_to_message(404) -> <<"Not found.">>; +code_to_message(405) -> <<"Method not allowed.">>; +code_to_message(413) -> <<"File size doesn't match requested size.">>; +code_to_message(500) -> <<"Internal server error.">>; +code_to_message(_Code) -> <<"">>. + +%%-------------------------------------------------------------------- +%% Image manipulation stuff +%%-------------------------------------------------------------------- +-spec identify(string()) -> {ok, media_info()} | {error, string()}. + +identify(Path) -> + Cmd = lists:flatten(io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", + [Path])), + Res = os:cmd(Cmd), + case string:tokens(Res, " ") of + ["ok", T, H, W] -> + {ok, #media_info{ + type = string:to_lower(T), + height = list_to_integer(H), + weight = list_to_integer(W)}}; + _ -> + ?ERROR_MSG("failed to identify type of ~s: ~s", [Path, Res]), + {error, Res} + end. + +-spec convert(string(), media_info()) -> {ok, string()} | pass. + +convert(Path, #media_info{type = T, weight = W, height = H}) -> + if W*H >= 25000000 -> + ?DEBUG("the image ~s is more than 25 Mbpx", [Path]), + pass; + (W =< 300) and (H =< 300) -> + {ok, Path}; + T == "gif"; T == "jpeg"; T == "png"; T == "webp" -> + Dir = filename:dirname(Path), + FileName = binary_to_list(randoms:get_string()) ++ "." ++ T, + OutPath = filename:join(Dir, FileName), + Cmd = lists:flatten(io_lib:fwrite("convert -resize 300 ~s ~s", + [Path, OutPath])), + case os:cmd(Cmd) of + "" -> + {ok, OutPath}; + Err -> + ?ERROR_MSG("failed to convert ~s to ~s: ~s", + [Path, OutPath, Err]), + pass + end; + true -> + ?DEBUG("do not call 'convert' for unknown type ~s", [T]), + pass + end. + +-spec thumb_el(string(), binary()) -> xmlel(). + +thumb_el(Path, URI) -> + ContentType = guess_content_type(Path), + case identify(Path) of + {ok, #media_info{height = H, weight = W}} -> + #xmlel{name = <<"thumbnail">>, + attrs = [{<<"xmlns">>, ?NS_THUMBS_1}, + {<<"media-type">>, ContentType}, + {<<"uri">>, URI}, + {<<"height">>, jlib:integer_to_binary(H)}, + {<<"width">>, jlib:integer_to_binary(W)}]}; + {error, _} -> + #xmlel{name = <<"thumbnail">>, + attrs = [{<<"xmlns">>, ?NS_THUMBS_1}, + {<<"uri">>, URI}, + {<<"media-type">>, ContentType}]} + end. + +%%-------------------------------------------------------------------- +%% Remove user. +%%-------------------------------------------------------------------- + +-spec remove_user(binary(), binary()) -> ok. + +remove_user(User, Server) -> + ServerHost = jlib:nameprep(Server), + DocRoot = gen_mod:get_module_opt(ServerHost, ?MODULE, docroot, + fun iolist_to_binary/1, + <<"@HOME@/upload">>), + JIDinURL = gen_mod:get_module_opt(ServerHost, ?MODULE, jid_in_url, + fun(sha1) -> sha1; + (node) -> node + end, + sha1), + UserStr = make_user_string(jlib:make_jid(User, Server, <<"">>), JIDinURL), + UserDir = str:join([expand_home(DocRoot), UserStr], <<$/>>), + case del_tree(UserDir) of + ok -> + ?INFO_MSG("Removed HTTP upload directory of ~s@~s", [User, Server]); + {error, enoent} -> + ?DEBUG("Found no HTTP upload directory of ~s@~s", [User, Server]); + {error, Error} -> + ?ERROR_MSG("Cannot remove HTTP upload directory of ~s@~s: ~p", + [User, Server, Error]) + end, + ok. + +-spec del_tree(file:filename_all()) -> ok | {error, term()}. + +del_tree(Dir) when is_binary(Dir) -> + del_tree(binary_to_list(Dir)); +del_tree(Dir) -> + try + {ok, Entries} = file:list_dir(Dir), + lists:foreach(fun(Path) -> + case filelib:is_dir(Path) of + true -> + ok = del_tree(Path); + false -> + ok = file:delete(Path) + end + end, [Dir ++ "/" ++ Entry || Entry <- Entries]), + ok = file:del_dir(Dir) + catch + _:{badmatch, {error, Error}} -> + {error, ?FORMAT(Error)}; + _:Error -> + {error, Error} + end. From 6f2e178de1370bd26437a504d50bc19dd66065ed Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 26 Oct 2015 15:05:28 +0300 Subject: [PATCH 320/695] Rename badly entitled record field --- src/mod_http_upload.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index a720e528adf..40f194be200 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -94,7 +94,7 @@ -record(media_info, {type :: string(), height :: integer(), - weight :: integer()}). + width :: integer()}). -type state() :: #state{}. -type slot() :: [binary()]. @@ -844,7 +844,7 @@ identify(Path) -> {ok, #media_info{ type = string:to_lower(T), height = list_to_integer(H), - weight = list_to_integer(W)}}; + width = list_to_integer(W)}}; _ -> ?ERROR_MSG("failed to identify type of ~s: ~s", [Path, Res]), {error, Res} @@ -852,7 +852,7 @@ identify(Path) -> -spec convert(string(), media_info()) -> {ok, string()} | pass. -convert(Path, #media_info{type = T, weight = W, height = H}) -> +convert(Path, #media_info{type = T, width = W, height = H}) -> if W*H >= 25000000 -> ?DEBUG("the image ~s is more than 25 Mbpx", [Path]), pass; @@ -882,7 +882,7 @@ convert(Path, #media_info{type = T, weight = W, height = H}) -> thumb_el(Path, URI) -> ContentType = guess_content_type(Path), case identify(Path) of - {ok, #media_info{height = H, weight = W}} -> + {ok, #media_info{height = H, width = W}} -> #xmlel{name = <<"thumbnail">>, attrs = [{<<"xmlns">>, ?NS_THUMBS_1}, {<<"media-type">>, ContentType}, From 5dfd95e5a7d9194dd882a1dbccd3d42f5fed005f Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 26 Oct 2015 13:10:10 +0100 Subject: [PATCH 321/695] Support user quotas for HTTP File Upload mod_http_upload_quota implements two features: - When a "hard quota" is exceeded during a file upload, old files are removed until the disk usage equals or falls below the "soft quota". - Once a day, all uploaded files (and directories) older than a configurable number of days are deleted. --- src/mod_http_upload_quota.erl | 345 ++++++++++++++++++++++++++++++++++ 1 file changed, 345 insertions(+) create mode 100644 src/mod_http_upload_quota.erl diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl new file mode 100644 index 00000000000..1b7828a54a2 --- /dev/null +++ b/src/mod_http_upload_quota.erl @@ -0,0 +1,345 @@ +%%%------------------------------------------------------------------- +%%% File : mod_http_upload_quota.erl +%%% Author : Holger Weiss +%%% Purpose : Quota management for HTTP File Upload (XEP-0363) +%%% Created : 15 Oct 2015 by Holger Weiss +%%%------------------------------------------------------------------- + +-module(mod_http_upload_quota). +-author('holger@zedat.fu-berlin.de'). + +-define(GEN_SERVER, gen_server). +-define(PROCNAME, ?MODULE). +-define(TIMEOUT, timer:hours(24)). +-define(INITIAL_TIMEOUT, timer:minutes(10)). +-define(FORMAT(Error), file:format_error(Error)). + +-behaviour(?GEN_SERVER). +-behaviour(gen_mod). + +%% gen_mod/supervisor callbacks. +-export([start_link/3, + start/2, + stop/1, + mod_opt_type/1]). + +%% gen_server callbacks. +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). + +%% ejabberd_hooks callback. +-export([handle_slot_request/5]). + +-include("jlib.hrl"). +-include("logger.hrl"). +-include_lib("kernel/include/file.hrl"). + +-record(state, + {server_host :: binary(), + access_soft_quota :: atom(), + access_hard_quota :: atom(), + max_days :: pos_integer() | infinity, + docroot :: binary(), + disk_usage = dict:new() :: term(), + timers :: [timer:tref()]}). + +-type state() :: #state{}. + +%%-------------------------------------------------------------------- +%% gen_mod/supervisor callbacks. +%%-------------------------------------------------------------------- + +-spec start_link(binary(), atom(), gen_mod:opts()) + -> {ok, pid()} | ignore | {error, _}. + +start_link(ServerHost, Proc, Opts) -> + ?GEN_SERVER:start_link({local, Proc}, ?MODULE, {ServerHost, Opts}, []). + +-spec start(binary(), gen_mod:opts()) -> {ok, _} | {ok, _, _} | {error, _}. + +start(ServerHost, Opts) -> + Proc = mod_http_upload:get_proc_name(ServerHost, ?PROCNAME), + Spec = {Proc, + {?MODULE, start_link, [ServerHost, Proc, Opts]}, + permanent, + 3000, + worker, + [?MODULE]}, + supervisor:start_child(ejabberd_sup, Spec). + +-spec stop(binary()) -> ok. + +stop(ServerHost) -> + Proc = mod_http_upload:get_proc_name(ServerHost, ?PROCNAME), + ok = supervisor:terminate_child(ejabberd_sup, Proc), + ok = supervisor:delete_child(ejabberd_sup, Proc). + +-spec mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()]. + +mod_opt_type(access_soft_quota) -> + fun(A) when is_atom(A) -> A end; +mod_opt_type(access_hard_quota) -> + fun(A) when is_atom(A) -> A end; +mod_opt_type(max_days) -> + fun(I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end; +mod_opt_type(_) -> + [access_soft_quota, access_hard_quota, max_days]. + +%%-------------------------------------------------------------------- +%% gen_server callbacks. +%%-------------------------------------------------------------------- + +-spec init({binary(), gen_mod:opts()}) -> {ok, state()}. + +init({ServerHost, Opts}) -> + process_flag(trap_exit, true), + AccessSoftQuota = gen_mod:get_opt(access_soft_quota, Opts, + fun(A) when is_atom(A) -> A end, + soft_upload_quota), + AccessHardQuota = gen_mod:get_opt(access_hard_quota, Opts, + fun(A) when is_atom(A) -> A end, + hard_upload_quota), + MaxDays = gen_mod:get_opt(max_days, Opts, + fun(I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end, + infinity), + DocRoot1 = gen_mod:get_module_opt(ServerHost, mod_http_upload, docroot, + fun iolist_to_binary/1, + <<"@HOME@/upload">>), + DocRoot2 = mod_http_upload:expand_home(str:strip(DocRoot1, right, $/)), + Timers = if MaxDays == infinity -> []; + true -> + {ok, T1} = timer:send_after(?INITIAL_TIMEOUT, sweep), + {ok, T2} = timer:send_interval(?TIMEOUT, sweep), + [T1, T2] + end, + ejabberd_hooks:add(http_upload_slot_request, ServerHost, ?MODULE, + handle_slot_request, 50), + {ok, #state{server_host = ServerHost, + access_soft_quota = AccessSoftQuota, + access_hard_quota = AccessHardQuota, + max_days = MaxDays, + docroot = DocRoot2, + timers = Timers}}. + +-spec handle_call(_, {pid(), _}, state()) -> {noreply, state()}. + +handle_call(Request, From, State) -> + ?ERROR_MSG("Got unexpected request from ~p: ~p", [From, Request]), + {noreply, State}. + +-spec handle_cast(_, state()) -> {noreply, state()}. + +handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, + #state{server_host = ServerHost, + access_soft_quota = AccessSoftQuota, + access_hard_quota = AccessHardQuota, + disk_usage = DiskUsage} = State) -> + HardQuota = case acl:match_rule(ServerHost, AccessHardQuota, JID) of + Hard when is_integer(Hard), Hard > 0 -> + Hard * 1024 * 1024; + _ -> + 0 + end, + SoftQuota = case acl:match_rule(ServerHost, AccessSoftQuota, JID) of + Soft when is_integer(Soft), Soft > 0 -> + Soft * 1024 * 1024; + _ -> + 0 + end, + OldSize = case dict:find({U, S}, DiskUsage) of + {ok, Value} -> + Value; + error -> + undefined + end, + NewSize = case {HardQuota, SoftQuota} of + {0, 0} -> + ?DEBUG("No quota specified for ~s", + [jlib:jid_to_string(JID)]), + Size; + {0, _} -> + ?WARNING_MSG("No hard quota specified for ~s", + [jlib:jid_to_string(JID)]), + enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); + {_, 0} -> + ?WARNING_MSG("No soft quota specified for ~s", + [jlib:jid_to_string(JID)]), + enforce_quota(Path, Size, OldSize, HardQuota, HardQuota); + _ when SoftQuota > HardQuota -> + ?WARNING_MSG("Bad quota for ~s (soft: ~p, hard: ~p)", + [jlib:jid_to_string(JID), + SoftQuota, HardQuota]), + enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); + _ -> + ?DEBUG("Enforcing quota for ~s", + [jlib:jid_to_string(JID)]), + enforce_quota(Path, Size, OldSize, SoftQuota, HardQuota) + end, + {noreply, State#state{disk_usage = dict:store({U, S}, NewSize, DiskUsage)}}; +handle_cast(Request, State) -> + ?ERROR_MSG("Got unexpected request: ~p", [Request]), + {noreply, State}. + +-spec handle_info(_, state()) -> {noreply, state()}. + +handle_info(sweep, #state{server_host = ServerHost, + docroot = DocRoot, + max_days = MaxDays} = State) + when is_integer(MaxDays), MaxDays > 0 -> + ?DEBUG("Got 'sweep' message for ~s", [ServerHost]), + case file:list_dir(DocRoot) of + {ok, Entries} -> + BackThen = secs_since_epoch() - (MaxDays * 86400), + DocRootS = binary_to_list(DocRoot), + PathNames = lists:map(fun(Entry) -> DocRootS ++ "/" ++ Entry end, + Entries), + UserDirs = lists:filter(fun filelib:is_dir/1, PathNames), + lists:foreach(fun(UserDir) -> delete_old_files(UserDir, BackThen) end, + UserDirs); + {error, Error} -> + ?ERROR_MSG("Cannot open document root ~s: ~s", + [DocRoot, ?FORMAT(Error)]) + end, + {noreply, State}; +handle_info(Info, State) -> + ?ERROR_MSG("Got unexpected info: ~p", [Info]), + {noreply, State}. + +-spec terminate(normal | shutdown | {shutdown, _} | _, _) -> ok. + +terminate(Reason, #state{server_host = ServerHost, timers = Timers}) -> + ?DEBUG("Stopping upload quota process for ~s: ~p", [ServerHost, Reason]), + ejabberd_hooks:delete(http_upload_slot_request, ServerHost, ?MODULE, + handle_slot_request, 50), + lists:foreach(fun(Timer) -> timer:cancel(Timer) end, Timers). + +-spec code_change({down, _} | _, state(), _) -> {ok, state()}. + +code_change(_OldVsn, #state{server_host = ServerHost} = State, _Extra) -> + ?DEBUG("Updating upload quota process for ~s", [ServerHost]), + {ok, State}. + +%%-------------------------------------------------------------------- +%% ejabberd_hooks callback. +%%-------------------------------------------------------------------- + +-spec handle_slot_request(term(), jid(), binary(), non_neg_integer(), binary()) + -> term(). + +handle_slot_request(allow, #jid{lserver = ServerHost} = JID, Path, Size, + _Lang) -> + Proc = mod_http_upload:get_proc_name(ServerHost, ?PROCNAME), + ?GEN_SERVER:cast(Proc, {handle_slot_request, JID, Path, Size}), + allow; +handle_slot_request(Acc, _JID, _Path, _Size, _Lang) -> Acc. + +%%-------------------------------------------------------------------- +%% Internal functions. +%%-------------------------------------------------------------------- + +-spec enforce_quota(file:filename_all(), non_neg_integer(), + non_neg_integer() | undefined, non_neg_integer(), + non_neg_integer()) + -> non_neg_integer(). + +enforce_quota(_UserDir, SlotSize, OldSize, _MinSize, MaxSize) + when is_integer(OldSize), OldSize + SlotSize =< MaxSize -> + OldSize + SlotSize; +enforce_quota(UserDir, SlotSize, _OldSize, MinSize, MaxSize) -> + Files = lists:sort(fun({_PathA, _SizeA, TimeA}, {_PathB, _SizeB, TimeB}) -> + TimeA > TimeB + end, gather_file_info(UserDir)), + {DelFiles, OldSize, NewSize} = + lists:foldl(fun({_Path, Size, _Time}, {[], AccSize, AccSize}) + when AccSize + Size + SlotSize =< MinSize -> + {[], AccSize + Size, AccSize + Size}; + ({Path, Size, _Time}, {[], AccSize, AccSize}) -> + {[Path], AccSize + Size, AccSize}; + ({Path, Size, _Time}, {AccFiles, AccSize, NewSize}) -> + {[Path | AccFiles], AccSize + Size, NewSize} + end, {[], 0, 0}, Files), + if OldSize + SlotSize > MaxSize -> + lists:foreach(fun(File) -> del_file_and_dir(File) end, DelFiles), + file:del_dir(UserDir), % In case it's empty, now. + NewSize + SlotSize; + true -> + OldSize + SlotSize + end. + +-spec delete_old_files(file:filename_all(), integer()) -> ok. + +delete_old_files(UserDir, Timestamp) -> + FileInfo = gather_file_info(UserDir), + case [Path || {Path, _Size, Time} <- FileInfo, Time < Timestamp] of + [] -> + ok; + OldFiles -> + lists:foreach(fun(File) -> del_file_and_dir(File) end, OldFiles), + file:del_dir(UserDir) % In case it's empty, now. + end. + +-spec gather_file_info(file:filename_all()) + -> [{binary(), non_neg_integer(), non_neg_integer()}]. + +gather_file_info(Dir) when is_binary(Dir) -> + gather_file_info(binary_to_list(Dir)); +gather_file_info(Dir) -> + case file:list_dir(Dir) of + {ok, Entries} -> + lists:foldl(fun(Entry, Acc) -> + Path = Dir ++ "/" ++ Entry, + case file:read_file_info(Path, [{time, posix}]) of + {ok, #file_info{type = directory}} -> + gather_file_info(Path) ++ Acc; + {ok, #file_info{type = regular, + mtime = Time, + size = Size}} -> + [{Path, Size, Time} | Acc]; + {ok, _Info} -> + ?DEBUG("Won't stat(2) non-regular file ~s", + [Path]), + Acc; + {error, Error} -> + ?ERROR_MSG("Cannot stat(2) ~s: ~s", + [Path, ?FORMAT(Error)]), + Acc + end + end, [], Entries); + {error, enoent} -> + ?DEBUG("Directory ~s doesn't exist", [Dir]), + []; + {error, Error} -> + ?ERROR_MSG("Cannot open directory ~s: ~s", [Dir, ?FORMAT(Error)]), + [] + end. + +-spec del_file_and_dir(file:name_all()) -> ok. + +del_file_and_dir(File) -> + case file:delete(File) of + ok -> + ?INFO_MSG("Removed ~s", [File]), + Dir = filename:dirname(File), + case file:del_dir(Dir) of + ok -> + ?DEBUG("Removed ~s", [Dir]); + {error, Error} -> + ?INFO_MSG("Cannot remove ~s: ~s", [Dir, ?FORMAT(Error)]) + end; + {error, Error} -> + ?WARNING_MSG("Cannot remove ~s: ~s", [File, ?FORMAT(Error)]) + end. + +-spec secs_since_epoch() -> non_neg_integer(). + +secs_since_epoch() -> + {MegaSecs, Secs, _MicroSecs} = os:timestamp(), + MegaSecs * 1000000 + Secs. From b5a09f8b1594f5775c48870032cfc702e0ca6017 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 26 Oct 2015 22:10:32 +0100 Subject: [PATCH 322/695] mod_http_upload: Strip newline from command output The list_to_integer/1 function doesn't cope with trailing newline characters. --- src/mod_http_upload.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 40f194be200..88ca53f7b1d 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -838,7 +838,7 @@ code_to_message(_Code) -> <<"">>. identify(Path) -> Cmd = lists:flatten(io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", [Path])), - Res = os:cmd(Cmd), + Res = string:strip(os:cmd(Cmd), right, $\n), case string:tokens(Res, " ") of ["ok", T, H, W] -> {ok, #media_info{ @@ -869,7 +869,7 @@ convert(Path, #media_info{type = T, width = W, height = H}) -> {ok, OutPath}; Err -> ?ERROR_MSG("failed to convert ~s to ~s: ~s", - [Path, OutPath, Err]), + [Path, OutPath, string:strip(Err, right, $\n)]), pass end; true -> From 3e7ee6af6d21d70e1d03ad84ba4f3f6f4ed8df95 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 26 Oct 2015 22:30:58 +0100 Subject: [PATCH 323/695] mod_http_upload: Add/fix function specifications --- src/mod_http_upload.erl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 88ca53f7b1d..817f93b6f52 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -719,6 +719,12 @@ iq_disco_info(Lang, Name) -> %% HTTP request handling. +-spec store_file(file:filename_all(), binary(), + integer() | undefined, + integer() | undefined, + binary(), binary(), boolean()) + -> ok | {ok, [{binary(), binary()}], binary()} | {error, term()}. + store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> case do_store_file(Path, Data, FileMode, DirMode) of ok when Thumbnail -> @@ -747,7 +753,9 @@ store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> Err end. --spec do_store_file(file:filename_all(), binary(), integer(), integer()) +-spec do_store_file(file:filename_all(), binary(), + integer() | undefined, + integer() | undefined) -> ok | {error, term()}. do_store_file(Path, Data, FileMode, DirMode) -> From 62ea763089850125eb17024a70aeec80db6a48ed Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 26 Oct 2015 22:32:12 +0100 Subject: [PATCH 324/695] mod_http_upload: Fix string()/binary() type issue --- src/mod_http_upload.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 817f93b6f52..35fd6ca34e8 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -888,7 +888,7 @@ convert(Path, #media_info{type = T, width = W, height = H}) -> -spec thumb_el(string(), binary()) -> xmlel(). thumb_el(Path, URI) -> - ContentType = guess_content_type(Path), + ContentType = guess_content_type(list_to_binary(Path)), case identify(Path) of {ok, #media_info{height = H, width = W}} -> #xmlel{name = <<"thumbnail">>, From 788049be7b649ad3c8ad0adb804a0496af5b6191 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 26 Oct 2015 22:42:07 +0100 Subject: [PATCH 325/695] ejabberdctl: export CONTRIB_MODULES_CONF_DIR --- ejabberdctl.template | 1 + 1 file changed, 1 insertion(+) diff --git a/ejabberdctl.template b/ejabberdctl.template index f90f71e5345..a4327ac9f86 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -156,6 +156,7 @@ export ERL_INETRC export ERL_MAX_PORTS export ERL_MAX_ETS_TABLES export CONTRIB_MODULES_PATH +export CONTRIB_MODULES_CONF_DIR export ERL_LIBS # start server From 47b17acbafd37ac423685f52c26839b33b856390 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 26 Oct 2015 22:46:58 +0100 Subject: [PATCH 326/695] ejabberdctl.cfg: Document CONTRIB_MODULES_CONF_DIR --- ejabberdctl.cfg.example | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ejabberdctl.cfg.example b/ejabberdctl.cfg.example index 63c91735863..d121aa82430 100644 --- a/ejabberdctl.cfg.example +++ b/ejabberdctl.cfg.example @@ -169,6 +169,18 @@ # #CONTRIB_MODULES_PATH=/opt/ejabberd-modules +#. +#' CONTRIB_MODULES_CONF_DIR: configuration directory for contributed modules +# +# Specify the full path to the configuration directory for contributed ejabberd +# modules. In order to configure a module named mod_foo, a mod_foo.yml file can +# be created in this directory. This file will then be used instead of the +# default configuration file provided with the module. +# +# Default: $CONTRIB_MODULES_PATH/conf +# +#CONTRIB_MODULES_CONF_DIR=/etc/ejabberd/modules + #. #' # vim: foldmarker=#',#. foldmethod=marker: From a497cdff5ee0bf41749d076a445ba7371ddbd69e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 28 Oct 2015 15:53:12 +0100 Subject: [PATCH 327/695] set dependencies versions for 15.10 --- rebar.config.script | 46 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index e0a8923cfc0..833595d481e 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -54,17 +54,17 @@ SrcDirs = lists:foldl( Acc end, [], Cfg), -Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, - {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, - {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}}, - {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, - {esip, ".*", {git, "https://github.com/processone/p1_sip"}}, - {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, - {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, - {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}, - {jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}, - {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, - {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], +Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab", "f7ea12b0ba962a3d2f9a406d2954cf7de4e27230"}}, + {p1_tls, ".*", {git, "https://github.com/processone/tls", "e56321afd974e9da33da913cd31beebc8e73e75f"}}, + {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep", "3c640237a3a7831dc39de6a6d329d3a9af25c579"}}, + {p1_xml, ".*", {git, "https://github.com/processone/xml", "1c8b016b0ac7986efb823baf1682a43565449e65"}}, + {esip, ".*", {git, "https://github.com/processone/p1_sip", "d662d3fe7f6288b444ea321d854de0bd6d40e022"}}, + {p1_stun, ".*", {git, "https://github.com/processone/stun", "061bdae484268cbf0457ad4797e74b8516df3ad1"}}, + {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", "79f756ba73a235c4d3836ec07b5f7f2b55f49638"}}, + {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", "d7800881e6702723ce58b7646b60c9e4cd25d563"}}, + {jiffy, ".*", {git, "https://github.com/davisp/jiffy", "cfc61a2e952dc3182e0f9b1473467563699992e2"}}, + {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git", "e6da9912e5d8f658e7e868f41a102d085bdbef59"}}, + {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git", "42e6e96a0fe7106830274feed915125feb1056f3"}}], CFLags = proplists:get_value(cflags, Cfg, ""), CPPFLags = proplists:get_value(cppflags, Cfg, ""), @@ -94,30 +94,30 @@ PostHooks = [ConfigureCmd("p1_tls", ""), CfgDeps = lists:flatmap( fun({mysql, true}) -> - [{p1_mysql, ".*", {git, "https://github.com/processone/mysql"}}]; + [{p1_mysql, ".*", {git, "https://github.com/processone/mysql", "dfa87da95f8fdb92e270741c2a53f796b682f918"}}]; ({pgsql, true}) -> - [{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql"}}]; + [{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", "e72c03c60bfcb56bbb5d259342021d9cb3581dac"}}]; ({sqlite, true}) -> - [{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3"}}]; + [{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3", "8350dc603804c503f99c92bfd2eab1dd6885758e"}}]; ({pam, true}) -> - [{p1_pam, ".*", {git, "https://github.com/processone/epam"}}]; + [{p1_pam, ".*", {git, "https://github.com/processone/epam", "d3ce290b7da75d780a03e86e7a8198a80e9826a6"}}]; ({zlib, true}) -> - [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; + [{p1_zlib, ".*", {git, "https://github.com/processone/zlib", "e3d4222b7aae616d7ef2e7e2fa0bbf451516c602"}}]; ({riak, true}) -> [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; ({elixir, true}) -> - [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, - {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; + [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin", "7058379b7c7e017555647f6b9cecfd87cd50f884"}}, + {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", "1d9548fd285d243721b7eba71912bde2ffd1f6c3"}}]; ({iconv, true}) -> - [{p1_iconv, ".*", {git, "https://github.com/processone/eiconv"}}]; + [{p1_iconv, ".*", {git, "https://github.com/processone/eiconv", "8b7542b1aaf0a851f335e464956956985af6d9a2"}}]; ({lager, true}) -> - [{lager, ".*", {git, "https://github.com/basho/lager"}}]; + [{lager, ".*", {git, "https://github.com/basho/lager", "4d2ec8c701e1fa2d386f92f2b83b23faf8608ac3"}}]; ({lager, false}) -> - [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}]; + [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger", "3e19507fd5606a73694917158767ecb3f5704e3f"}}]; ({tools, true}) -> - [{meck, "0.*", {git, "https://github.com/eproxus/meck"}}]; + [{meck, "0.*", {git, "https://github.com/eproxus/meck", "0845277398b8326f9dddddd9fc3cf73467ba6877"}}]; ({redis, true}) -> - [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; + [{eredis, ".*", {git, "https://github.com/wooga/eredis", "bf12ecb30253c84a2331f4f0d93fd68856fcb9f4"}}]; (_) -> [] end, Cfg), From 1d5a441ce87ede4fc74e43fe4b76c8a2278c4350 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 28 Oct 2015 16:07:00 +0100 Subject: [PATCH 328/695] Revert "set dependencies versions for 15.10" This reverts commit a497cdff5ee0bf41749d076a445ba7371ddbd69e. --- rebar.config.script | 46 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index 833595d481e..e0a8923cfc0 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -54,17 +54,17 @@ SrcDirs = lists:foldl( Acc end, [], Cfg), -Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab", "f7ea12b0ba962a3d2f9a406d2954cf7de4e27230"}}, - {p1_tls, ".*", {git, "https://github.com/processone/tls", "e56321afd974e9da33da913cd31beebc8e73e75f"}}, - {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep", "3c640237a3a7831dc39de6a6d329d3a9af25c579"}}, - {p1_xml, ".*", {git, "https://github.com/processone/xml", "1c8b016b0ac7986efb823baf1682a43565449e65"}}, - {esip, ".*", {git, "https://github.com/processone/p1_sip", "d662d3fe7f6288b444ea321d854de0bd6d40e022"}}, - {p1_stun, ".*", {git, "https://github.com/processone/stun", "061bdae484268cbf0457ad4797e74b8516df3ad1"}}, - {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", "79f756ba73a235c4d3836ec07b5f7f2b55f49638"}}, - {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", "d7800881e6702723ce58b7646b60c9e4cd25d563"}}, - {jiffy, ".*", {git, "https://github.com/davisp/jiffy", "cfc61a2e952dc3182e0f9b1473467563699992e2"}}, - {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git", "e6da9912e5d8f658e7e868f41a102d085bdbef59"}}, - {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git", "42e6e96a0fe7106830274feed915125feb1056f3"}}], +Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, + {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, + {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}}, + {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, + {esip, ".*", {git, "https://github.com/processone/p1_sip"}}, + {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, + {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, + {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}, + {jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}, + {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, + {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], CFLags = proplists:get_value(cflags, Cfg, ""), CPPFLags = proplists:get_value(cppflags, Cfg, ""), @@ -94,30 +94,30 @@ PostHooks = [ConfigureCmd("p1_tls", ""), CfgDeps = lists:flatmap( fun({mysql, true}) -> - [{p1_mysql, ".*", {git, "https://github.com/processone/mysql", "dfa87da95f8fdb92e270741c2a53f796b682f918"}}]; + [{p1_mysql, ".*", {git, "https://github.com/processone/mysql"}}]; ({pgsql, true}) -> - [{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", "e72c03c60bfcb56bbb5d259342021d9cb3581dac"}}]; + [{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql"}}]; ({sqlite, true}) -> - [{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3", "8350dc603804c503f99c92bfd2eab1dd6885758e"}}]; + [{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3"}}]; ({pam, true}) -> - [{p1_pam, ".*", {git, "https://github.com/processone/epam", "d3ce290b7da75d780a03e86e7a8198a80e9826a6"}}]; + [{p1_pam, ".*", {git, "https://github.com/processone/epam"}}]; ({zlib, true}) -> - [{p1_zlib, ".*", {git, "https://github.com/processone/zlib", "e3d4222b7aae616d7ef2e7e2fa0bbf451516c602"}}]; + [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; ({riak, true}) -> [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; ({elixir, true}) -> - [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin", "7058379b7c7e017555647f6b9cecfd87cd50f884"}}, - {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", "1d9548fd285d243721b7eba71912bde2ffd1f6c3"}}]; + [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, + {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; ({iconv, true}) -> - [{p1_iconv, ".*", {git, "https://github.com/processone/eiconv", "8b7542b1aaf0a851f335e464956956985af6d9a2"}}]; + [{p1_iconv, ".*", {git, "https://github.com/processone/eiconv"}}]; ({lager, true}) -> - [{lager, ".*", {git, "https://github.com/basho/lager", "4d2ec8c701e1fa2d386f92f2b83b23faf8608ac3"}}]; + [{lager, ".*", {git, "https://github.com/basho/lager"}}]; ({lager, false}) -> - [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger", "3e19507fd5606a73694917158767ecb3f5704e3f"}}]; + [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}]; ({tools, true}) -> - [{meck, "0.*", {git, "https://github.com/eproxus/meck", "0845277398b8326f9dddddd9fc3cf73467ba6877"}}]; + [{meck, "0.*", {git, "https://github.com/eproxus/meck"}}]; ({redis, true}) -> - [{eredis, ".*", {git, "https://github.com/wooga/eredis", "bf12ecb30253c84a2331f4f0d93fd68856fcb9f4"}}]; + [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; (_) -> [] end, Cfg), From f112a913218ffedc86c643fcefe5c3c44bf0aa5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 28 Oct 2015 18:12:39 +0100 Subject: [PATCH 329/695] Copy elixir files in copy-files makefile target --- Makefile.in | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index 391d816123d..f12ccf39769 100644 --- a/Makefile.in +++ b/Makefile.in @@ -112,12 +112,19 @@ spec: $(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \ 'case xml_gen:compile("tools/xmpp_codec.spec") of ok -> halt(0); _ -> halt(1) end.' -TO_DEST=$(foreach path,$(1),$(if $(filter deps/%,$(path)),$(patsubst deps/%,$(LIBDIR)/%,$(path)),$(patsubst %,$(LIBDIR)/ejabberd/%,$(path)))) +JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1)) + +ELIXIR_TO_DEST=$(LIBDIR) $(wordlist 2,2,$(1)) $(wordlist 5,1000,$(1)) +DEPS_TO_DEST=$(LIBDIR) $(wordlist 2,1000,$(1)) +MAIN_TO_DEST=$(LIBDIR) ejabberd $(1) +TO_DEST_SINGLE=$(if $(subst XdepsX,,X$(word 1,$(1))X),$(call MAIN_TO_DEST,$(1)),$(if $(subst XlibX,,X$(word 3,$(1))X),$(call DEPS_TO_DEST,$(1)),$(call ELIXIR_TO_DEST,$(1)))) +TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(call TO_DEST_SINGLE,$(subst /, ,$(path))))) + FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path))) FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w)))) -DEPS_FILES:=$(call FILES_WILDCARD,deps/*/ebin/*.beam deps/*/ebin/*.app deps/*/priv/* deps/*/priv/lib/* deps/*/priv/bin/* deps/*/include/*.hrl) -DEPS_FILES_FILTERED:=$(filter-out %/epam,$(DEPS_FILES)) +DEPS_FILES:=$(call FILES_WILDCARD,deps/*/ebin/*.beam deps/*/ebin/*.app deps/*/priv/* deps/*/priv/lib/* deps/*/priv/bin/* deps/*/include/*.hrl deps/*/lib/*/ebin/*.beam deps/*/lib/*/ebin/*.app) +DEPS_FILES_FILTERED:=$(filter-out %/epam deps/elixir/ebin/elixir.app,$(DEPS_FILES)) DEPS_DIRS:=$(sort deps/ $(wildcard deps/*) $(dir $(DEPS_FILES))) MAIN_FILES:=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/*.app priv/msgs/*.msg priv/lib/* include/*.hrl)) @@ -129,7 +136,7 @@ endef $(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,$(file)))) -$(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS)): +$(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))): $(INSTALL) -d $@ $(call TO_DEST,deps/p1_pam/priv/bin/epam): $(LIBDIR)/%: deps/% $(call TO_DEST,deps/p1_pam/priv/bin/) @@ -172,10 +179,6 @@ install: all copy-files -e "s*@installuser@*$(INIT_USER)*" ejabberd.init.template \ > ejabberd.init chmod 755 ejabberd.init - # Install Elixir and Elixir dependancies - -$(INSTALL) -m 644 deps/*/lib/*/ebin/*.app $(BEAMDIR) - -$(INSTALL) -m 644 deps/*/lib/*/ebin/*.beam $(BEAMDIR) - rm -f $(BEAMDIR)/configure.beam # # Binary C programs $(INSTALL) -d $(PBINDIR) From 32fe74c923f151334dab5656dcc2ac5ea328b09d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 28 Oct 2015 23:52:33 +0100 Subject: [PATCH 330/695] mod_http_upload: Document protocol support --- src/mod_http_upload.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 35fd6ca34e8..68a7818fc3b 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -8,6 +8,8 @@ -module(mod_http_upload). -author('holger@zedat.fu-berlin.de'). +-protocol({xep, 363, '0.1'}) + -define(GEN_SERVER, gen_server). -define(SERVICE_REQUEST_TIMEOUT, 5000). % 5 seconds. -define(SLOT_TIMEOUT, 18000000). % 5 hours. From 43e78147143fdf2a31add628fe589134abde506c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 28 Oct 2015 23:53:53 +0100 Subject: [PATCH 331/695] mod_mam: Update supported XEP version --- src/mod_mam.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 7781cff9a5e..c23e695d98f 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -25,7 +25,7 @@ %%%------------------------------------------------------------------- -module(mod_mam). --protocol({xep, 313, '0.3'}). +-protocol({xep, 313, '0.4'}). -behaviour(gen_mod). From 915383e150a4d25144f363310ba9a0882493f752 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 29 Oct 2015 10:09:55 +0100 Subject: [PATCH 332/695] mod_http_upload: Add missing trailing dot (Thanks to Matthias Rieber.) --- src/mod_http_upload.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 68a7818fc3b..6356e63682c 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -8,7 +8,7 @@ -module(mod_http_upload). -author('holger@zedat.fu-berlin.de'). --protocol({xep, 363, '0.1'}) +-protocol({xep, 363, '0.1'}). -define(GEN_SERVER, gen_server). -define(SERVICE_REQUEST_TIMEOUT, 5000). % 5 seconds. From bee767158da6240f13cf9d56e857d72ec3b7dbf1 Mon Sep 17 00:00:00 2001 From: Arno B Date: Thu, 29 Oct 2015 19:39:21 +0100 Subject: [PATCH 333/695] feat(ejabberdctl): Foreground option for docker Docker needs services to run in foreground. --- ejabberdctl.template | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index a4327ac9f86..147bff97e21 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -228,6 +228,21 @@ iexlive() --erl \"$ERLANG_OPTS\" --erl $ARGS --erl \"$@\"" } +# start server in the foreground +foreground() +{ + check_start + $EXEC_CMD "$ERL \ + $NAME $ERLANG_NODE \ + -noinput \ + -pa $EJABBERD_EBIN_PATH \ + $MNESIA_OPTS \ + $KERNEL_OPTS \ + $EJABBERD_OPTS \ + -s ejabberd \ + $ERLANG_OPTS $ARGS \"$@\"" +} + debugwarning() { if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then @@ -300,11 +315,12 @@ help() { echo "" echo "Commands to start an ejabberd node:" - echo " start Start an ejabberd node in server mode" - echo " debug Attach an interactive Erlang shell to a running ejabberd node" - echo " iexdebug Attach an interactive Elixir shell to a running ejabberd node" - echo " live Start an ejabberd node in live (interactive) mode" - echo " iexlive Start an ejabberd node in live (interactive) mode, within an Elixir shell" + echo " start Start an ejabberd node in server mode" + echo " debug Attach an interactive Erlang shell to a running ejabberd node" + echo " iexdebug Attach an interactive Elixir shell to a running ejabberd node" + echo " live Start an ejabberd node in live (interactive) mode" + echo " iexlive Start an ejabberd node in live (interactive) mode, within an Elixir shell" + echo " foreground Start an ejabberd node in server mode (attached)" echo "" echo "Optional parameters when starting an ejabberd node:" echo " --config-dir dir Config ejabberd: $ETC_DIR" @@ -468,6 +484,7 @@ case $ARGS in ' iexdebug') iexdebug;; ' live') live;; ' iexlive') iexlive;; + ' foreground') foreground;; ' ping'*) ping ${ARGS# ping};; ' etop') etop;; ' started') wait_for_status 0 30 2;; # wait 30x2s before timeout From 99f506135bff2660e1c91cb5cd1120bbd6c3fd84 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 30 Oct 2015 17:20:15 +0300 Subject: [PATCH 334/695] Fix ipv6 configuration processing (#803) --- src/ejabberd_listener.erl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index 0bea9c97b73..bebb15c4846 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -225,8 +225,8 @@ listen_tcp(PortIP, Module, SockOpts, Port, IPS) -> %% so the option inet/inet6 is only used when no IP is specified at all. parse_listener_portip(PortIP, Opts) -> {IPOpt, Opts2} = strip_ip_option(Opts), - {IPVOpt, OptsClean} = case lists:member(inet6, Opts2) of - true -> {inet6, Opts2 -- [inet6]}; + {IPVOpt, OptsClean} = case proplists:get_bool(inet6, Opts2) of + true -> {inet6, proplists:delete(inet6, Opts2)}; false -> {inet, Opts2} end, {Port, IPT, IPS, Proto} = @@ -569,11 +569,8 @@ transform_option({{Port, IP, Transport}, Mod, Opts}) -> Opts1 = lists:map( fun({ip, IPT}) when is_tuple(IPT) -> {ip, list_to_binary(inet_parse:ntoa(IP))}; - (tls) -> {tls, true}; (ssl) -> {tls, true}; - (zlib) -> {zlib, true}; - (starttls) -> {starttls, true}; - (starttls_required) -> {starttls_required, true}; + (A) when is_atom(A) -> {A, true}; (Opt) -> Opt end, Opts), Opts2 = lists:foldl( @@ -593,11 +590,11 @@ transform_option({{Port, IP, Transport}, Mod, Opts}) -> IPOpt ++ TransportOpt ++ [{port, Port}, {module, Mod} | Opts2]; transform_option({{Port, Transport}, Mod, Opts}) when ?IS_TRANSPORT(Transport) -> - transform_option({{Port, {0,0,0,0}, Transport}, Mod, Opts}); + transform_option({{Port, all_zero_ip(Opts), Transport}, Mod, Opts}); transform_option({{Port, IP}, Mod, Opts}) -> transform_option({{Port, IP, tcp}, Mod, Opts}); transform_option({Port, Mod, Opts}) -> - transform_option({{Port, {0,0,0,0}, tcp}, Mod, Opts}); + transform_option({{Port, all_zero_ip(Opts), tcp}, Mod, Opts}); transform_option(Opt) -> Opt. @@ -633,7 +630,7 @@ validate_cfg(L) -> {Port, prepare_mod(Mod), Opts}; (Opt, {Port, Mod, Opts}) -> {Port, Mod, [Opt|Opts]} - end, {{5222, {0,0,0,0}, tcp}, ejabberd_c2s, []}, LOpts) + end, {{5222, all_zero_ip(LOpts), tcp}, ejabberd_c2s, []}, LOpts) end, L). prepare_ip({A, B, C, D} = IP) @@ -656,5 +653,11 @@ prepare_mod(sip) -> prepare_mod(Mod) when is_atom(Mod) -> Mod. +all_zero_ip(Opts) -> + case proplists:get_bool(inet6, Opts) of + true -> {0,0,0,0,0,0,0,0}; + false -> {0,0,0,0} + end. + opt_type(listen) -> fun validate_cfg/1; opt_type(_) -> [listen]. From eeb705fc2f7fa3ba4512d61bef91b5fc2220b43d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 1 Nov 2015 23:29:22 +0100 Subject: [PATCH 335/695] mod_http_upload: Suppress error on non-image files Don't log an error (but only a debug) message if ImageMagick fails to indentify the file type for thumbnail creation. The image might be encrypted, or it could be a non-image file. Closes #809. --- src/mod_http_upload.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 6356e63682c..c88e768f2ea 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -856,7 +856,7 @@ identify(Path) -> height = list_to_integer(H), width = list_to_integer(W)}}; _ -> - ?ERROR_MSG("failed to identify type of ~s: ~s", [Path, Res]), + ?DEBUG("failed to identify type of ~s: ~s", [Path, Res]), {error, Res} end. From 9d2f1d5f0d8215142d53e3d095f4f3638b172abb Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 2 Nov 2015 01:12:10 +0100 Subject: [PATCH 336/695] mod_http_upload: Check availability of ImageMagick Log an error message during startup if the thumbnail option is enabled but ImageMagick is not installed. --- src/mod_http_upload.erl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index c88e768f2ea..a2aee27d761 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -272,6 +272,18 @@ init({ServerHost, Opts}) -> Mode -> file:change_mode(DocRoot, Mode) end, + case Thumbnail of + true -> + case string:str(os:cmd("identify"), "Magick") of + 0 -> + ?ERROR_MSG("Cannot find 'identify' command, please install " + "ImageMagick or disable thumbnail creation", []); + _ -> + ok + end; + false -> + ok + end, ejabberd_router:register_route(Host), {ok, #state{server_host = ServerHost, host = Host, name = Name, access = Access, max_size = MaxSize, From 1b368a86b709053ded0ebdfa0499cbd78712fce6 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 2 Nov 2015 23:46:31 +0100 Subject: [PATCH 337/695] mod_http_upload: Use binary strings in most places Switch to binary strings to fix a type issue, and for consistency. Closes #808. --- src/mod_http_upload.erl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index a2aee27d761..d3eace3537d 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -94,7 +94,7 @@ slots = dict:new() :: term()}). % dict:dict() requires Erlang 17. -record(media_info, - {type :: string(), + {type :: binary(), height :: integer(), width :: integer()}). @@ -733,7 +733,7 @@ iq_disco_info(Lang, Name) -> %% HTTP request handling. --spec store_file(file:filename_all(), binary(), +-spec store_file(binary(), binary(), integer() | undefined, integer() | undefined, binary(), binary(), boolean()) @@ -855,7 +855,7 @@ code_to_message(_Code) -> <<"">>. %%-------------------------------------------------------------------- %% Image manipulation stuff %%-------------------------------------------------------------------- --spec identify(string()) -> {ok, media_info()} | {error, string()}. +-spec identify(binary()) -> {ok, media_info()} | {error, binary()}. identify(Path) -> Cmd = lists:flatten(io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", @@ -864,15 +864,15 @@ identify(Path) -> case string:tokens(Res, " ") of ["ok", T, H, W] -> {ok, #media_info{ - type = string:to_lower(T), + type = list_to_binary(string:to_lower(T)), height = list_to_integer(H), width = list_to_integer(W)}}; _ -> ?DEBUG("failed to identify type of ~s: ~s", [Path, Res]), - {error, Res} + {error, list_to_binary(Res)} end. --spec convert(string(), media_info()) -> {ok, string()} | pass. +-spec convert(binary(), media_info()) -> {ok, binary()} | pass. convert(Path, #media_info{type = T, width = W, height = H}) -> if W*H >= 25000000 -> @@ -880,9 +880,9 @@ convert(Path, #media_info{type = T, width = W, height = H}) -> pass; (W =< 300) and (H =< 300) -> {ok, Path}; - T == "gif"; T == "jpeg"; T == "png"; T == "webp" -> + T == <<"gif">>; T == <<"jpeg">>; T == <<"png">>; T == <<"webp">> -> Dir = filename:dirname(Path), - FileName = binary_to_list(randoms:get_string()) ++ "." ++ T, + FileName = <<(randoms:get_string())/binary, $., T/binary>>, OutPath = filename:join(Dir, FileName), Cmd = lists:flatten(io_lib:fwrite("convert -resize 300 ~s ~s", [Path, OutPath])), @@ -899,10 +899,10 @@ convert(Path, #media_info{type = T, width = W, height = H}) -> pass end. --spec thumb_el(string(), binary()) -> xmlel(). +-spec thumb_el(binary(), binary()) -> xmlel(). thumb_el(Path, URI) -> - ContentType = guess_content_type(list_to_binary(Path)), + ContentType = guess_content_type(Path), case identify(Path) of {ok, #media_info{height = H, width = W}} -> #xmlel{name = <<"thumbnail">>, From 4566325241a7c589416d50ebfda4f8ccf1460d8b Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 2 Nov 2015 23:46:58 +0100 Subject: [PATCH 338/695] mod_http_upload: Don't complain during shutdown Ignore the case where, for some reason, no process is found to be stopped. Closes #810. --- src/mod_http_upload.erl | 4 ++-- src/mod_http_upload_quota.erl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index d3eace3537d..c51c60e0b19 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -148,8 +148,8 @@ stop(ServerHost) -> false -> ok end, Proc = get_proc_name(ServerHost, ?PROCNAME), - ok = supervisor:terminate_child(ejabberd_sup, Proc), - ok = supervisor:delete_child(ejabberd_sup, Proc). + supervisor:terminate_child(ejabberd_sup, Proc), + supervisor:delete_child(ejabberd_sup, Proc). -spec mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()]. diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index 1b7828a54a2..6ff8c840b75 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -75,8 +75,8 @@ start(ServerHost, Opts) -> stop(ServerHost) -> Proc = mod_http_upload:get_proc_name(ServerHost, ?PROCNAME), - ok = supervisor:terminate_child(ejabberd_sup, Proc), - ok = supervisor:delete_child(ejabberd_sup, Proc). + supervisor:terminate_child(ejabberd_sup, Proc), + supervisor:delete_child(ejabberd_sup, Proc). -spec mod_opt_type(atom()) -> fun((term()) -> term()) | [atom()]. From ff467382188c358e730dcb24adb5b154dc283ec7 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 3 Nov 2015 00:00:44 +0100 Subject: [PATCH 339/695] mod_http_upload_quota: Omit info message The mod_http_upload_quota module attempts to delete a directory whenever it removes a file from that directory. However, if thumbnail creation is enabled, directories will often contain two files. Therefore, don't log an info (but only a debug) message if directory removal fails. --- src/mod_http_upload_quota.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index 6ff8c840b75..7d8ff103a60 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -332,7 +332,7 @@ del_file_and_dir(File) -> ok -> ?DEBUG("Removed ~s", [Dir]); {error, Error} -> - ?INFO_MSG("Cannot remove ~s: ~s", [Dir, ?FORMAT(Error)]) + ?DEBUG("Cannot remove ~s: ~s", [Dir, ?FORMAT(Error)]) end; {error, Error} -> ?WARNING_MSG("Cannot remove ~s: ~s", [File, ?FORMAT(Error)]) From e54e543a66dcb7751e3c4b992fce7d5a12c22f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 3 Nov 2015 14:40:52 +0100 Subject: [PATCH 340/695] Faster string_to_jid/1 implementation This version is about 10-15% faster than old one --- src/ejabberd_app.erl | 1 + src/jlib.erl | 80 ++++++++++++++++++++++++++------------------ 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 657785ff982..ad51db7ebd3 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -43,6 +43,7 @@ start(normal, _Args) -> ejabberd_logger:start(), write_pid_file(), + jlib:start(), start_apps(), ejabberd:check_app(ejabberd), randoms:start(), diff --git a/src/jlib.erl b/src/jlib.erl index cc0f826ab6d..52dd9b2c923 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -58,11 +58,19 @@ atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1, l2i/1, i2l/1, i2l/2, queue_drop_while/2]). +-export([start/0]). + -include("ejabberd.hrl"). -include("jlib.hrl"). -export_type([jid/0]). +start() -> + SplitPattern = binary:compile_pattern([<<"@">>, <<"/">>]), + catch ets:new(jlib, [named_table, protected, set, {keypos, 1}]), + ets:insert(jlib, {string_to_jid_pattern, SplitPattern}), + ok. + %send_iq(From, To, ID, SubTags) -> % ok. @@ -215,7 +223,7 @@ make_jid({User, Server, Resource}) -> make_jid(User, Server, Resource). %% This is the reverse of make_jid/1 --spec split_jid(jid()) -> {binary(), binary(), binary()} | error. +-spec split_jid(jid()) -> {binary(), binary(), binary()} | error. split_jid(#jid{user = U, server = S, resource = R}) -> {U, S, R}; split_jid(_) -> @@ -224,36 +232,44 @@ split_jid(_) -> -spec string_to_jid(binary()) -> jid() | error. string_to_jid(S) -> - string_to_jid1(binary_to_list(S), ""). - -string_to_jid1([$@ | _J], "") -> error; -string_to_jid1([$@ | J], N) -> - string_to_jid2(J, lists:reverse(N), ""); -string_to_jid1([$/ | _J], "") -> error; -string_to_jid1([$/ | J], N) -> - string_to_jid3(J, "", lists:reverse(N), ""); -string_to_jid1([C | J], N) -> - string_to_jid1(J, [C | N]); -string_to_jid1([], "") -> error; -string_to_jid1([], N) -> - make_jid(<<"">>, list_to_binary(lists:reverse(N)), <<"">>). - -%% Only one "@" is admitted per JID -string_to_jid2([$@ | _J], _N, _S) -> error; -string_to_jid2([$/ | _J], _N, "") -> error; -string_to_jid2([$/ | J], N, S) -> - string_to_jid3(J, N, lists:reverse(S), ""); -string_to_jid2([C | J], N, S) -> - string_to_jid2(J, N, [C | S]); -string_to_jid2([], _N, "") -> error; -string_to_jid2([], N, S) -> - make_jid(list_to_binary(N), list_to_binary(lists:reverse(S)), <<"">>). - -string_to_jid3([C | J], N, S, R) -> - string_to_jid3(J, N, S, [C | R]); -string_to_jid3([], N, S, R) -> - make_jid(list_to_binary(N), list_to_binary(S), - list_to_binary(lists:reverse(R))). + SplitPattern = ets:lookup_element(jlib, string_to_jid_pattern, 2), + Size = size(S), + End = Size-1, + case binary:match(S, SplitPattern) of + {0, _} -> + error; + {End, _} -> + error; + {Pos1, _} -> + case binary:at(S, Pos1) of + $/ -> + make_jid(<<>>, + binary:part(S, 0, Pos1), + binary:part(S, Pos1+1, Size-Pos1-1)); + _ -> + Pos1N = Pos1+1, + case binary:match(S, SplitPattern, [{scope, {Pos1+1, Size-Pos1-1}}]) of + {End, _} -> + error; + {Pos1N, _} -> + error; + {Pos2, _} -> + case binary:at(S, Pos2) of + $/ -> + make_jid(binary:part(S, 0, Pos1), + binary:part(S, Pos1+1, Pos2-Pos1-1), + binary:part(S, Pos2+1, Size-Pos2-1)); + _ -> error + end; + _ -> + make_jid(binary:part(S, 0, Pos1), + binary:part(S, Pos1+1, Size-Pos1-1), + <<>>) + end + end; + _ -> + make_jid(<<>>, S, <<>>) + end. -spec jid_to_string(jid() | ljid()) -> binary(). @@ -856,7 +872,7 @@ decode_base64(S) -> decode_base64_bin(S, <<>>) end. -take_without_spaces(Bin, Count) -> +take_without_spaces(Bin, Count) -> take_without_spaces(Bin, Count, <<>>). take_without_spaces(Bin, 0, Acc) -> From 46bf190fd0458306f7eec05dfe58960d88db7f3d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 4 Nov 2015 01:19:19 +0100 Subject: [PATCH 341/695] mod_client_state: Add my email address to header --- src/mod_client_state.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index eb40db1095f..4934db3bc2c 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -1,8 +1,8 @@ %%%---------------------------------------------------------------------- %%% File : mod_client_state.erl -%%% Author : Holger Weiss +%%% Author : Holger Weiss %%% Purpose : Filter stanzas sent to inactive clients (XEP-0352) -%%% Created : 11 Sep 2014 by Holger Weiss +%%% Created : 11 Sep 2014 by Holger Weiss %%% %%% %%% ejabberd, Copyright (C) 2014-2015 ProcessOne From fec7e47169142d428cb6f779552b6bf2e1dea91b Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 4 Nov 2015 01:22:39 +0100 Subject: [PATCH 342/695] Add copyright and license to HTTP upload modules --- src/mod_http_upload.erl | 22 ++++++++++++++++++++-- src/mod_http_upload_quota.erl | 22 ++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index c51c60e0b19..72642665b8f 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -1,9 +1,27 @@ -%%%------------------------------------------------------------------- +%%%---------------------------------------------------------------------- %%% File : mod_http_upload.erl %%% Author : Holger Weiss %%% Purpose : HTTP File Upload (XEP-0363) %%% Created : 20 Aug 2015 by Holger Weiss -%%%------------------------------------------------------------------- +%%% +%%% +%%% ejabberd, Copyright (C) 2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(mod_http_upload). -author('holger@zedat.fu-berlin.de'). diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index 7d8ff103a60..8042ffd82f7 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -1,9 +1,27 @@ -%%%------------------------------------------------------------------- +%%%---------------------------------------------------------------------- %%% File : mod_http_upload_quota.erl %%% Author : Holger Weiss %%% Purpose : Quota management for HTTP File Upload (XEP-0363) %%% Created : 15 Oct 2015 by Holger Weiss -%%%------------------------------------------------------------------- +%%% +%%% +%%% ejabberd, Copyright (C) 2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(mod_http_upload_quota). -author('holger@zedat.fu-berlin.de'). From 341be9b6820d2d2ee0113dce3f66b0d6571fd95f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 4 Nov 2015 16:24:35 +0100 Subject: [PATCH 343/695] Remove supervisor option, disable it for c2s and muc --- configure.ac | 9 --------- rebar.config.script | 2 -- src/ejabberd_c2s.erl | 13 +++---------- src/ejabberd_s2s_in.erl | 19 +++---------------- src/ejabberd_s2s_out.erl | 12 ++---------- src/ejabberd_sup.erl | 8 -------- src/mod_muc.erl | 15 --------------- src/mod_muc_room.erl | 25 ++++++------------------- vars.config.in | 1 - 9 files changed, 14 insertions(+), 90 deletions(-) diff --git a/configure.ac b/configure.ac index c7e7bcd4ad2..57b9aa7473d 100644 --- a/configure.ac +++ b/configure.ac @@ -83,14 +83,6 @@ AC_ARG_ENABLE(roster_gateway_workaround, *) AC_MSG_ERROR(bad value ${enableval} for --enable-roster-gateway-workaround) ;; esac],[roster_gateway_workaround=false]) -AC_ARG_ENABLE(transient_supervisors, -[AC_HELP_STRING([--disable-transient-supervisors], [disable Erlang supervision for transient processes (default: no)])], -[case "${enableval}" in - yes) transient_supervisors=true ;; - no) transient_supervisors=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-transient_supervisors) ;; -esac],[transient_supervisors=true]) - AC_ARG_ENABLE(full_xml, [AC_HELP_STRING([--enable-full-xml], [use XML features in XMPP stream (ex: CDATA) (default: no, requires XML compliant clients)])], [case "${enableval}" in @@ -256,7 +248,6 @@ fi AC_SUBST(hipe) AC_SUBST(roster_gateway_workaround) -AC_SUBST(transient_supervisors) AC_SUBST(full_xml) AC_SUBST(nif) AC_SUBST(db_type) diff --git a/rebar.config.script b/rebar.config.script index e0a8923cfc0..cdd2a65ce0a 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -19,8 +19,6 @@ Cfg = case file:consult("vars.config") of Macros = lists:flatmap( fun({roster_gateway_workaround, true}) -> [{d, 'ROSTER_GATEWAY_WORKAROUND'}]; - ({transient_supervisors, false}) -> - [{d, 'NO_TRANSIENT_SUPERVISORS'}]; ({nif, true}) -> [{d, 'NIF'}]; ({db_type, mssql}) -> diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 69b46523845..57cf50641ed 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -129,15 +129,6 @@ -endif. -%% Module start with or without supervisor: --ifdef(NO_TRANSIENT_SUPERVISORS). --define(SUPERVISOR_START, ?GEN_FSM:start(ejabberd_c2s, [SockData, Opts], - fsm_limit_opts(Opts) ++ ?FSMOPTS)). --else. --define(SUPERVISOR_START, supervisor:start_child(ejabberd_c2s_sup, - [SockData, Opts])). --endif. - %% This is the timeout to apply between event when starting a new %% session: -define(C2S_OPEN_TIMEOUT, 60000). @@ -201,7 +192,9 @@ %%% API %%%---------------------------------------------------------------------- start(SockData, Opts) -> - ?SUPERVISOR_START. + ?GEN_FSM:start(ejabberd_c2s, + [SockData, Opts], + fsm_limit_opts(Opts) ++ ?FSMOPTS). start_link(SockData, Opts) -> (?GEN_FSM):start_link(ejabberd_c2s, diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index d840c315877..e655397b81e 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -74,21 +74,6 @@ -endif. -%% Module start with or without supervisor: --ifdef(NO_TRANSIENT_SUPERVISORS). - --define(SUPERVISOR_START, - p1_fsm:start(ejabberd_s2s_in, [SockData, Opts], - ?FSMOPTS ++ fsm_limit_opts(Opts))). - --else. - --define(SUPERVISOR_START, - supervisor:start_child(ejabberd_s2s_in_sup, - [SockData, Opts])). - --endif. - -define(STREAM_HEADER(Version), <<" <<"text/xml; charset=utf-8">>}], xml:element_to_binary(ThumbEl)} end; - {error, _} -> + pass -> ok end; ok -> @@ -873,7 +873,7 @@ code_to_message(_Code) -> <<"">>. %%-------------------------------------------------------------------- %% Image manipulation stuff %%-------------------------------------------------------------------- --spec identify(binary()) -> {ok, media_info()} | {error, binary()}. +-spec identify(binary()) -> {ok, media_info()} | pass. identify(Path) -> Cmd = lists:flatten(io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", @@ -887,7 +887,7 @@ identify(Path) -> width = list_to_integer(W)}}; _ -> ?DEBUG("failed to identify type of ~s: ~s", [Path, Res]), - {error, list_to_binary(Res)} + pass end. -spec convert(binary(), media_info()) -> {ok, binary()} | pass. @@ -929,7 +929,7 @@ thumb_el(Path, URI) -> {<<"uri">>, URI}, {<<"height">>, jlib:integer_to_binary(H)}, {<<"width">>, jlib:integer_to_binary(W)}]}; - {error, _} -> + pass -> #xmlel{name = <<"thumbnail">>, attrs = [{<<"xmlns">>, ?NS_THUMBS_1}, {<<"uri">>, URI}, From 842db2ca15e9d64a3427b07fb7021666b5c46206 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 9 Nov 2015 18:50:45 +0100 Subject: [PATCH 347/695] mod_http_upload: Don't flatten command strings --- src/mod_http_upload.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 3e154d1cec4..b79c4530989 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -876,8 +876,7 @@ code_to_message(_Code) -> <<"">>. -spec identify(binary()) -> {ok, media_info()} | pass. identify(Path) -> - Cmd = lists:flatten(io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", - [Path])), + Cmd = io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", [Path]), Res = string:strip(os:cmd(Cmd), right, $\n), case string:tokens(Res, " ") of ["ok", T, H, W] -> @@ -902,8 +901,7 @@ convert(Path, #media_info{type = T, width = W, height = H}) -> Dir = filename:dirname(Path), FileName = <<(randoms:get_string())/binary, $., T/binary>>, OutPath = filename:join(Dir, FileName), - Cmd = lists:flatten(io_lib:fwrite("convert -resize 300 ~s ~s", - [Path, OutPath])), + Cmd = io_lib:fwrite("convert -resize 300 ~s ~s", [Path, OutPath]), case os:cmd(Cmd) of "" -> {ok, OutPath}; From 113c31585752cd2028fa038c439fffc58deff8ea Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 9 Nov 2015 19:12:08 +0100 Subject: [PATCH 348/695] mod_http_upload: Apply cosmetic changes --- src/mod_http_upload.erl | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index b79c4530989..e5b9d52253c 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -117,7 +117,7 @@ width :: integer()}). -type state() :: #state{}. --type slot() :: [binary()]. +-type slot() :: [binary(), ...]. -type media_info() :: #media_info{}. %%-------------------------------------------------------------------- @@ -450,7 +450,7 @@ process(LocalPath, #request{method = Method, host = Host, ip = IP}) [Path, ?ADDR_TO_STR(IP)]), http_response(Host, 403); {error, enoent} -> - ?INFO_MSG("Cannot serve ~s to ~s: No such file or directory", + ?INFO_MSG("Cannot serve ~s to ~s: No such file", [Path, ?ADDR_TO_STR(IP)]), http_response(Host, 404); {error, eisdir} -> @@ -636,7 +636,7 @@ create_slot(#state{service_url = ServiceURL}, [jlib:jid_to_string(JID), File]), {ok, PutURL, GetURL}; Lines -> - ?ERROR_MSG("Cannot parse data received for ~s from <~s>: ~p", + ?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p", [jlib:jid_to_string(JID), ServiceURL, Lines]), {error, ?ERR_SERVICE_UNAVAILABLE} end; @@ -754,7 +754,7 @@ iq_disco_info(Lang, Name) -> -spec store_file(binary(), binary(), integer() | undefined, integer() | undefined, - binary(), binary(), boolean()) + binary(), slot(), boolean()) -> ok | {ok, [{binary(), binary()}], binary()} | {error, term()}. store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> @@ -763,10 +763,8 @@ store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> case identify(Path) of {ok, MediaInfo} -> case convert(Path, MediaInfo) of - pass -> - ok; {ok, OutPath} -> - [UserDir, RandDir|_] = LocalPath, + [UserDir, RandDir | _] = LocalPath, FileName = filename:basename(OutPath), URL = str:join([GetPrefix, UserDir, RandDir, FileName], <<$/>>), @@ -774,7 +772,9 @@ store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> {ok, [{<<"Content-Type">>, <<"text/xml; charset=utf-8">>}], - xml:element_to_binary(ThumbEl)} + xml:element_to_binary(ThumbEl)}; + pass -> + ok end; pass -> ok @@ -871,47 +871,47 @@ code_to_message(500) -> <<"Internal server error.">>; code_to_message(_Code) -> <<"">>. %%-------------------------------------------------------------------- -%% Image manipulation stuff +%% Image manipulation stuff. %%-------------------------------------------------------------------- + -spec identify(binary()) -> {ok, media_info()} | pass. identify(Path) -> - Cmd = io_lib:fwrite("identify -format \"ok %m %h %w\" ~s", [Path]), + Cmd = io_lib:format("identify -format 'ok %m %h %w' ~s", [Path]), Res = string:strip(os:cmd(Cmd), right, $\n), case string:tokens(Res, " ") of ["ok", T, H, W] -> - {ok, #media_info{ - type = list_to_binary(string:to_lower(T)), - height = list_to_integer(H), - width = list_to_integer(W)}}; + {ok, #media_info{type = list_to_binary(string:to_lower(T)), + height = list_to_integer(H), + width = list_to_integer(W)}}; _ -> - ?DEBUG("failed to identify type of ~s: ~s", [Path, Res]), + ?DEBUG("Cannot identify type of ~s: ~s", [Path, Res]), pass end. -spec convert(binary(), media_info()) -> {ok, binary()} | pass. convert(Path, #media_info{type = T, width = W, height = H}) -> - if W*H >= 25000000 -> - ?DEBUG("the image ~s is more than 25 Mbpx", [Path]), + if W * H >= 25000000 -> + ?DEBUG("The image ~s is more than 25 Mpix", [Path]), pass; - (W =< 300) and (H =< 300) -> + W =< 300, H =< 300 -> {ok, Path}; T == <<"gif">>; T == <<"jpeg">>; T == <<"png">>; T == <<"webp">> -> Dir = filename:dirname(Path), FileName = <<(randoms:get_string())/binary, $., T/binary>>, OutPath = filename:join(Dir, FileName), - Cmd = io_lib:fwrite("convert -resize 300 ~s ~s", [Path, OutPath]), + Cmd = io_lib:format("convert -resize 300 ~s ~s", [Path, OutPath]), case os:cmd(Cmd) of "" -> {ok, OutPath}; Err -> - ?ERROR_MSG("failed to convert ~s to ~s: ~s", + ?ERROR_MSG("Failed to convert ~s to ~s: ~s", [Path, OutPath, string:strip(Err, right, $\n)]), pass end; true -> - ?DEBUG("do not call 'convert' for unknown type ~s", [T]), + ?DEBUG("Won't call 'convert' for unknown type ~s", [T]), pass end. From 20709f9880203a050ccbc283deed11778a761ef8 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 9 Nov 2015 19:23:52 +0100 Subject: [PATCH 349/695] mod_http_upload: Make case indentation consistent Use four spaces (or the corresponding amount of tab characters) for case indentation everywhere in mod_http_upload and mod_http_upload_quota. --- src/mod_http_upload.erl | 439 +++++++++++++++++----------------- src/mod_http_upload_quota.erl | 153 ++++++------ 2 files changed, 300 insertions(+), 292 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index e5b9d52253c..a0cefde50eb 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -136,12 +136,13 @@ start(ServerHost, Opts) -> case gen_mod:get_opt(rm_on_unregister, Opts, fun(B) when is_boolean(B) -> B end, true) of - true -> - ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, - remove_user, 50), - ejabberd_hooks:add(anonymous_purge_hook, ServerHost, ?MODULE, - remove_user, 50); - false -> ok + true -> + ejabberd_hooks:add(remove_user, ServerHost, ?MODULE, + remove_user, 50), + ejabberd_hooks:add(anonymous_purge_hook, ServerHost, ?MODULE, + remove_user, 50); + false -> + ok end, Proc = get_proc_name(ServerHost, ?PROCNAME), Spec = {Proc, @@ -158,12 +159,13 @@ stop(ServerHost) -> case gen_mod:get_module_opt(ServerHost, ?MODULE, rm_on_unregister, fun(B) when is_boolean(B) -> B end, true) of - true -> - ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, - remove_user, 50), - ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, ?MODULE, - remove_user, 50); - false -> ok + true -> + ejabberd_hooks:delete(remove_user, ServerHost, ?MODULE, + remove_user, 50), + ejabberd_hooks:delete(anonymous_purge_hook, ServerHost, ?MODULE, + remove_user, 50); + false -> + ok end, Proc = get_proc_name(ServerHost, ?PROCNAME), supervisor:terminate_child(ejabberd_sup, Proc), @@ -273,34 +275,34 @@ init({ServerHost, Opts}) -> fun(B) when is_boolean(B) -> B end, true), case ServiceURL of - undefined -> - ok; - <<"http://", _/binary>> -> - application:start(inets); - <<"https://", _/binary>> -> - application:start(inets), - application:start(crypto), - application:start(asn1), - application:start(public_key), - application:start(ssl) + undefined -> + ok; + <<"http://", _/binary>> -> + application:start(inets); + <<"https://", _/binary>> -> + application:start(inets), + application:start(crypto), + application:start(asn1), + application:start(public_key), + application:start(ssl) end, case DirMode of - undefined -> - ok; - Mode -> - file:change_mode(DocRoot, Mode) + undefined -> + ok; + Mode -> + file:change_mode(DocRoot, Mode) end, case Thumbnail of - true -> - case string:str(os:cmd("identify"), "Magick") of - 0 -> - ?ERROR_MSG("Cannot find 'identify' command, please install " - "ImageMagick or disable thumbnail creation", []); - _ -> - ok - end; - false -> - ok + true -> + case string:str(os:cmd("identify"), "Magick") of + 0 -> + ?ERROR_MSG("Cannot find 'identify' command, please install " + "ImageMagick or disable thumbnail creation", []); + _ -> + ok + end; + false -> + ok end, ejabberd_router:register_route(Host), {ok, #state{server_host = ServerHost, host = Host, name = Name, @@ -325,14 +327,14 @@ handle_call({use_slot, Slot}, _From, #state{file_mode = FileMode, thumbnail = Thumbnail, docroot = DocRoot} = State) -> case get_slot(Slot, State) of - {ok, {Size, Timer}} -> - timer:cancel(Timer), - NewState = del_slot(Slot, State), - Path = str:join([DocRoot | Slot], <<$/>>), - {reply, {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail}, - NewState}; - error -> - {reply, {error, <<"Invalid slot">>}, State} + {ok, {Size, Timer}} -> + timer:cancel(Timer), + NewState = del_slot(Slot, State), + Path = str:join([DocRoot | Slot], <<$/>>), + {reply, {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail}, + NewState}; + error -> + {reply, {error, <<"Invalid slot">>}, State} end; handle_call(get_docroot, _From, #state{docroot = DocRoot} = State) -> {reply, {ok, DocRoot}, State}; @@ -351,12 +353,12 @@ handle_cast(Request, State) -> handle_info({route, From, To, #xmlel{name = <<"iq">>} = Stanza}, State) -> Request = jlib:iq_query_info(Stanza), {Reply, NewState} = case process_iq(From, Request, State) of - R when is_record(R, iq) -> - {R, State}; - {R, S} -> - {R, S}; - not_request -> - {none, State} + R when is_record(R, iq) -> + {R, State}; + {R, S} -> + {R, S}; + not_request -> + {none, State} end, if Reply /= none -> ejabberd_router:route(To, From, jlib:iq_to_xml(Reply)); @@ -395,77 +397,77 @@ process(LocalPath, #request{method = 'PUT', host = Host, ip = IP, data = Data}) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), case catch gen_server:call(Proc, {use_slot, LocalPath}) of - {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail} - when byte_size(Data) == Size -> - ?DEBUG("Storing file from ~s for ~s: ~s", - [?ADDR_TO_STR(IP), Host, Path]), - case store_file(Path, Data, FileMode, DirMode, - GetPrefix, LocalPath, Thumbnail) of - ok -> - http_response(Host, 201); - {ok, Headers, OutData} -> - http_response(Host, 201, Headers, OutData); - {error, Error} -> - ?ERROR_MSG("Cannot store file ~s from ~s for ~s: ~p", - [Path, ?ADDR_TO_STR(IP), Host, Error]), - http_response(Host, 500) - end; - {ok, Size, Path} -> - ?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B", - [Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]), - http_response(Host, 413); - {error, Error} -> - ?INFO_MSG("Rejecting file from ~s for ~s: ~p", - [?ADDR_TO_STR(IP), Host, Error]), - http_response(Host, 403); - Error -> - ?ERROR_MSG("Cannot handle PUT request from ~s for ~s: ~p", - [?ADDR_TO_STR(IP), Host, Error]), - http_response(Host, 500) + {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail} + when byte_size(Data) == Size -> + ?DEBUG("Storing file from ~s for ~s: ~s", + [?ADDR_TO_STR(IP), Host, Path]), + case store_file(Path, Data, FileMode, DirMode, + GetPrefix, LocalPath, Thumbnail) of + ok -> + http_response(Host, 201); + {ok, Headers, OutData} -> + http_response(Host, 201, Headers, OutData); + {error, Error} -> + ?ERROR_MSG("Cannot store file ~s from ~s for ~s: ~p", + [Path, ?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 500) + end; + {ok, Size, Path} -> + ?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B", + [Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]), + http_response(Host, 413); + {error, Error} -> + ?INFO_MSG("Rejecting file from ~s for ~s: ~p", + [?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 403); + Error -> + ?ERROR_MSG("Cannot handle PUT request from ~s for ~s: ~p", + [?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 500) end; process(LocalPath, #request{method = Method, host = Host, ip = IP}) when Method == 'GET'; Method == 'HEAD' -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), case catch gen_server:call(Proc, get_docroot) of - {ok, DocRoot} -> - Path = str:join([DocRoot | LocalPath], <<$/>>), - case file:read_file(Path) of - {ok, Data} -> - ?INFO_MSG("Serving ~s to ~s", [Path, ?ADDR_TO_STR(IP)]), - FileName = lists:last(LocalPath), - ContentType = guess_content_type(FileName), - Headers1 = case ContentType of - <<"image/", _SubType/binary>> -> []; - <<"text/", _SubType/binary>> -> []; - _ -> - [{<<"Content-Disposition">>, - <<"attachment; filename=", - $", FileName/binary, $">>}] - end, - Headers2 = [{<<"Content-Type">>, ContentType} | Headers1], - http_response(Host, 200, Headers2, Data); - {error, eacces} -> - ?INFO_MSG("Cannot serve ~s to ~s: Permission denied", - [Path, ?ADDR_TO_STR(IP)]), - http_response(Host, 403); - {error, enoent} -> - ?INFO_MSG("Cannot serve ~s to ~s: No such file", - [Path, ?ADDR_TO_STR(IP)]), - http_response(Host, 404); - {error, eisdir} -> - ?INFO_MSG("Cannot serve ~s to ~s: Is a directory", - [Path, ?ADDR_TO_STR(IP)]), - http_response(Host, 404); - {error, Error} -> - ?INFO_MSG("Cannot serve ~s to ~s: ~s", - [Path, ?ADDR_TO_STR(IP), ?FORMAT(Error)]), - http_response(Host, 500) - end; - Error -> - ?ERROR_MSG("Cannot handle ~s request from ~s for ~s: ~p", - [Method, ?ADDR_TO_STR(IP), Host, Error]), - http_response(Host, 500) + {ok, DocRoot} -> + Path = str:join([DocRoot | LocalPath], <<$/>>), + case file:read_file(Path) of + {ok, Data} -> + ?INFO_MSG("Serving ~s to ~s", [Path, ?ADDR_TO_STR(IP)]), + FileName = lists:last(LocalPath), + ContentType = guess_content_type(FileName), + Headers1 = case ContentType of + <<"image/", _SubType/binary>> -> []; + <<"text/", _SubType/binary>> -> []; + _ -> + [{<<"Content-Disposition">>, + <<"attachment; filename=", + $", FileName/binary, $">>}] + end, + Headers2 = [{<<"Content-Type">>, ContentType} | Headers1], + http_response(Host, 200, Headers2, Data); + {error, eacces} -> + ?INFO_MSG("Cannot serve ~s to ~s: Permission denied", + [Path, ?ADDR_TO_STR(IP)]), + http_response(Host, 403); + {error, enoent} -> + ?INFO_MSG("Cannot serve ~s to ~s: No such file", + [Path, ?ADDR_TO_STR(IP)]), + http_response(Host, 404); + {error, eisdir} -> + ?INFO_MSG("Cannot serve ~s to ~s: Is a directory", + [Path, ?ADDR_TO_STR(IP)]), + http_response(Host, 404); + {error, Error} -> + ?INFO_MSG("Cannot serve ~s to ~s: ~s", + [Path, ?ADDR_TO_STR(IP), ?FORMAT(Error)]), + http_response(Host, 500) + end; + Error -> + ?ERROR_MSG("Cannot handle ~s request from ~s for ~s: ~p", + [Method, ?ADDR_TO_STR(IP), Host, Error]), + http_response(Host, 500) end; process(_LocalPath, #request{method = 'OPTIONS', host = Host, ip = IP}) -> ?DEBUG("Responding to OPTIONS request from ~s for ~s", @@ -525,31 +527,33 @@ process_iq(From, when XMLNS == ?NS_HTTP_UPLOAD; XMLNS == ?NS_HTTP_UPLOAD_OLD -> case acl:match_rule(ServerHost, Access, From) of - allow -> - case parse_request(SubEl, Lang) of - {ok, File, Size, ContentType} -> - case create_slot(State, From, File, Size, ContentType, Lang) of - {ok, Slot} -> - {ok, Timer} = timer:send_after(?SLOT_TIMEOUT, - {slot_timed_out, Slot}), - NewState = add_slot(Slot, Size, Timer, State), - SlotEl = slot_el(Slot, State, XMLNS), - {IQ#iq{type = result, sub_el = [SlotEl]}, NewState}; - {ok, PutURL, GetURL} -> - SlotEl = slot_el(PutURL, GetURL, XMLNS), - IQ#iq{type = result, sub_el = [SlotEl]}; - {error, Error} -> - IQ#iq{type = error, sub_el = [SubEl, Error]} - end; - {error, Error} -> - ?DEBUG("Cannot parse request from ~s", - [jlib:jid_to_string(From)]), - IQ#iq{type = error, sub_el = [SubEl, Error]} - end; - deny -> - ?DEBUG("Denying HTTP upload slot request from ~s", - [jlib:jid_to_string(From)]), - IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} + allow -> + case parse_request(SubEl, Lang) of + {ok, File, Size, ContentType} -> + case create_slot(State, From, File, Size, ContentType, + Lang) of + {ok, Slot} -> + {ok, Timer} = timer:send_after(?SLOT_TIMEOUT, + {slot_timed_out, + Slot}), + NewState = add_slot(Slot, Size, Timer, State), + SlotEl = slot_el(Slot, State, XMLNS), + {IQ#iq{type = result, sub_el = [SlotEl]}, NewState}; + {ok, PutURL, GetURL} -> + SlotEl = slot_el(PutURL, GetURL, XMLNS), + IQ#iq{type = result, sub_el = [SlotEl]}; + {error, Error} -> + IQ#iq{type = error, sub_el = [SubEl, Error]} + end; + {error, Error} -> + ?DEBUG("Cannot parse request from ~s", + [jlib:jid_to_string(From)]), + IQ#iq{type = error, sub_el = [SubEl, Error]} + end; + deny -> + ?DEBUG("Denying HTTP upload slot request from ~s", + [jlib:jid_to_string(From)]), + IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; process_iq(_From, #iq{sub_el = SubEl} = IQ, _State) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; @@ -563,25 +567,25 @@ process_iq(_From, invalid, _State) -> parse_request(#xmlel{name = <<"request">>, attrs = Attrs} = Request, Lang) -> case xml:get_attr(<<"xmlns">>, Attrs) of - {value, XMLNS} when XMLNS == ?NS_HTTP_UPLOAD; - XMLNS == ?NS_HTTP_UPLOAD_OLD -> - case {xml:get_subtag_cdata(Request, <<"filename">>), - xml:get_subtag_cdata(Request, <<"size">>), - xml:get_subtag_cdata(Request, <<"content-type">>)} of - {File, SizeStr, ContentType} when byte_size(File) > 0 -> - case catch jlib:binary_to_integer(SizeStr) of - Size when is_integer(Size), Size > 0 -> - {ok, File, Size, yield_content_type(ContentType)}; - _ -> - Text = <<"Please specify file size.">>, - {error, ?ERRT_BAD_REQUEST(Lang, Text)} - end; - _ -> - Text = <<"Please specify file name.">>, - {error, ?ERRT_BAD_REQUEST(Lang, Text)} - end; - _ -> - {error, ?ERR_BAD_REQUEST} + {value, XMLNS} when XMLNS == ?NS_HTTP_UPLOAD; + XMLNS == ?NS_HTTP_UPLOAD_OLD -> + case {xml:get_subtag_cdata(Request, <<"filename">>), + xml:get_subtag_cdata(Request, <<"size">>), + xml:get_subtag_cdata(Request, <<"content-type">>)} of + {File, SizeStr, ContentType} when byte_size(File) > 0 -> + case catch jlib:binary_to_integer(SizeStr) of + Size when is_integer(Size), Size > 0 -> + {ok, File, Size, yield_content_type(ContentType)}; + _ -> + Text = <<"Please specify file size.">>, + {error, ?ERRT_BAD_REQUEST(Lang, Text)} + end; + _ -> + Text = <<"Please specify file name.">>, + {error, ?ERRT_BAD_REQUEST(Lang, Text)} + end; + _ -> + {error, ?ERR_BAD_REQUEST} end; parse_request(_El, _Lang) -> {error, ?ERR_BAD_REQUEST}. @@ -606,16 +610,16 @@ create_slot(#state{service_url = undefined, UserDir = <>, case ejabberd_hooks:run_fold(http_upload_slot_request, ServerHost, allow, [JID, UserDir, Size, Lang]) of - allow -> - RandStr = make_rand_string(SecretLength), - FileStr = make_file_string(File), - ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", - [jlib:jid_to_string(JID), File]), - {ok, [UserStr, RandStr, FileStr]}; - deny -> - {error, ?ERR_SERVICE_UNAVAILABLE}; - #xmlel{} = Error -> - {error, Error} + allow -> + RandStr = make_rand_string(SecretLength), + FileStr = make_file_string(File), + ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", + [jlib:jid_to_string(JID), File]), + {ok, [UserStr, RandStr, FileStr]}; + deny -> + {error, ?ERR_SERVICE_UNAVAILABLE}; + #xmlel{} = Error -> + {error, Error} end; create_slot(#state{service_url = ServiceURL}, #jid{luser = U, lserver = S} = JID, File, Size, ContentType, @@ -629,37 +633,38 @@ create_slot(#state{service_url = ServiceURL}, "&size=" ++ ?URL_ENC(SizeStr) ++ "&content_type=" ++ ?URL_ENC(ContentType), case httpc:request(get, {GetRequest, []}, HttpOptions, Options) of - {ok, {Code, Body}} when Code >= 200, Code =< 299 -> - case binary:split(Body, <<$\n>>, [global, trim]) of - [<<"http", _/binary>> = PutURL, <<"http", _/binary>> = GetURL] -> - ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", - [jlib:jid_to_string(JID), File]), - {ok, PutURL, GetURL}; - Lines -> - ?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p", - [jlib:jid_to_string(JID), ServiceURL, Lines]), - {error, ?ERR_SERVICE_UNAVAILABLE} - end; - {ok, {402, _Body}} -> - ?INFO_MSG("Got status code 402 for ~s from <~s>", - [jlib:jid_to_string(JID), ServiceURL]), - {error, ?ERR_RESOURCE_CONSTRAINT}; - {ok, {403, _Body}} -> - ?INFO_MSG("Got status code 403 for ~s from <~s>", - [jlib:jid_to_string(JID), ServiceURL]), - {error, ?ERR_NOT_ALLOWED}; - {ok, {413, _Body}} -> - ?INFO_MSG("Got status code 413 for ~s from <~s>", - [jlib:jid_to_string(JID), ServiceURL]), - {error, ?ERR_NOT_ACCEPTABLE}; - {ok, {Code, _Body}} -> - ?ERROR_MSG("Got unexpected status code for ~s from <~s>: ~B", - [jlib:jid_to_string(JID), ServiceURL, Code]), - {error, ?ERR_SERVICE_UNAVAILABLE}; - {error, Reason} -> - ?ERROR_MSG("Error requesting upload slot for ~s from <~s>: ~p", - [jlib:jid_to_string(JID), ServiceURL, Reason]), - {error, ?ERR_SERVICE_UNAVAILABLE} + {ok, {Code, Body}} when Code >= 200, Code =< 299 -> + case binary:split(Body, <<$\n>>, [global, trim]) of + [<<"http", _/binary>> = PutURL, + <<"http", _/binary>> = GetURL] -> + ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", + [jlib:jid_to_string(JID), File]), + {ok, PutURL, GetURL}; + Lines -> + ?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p", + [jlib:jid_to_string(JID), ServiceURL, Lines]), + {error, ?ERR_SERVICE_UNAVAILABLE} + end; + {ok, {402, _Body}} -> + ?INFO_MSG("Got status code 402 for ~s from <~s>", + [jlib:jid_to_string(JID), ServiceURL]), + {error, ?ERR_RESOURCE_CONSTRAINT}; + {ok, {403, _Body}} -> + ?INFO_MSG("Got status code 403 for ~s from <~s>", + [jlib:jid_to_string(JID), ServiceURL]), + {error, ?ERR_NOT_ALLOWED}; + {ok, {413, _Body}} -> + ?INFO_MSG("Got status code 413 for ~s from <~s>", + [jlib:jid_to_string(JID), ServiceURL]), + {error, ?ERR_NOT_ACCEPTABLE}; + {ok, {Code, _Body}} -> + ?ERROR_MSG("Got unexpected status code for ~s from <~s>: ~B", + [jlib:jid_to_string(JID), ServiceURL, Code]), + {error, ?ERR_SERVICE_UNAVAILABLE}; + {error, Reason} -> + ?ERROR_MSG("Error requesting upload slot for ~s from <~s>: ~p", + [jlib:jid_to_string(JID), ServiceURL, Reason]), + {error, ?ERR_SERVICE_UNAVAILABLE} end. -spec add_slot(slot(), pos_integer(), timer:tref(), state()) -> state(). @@ -811,10 +816,10 @@ do_store_file(Path, Data, FileMode, DirMode) -> end, ok = Ok % Raise an exception if file:write/2 failed. catch - _:{badmatch, {error, Error}} -> - {error, ?FORMAT(Error)}; - _:Error -> - {error, Error} + _:{badmatch, {error, Error}} -> + {error, ?FORMAT(Error)}; + _:Error -> + {error, Error} end. -spec guess_content_type(binary()) -> binary(). @@ -852,11 +857,11 @@ http_response(Host, Code, ExtraHeaders, Body) -> end, []), Headers = case proplists:is_defined(<<"Content-Type">>, ExtraHeaders) of - true -> - [ServerHeader | ExtraHeaders]; - false -> - [ServerHeader, {<<"Content-Type">>, <<"text/plain">>} | - ExtraHeaders] + true -> + [ServerHeader | ExtraHeaders]; + false -> + [ServerHeader, {<<"Content-Type">>, <<"text/plain">>} | + ExtraHeaders] end ++ CustomHeaders, {Code, Headers, Body}. @@ -972,16 +977,16 @@ del_tree(Dir) -> {ok, Entries} = file:list_dir(Dir), lists:foreach(fun(Path) -> case filelib:is_dir(Path) of - true -> - ok = del_tree(Path); - false -> - ok = file:delete(Path) + true -> + ok = del_tree(Path); + false -> + ok = file:delete(Path) end end, [Dir ++ "/" ++ Entry || Entry <- Entries]), ok = file:del_dir(Dir) catch - _:{badmatch, {error, Error}} -> - {error, ?FORMAT(Error)}; - _:Error -> - {error, Error} + _:{badmatch, {error, Error}} -> + {error, ?FORMAT(Error)}; + _:Error -> + {error, Error} end. diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index 8042ffd82f7..c0f138f763f 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -161,42 +161,42 @@ handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, access_hard_quota = AccessHardQuota, disk_usage = DiskUsage} = State) -> HardQuota = case acl:match_rule(ServerHost, AccessHardQuota, JID) of - Hard when is_integer(Hard), Hard > 0 -> - Hard * 1024 * 1024; - _ -> - 0 + Hard when is_integer(Hard), Hard > 0 -> + Hard * 1024 * 1024; + _ -> + 0 end, SoftQuota = case acl:match_rule(ServerHost, AccessSoftQuota, JID) of - Soft when is_integer(Soft), Soft > 0 -> - Soft * 1024 * 1024; - _ -> - 0 + Soft when is_integer(Soft), Soft > 0 -> + Soft * 1024 * 1024; + _ -> + 0 end, OldSize = case dict:find({U, S}, DiskUsage) of - {ok, Value} -> - Value; - error -> - undefined + {ok, Value} -> + Value; + error -> + undefined end, NewSize = case {HardQuota, SoftQuota} of - {0, 0} -> - ?DEBUG("No quota specified for ~s", - [jlib:jid_to_string(JID)]), - Size; - {0, _} -> + {0, 0} -> + ?DEBUG("No quota specified for ~s", + [jlib:jid_to_string(JID)]), + Size; + {0, _} -> ?WARNING_MSG("No hard quota specified for ~s", [jlib:jid_to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); - {_, 0} -> + {_, 0} -> ?WARNING_MSG("No soft quota specified for ~s", [jlib:jid_to_string(JID)]), enforce_quota(Path, Size, OldSize, HardQuota, HardQuota); - _ when SoftQuota > HardQuota -> + _ when SoftQuota > HardQuota -> ?WARNING_MSG("Bad quota for ~s (soft: ~p, hard: ~p)", [jlib:jid_to_string(JID), SoftQuota, HardQuota]), enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); - _ -> + _ -> ?DEBUG("Enforcing quota for ~s", [jlib:jid_to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, HardQuota) @@ -214,17 +214,19 @@ handle_info(sweep, #state{server_host = ServerHost, when is_integer(MaxDays), MaxDays > 0 -> ?DEBUG("Got 'sweep' message for ~s", [ServerHost]), case file:list_dir(DocRoot) of - {ok, Entries} -> - BackThen = secs_since_epoch() - (MaxDays * 86400), - DocRootS = binary_to_list(DocRoot), - PathNames = lists:map(fun(Entry) -> DocRootS ++ "/" ++ Entry end, - Entries), - UserDirs = lists:filter(fun filelib:is_dir/1, PathNames), - lists:foreach(fun(UserDir) -> delete_old_files(UserDir, BackThen) end, - UserDirs); - {error, Error} -> - ?ERROR_MSG("Cannot open document root ~s: ~s", - [DocRoot, ?FORMAT(Error)]) + {ok, Entries} -> + BackThen = secs_since_epoch() - (MaxDays * 86400), + DocRootS = binary_to_list(DocRoot), + PathNames = lists:map(fun(Entry) -> + DocRootS ++ "/" ++ Entry + end, Entries), + UserDirs = lists:filter(fun filelib:is_dir/1, PathNames), + lists:foreach(fun(UserDir) -> + delete_old_files(UserDir, BackThen) + end, UserDirs); + {error, Error} -> + ?ERROR_MSG("Cannot open document root ~s: ~s", + [DocRoot, ?FORMAT(Error)]) end, {noreply, State}; handle_info(Info, State) -> @@ -294,14 +296,14 @@ enforce_quota(UserDir, SlotSize, _OldSize, MinSize, MaxSize) -> -spec delete_old_files(file:filename_all(), integer()) -> ok. -delete_old_files(UserDir, Timestamp) -> +delete_old_files(UserDir, CutOff) -> FileInfo = gather_file_info(UserDir), - case [Path || {Path, _Size, Time} <- FileInfo, Time < Timestamp] of - [] -> - ok; - OldFiles -> - lists:foreach(fun(File) -> del_file_and_dir(File) end, OldFiles), - file:del_dir(UserDir) % In case it's empty, now. + case [Path || {Path, _Size, Time} <- FileInfo, Time < CutOff] of + [] -> + ok; + OldFiles -> + lists:foreach(fun(File) -> del_file_and_dir(File) end, OldFiles), + file:del_dir(UserDir) % In case it's empty, now. end. -spec gather_file_info(file:filename_all()) @@ -311,49 +313,50 @@ gather_file_info(Dir) when is_binary(Dir) -> gather_file_info(binary_to_list(Dir)); gather_file_info(Dir) -> case file:list_dir(Dir) of - {ok, Entries} -> - lists:foldl(fun(Entry, Acc) -> - Path = Dir ++ "/" ++ Entry, - case file:read_file_info(Path, [{time, posix}]) of - {ok, #file_info{type = directory}} -> - gather_file_info(Path) ++ Acc; - {ok, #file_info{type = regular, - mtime = Time, - size = Size}} -> - [{Path, Size, Time} | Acc]; - {ok, _Info} -> - ?DEBUG("Won't stat(2) non-regular file ~s", - [Path]), - Acc; - {error, Error} -> - ?ERROR_MSG("Cannot stat(2) ~s: ~s", - [Path, ?FORMAT(Error)]), - Acc - end - end, [], Entries); - {error, enoent} -> - ?DEBUG("Directory ~s doesn't exist", [Dir]), - []; - {error, Error} -> - ?ERROR_MSG("Cannot open directory ~s: ~s", [Dir, ?FORMAT(Error)]), - [] + {ok, Entries} -> + lists:foldl(fun(Entry, Acc) -> + Path = Dir ++ "/" ++ Entry, + case file:read_file_info(Path, + [{time, posix}]) of + {ok, #file_info{type = directory}} -> + gather_file_info(Path) ++ Acc; + {ok, #file_info{type = regular, + mtime = Time, + size = Size}} -> + [{Path, Size, Time} | Acc]; + {ok, _Info} -> + ?DEBUG("Won't stat(2) non-regular file ~s", + [Path]), + Acc; + {error, Error} -> + ?ERROR_MSG("Cannot stat(2) ~s: ~s", + [Path, ?FORMAT(Error)]), + Acc + end + end, [], Entries); + {error, enoent} -> + ?DEBUG("Directory ~s doesn't exist", [Dir]), + []; + {error, Error} -> + ?ERROR_MSG("Cannot open directory ~s: ~s", [Dir, ?FORMAT(Error)]), + [] end. -spec del_file_and_dir(file:name_all()) -> ok. del_file_and_dir(File) -> case file:delete(File) of - ok -> - ?INFO_MSG("Removed ~s", [File]), - Dir = filename:dirname(File), - case file:del_dir(Dir) of - ok -> - ?DEBUG("Removed ~s", [Dir]); - {error, Error} -> - ?DEBUG("Cannot remove ~s: ~s", [Dir, ?FORMAT(Error)]) - end; - {error, Error} -> - ?WARNING_MSG("Cannot remove ~s: ~s", [File, ?FORMAT(Error)]) + ok -> + ?INFO_MSG("Removed ~s", [File]), + Dir = filename:dirname(File), + case file:del_dir(Dir) of + ok -> + ?DEBUG("Removed ~s", [Dir]); + {error, Error} -> + ?DEBUG("Cannot remove ~s: ~s", [Dir, ?FORMAT(Error)]) + end; + {error, Error} -> + ?WARNING_MSG("Cannot remove ~s: ~s", [File, ?FORMAT(Error)]) end. -spec secs_since_epoch() -> non_neg_integer(). From 415a75c25aa8efc67e4866e9e0da2bd3ff5ce0ee Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 10 Nov 2015 22:08:16 +0100 Subject: [PATCH 350/695] mod_http_upload_quota: Don't track all users Don't track the disk usage of accounts that have an unlimited quota. --- src/mod_http_upload_quota.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index c0f138f763f..d7576567e59 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -182,7 +182,7 @@ handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, {0, 0} -> ?DEBUG("No quota specified for ~s", [jlib:jid_to_string(JID)]), - Size; + undefined; {0, _} -> ?WARNING_MSG("No hard quota specified for ~s", [jlib:jid_to_string(JID)]), @@ -201,7 +201,12 @@ handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, [jlib:jid_to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, HardQuota) end, - {noreply, State#state{disk_usage = dict:store({U, S}, NewSize, DiskUsage)}}; + NewDiskUsage = if is_integer(NewSize) -> + dict:store({U, S}, NewSize, DiskUsage); + true -> + DiskUsage + end, + {noreply, State#state{disk_usage = NewDiskUsage}}; handle_cast(Request, State) -> ?ERROR_MSG("Got unexpected request: ~p", [Request]), {noreply, State}. From 55a92c2983d220bd56198144e8f0f5d4fef8263f Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 11 Nov 2015 22:51:40 +0100 Subject: [PATCH 351/695] mod_http_upload: Log message if URL looks wrong Log an [info] message if a PUT request looks like the specified "put_url" contains a path component that doesn't match the "request_handlers" path, as in the following configuration: listen: - module: ejabberd_http port: 5444 request_handlers: "/": mod_http_upload modules: mod_http_upload: put_url: "http://example.com/path/" --- src/mod_http_upload.erl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index a0cefde50eb..d32c5f097bc 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -393,16 +393,16 @@ code_change(_OldVsn, #state{server_host = ServerHost} = State, _Extra) -> -spec process([binary()], #request{}) -> {pos_integer(), [{binary(), binary()}], binary()}. -process(LocalPath, #request{method = 'PUT', host = Host, ip = IP, - data = Data}) -> +process([_UserDir, _RandDir, _FileName] = Slot, + #request{method = 'PUT', host = Host, ip = IP, data = Data}) -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), - case catch gen_server:call(Proc, {use_slot, LocalPath}) of + case catch gen_server:call(Proc, {use_slot, Slot}) of {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail} when byte_size(Data) == Size -> ?DEBUG("Storing file from ~s for ~s: ~s", [?ADDR_TO_STR(IP), Host, Path]), case store_file(Path, Data, FileMode, DirMode, - GetPrefix, LocalPath, Thumbnail) of + GetPrefix, Slot, Thumbnail) of ok -> http_response(Host, 201); {ok, Headers, OutData} -> @@ -425,17 +425,17 @@ process(LocalPath, #request{method = 'PUT', host = Host, ip = IP, [?ADDR_TO_STR(IP), Host, Error]), http_response(Host, 500) end; -process(LocalPath, #request{method = Method, host = Host, ip = IP}) +process([_UserDir, _RandDir, FileName] = Slot, + #request{method = Method, host = Host, ip = IP}) when Method == 'GET'; Method == 'HEAD' -> Proc = gen_mod:get_module_proc(Host, ?PROCNAME), case catch gen_server:call(Proc, get_docroot) of {ok, DocRoot} -> - Path = str:join([DocRoot | LocalPath], <<$/>>), + Path = str:join([DocRoot | Slot], <<$/>>), case file:read_file(Path) of {ok, Data} -> ?INFO_MSG("Serving ~s to ~s", [Path, ?ADDR_TO_STR(IP)]), - FileName = lists:last(LocalPath), ContentType = guess_content_type(FileName), Headers1 = case ContentType of <<"image/", _SubType/binary>> -> []; @@ -469,6 +469,19 @@ process(LocalPath, #request{method = Method, host = Host, ip = IP}) [Method, ?ADDR_TO_STR(IP), Host, Error]), http_response(Host, 500) end; +process(LocalPath, #request{method = 'PUT', host = Host, ip = IP}) + when length(LocalPath) > 3 -> + ?INFO_MSG("Rejecting PUT request from ~s for ~s: Too many path components", + [?ADDR_TO_STR(IP), Host]), + ?INFO_MSG("Check whether 'request_handlers' path matches 'put_url'", []), + http_response(Host, 404); +process(_LocalPath, #request{method = Method, host = Host, ip = IP}) + when Method == 'PUT'; + Method == 'GET'; + Method == 'HEAD' -> + ?DEBUG("Rejecting ~s request from ~s for ~s: Too few/many path components", + [Method, ?ADDR_TO_STR(IP), Host]), + http_response(Host, 404); process(_LocalPath, #request{method = 'OPTIONS', host = Host, ip = IP}) -> ?DEBUG("Responding to OPTIONS request from ~s for ~s", [?ADDR_TO_STR(IP), Host]), From 3ee5195b7a7dc1ac19396a8f3e289b468f635071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 12 Nov 2015 17:23:39 +0100 Subject: [PATCH 352/695] Fix problem with pipelined http requests arriving in single packet This fixes github issue ejabberd#835 --- src/ejabberd_http.erl | 122 ++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index d2649846bf0..9856777710c 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -287,16 +287,18 @@ process_header(State, Data) -> HostProvided), State2 = State#state{request_host = Host, request_port = Port, request_tp = TP}, - Out = process_request(State2), - send_text(State2, Out), - case State2#state.request_keepalive of + {State3, Out} = process_request(State2), + send_text(State3, Out), + case State3#state.request_keepalive of true -> #state{sockmod = SockMod, socket = Socket, + trail = State3#state.trail, options = State#state.options, default_host = State#state.default_host, request_handlers = State#state.request_handlers}; _ -> #state{end_of_request = true, + trail = State3#state.trail, options = State#state.options, default_host = State#state.default_host, request_handlers = State#state.request_handlers} @@ -366,20 +368,20 @@ process(Handlers, Request, Socket, SockMod, Trail) -> end. extract_path_query(#state{request_method = Method, - request_path = {abs_path, Path}}) + request_path = {abs_path, Path}} = State) when Method =:= 'GET' orelse Method =:= 'HEAD' orelse Method =:= 'DELETE' orelse Method =:= 'OPTIONS' -> case catch url_decode_q_split(Path) of - {'EXIT', _} -> false; - {NPath, Query} -> - LPath = normalize_path([NPE - || NPE <- str:tokens(path_decode(NPath), <<"/">>)]), - LQuery = case catch parse_urlencoded(Query) of - {'EXIT', _Reason} -> []; - LQ -> LQ - end, - {LPath, LQuery, <<"">>} + {'EXIT', _} -> {State, false}; + {NPath, Query} -> + LPath = normalize_path([NPE + || NPE <- str:tokens(path_decode(NPath), <<"/">>)]), + LQuery = case catch parse_urlencoded(Query) of + {'EXIT', _Reason} -> []; + LQ -> LQ + end, + {State, {LPath, LQuery, <<"">>}} end; extract_path_query(#state{request_method = Method, request_path = {abs_path, Path}, @@ -388,21 +390,21 @@ extract_path_query(#state{request_method = Method, socket = _Socket} = State) when (Method =:= 'POST' orelse Method =:= 'PUT') andalso is_integer(Len) -> - Data = recv_data(State, Len), + {NewState, Data} = recv_data(State, Len), ?DEBUG("client data: ~p~n", [Data]), case catch url_decode_q_split(Path) of - {'EXIT', _} -> false; - {NPath, _Query} -> - LPath = normalize_path([NPE - || NPE <- str:tokens(path_decode(NPath), <<"/">>)]), - LQuery = case catch parse_urlencoded(Data) of - {'EXIT', _Reason} -> []; - LQ -> LQ - end, - {LPath, LQuery, Data} + {'EXIT', _} -> {NewState, false}; + {NPath, _Query} -> + LPath = normalize_path([NPE + || NPE <- str:tokens(path_decode(NPath), <<"/">>)]), + LQuery = case catch parse_urlencoded(Data) of + {'EXIT', _Reason} -> []; + LQ -> LQ + end, + {NewState, {LPath, LQuery, Data}} end; -extract_path_query(_State) -> - false. +extract_path_query(State) -> + {State, false}. process_request(#state{request_method = Method, request_auth = Auth, @@ -417,9 +419,9 @@ process_request(#state{request_method = Method, request_handlers = RequestHandlers, trail = Trail} = State) -> case extract_path_query(State) of - false -> - make_bad_request(State); - {LPath, LQuery, Data} -> + {State2, false} -> + {State2, make_bad_request(State)}; + {State2, {LPath, LQuery, Data}} -> PeerName = case SockMod of gen_tcp -> @@ -445,23 +447,24 @@ process_request(#state{request_method = Method, opts = Options, headers = RequestHeaders, ip = IP}, - case process(RequestHandlers, Request, Socket, SockMod, Trail) of - El when is_record(El, xmlel) -> - make_xhtml_output(State, 200, [], El); - {Status, Headers, El} - when is_record(El, xmlel) -> - make_xhtml_output(State, Status, Headers, El); - Output when is_binary(Output) or is_list(Output) -> - make_text_output(State, 200, [], Output); - {Status, Headers, Output} - when is_binary(Output) or is_list(Output) -> - make_text_output(State, Status, Headers, Output); - {Status, Reason, Headers, Output} - when is_binary(Output) or is_list(Output) -> - make_text_output(State, Status, Reason, Headers, Output); - _ -> - none - end + Res = case process(RequestHandlers, Request, Socket, SockMod, Trail) of + El when is_record(El, xmlel) -> + make_xhtml_output(State, 200, [], El); + {Status, Headers, El} + when is_record(El, xmlel) -> + make_xhtml_output(State, Status, Headers, El); + Output when is_binary(Output) or is_list(Output) -> + make_text_output(State, 200, [], Output); + {Status, Headers, Output} + when is_binary(Output) or is_list(Output) -> + make_text_output(State, Status, Headers, Output); + {Status, Reason, Headers, Output} + when is_binary(Output) or is_list(Output) -> + make_text_output(State, Status, Reason, Headers, Output); + _ -> + none + end, + {State2, Res} end. make_bad_request(State) -> @@ -501,21 +504,24 @@ is_ipchain_trusted(UserIPs, TrustedIPs) -> recv_data(State, Len) -> recv_data(State, Len, <<>>). -recv_data(_State, 0, Acc) -> (iolist_to_binary(Acc)); +recv_data(State, 0, Acc) -> {State, Acc}; +recv_data(#state{trail = Trail} = State, Len, <<>>) when byte_size(Trail) > Len -> + <> = Trail, + {State#state{trail = Rest}, Data}; recv_data(State, Len, Acc) -> case State#state.trail of - <<>> -> - case (State#state.sockmod):recv(State#state.socket, Len, - 300000) - of - {ok, Data} -> - recv_data(State, Len - byte_size(Data), <>); - _ -> <<"">> - end; - _ -> - Trail = (State#state.trail), - recv_data(State#state{trail = <<>>}, - Len - byte_size(Trail), <>) + <<>> -> + case (State#state.sockmod):recv(State#state.socket, Len, + 300000) + of + {ok, Data} -> + recv_data(State, Len - byte_size(Data), <>); + _ -> <<"">> + end; + _ -> + Trail = (State#state.trail), + recv_data(State#state{trail = <<>>}, + Len - byte_size(Trail), <>) end. make_xhtml_output(State, Status, Headers, XHTML) -> From aa5caa30e27030cd7813d47b0fda13615f793846 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 12 Nov 2015 19:51:20 +0300 Subject: [PATCH 353/695] Support for muc#roomconfig_presencebroadcast option --- include/mod_muc_room.hrl | 2 + src/mod_muc_room.erl | 111 ++++++++++++++++++++++++++++++++++----- 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index c90a5c0288b..51e575db01e 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -56,6 +56,8 @@ password_protected = false :: boolean(), password = <<"">> :: binary(), anonymous = true :: boolean(), + presence_broadcast = [moderator, participant, visitor] :: + [moderator | participant | visitor], allow_voice_requests = true :: boolean(), voice_request_min_interval = 1800 :: non_neg_integer(), max_users = ?MAX_USERS_DEFAULT :: non_neg_integer() | none, diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index dcf276b8b63..0572bca2ea8 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -363,7 +363,8 @@ normal_state({route, From, <<"">>, catch send_new_presence(TargetJid, Reason, - NSD), + NSD, + StateData), NSD; _ -> StateData end @@ -1031,7 +1032,7 @@ process_presence(From, Nick, StateData), case (?DICT):find(Nick, StateData#state.nicks) of {ok, [_, _ | _]} -> ok; - _ -> send_new_presence(From, NewState) + _ -> send_new_presence(From, NewState, StateData) end, Reason = case xml:get_subtag(NewPacket, <<"status">>) @@ -1109,7 +1110,8 @@ process_presence(From, Nick, end, NewState = add_user_presence(From, Stanza, StateData), - send_new_presence(From, NewState), + send_new_presence( + From, NewState, StateData), NewState end end @@ -1315,7 +1317,7 @@ expulse_participant(Packet, From, StateData, Reason1) -> [{xmlcdata, Reason2}]}]}, StateData), - send_new_presence(From, NewState), + send_new_presence(From, NewState, StateData), remove_online_user(From, NewState). set_affiliation(JID, Affiliation, StateData) -> @@ -1839,7 +1841,7 @@ add_new_user(From, Nick, add_online_user(From, Nick, Role, StateData)), send_existing_presences(From, NewState), - send_new_presence(From, NewState), + send_new_presence(From, NewState, StateData), Shift = count_stanza_shift(Nick, Els, NewState), case send_history(From, Shift, NewState) of true -> ok; @@ -2070,6 +2072,10 @@ is_room_overcrowded(StateData) -> ?DEFAULT_MAX_USERS_PRESENCE), (?DICT):size(StateData#state.users) > MaxUsersPresence. +presence_broadcast_allowed(JID, StateData) -> + Role = get_role(JID, StateData), + lists:member(Role, (StateData#state.config)#config.presence_broadcast). + send_update_presence(JID, StateData) -> send_update_presence(JID, <<"">>, StateData). @@ -2097,15 +2103,17 @@ send_update_presence1(JID, Reason, StateData) -> end end, lists:foreach(fun (J) -> - send_new_presence(J, Reason, StateData) + send_new_presence(J, Reason, StateData, StateData) end, LJIDs). -send_new_presence(NJID, StateData) -> - send_new_presence(NJID, <<"">>, StateData). +send_new_presence(NJID, StateData, OldStateData) -> + send_new_presence(NJID, <<"">>, StateData, OldStateData). -send_new_presence(NJID, Reason, StateData) -> - case is_room_overcrowded(StateData) of +send_new_presence(NJID, Reason, StateData, OldStateData) -> + case is_room_overcrowded(StateData) orelse + not (presence_broadcast_allowed(NJID, StateData) orelse + presence_broadcast_allowed(NJID, OldStateData)) of true -> ok; false -> send_new_presence1(NJID, Reason, StateData) end. @@ -2289,8 +2297,12 @@ change_nick(JID, Nick, StateData) -> end, NewStateData = StateData#state{users = Users, nicks = Nicks}, - send_nick_changing(JID, OldNick, NewStateData, - SendOldUnavailable, SendNewAvailable), + case presence_broadcast_allowed(JID, NewStateData) of + true -> + send_nick_changing(JID, OldNick, NewStateData, + SendOldUnavailable, SendNewAvailable); + false -> ok + end, add_to_log(nickchange, {OldNick, Nick}, StateData), NewStateData. @@ -2666,7 +2678,7 @@ process_item_change(E, SD, UJID) -> {JID, role, Role, Reason} -> SD1 = set_role(JID, Role, SD), catch - send_new_presence(JID, Reason, SD1), + send_new_presence(JID, Reason, SD1, SD), SD1; {JID, affiliation, A, _Reason} -> SD1 = set_affiliation(JID, A, SD), @@ -3406,6 +3418,53 @@ get_config(Lang, StateData, From) -> children = [{xmlcdata, <<"anyone">>}]}]}]}, + #xmlel{name = <<"field">>, + attrs = + [{<<"type">>, <<"list-multi">>}, + {<<"label">>, + translate:translate(Lang, + <<"Roles for which Presence is Broadcasted">>)}, + {<<"var">>, <<"muc#roomconfig_presencebroadcast">>}], + children = + lists:map( + fun(Role) -> + #xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + atom_to_binary(Role, utf8)}]} + end, Config#config.presence_broadcast + ) ++ + [#xmlel{name = <<"option">>, + attrs = + [{<<"label">>, + translate:translate(Lang, + <<"Moderator">>)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"moderator">>}]}]}, + #xmlel{name = <<"option">>, + attrs = + [{<<"label">>, + translate:translate(Lang, + <<"Participant">>)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"participant">>}]}]}, + #xmlel{name = <<"option">>, + attrs = + [{<<"label">>, + translate:translate(Lang, + <<"Visitor">>)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"visitor">>}]}]} + ]}, ?BOOLXFIELD(<<"Make room members-only">>, <<"muc#roomconfig_membersonly">>, (Config#config.members_only)), @@ -3679,6 +3738,28 @@ set_xoption([{<<"muc#roomconfig_roomsecret">>, [Val]} set_xoption([{<<"anonymous">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(anonymous, Val); +set_xoption([{<<"muc#roomconfig_presencebroadcast">>, Vals} | Opts], + Config) -> + Roles = + lists:foldl( + fun(_S, error) -> error; + (S, {M, P, V}) -> + case S of + <<"moderator">> -> {true, P, V}; + <<"participant">> -> {M, true, V}; + <<"visitor">> -> {M, P, true}; + _ -> error + end + end, {false, false, false}, Vals), + case Roles of + error -> {error, ?ERR_BAD_REQUEST}; + {M, P, V} -> + Res = + if M -> [moderator]; true -> [] end ++ + if P -> [participant]; true -> [] end ++ + if V -> [visitor]; true -> [] end, + set_xoption(Opts, Config#config{presence_broadcast = Res}) + end; set_xoption([{<<"muc#roomconfig_allowvoicerequests">>, [Val]} | Opts], @@ -3872,6 +3953,10 @@ set_opts([{Opt, Val} | Opts], StateData) -> StateData#state{config = (StateData#state.config)#config{anonymous = Val}}; + presence_broadcast -> + StateData#state{config = + (StateData#state.config)#config{presence_broadcast = + Val}}; logging -> StateData#state{config = (StateData#state.config)#config{logging = From f6d8f4745104d4798e6fcf0bc995370636074241 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 13 Nov 2015 19:30:11 +0100 Subject: [PATCH 354/695] Disable vJUD search in the default config and when not specified --- ejabberd.yml.example | 3 ++- src/mod_vcard.erl | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index b4278eed4ea..19e2070913d 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -658,7 +658,8 @@ modules: mod_shared_roster: {} mod_stats: {} mod_time: {} - mod_vcard: {} + mod_vcard: + search: false mod_version: {} ## diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 306bd84458e..ed6bff11fb0 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -94,7 +94,7 @@ start(Host, Opts) -> <<"vjud.@HOST@">>), Search = gen_mod:get_opt(search, Opts, fun(B) when is_boolean(B) -> B end, - true), + false), register(gen_mod:get_module_proc(Host, ?PROCNAME), spawn(?MODULE, init, [MyHost, Host, Search])). From 53d72bd85ae46f8d677e4342ee24fc614a1daecf Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 13 Nov 2015 19:33:23 +0100 Subject: [PATCH 355/695] Disable vJUD by default also in mod_vcard_ldap source code --- src/mod_vcard_ldap.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index f75bb07124f..3f6b41a70b9 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -55,7 +55,7 @@ {serverhost = <<"">> :: binary(), myhost = <<"">> :: binary(), eldap_id = <<"">> :: binary(), - search = true :: boolean(), + search = false :: boolean(), servers = [] :: [binary()], backups = [] :: [binary()], port = ?LDAP_PORT :: inet:port_number(), @@ -735,7 +735,7 @@ parse_options(Host, Opts) -> <<"vjud.@HOST@">>), Search = gen_mod:get_opt(search, Opts, fun(B) when is_boolean(B) -> B end, - true), + false), Matches = gen_mod:get_opt(matches, Opts, fun(infinity) -> 0; (I) when is_integer(I), I>0 -> I From 43626f5c97b1926afedfe6f5822dd1662b87e7f6 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 17 Nov 2015 00:12:20 +0100 Subject: [PATCH 356/695] mod_http_upload: Return error atoms, not strings Don't convert error atoms to strings before actually logging them. This avoids a bogus error message when a user who has no uploaded files is removed. --- src/mod_http_upload.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index d32c5f097bc..87707790685 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -409,7 +409,7 @@ process([_UserDir, _RandDir, _FileName] = Slot, http_response(Host, 201, Headers, OutData); {error, Error} -> ?ERROR_MSG("Cannot store file ~s from ~s for ~s: ~p", - [Path, ?ADDR_TO_STR(IP), Host, Error]), + [Path, ?ADDR_TO_STR(IP), Host, ?FORMAT(Error)]), http_response(Host, 500) end; {ok, Size, Path} -> @@ -830,7 +830,7 @@ do_store_file(Path, Data, FileMode, DirMode) -> ok = Ok % Raise an exception if file:write/2 failed. catch _:{badmatch, {error, Error}} -> - {error, ?FORMAT(Error)}; + {error, Error}; _:Error -> {error, Error} end. @@ -977,7 +977,7 @@ remove_user(User, Server) -> ?DEBUG("Found no HTTP upload directory of ~s@~s", [User, Server]); {error, Error} -> ?ERROR_MSG("Cannot remove HTTP upload directory of ~s@~s: ~p", - [User, Server, Error]) + [User, Server, ?FORMAT(Error)]) end, ok. @@ -999,7 +999,7 @@ del_tree(Dir) -> ok = file:del_dir(Dir) catch _:{badmatch, {error, Error}} -> - {error, ?FORMAT(Error)}; + {error, Error}; _:Error -> {error, Error} end. From 2f9f4e693867b5ca687f072d735948db3506de1a Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 17 Nov 2015 21:33:28 +0100 Subject: [PATCH 357/695] Fix example config about ejabberd_xmlrpc (#771) --- ejabberd.yml.example | 1 + 1 file changed, 1 insertion(+) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 19e2070913d..e20dc0dfb4e 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -167,6 +167,7 @@ listen: ## - ## port: 4560 ## module: ejabberd_xmlrpc + ## access_commands: {} - port: 5280 module: ejabberd_http From 49a8de7c56d5c1348cc0527c2894367ce0f65902 Mon Sep 17 00:00:00 2001 From: Nycholas de Oliveira e Oliveira Date: Wed, 18 Nov 2015 10:25:01 -0200 Subject: [PATCH 358/695] Adding ping_ack_timeout in mod_opt_type configuration Avoid the error output ``` 2015-11-18 12:02:40.297 [error] <0.37.0>@gen_mod:validate_opts:250 unknown option 'ping_ack_timeout' for module 'mod_ping' will be likely ignored, available options are: 'iqdisc', 'ping_interval', 'send_pings', 'timeout_action' 2015-11-18 12:02:40.334 [error] <0.37.0>@gen_mod:validate_opts:250 unknown option 'ping_ack_timeout' for module 'mod_ping' will be likely ignored, available options are: 'iqdisc', 'ping_interval', 'send_pings', 'timeout_action' ``` In setting mod_opt_type default, ping_ack_timeout parameter was added. --- src/mod_ping.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod_ping.erl b/src/mod_ping.erl index 9964daf0374..54aa6086585 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -255,6 +255,8 @@ cancel_timer(TRef) -> mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; mod_opt_type(ping_interval) -> fun (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(ping_ack_timeout) -> + fun (I) when is_integer(I), I > 0 -> I end; mod_opt_type(send_pings) -> fun (B) when is_boolean(B) -> B end; mod_opt_type(timeout_action) -> @@ -262,4 +264,4 @@ mod_opt_type(timeout_action) -> (kill) -> kill end; mod_opt_type(_) -> - [iqdisc, ping_interval, send_pings, timeout_action]. + [iqdisc, ping_interval, ping_ack_timeout, send_pings, timeout_action]. From 2659e2c4a090cddf8aab5e5f44608c9eab9c1167 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 18 Nov 2015 13:25:19 +0100 Subject: [PATCH 359/695] Explain that reload_config only affects to ACL and Access --- src/ejabberd_admin.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 2068f10c873..2c4a72bf920 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -141,7 +141,7 @@ commands() -> args = [], result = {vhosts, {list, {vhost, string}}}}, #ejabberd_commands{name = reload_config, tags = [server], - desc = "Reload ejabberd configuration file into memory", + desc = "Reload config file in memory (only affects ACL and Access)", module = ?MODULE, function = reload_config, args = [], result = {res, rescode}}, From 67a70b9107a051209a58ad332b23a0aaa424359c Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 20 Nov 2015 09:53:53 +0100 Subject: [PATCH 360/695] Integrate join/leave cluster as ejabberd command --- Makefile.in | 2 - ejabberdctl.template | 12 --- src/ejabberd_admin.erl | 31 ++++++++ src/ejabberd_cluster.erl | 51 +++++++++++++ tools/joincluster | 153 --------------------------------------- tools/leavecluster | 109 ---------------------------- 6 files changed, 82 insertions(+), 276 deletions(-) delete mode 100755 tools/joincluster delete mode 100755 tools/leavecluster diff --git a/Makefile.in b/Makefile.in index 391d816123d..8dd6bf585c3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -180,8 +180,6 @@ install: all copy-files # Binary C programs $(INSTALL) -d $(PBINDIR) $(INSTALL) -m 750 $(O_USER) tools/captcha.sh $(PBINDIR) - $(INSTALL) -m 750 $(O_USER) tools/joincluster $(PBINDIR) - $(INSTALL) -m 750 $(O_USER) tools/leavecluster $(PBINDIR) # # Copy lite.sql [ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR) || true diff --git a/ejabberdctl.template b/ejabberdctl.template index a4327ac9f86..c7d76eff739 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -431,16 +431,6 @@ check_start() } } -# cluster setup -join_cluster() -{ - $EXEC_CMD "$EJABBERD_BIN_PATH/joincluster $*" -} -leave_cluster() -{ - $EXEC_CMD "$EJABBERD_BIN_PATH/leavecluster $*" -} - # allow sync calls wait_for_status() { @@ -472,7 +462,5 @@ case $ARGS in ' etop') etop;; ' started') wait_for_status 0 30 2;; # wait 30x2s before timeout ' stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout - ' join_cluster'*) join_cluster ${ARGS# join_cluster};; - ' leave_cluster'*) leave_cluster ${ARGS# leave_cluster};; *) ctl $ARGS;; esac diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 2068f10c873..c51a27545f1 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -33,6 +33,8 @@ stop_kindly/2, send_service_message_all_mucs/2, registered_vhosts/0, reload_config/0, + %% Cluster + join_cluster/1, leave_cluster/1, list_cluster/0, %% Erlang update_list/0, update/1, %% Accounts @@ -146,6 +148,22 @@ commands() -> args = [], result = {res, rescode}}, + #ejabberd_commands{name = join_cluster, tags = [cluster], + desc = "Join this node into the cluster handled by Node", + module = ?MODULE, function = join_cluster, + args = [{node, binary}], + result = {res, rescode}}, + #ejabberd_commands{name = leave_cluster, tags = [cluster], + desc = "Remove node handled by Node from the cluster", + module = ?MODULE, function = leave_cluster, + args = [{node, binary}], + result = {res, rescode}}, + #ejabberd_commands{name = list_cluster, tags = [cluster], + desc = "List nodes that are part of the cluster handled by Node", + module = ?MODULE, function = list_cluster, + args = [], + result = {nodes, {list, {node, atom}}}}, + #ejabberd_commands{name = import_file, tags = [mnesia], desc = "Import user data from jabberd14 spool file", module = ?MODULE, function = import_file, @@ -373,6 +391,19 @@ reload_config() -> acl:start(), shaper:start(). +%%% +%%% Cluster management +%%% + +join_cluster(NodeBin) -> + ejabberd_cluster:join(list_to_atom(binary_to_list(NodeBin))). + +leave_cluster(NodeBin) -> + ejabberd_cluster:leave(list_to_atom(binary_to_list(NodeBin))). + +list_cluster() -> + ejabberd_cluster:get_nodes(). + %%% %%% Migration management %%% diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl index 5c3a0fc5b9f..eb523fee20c 100644 --- a/src/ejabberd_cluster.erl +++ b/src/ejabberd_cluster.erl @@ -27,6 +27,7 @@ %% API -export([get_nodes/0, call/4, multicall/3, multicall/4]). +-export([join/1, leave/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -51,3 +52,53 @@ multicall(Module, Function, Args) -> multicall(Nodes, Module, Function, Args) -> rpc:multicall(Nodes, Module, Function, Args, 5000). +-spec join(node()) -> ok | {error, any()}. + +join(Node) -> + case {node(), net_adm:ping(Node)} of + {Node, _} -> + {error, {not_master, Node}}; + {_, pong} -> + application:stop(ejabberd), + application:stop(mnesia), + mnesia:delete_schema([node()]), + application:start(mnesia), + mnesia:change_config(extra_db_nodes, [Node]), + mnesia:change_table_copy_type(schema, node(), disc_copies), + spawn(fun() -> + lists:foreach(fun(Table) -> + Type = call(Node, mnesia, table_info, [Table, storage_type]), + mnesia:add_table_copy(Table, node(), Type) + end, mnesia:system_info(tables)--[schema]) + end), + application:start(ejabberd); + _ -> + {error, {no_ping, Node}} + end. + +-spec leave(node()) -> ok | {error, any()}. + +leave(Node) -> + case {node(), net_adm:ping(Node)} of + {Node, _} -> + Cluster = get_nodes()--[Node], + leave(Cluster, Node); + {_, pong} -> + rpc:call(Node, ?MODULE, leave, [Node], 10000); + {_, pang} -> + case mnesia:del_table_copy(schema, Node) of + {atomic, ok} -> ok; + {aborted, Reason} -> {error, Reason} + end + end. +leave([], Node) -> + {error, {no_cluster, Node}}; +leave([Master|_], Node) -> + application:stop(ejabberd), + application:stop(mnesia), + call(Master, mnesia, del_table_copy, [schema, Node]), + spawn(fun() -> + mnesia:delete_schema([node()]), + erlang:halt(0) + end), + ok. diff --git a/tools/joincluster b/tools/joincluster deleted file mode 100755 index 7db63993045..00000000000 --- a/tools/joincluster +++ /dev/null @@ -1,153 +0,0 @@ -#!/bin/sh - -# Add the current ejabberd node in a cluster - -# copyright (c) 2010-2015 ProcessOne - -# Return Code: -# 0 : groovy baby -# 10 : ejabberdctl not found -# 11 : erl not found -# 12 : erlc not found -# 20 : database dir can not be created -# 21 : database dir not writable -# 22 : temporary dir can not be created -# 30 : network issue -# 31 : node names incompatibility - -error() -{ - echo "Error: $1" >&2 - exit $2 -} - -[ -z $NO_WARNINGS ] && { - echo "--------------------------------------------------------------------" - echo "" - echo "ejabberd cluster configuration" - echo "" - echo "This ejabberd node will be configured for use in an ejabberd cluster." - echo "IMPORTANT: all local data from the database will be lost, and" - echo "cluster database will be initialized. All data from the master" - echo "node will be replicated to this one." - echo "" - echo "--------------------------------------------------------------------" - echo "Press any key to continue, or Ctrl+C to stop now" - read foo - echo "" -} - -[ $# -eq 0 ] && { - echo "Make sure you have a running remote master ejabberd node" - echo "Before continuing, you must copy the ~/.erlang.cookie file from" - echo "remote master node and check ejabberd.cfg compatibility." - echo "e.g. hosts definition must match on all nodes" - echo "" - echo "The remote master node name is defined as ERLANG_NODE into" - echo "ejabberdctl.cfg on that remote node." - echo "" - echo -n "Remote master node name: " - read REMOTE - echo "" -} || { - echo "Using passed parameter for remote master node name: $1" - REMOTE=$1 -} - -PA=/tmp/clustersetup_$$ -CTL=$(which ejabberdctl) -[ -x "$CTL" ] || { - HERE=`which "$0"` - BASE=`dirname $HERE`/.. - ROOTDIR=`cd $BASE; pwd` - PATH=$ROOTDIR/bin:$PATH - PA=$ROOTDIR/clustersetup_$$ - CTL=$(which ejabberdctl) -} -echo "Using commands:" -[ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 - -exec $CTL stop 2>/dev/null >/dev/null -ERLC=${ERL}c - -[ -x $ERL ] && echo $ERL || error "can't find erl" 11 -[ -x $ERLC ] && echo $ERLC || error "can't find erlc" 12 -echo "" - -NAME=-name -[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname -CLUSTERSETUP=clustersetup -CLUSTERSETUP_ERL=$PA/$CLUSTERSETUP.erl - -REMOTENAME=-name -[ "$REMOTE" = "${REMOTE%.*}" ] && REMOTENAME=-sname -[ "$REMOTENAME" = "$NAME" ] || { - echo "IMPORTANT!: node names are incompatible" - echo "Remote node name is $REMOTE" - echo "Local node name is $ERLANG_NODE" - echo "" - echo "Both node names must be short or fqdn names." - echo "Using short and fqdn names is impossible." - echo "" - error "incompatible node names" 31 -} - -set -o errexit -set -o nounset - -[ -d $SPOOL_DIR ] && rm -Rf $SPOOL_DIR/* || mkdir -p $SPOOL_DIR || error "$SPOOL_DIR cannot be created" 20 -[ -w $SPOOL_DIR ] || error "$SPOOL_DIR directory is not writable" 21 -mkdir -p $PA || error "$PA cannot be created" 22 -cd $PA -cat < $CLUSTERSETUP_ERL --module($CLUSTERSETUP). - --export([start/0]). - -set_table_copy(Table, _Node, {badrpc, Reason}) -> - io:format("Error: cannot get storage type for table ~p on node $REMOTE:~n ~p~n",[Table, Reason]); -set_table_copy(Table, Node, Type) -> - io:format("setting table ~p to mode ~p~n",[Table, Type]), - case mnesia:add_table_copy(Table, Node, Type) of - {aborted, _} -> - mnesia:change_table_copy_type(Table, Node, Type); - _ -> - ok - end. - -set_tables({badrpc, Reason}) -> - io:format("ERROR: cannot get tables list on $REMOTE : ~p~n",[Reason]); -set_tables([]) -> - ok; -set_tables([schema | Tables]) -> - set_tables(Tables); -set_tables([s2s | Tables]) -> - set_tables(Tables); -set_tables([session | Tables]) -> - set_tables(Tables); -set_tables([Table | Tables]) -> - set_table_copy(Table, node(), - rpc:call('$REMOTE', mnesia, table_info, [Table, storage_type])), - set_tables(Tables). - -start() -> - io:format("~n",[]), - R = case net_adm:ping('$REMOTE') of - pong -> - set_table_copy(schema, node(), disc_copies), - set_tables(rpc:call('$REMOTE', mnesia, system_info, [tables])), - 0; - pang -> - io:format("node ~p is not reachable, please check epmd port, and FIREWALL_WINDOW ports~n", ['$REMOTE']), - 1 - end, - halt(R). -EOF - -$ERLC -o $PA $CLUSTERSETUP_ERL -$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia extra_db_nodes "['$REMOTE']" dir "\"$SPOOL_DIR\"" -s mnesia -s $CLUSTERSETUP start -cd - -rm -Rf $PA - -echo "End." -echo "Check that there is no error in the above messages." diff --git a/tools/leavecluster b/tools/leavecluster deleted file mode 100755 index 736020446a4..00000000000 --- a/tools/leavecluster +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/sh - -# Remove the current ejabberd node in a cluster - -# copyright (c) 2010-2015 ProcessOne - -# Return Code: -# 0 : groovy baby -# 10 : ejabberdctl not found -# 11 : erl not found -# 12 : erlc not found -# 22 : temporary dir can not be created - -error() -{ - echo "Error: $1" >&2 - exit $2 -} - -[ -z $NO_WARNINGS ] && { - echo "--------------------------------------------------------------------" - echo "" - echo "ejabberd cluster configuration" - echo "" - echo "This ejabberd node will be removed from the cluster." - echo "IMPORTANT: this node will be stopped. At least one other clustered" - echo "node must be running." - echo "" - echo "--------------------------------------------------------------------" - echo "Press any key to continue, or Ctrl+C to stop now" - read foo - echo "" -} - -PA=/tmp/clustersetup_$$ -CTL=$(which ejabberdctl) -[ -x "$CTL" ] || { - HERE=`which "$0"` - BASE=`dirname $HERE`/.. - ROOTDIR=`cd $BASE; pwd` - PATH=$ROOTDIR/bin:$PATH - PA=$ROOTDIR/clustersetup_$$ - CTL=$(which ejabberdctl) -} -echo "Using commands:" -[ -x "$CTL" ] && echo $CTL || error "can't find ejabberdctl" 10 - -exec $CTL stop 2>/dev/null >/dev/null -ERLC=${ERL}c - -[ -x $ERL ] && echo $ERL || error "can't find erl" 11 -[ -x $ERLC ] && echo $ERLC || error "can't find erlc" 12 -echo "" - -$CTL stopped - -CLUSTERSETUP=clustersetup -CLUSTERSETUP_ERL=$PA/$CLUSTERSETUP.erl - -set -o errexit -set -o nounset - -mkdir -p $PA || error "$PA cannot be created" 22 -cd $PA -cat < $CLUSTERSETUP_ERL --module($CLUSTERSETUP). - --export([start/0]). - -del_table_copy(Table, Node) -> - case mnesia:del_table_copy(Table, Node) of - {aborted, Reason} -> io:format("Error: can not remove ~p table: ~p~n", [Table, Reason]); - _ -> io:format("table ~p removed from cluster~n", [Table]) - end. - -del_tables([],_) -> - ok; -del_tables([schema | Tables], Node) -> - del_tables(Tables, Node); -del_tables([Table | Tables], Node) -> - del_table_copy(Table, Node), - del_tables(Tables, Node). - -start() -> - io:format("~n",[]), - Removed = node(), - case mnesia:system_info(running_db_nodes)--[Removed] of - [] -> io:format("Error: no other node running in the cluster~n"); - Nodes -> - del_tables(mnesia:system_info(local_tables), Removed), - mnesia:stop(), - case rpc:call(hd(Nodes), mnesia, del_table_copy, [schema, Removed]) of - {badrpc,Reason} -> io:format("Error: can not unregister node ~p from cluster: ~p~n", [Removed, Reason]); - {aborted,Reason} -> io:format("Error: can not unregister node ~p from cluster: ~p~n", [Removed, Reason]); - {atomic, ok} -> - mnesia:delete_schema([Removed]), - io:format("node ~p removed from cluster~n", [Removed]) - end - end, - halt(0). -EOF - -$ERLC -o $PA $CLUSTERSETUP_ERL -$ERL $NAME $ERLANG_NODE -pa $PA $KERNEL_OPTS -mnesia dir "\"$SPOOL_DIR\"" -s mnesia -s $CLUSTERSETUP start -cd - -rm -Rf $PA - -echo "End." -echo "Check that there is no error in the above messages." From b4ae1b63bc18686ed231956737e3c847fdbbc45e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 20 Nov 2015 09:57:55 +0100 Subject: [PATCH 361/695] Allow longer command execution time --- src/ejabberd_ctl.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 70e17b4133d..ec916b32b54 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -80,7 +80,7 @@ start() -> end end, Node = list_to_atom(SNode1), - Status = case ejabberd_cluster:call(Node, ?MODULE, process, [Args]) of + Status = case rpc:call(Node, ?MODULE, process, [Args], 60000) of {badrpc, Reason} -> print("Failed RPC connection to the node ~p: ~p~n", [Node, Reason]), From f3ff660eae78c6b94dd245814398d7f3f79e865f Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 23 Nov 2015 11:53:36 +0100 Subject: [PATCH 362/695] Export content_type/3 needed by mod_http_upload --- src/mod_http_fileserver.erl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 8b4d7337ec7..01199f9fcdb 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -43,6 +43,9 @@ %% request_handlers callbacks -export([process/2]). +%% utility for other http modules +-export([content_type/3]). + -export([reopen_log/1, mod_opt_type/1]). -include("ejabberd.hrl"). From 16881597c975d6d16793dee4c180e479ca6e8e4a Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 23 Nov 2015 12:03:08 +0100 Subject: [PATCH 363/695] Remove useless export_all flag --- src/mod_http_fileserver.erl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 01199f9fcdb..7ebbc81ff53 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -88,8 +88,6 @@ {<<".xpi">>, <<"application/x-xpinstall">>}, {<<".xul">>, <<"application/vnd.mozilla.xul+xml">>}]). --compile(export_all). - %%==================================================================== %% gen_mod callbacks %%==================================================================== From 7eddfe073b0daf74796a7aac6bc3f9c3da0a2dbd Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 23 Nov 2015 12:50:08 +0300 Subject: [PATCH 364/695] Make Riak working on R18 --- rebar.config.script | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index cdd2a65ce0a..9e213b86364 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -102,7 +102,7 @@ CfgDeps = lists:flatmap( ({zlib, true}) -> [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; ({riak, true}) -> - [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", {tag, "1.4.2"}}}]; + [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client"}}]; ({elixir, true}) -> [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; @@ -113,7 +113,7 @@ CfgDeps = lists:flatmap( ({lager, false}) -> [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}]; ({tools, true}) -> - [{meck, "0.*", {git, "https://github.com/eproxus/meck"}}]; + [{meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}]; ({redis, true}) -> [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; (_) -> From 95265dd3ad8e149d94d08e1a73970fb0bbf55b49 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 24 Nov 2015 18:44:13 +0300 Subject: [PATCH 365/695] Move JID related functions to jid.erl (#847) --- src/acl.erl | 8 +- src/cyrsasl.erl | 8 +- src/cyrsasl_scram.erl | 2 +- src/ejabberd_app.erl | 2 +- src/ejabberd_auth.erl | 8 +- src/ejabberd_auth_anonymous.erl | 4 +- src/ejabberd_auth_internal.erl | 42 +++--- src/ejabberd_auth_ldap.erl | 4 +- src/ejabberd_auth_odbc.erl | 46 +++--- src/ejabberd_auth_riak.erl | 40 +++--- src/ejabberd_c2s.erl | 124 ++++++++-------- src/ejabberd_captcha.erl | 6 +- src/ejabberd_commands.erl | 4 +- src/ejabberd_config.erl | 2 +- src/ejabberd_http_bind.erl | 2 +- src/ejabberd_oauth.erl | 10 +- src/ejabberd_piefxis.erl | 28 ++-- src/ejabberd_rdbms.erl | 2 +- src/ejabberd_router.erl | 12 +- src/ejabberd_router_multicast.erl | 8 +- src/ejabberd_s2s.erl | 18 +-- src/ejabberd_s2s_in.erl | 26 ++-- src/ejabberd_s2s_out.erl | 4 +- src/ejabberd_service.erl | 10 +- src/ejabberd_sm.erl | 74 +++++----- src/ejabberd_system_monitor.erl | 12 +- src/ejabberd_web_admin.erl | 24 ++-- src/ejd2odbc.erl | 10 +- src/extauth.erl | 2 +- src/jd2ejd.erl | 16 +-- src/jid.erl | 228 ++++++++++++++++++++++++++++++ src/jlib.erl | 165 ++++----------------- src/mod_adhoc.erl | 2 +- src/mod_admin_extra.erl | 46 +++--- src/mod_announce.erl | 24 ++-- src/mod_blocking.erl | 10 +- src/mod_caps.erl | 12 +- src/mod_carboncopy.erl | 24 ++-- src/mod_configure.erl | 24 ++-- src/mod_echo.erl | 2 +- src/mod_http_api.erl | 2 +- src/mod_http_upload.erl | 28 ++-- src/mod_http_upload_quota.erl | 10 +- src/mod_irc.erl | 26 ++-- src/mod_irc_connection.erl | 58 ++++---- src/mod_last.erl | 8 +- src/mod_mam.erl | 54 +++---- src/mod_metrics.erl | 4 +- src/mod_muc.erl | 50 +++---- src/mod_muc_admin.erl | 14 +- src/mod_muc_log.erl | 6 +- src/mod_muc_room.erl | 222 ++++++++++++++--------------- src/mod_multicast.erl | 6 +- src/mod_offline.erl | 50 +++---- src/mod_ping.erl | 6 +- src/mod_pres_counter.erl | 4 +- src/mod_privacy.erl | 40 +++--- src/mod_private.erl | 4 +- src/mod_proxy65_service.erl | 6 +- src/mod_proxy65_stream.erl | 4 +- src/mod_pubsub.erl | 118 ++++++++-------- src/mod_register.erl | 32 ++--- src/mod_register_web.erl | 4 +- src/mod_roster.erl | 122 ++++++++-------- src/mod_service_log.erl | 8 +- src/mod_shared_roster.erl | 64 ++++----- src/mod_shared_roster_ldap.erl | 18 +-- src/mod_sip.erl | 14 +- src/mod_sip_proxy.erl | 12 +- src/mod_sip_registrar.erl | 4 +- src/mod_vcard.erl | 10 +- src/mod_vcard_ldap.erl | 4 +- src/node_flat.erl | 58 ++++---- src/node_flat_odbc.erl | 64 ++++----- src/node_hometree.erl | 2 +- src/node_pep.erl | 12 +- src/node_pep_odbc.erl | 10 +- src/nodetree_dag.erl | 2 +- src/nodetree_tree.erl | 2 +- src/nodetree_tree_odbc.erl | 2 +- src/scram.erl | 2 +- 81 files changed, 1189 insertions(+), 1072 deletions(-) create mode 100644 src/jid.erl diff --git a/src/acl.erl b/src/acl.erl index f69472d7283..41e29ce8c8a 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -208,13 +208,13 @@ b(S) -> iolist_to_binary(S). nodeprep(S) -> - jlib:nodeprep(b(S)). + jid:nodeprep(b(S)). nameprep(S) -> - jlib:nameprep(b(S)). + jid:nameprep(b(S)). resourceprep(S) -> - jlib:resourceprep(b(S)). + jid:resourceprep(b(S)). normalize_spec(Spec) -> case Spec of @@ -295,7 +295,7 @@ match_acl(ACL, IP, Host) when tuple_size(IP) == 4; false end, get_aclspecs(ACL, Host)); match_acl(ACL, JID, Host) -> - {User, Server, Resource} = jlib:jid_tolower(JID), + {User, Server, Resource} = jid:tolower(JID), lists:any( fun(#acl{aclspec = Spec}) -> case Spec of diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 518bb84ff50..b15bcdfbdee 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -112,12 +112,12 @@ register_mechanism(Mechanism, Module, PasswordType) -> %%-include("jlib.hrl"). %%check_authzid(_State, Props) -> %% AuthzId = xml:get_attr_s(authzid, Props), -%% case jlib:string_to_jid(AuthzId) of +%% case jid:from_string(AuthzId) of %% error -> %% {error, "invalid-authzid"}; %% JID -> -%% LUser = jlib:nodeprep(xml:get_attr_s(username, Props)), -%% {U, S, R} = jlib:jid_tolower(JID), +%% LUser = jid:nodeprep(xml:get_attr_s(username, Props)), +%% {U, S, R} = jid:tolower(JID), %% case R of %% "" -> %% {error, "invalid-authzid"}; @@ -133,7 +133,7 @@ register_mechanism(Mechanism, Module, PasswordType) -> check_credentials(_State, Props) -> User = proplists:get_value(username, Props, <<>>), - case jlib:nodeprep(User) of + case jid:nodeprep(User) of error -> {error, <<"not-authorized">>}; <<"">> -> {error, <<"not-authorized">>}; _LUser -> ok diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl index 1805a16e00c..17a32ef9bfb 100644 --- a/src/cyrsasl_scram.erl +++ b/src/cyrsasl_scram.erl @@ -79,7 +79,7 @@ mech_step(#state{step = 2} = State, ClientIn) -> case parse_attribute(ClientNonceAttribute) of {$r, ClientNonce} -> {Ret, _AuthModule} = (State#state.get_password)(UserName), - case {Ret, jlib:resourceprep(Ret)} of + case {Ret, jid:resourceprep(Ret)} of {false, _} -> {error, <<"not-authorized">>, UserName}; {_, error} when is_binary(Ret) -> ?WARNING_MSG("invalid plain password", []), {error, <<"not-authorized">>, UserName}; {Ret, _} -> diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index ad51db7ebd3..6e392150479 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -43,7 +43,7 @@ start(normal, _Args) -> ejabberd_logger:start(), write_pid_file(), - jlib:start(), + jid:start(), start_apps(), ejabberd:check_app(ejabberd), randoms:start(), diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 6fb3caa000f..9a77de140ae 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -187,7 +187,7 @@ try_register(User, Server, Password) -> case is_user_exists(User, Server) of true -> {atomic, exists}; false -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case lists:member(LServer, ?MYHOSTS) of true -> Res = lists:foldl(fun (_M, {atomic, ok} = Res) -> Res; @@ -358,7 +358,7 @@ remove_user(User, Server) -> lists:foreach(fun (M) -> M:remove_user(User, Server) end, auth_modules(Server)), - ejabberd_hooks:run(remove_user, jlib:nameprep(Server), + ejabberd_hooks:run(remove_user, jid:nameprep(Server), [User, Server]), ok. @@ -376,7 +376,7 @@ remove_user(User, Server, Password) -> error, auth_modules(Server)), case R of ok -> - ejabberd_hooks:run(remove_user, jlib:nameprep(Server), + ejabberd_hooks:run(remove_user, jid:nameprep(Server), [User, Server]); _ -> none end, @@ -427,7 +427,7 @@ auth_modules() -> %% Return the list of authenticated modules for a given host auth_modules(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), Default = case gen_mod:default_db(LServer) of mnesia -> internal; DBType -> DBType diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index 7533565217a..7a1d8fe84f0 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -122,8 +122,8 @@ allow_multiple_connections(Host) -> %% Check if user exist in the anonymus database anonymous_user_exist(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read({anonymous, US}) of [] -> diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index d7f2a5ae5af..78ec4c189ef 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -70,7 +70,7 @@ start(Host) -> update_reg_users_counter_table(Server) -> Set = get_vh_registered_users(Server), Size = length(Set), - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), F = fun () -> mnesia:write(#reg_users_counter{vhost = LServer, count = Size}) @@ -87,8 +87,8 @@ store_type() -> end. check_password(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read({passwd, US}) of [#passwd{password = Password}] @@ -102,8 +102,8 @@ check_password(User, Server, Password) -> check_password(User, Server, Password, Digest, DigestGen) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read({passwd, US}) of [#passwd{password = Passwd}] when is_binary(Passwd) -> @@ -130,8 +130,8 @@ check_password(User, Server, Password, Digest, %% @spec (User::string(), Server::string(), Password::string()) -> %% ok | {error, invalid_jid} set_password(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, if (LUser == error) or (LServer == error) -> {error, invalid_jid}; @@ -150,8 +150,8 @@ set_password(User, Server, Password) -> %% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} | {error, not_allowed} | {error, Reason} try_register(User, Server, PasswordList) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), Password = if is_list(PasswordList); is_binary(PasswordList) -> iolist_to_binary(PasswordList); true -> PasswordList @@ -185,7 +185,7 @@ dirty_get_registered_users() -> mnesia:dirty_all_keys(passwd). get_vh_registered_users(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), mnesia:dirty_select(passwd, [{#passwd{us = '$1', _ = '_'}, [{'==', {element, 2, '$1'}, LServer}], ['$1']}]). @@ -244,7 +244,7 @@ get_vh_registered_users(Server, _) -> get_vh_registered_users(Server). get_vh_registered_users_number(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), Query = mnesia:dirty_select(reg_users_counter, [{#reg_users_counter{vhost = LServer, count = '$1'}, @@ -265,8 +265,8 @@ get_vh_registered_users_number(Server, _) -> get_vh_registered_users_number(Server). get_password(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read(passwd, US) of [#passwd{password = Password}] @@ -282,8 +282,8 @@ get_password(User, Server) -> end. get_password_s(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read(passwd, US) of [#passwd{password = Password}] @@ -297,8 +297,8 @@ get_password_s(User, Server) -> %% @spec (User, Server) -> true | false | {error, Error} is_user_exists(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, case catch mnesia:dirty_read({passwd, US}) of [] -> false; @@ -310,8 +310,8 @@ is_user_exists(User, Server) -> %% @doc Remove user. %% Note: it returns ok even if there was some problem removing the user. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, F = fun () -> mnesia:delete({passwd, US}), @@ -324,8 +324,8 @@ remove_user(User, Server) -> %% @spec (User, Server, Password) -> ok | not_exists | not_allowed | bad_request %% @doc Remove user if the provided password is correct. remove_user(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, F = fun () -> case mnesia:read({passwd, US}) of diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index 4fdb87b2079..d637b6b85ba 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -228,11 +228,11 @@ get_vh_registered_users_ldap(Server) -> UIDFormat) of {ok, U} -> - case jlib:nodeprep(U) of + case jid:nodeprep(U) of error -> []; LU -> [{LU, - jlib:nameprep(Server)}] + jid:nameprep(Server)}] end; _ -> [] end diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index de9114037e4..d57c185da02 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -65,8 +65,8 @@ store_type() -> %% @spec (User, Server, Password) -> true | false | {error, Error} check_password(User, Server, Password) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> false; (LUser == <<>>) or (LServer == <<>>) -> @@ -115,8 +115,8 @@ check_password(User, Server, Password) -> %% @spec (User, Server, Password, Digest, DigestGen) -> true | false | {error, Error} check_password(User, Server, Password, Digest, DigestGen) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> false; (LUser == <<>>) or (LServer == <<>>) -> @@ -151,8 +151,8 @@ check_password(User, Server, Password, Digest, %% @spec (User::string(), Server::string(), Password::string()) -> %% ok | {error, invalid_jid} set_password(User, Server, Password) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> {error, invalid_jid}; (LUser == <<>>) or (LServer == <<>>) -> @@ -187,8 +187,8 @@ set_password(User, Server, Password) -> %% @spec (User, Server, Password) -> {atomic, ok} | {atomic, exists} | {error, invalid_jid} try_register(User, Server, Password) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> {error, invalid_jid}; (LUser == <<>>) or (LServer == <<>>) -> @@ -228,7 +228,7 @@ dirty_get_registered_users() -> Servers). get_vh_registered_users(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case catch odbc_queries:list_users(LServer) of {selected, [<<"username">>], Res} -> [{U, LServer} || [U] <- Res]; @@ -236,7 +236,7 @@ get_vh_registered_users(Server) -> end. get_vh_registered_users(Server, Opts) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case catch odbc_queries:list_users(LServer, Opts) of {selected, [<<"username">>], Res} -> [{U, LServer} || [U] <- Res]; @@ -244,7 +244,7 @@ get_vh_registered_users(Server, Opts) -> end. get_vh_registered_users_number(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case catch odbc_queries:users_number(LServer) of {selected, [_], [[Res]]} -> jlib:binary_to_integer(Res); @@ -252,7 +252,7 @@ get_vh_registered_users_number(Server) -> end. get_vh_registered_users_number(Server, Opts) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case catch odbc_queries:users_number(LServer, Opts) of {selected, [_], [[Res]]} -> jlib:binary_to_integer(Res); @@ -260,8 +260,8 @@ get_vh_registered_users_number(Server, Opts) -> end. get_password(User, Server) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> false; (LUser == <<>>) or (LServer == <<>>) -> @@ -291,8 +291,8 @@ get_password(User, Server) -> end. get_password_s(User, Server) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> <<"">>; (LUser == <<>>) or (LServer == <<>>) -> @@ -311,11 +311,11 @@ get_password_s(User, Server) -> %% @spec (User, Server) -> true | false | {error, Error} is_user_exists(User, Server) -> - case jlib:nodeprep(User) of + case jid:nodeprep(User) of error -> false; LUser -> Username = ejabberd_odbc:escape(LUser), - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), try odbc_queries:get_password(LServer, Username) of {selected, [<<"password">>], [[_Password]]} -> true; %% Account exists @@ -331,11 +331,11 @@ is_user_exists(User, Server) -> %% @doc Remove user. %% Note: it may return ok even if there was some problem removing the user. remove_user(User, Server) -> - case jlib:nodeprep(User) of + case jid:nodeprep(User) of error -> error; LUser -> Username = ejabberd_odbc:escape(LUser), - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), catch odbc_queries:del_user(LServer, Username), ok end. @@ -343,8 +343,8 @@ remove_user(User, Server) -> %% @spec (User, Server, Password) -> ok | error | not_exists | not_allowed %% @doc Remove user if the provided password is correct. remove_user(User, Server, Password) -> - LServer = jlib:nameprep(Server), - LUser = jlib:nodeprep(User), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), if (LUser == error) or (LServer == error) -> error; (LUser == <<>>) or (LServer == <<>>) -> @@ -429,7 +429,7 @@ set_password_scram_t(Username, <<"'">>]). convert_to_scram(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), if LServer == error; LServer == <<>> -> diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 3f3484c146b..3d7f1c1dba4 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -67,8 +67,8 @@ passwd_schema() -> {record_info(fields, passwd), #passwd{}}. check_password(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {ok, #passwd{password = Password}} when is_binary(Password) -> Password /= <<"">>; @@ -80,8 +80,8 @@ check_password(User, Server, Password) -> check_password(User, Server, Password, Digest, DigestGen) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {ok, #passwd{password = Passwd}} when is_binary(Passwd) -> DigRes = if Digest /= <<"">> -> @@ -105,8 +105,8 @@ check_password(User, Server, Password, Digest, end. set_password(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, if (LUser == error) or (LServer == error) -> {error, invalid_jid}; @@ -122,8 +122,8 @@ set_password(User, Server, Password) -> end. try_register(User, Server, PasswordList) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), Password = if is_list(PasswordList); is_binary(PasswordList) -> iolist_to_binary(PasswordList); true -> PasswordList @@ -159,7 +159,7 @@ dirty_get_registered_users() -> end, ejabberd_config:get_vh_by_auth_method(riak)). get_vh_registered_users(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case ejabberd_riak:get_keys_by_index(passwd, <<"host">>, LServer) of {ok, Users} -> Users; @@ -171,7 +171,7 @@ get_vh_registered_users(Server, _) -> get_vh_registered_users(Server). get_vh_registered_users_number(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case ejabberd_riak:count_by_index(passwd, <<"host">>, LServer) of {ok, N} -> N; @@ -183,8 +183,8 @@ get_vh_registered_users_number(Server, _) -> get_vh_registered_users_number(Server). get_password(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {ok, #passwd{password = Password}} when is_binary(Password) -> @@ -199,8 +199,8 @@ get_password(User, Server) -> end. get_password_s(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {ok, #passwd{password = Password}} when is_binary(Password) -> @@ -212,8 +212,8 @@ get_password_s(User, Server) -> end. is_user_exists(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {error, notfound} -> false; {ok, _} -> true; @@ -221,14 +221,14 @@ is_user_exists(User, Server) -> end. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), ejabberd_riak:delete(passwd, {LUser, LServer}), ok. remove_user(User, Server, Password) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case ejabberd_riak:get(passwd, passwd_schema(), {LUser, LServer}) of {ok, #passwd{password = Password}} when is_binary(Password) -> diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 57cf50641ed..f552964180a 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -224,7 +224,7 @@ del_aux_field(Key, #state{aux_fields = Opts} = State) -> State#state{aux_fields = Opts1}. get_subscription(From = #jid{}, StateData) -> - get_subscription(jlib:jid_tolower(From), StateData); + get_subscription(jid:tolower(From), StateData); get_subscription(LFrom, StateData) -> LBFrom = setelement(3, LFrom, <<"">>), F = (?SETS):is_element(LFrom, StateData#state.pres_f) @@ -347,7 +347,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> Server = case StateData#state.server of <<"">> -> - jlib:nameprep(xml:get_attr_s(<<"to">>, Attrs)); + jid:nameprep(xml:get_attr_s(<<"to">>, Attrs)); S -> S end, Lang = case xml:get_attr_s(<<"xml:lang">>, Attrs) of @@ -366,7 +366,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> IsBlacklistedIP = is_ip_blacklisted(StateData#state.ip, Lang), case lists:member(Server, ?MYHOSTS) of true when IsBlacklistedIP == false -> - change_shaper(StateData, jlib:make_jid(<<"">>, Server, <<"">>)), + change_shaper(StateData, jid:make(<<"">>, Server, <<"">>)), case xml:get_attr_s(<<"version">>, Attrs) of <<"1.0">> -> send_header(StateData, Server, <<"1.0">>, DefaultLang), @@ -605,7 +605,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> send_element(StateData, Err), fsm_next_state(wait_for_auth, StateData); {auth, _ID, set, {U, P, D, R}} -> - JID = jlib:make_jid(U, StateData#state.server, R), + JID = jid:make(U, StateData#state.server, R), case JID /= error andalso acl:match_rule(StateData#state.server, StateData#state.access, JID) @@ -622,7 +622,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> {true, AuthModule} -> ?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s", [StateData#state.socket, - jlib:jid_to_string(JID), AuthModule, + jid:to_string(JID), AuthModule, ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [true, U, StateData#state.server, @@ -642,7 +642,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> StateData#state.server, {[], []}, [U, StateData#state.server]), - LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + LJID = jid:tolower(jid:remove_resource(JID)), Fs1 = [LJID | Fs], Ts1 = [LJID | Ts], PrivList = ejabberd_hooks:run_fold(privacy_get_user_list, @@ -661,7 +661,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> _ -> ?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s", [StateData#state.socket, - jlib:jid_to_string(JID), + jid:to_string(JID), ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, U, StateData#state.server, @@ -682,7 +682,7 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> ?INFO_MSG("(~w) Forbidden legacy authentication " "for ~s from ~s", [StateData#state.socket, - jlib:jid_to_string(JID), + jid:to_string(JID), ejabberd_config:may_hide_data(jlib:ip_to_list(StateData#state.ip))]), ejabberd_hooks:run(c2s_auth_result, StateData#state.server, [false, U, StateData#state.server, @@ -1038,7 +1038,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> U = StateData#state.user, R1 = xml:get_path_s(SubEl, [{elem, <<"resource">>}, cdata]), - R = case jlib:resourceprep(R1) of + R = case jid:resourceprep(R1) of error -> error; <<"">> -> iolist_to_binary([randoms:get_string() @@ -1063,7 +1063,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> send_element(StateData, Err), fsm_next_state(wait_for_bind, StateData); {accept_resource, R2} -> - JID = jlib:make_jid(U, StateData#state.server, R2), + JID = jid:make(U, StateData#state.server, R2), Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"bind">>, @@ -1073,7 +1073,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> attrs = [], children = [{xmlcdata, - jlib:jid_to_string(JID)}]}]}]}, + jid:to_string(JID)}]}]}]}, send_element(StateData, jlib:iq_to_xml(Res)), fsm_next_state(wait_for_session, StateData#state{resource = R2, jid = JID}) @@ -1108,7 +1108,7 @@ wait_for_session({xmlstreamelement, El}, StateData) -> NewStateData#state.access, JID) of allow -> ?INFO_MSG("(~w) Opened session for ~s", - [NewStateData#state.socket, jlib:jid_to_string(JID)]), + [NewStateData#state.socket, jid:to_string(JID)]), Res = jlib:make_result_iq_reply(El#xmlel{children = []}), NewState = send_stanza(NewStateData, Res), change_shaper(NewState, JID), @@ -1117,7 +1117,7 @@ wait_for_session({xmlstreamelement, El}, StateData) -> NewState#state.server, {[], []}, [U, NewState#state.server]), - LJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + LJID = jid:tolower(jid:remove_resource(JID)), Fs1 = [LJID | Fs], Ts1 = [LJID | Ts], PrivList = @@ -1143,7 +1143,7 @@ wait_for_session({xmlstreamelement, El}, StateData) -> ejabberd_hooks:run(forbidden_session_hook, NewStateData#state.server, [JID]), ?INFO_MSG("(~w) Forbidden session for ~s", - [NewStateData#state.socket, jlib:jid_to_string(JID)]), + [NewStateData#state.socket, jid:to_string(JID)]), Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), send_element(NewStateData, Err), fsm_next_state(wait_for_session, NewStateData) @@ -1226,8 +1226,8 @@ session_established2(El, StateData) -> FromJID = NewStateData#state.jid, To = xml:get_attr_s(<<"to">>, Attrs), ToJID = case To of - <<"">> -> jlib:make_jid(User, Server, <<"">>); - _ -> jlib:string_to_jid(To) + <<"">> -> jid:make(User, Server, <<"">>); + _ -> jid:from_string(To) end, NewEl1 = jlib:remove_attr(<<"xmlns">>, El), NewEl = case xml:get_attr_s(<<"xml:lang">>, Attrs) of @@ -1303,7 +1303,7 @@ wait_for_resume({xmlstreamelement, _El} = Event, StateData) -> fsm_next_state(wait_for_resume, StateData); wait_for_resume(timeout, StateData) -> ?DEBUG("Timed out waiting for resumption of stream for ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), {stop, normal, StateData}; wait_for_resume(Event, StateData) -> ?DEBUG("Ignoring event while waiting for resumption: ~p", [Event]), @@ -1395,7 +1395,7 @@ handle_info({route, _From, _To, {broadcast, Data}}, PrivListName}], children = []}]}]}, PrivPushEl = jlib:replace_from_to( - jlib:jid_remove_resource(StateData#state.jid), + jid:remove_resource(StateData#state.jid), StateData#state.jid, jlib:iq_to_xml(PrivPushIQ)), NewState = send_stanza( @@ -1423,9 +1423,9 @@ handle_info({route, From, To, Packet}]), case xml:get_attr_s(<<"type">>, Attrs) of <<"probe">> -> - LFrom = jlib:jid_tolower(From), + LFrom = jid:tolower(From), LBFrom = - jlib:jid_remove_resource(LFrom), + jid:remove_resource(LFrom), NewStateData = case (?SETS):is_element(LFrom, State#state.pres_a) @@ -1468,7 +1468,7 @@ handle_info({route, From, To, {false, Attrs, NewStateData}; <<"error">> -> NewA = - remove_element(jlib:jid_tolower(From), + remove_element(jid:tolower(From), State#state.pres_a), {true, Attrs, State#state{pres_a = NewA}}; @@ -1504,9 +1504,9 @@ handle_info({route, From, To, of allow -> LFrom = - jlib:jid_tolower(From), + jid:tolower(From), LBFrom = - jlib:jid_remove_resource(LFrom), + jid:remove_resource(LFrom), case (?SETS):is_element(LFrom, State#state.pres_a) @@ -1557,9 +1557,9 @@ handle_info({route, From, To, IQ = jlib:iq_query_info(Packet), case IQ of #iq{xmlns = ?NS_LAST} -> - LFrom = jlib:jid_tolower(From), + LFrom = jid:tolower(From), LBFrom = - jlib:jid_remove_resource(LFrom), + jid:remove_resource(LFrom), HasFromSub = ((?SETS):is_element(LFrom, StateData#state.pres_f) @@ -1654,8 +1654,8 @@ handle_info({route, From, To, end, if Pass -> Attrs2 = - jlib:replace_from_to_attrs(jlib:jid_to_string(From), - jlib:jid_to_string(To), NewAttrs), + jlib:replace_from_to_attrs(jid:to_string(From), + jid:to_string(To), NewAttrs), FixedPacket0 = #xmlel{name = Name, attrs = Attrs2, children = Els}, FixedPacket = ejabberd_hooks:run_fold( user_receive_packet, @@ -1717,8 +1717,8 @@ handle_info({send_filtered, Feature, From, To, Packet}, StateName, StateData) -> Feature, To, Packet]), NewStateData = if Drop -> ?DEBUG("Dropping packet from ~p to ~p", - [jlib:jid_to_string(From), - jlib:jid_to_string(To)]), + [jid:to_string(From), + jid:to_string(To)]), StateData; true -> FinalPacket = jlib:replace_from_to(From, To, Packet), @@ -1745,7 +1745,7 @@ handle_info({broadcast, Type, From, Packet}, StateName, StateData) -> lists:foreach( fun(USR) -> ejabberd_router:route( - From, jlib:make_jid(USR), Packet) + From, jid:make(USR), Packet) end, lists:usort(Recipients)), fsm_next_state(StateName, StateData); handle_info(Info, StateName, StateData) -> @@ -1761,7 +1761,7 @@ terminate(_Reason, StateName, StateData) -> case StateData#state.mgmt_state of resumed -> ?INFO_MSG("Closing former stream of resumed session for ~s", - [jlib:jid_to_string(StateData#state.jid)]); + [jid:to_string(StateData#state.jid)]); _ -> if StateName == session_established; StateName == wait_for_resume -> @@ -1769,7 +1769,7 @@ terminate(_Reason, StateName, StateData) -> replaced -> ?INFO_MSG("(~w) Replaced session for ~s", [StateData#state.socket, - jlib:jid_to_string(StateData#state.jid)]), + jid:to_string(StateData#state.jid)]), From = StateData#state.jid, Packet = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], @@ -1789,7 +1789,7 @@ terminate(_Reason, StateName, StateData) -> _ -> ?INFO_MSG("(~w) Close session for ~s", [StateData#state.socket, - jlib:jid_to_string(StateData#state.jid)]), + jid:to_string(StateData#state.jid)]), EmptySet = (?SETS):new(), case StateData of #state{pres_last = undefined, pres_a = EmptySet} -> @@ -1978,7 +1978,7 @@ get_conn_type(StateData) -> end. process_presence_probe(From, To, StateData) -> - LFrom = jlib:jid_tolower(From), + LFrom = jid:tolower(From), LBFrom = setelement(3, LFrom, <<"">>), case StateData#state.pres_last of undefined -> @@ -2076,7 +2076,7 @@ presence_update(From, Packet, StateData) -> %% User sends a directed presence packet presence_track(From, To, Packet, StateData) -> #xmlel{attrs = Attrs} = Packet, - LTo = jlib:jid_tolower(To), + LTo = jid:tolower(To), User = StateData#state.user, Server = StateData#state.server, case xml:get_attr_s(<<"type">>, Attrs) of @@ -2089,14 +2089,14 @@ presence_track(From, To, Packet, StateData) -> ejabberd_hooks:run(roster_out_subscription, Server, [User, Server, To, subscribed]), check_privacy_route(From, StateData, - jlib:jid_remove_resource(From), To, Packet); + jid:remove_resource(From), To, Packet); <<"unsubscribe">> -> try_roster_subscribe(unsubscribe, User, Server, From, To, Packet, StateData); <<"unsubscribed">> -> ejabberd_hooks:run(roster_out_subscription, Server, [User, Server, To, unsubscribed]), check_privacy_route(From, StateData, - jlib:jid_remove_resource(From), To, Packet); + jid:remove_resource(From), To, Packet); <<"error">> -> check_privacy_route(From, StateData, From, To, Packet); <<"probe">> -> @@ -2139,7 +2139,7 @@ is_privacy_allow(StateData, From, To, Packet, Dir) -> %%% Check ACL before allowing to send a subscription stanza try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) -> - JID1 = jlib:make_jid(User, Server, <<"">>), + JID1 = jid:make(User, Server, <<"">>), Access = gen_mod:get_module_opt(Server, mod_roster, access, fun(A) when is_atom(A) -> A end, all), case acl:match_rule(Server, Access, JID1) of deny -> @@ -2149,7 +2149,7 @@ try_roster_subscribe(Type, User, Server, From, To, Packet, StateData) -> ejabberd_hooks:run(roster_out_subscription, Server, [User, Server, To, Type]), - check_privacy_route(From, StateData, jlib:jid_remove_resource(From), + check_privacy_route(From, StateData, jid:remove_resource(From), To, Packet) end. @@ -2191,7 +2191,7 @@ presence_broadcast_first(From, StateData, Packet) -> StateData#state{pres_a = As}. format_and_check_privacy(From, StateData, Packet, JIDs, Dir) -> - FJIDs = [jlib:make_jid(JID) || JID <- JIDs], + FJIDs = [jid:make(JID) || JID <- JIDs], lists:filter( fun(FJID) -> case ejabberd_hooks:run_fold( @@ -2218,7 +2218,7 @@ remove_element(E, Set) -> end. roster_change(IJID, ISubscription, StateData) -> - LIJID = jlib:jid_tolower(IJID), + LIJID = jid:tolower(IJID), IsFrom = (ISubscription == both) or (ISubscription == from), IsTo = (ISubscription == both) or (ISubscription == to), OldIsFrom = (?SETS):is_element(LIJID, StateData#state.pres_f), @@ -2237,7 +2237,7 @@ roster_change(IJID, ISubscription, StateData) -> ?DEBUG("roster changed for ~p~n", [StateData#state.user]), From = StateData#state.jid, - To = jlib:make_jid(IJID), + To = jid:make(IJID), Cond1 = IsFrom andalso not OldIsFrom, Cond2 = not IsFrom andalso OldIsFrom andalso ((?SETS):is_element(LIJID, StateData#state.pres_a)), @@ -2385,10 +2385,10 @@ process_unauthenticated_stanza(StateData, El) -> empty -> ResIQ = IQ#iq{type = error, sub_el = [?ERR_SERVICE_UNAVAILABLE]}, - Res1 = jlib:replace_from_to(jlib:make_jid(<<"">>, + Res1 = jlib:replace_from_to(jid:make(<<"">>, StateData#state.server, <<"">>), - jlib:make_jid(<<"">>, <<"">>, + jid:make(<<"">>, <<"">>, <<"">>), jlib:iq_to_xml(ResIQ)), send_element(StateData, @@ -2426,7 +2426,7 @@ fsm_next_state_gc(StateName, PackedStateData) -> fsm_next_state(session_established, #state{mgmt_max_queue = exceeded} = StateData) -> ?WARNING_MSG("ACK queue too long, terminating session for ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), Err = ?SERRT_POLICY_VIOLATION(StateData#state.lang, <<"Too many unacked stanzas">>), send_element(StateData, Err), @@ -2442,7 +2442,7 @@ fsm_next_state(wait_for_resume, #state{mgmt_timeout = 0} = StateData) -> fsm_next_state(wait_for_resume, #state{mgmt_pending_since = undefined} = StateData) -> ?INFO_MSG("Waiting for resumption of stream for ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), {next_state, wait_for_resume, StateData#state{mgmt_state = pending, mgmt_pending_since = os:timestamp()}, StateData#state.mgmt_timeout}; @@ -2477,7 +2477,7 @@ check_from(El, FromJID) -> false -> El; {value, SJID} -> - JID = jlib:string_to_jid(SJID), + JID = jid:from_string(SJID), case JID of error -> 'invalid-from'; @@ -2530,7 +2530,7 @@ route_blocking(What, StateData) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string(JID)}], + jid:to_string(JID)}], children = []} end, JIDs)}; @@ -2542,7 +2542,7 @@ route_blocking(What, StateData) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string(JID)}], + jid:to_string(JID)}], children = []} end, JIDs)}; @@ -2552,7 +2552,7 @@ route_blocking(What, StateData) -> end, PrivPushIQ = #iq{type = set, id = <<"push">>, sub_el = [SubEl]}, PrivPushEl = - jlib:replace_from_to(jlib:jid_remove_resource(StateData#state.jid), + jlib:replace_from_to(jid:remove_resource(StateData#state.jid), StateData#state.jid, jlib:iq_to_xml(PrivPushIQ)), %% No need to replace active privacy list here, %% blocking pushes are always accompanied by @@ -2653,13 +2653,13 @@ handle_enable(#state{mgmt_timeout = DefaultTimeout, ResAttrs = [{<<"xmlns">>, StateData#state.mgmt_xmlns}] ++ if Timeout > 0 -> ?INFO_MSG("Stream management with resumption enabled for ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), [{<<"id">>, make_resume_id(StateData)}, {<<"resume">>, <<"true">>}, {<<"max">>, jlib:integer_to_binary(Timeout)}]; true -> ?INFO_MSG("Stream management without resumption enabled for ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), [] end, Res = #xmlel{name = <<"enabled">>, @@ -2685,7 +2685,7 @@ handle_a(StateData, Attrs) -> check_h_attribute(StateData, H); _ -> ?DEBUG("Ignoring invalid ACK element from ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), StateData end. @@ -2740,7 +2740,7 @@ handle_resume(StateData, Attrs) -> FlushedState = csi_queue_flush(NewState), NewStateData = FlushedState#state{csi_state = active}, ?INFO_MSG("Resumed session for ~s", - [jlib:jid_to_string(NewStateData#state.jid)]), + [jid:to_string(NewStateData#state.jid)]), {ok, NewStateData}; {error, El, Msg} -> send_element(StateData, El), @@ -2752,11 +2752,11 @@ handle_resume(StateData, Attrs) -> check_h_attribute(#state{mgmt_stanzas_out = NumStanzasOut} = StateData, H) when H > NumStanzasOut -> ?DEBUG("~s acknowledged ~B stanzas, but only ~B were sent", - [jlib:jid_to_string(StateData#state.jid), H, NumStanzasOut]), + [jid:to_string(StateData#state.jid), H, NumStanzasOut]), mgmt_queue_drop(StateData#state{mgmt_stanzas_out = H}, NumStanzasOut); check_h_attribute(#state{mgmt_stanzas_out = NumStanzasOut} = StateData, H) -> ?DEBUG("~s acknowledged ~B of ~B stanzas", - [jlib:jid_to_string(StateData#state.jid), H, NumStanzasOut]), + [jid:to_string(StateData#state.jid), H, NumStanzasOut]), mgmt_queue_drop(StateData, H). update_num_stanzas_in(#state{mgmt_state = active} = StateData, El) -> @@ -2823,13 +2823,13 @@ handle_unacked_stanzas(StateData, F) ok; N -> ?INFO_MSG("~B stanzas were not acknowledged by ~s", - [N, jlib:jid_to_string(StateData#state.jid)]), + [N, jid:to_string(StateData#state.jid)]), lists:foreach( fun({_, Time, #xmlel{attrs = Attrs} = El}) -> From_s = xml:get_attr_s(<<"from">>, Attrs), - From = jlib:string_to_jid(From_s), + From = jid:from_string(From_s), To_s = xml:get_attr_s(<<"to">>, Attrs), - To = jlib:string_to_jid(To_s), + To = jid:from_string(To_s), F(From, To, El, Time) end, queue:to_list(Queue)) end; @@ -2863,7 +2863,7 @@ handle_unacked_stanzas(StateData) end, F = fun(From, _To, #xmlel{name = <<"presence">>}, _Time) -> ?DEBUG("Dropping presence stanza from ~s", - [jlib:jid_to_string(From)]); + [jid:to_string(From)]); (From, To, #xmlel{name = <<"iq">>} = El, _Time) -> Err = jlib:make_error_reply(El, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route(To, From, Err); @@ -2986,7 +2986,7 @@ csi_filter_stanza(#state{csi_state = CsiState, jid = JID} = StateData, StateData#state.server, send, [Stanza]), ?DEBUG("Going to ~p stanza for inactive client ~p", - [Action, jlib:jid_to_string(JID)]), + [Action, jid:to_string(JID)]), case Action of queue -> csi_queue_add(StateData, Stanza); drop -> StateData; @@ -3021,7 +3021,7 @@ csi_queue_send(#state{csi_queue = Queue, csi_state = CsiState, server = Host} = csi_queue_flush(#state{csi_queue = Queue, csi_state = CsiState, jid = JID, server = Host} = StateData) -> - ?DEBUG("Flushing CSI queue for ~s", [jlib:jid_to_string(JID)]), + ?DEBUG("Flushing CSI queue for ~s", [jid:to_string(JID)]), NewStateData = lists:foldl(fun({_From, Time, Stanza}, AccState) -> NewStanza = diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 8815c43678e..6006b28513c 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -88,7 +88,7 @@ create_captcha(SID, From, To, Lang, Limiter, Args) -> {ok, Type, Key, Image} -> Id = <<(randoms:get_string())/binary>>, B64Image = jlib:encode_base64((Image)), - JID = jlib:jid_to_string(From), + JID = jid:to_string(From), CID = <<"sha1+", (p1_sha:sha(Image))/binary, "@bob.xmpp.org">>, Data = #xmlel{name = <<"data">>, @@ -109,7 +109,7 @@ create_captcha(SID, From, To, Lang, Limiter, Args) -> {xmlcdata, ?NS_CAPTCHA}), ?VFIELD(<<"hidden">>, <<"from">>, {xmlcdata, - jlib:jid_to_string(To)}), + jid:to_string(To)}), ?VFIELD(<<"hidden">>, <<"challenge">>, {xmlcdata, Id}), @@ -233,7 +233,7 @@ create_captcha_x(SID, To, Lang, Limiter, HeadEls, [{xmlcdata, Imageurl}]}]}, ?VFIELD(<<"hidden">>, <<"from">>, - {xmlcdata, jlib:jid_to_string(To)}), + {xmlcdata, jid:to_string(To)}), ?VFIELD(<<"hidden">>, <<"challenge">>, {xmlcdata, Id}), ?VFIELD(<<"hidden">>, <<"sid">>, diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index 906c8dffc98..be798c6f0ab 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -514,7 +514,7 @@ check_access2(?POLICY_ACCESS, _User, _Server) -> true; check_access2(Access, User, Server) -> %% Check this user has access permission - case acl:match_rule(Server, Access, jlib:make_jid(User, Server, <<"">>)) of + case acl:match_rule(Server, Access, jid:make(User, Server, <<"">>)) of allow -> true; deny -> false end. @@ -597,7 +597,7 @@ is_admin(Name, {User, Server, _, true} = Auth) -> fun(A) when is_atom(A) -> A end, none), case acl:match_rule(Server, AdminAccess, - jlib:make_jid(User, Server, <<"">>)) of + jid:make(User, Server, <<"">>)) of allow -> case catch check_auth(get_command_definition(Name), Auth) of {ok, _, _} -> true; diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 8553b777258..6e738581121 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -306,7 +306,7 @@ normalize_hosts(Hosts) -> normalize_hosts([], PrepHosts) -> lists:reverse(PrepHosts); normalize_hosts([Host|Hosts], PrepHosts) -> - case jlib:nodeprep(iolist_to_binary(Host)) of + case jid:nodeprep(iolist_to_binary(Host)) of error -> ?ERROR_MSG("Can't load config file: " "invalid host name [~p]", [Host]), diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index de3eb70dbb5..a3098779f39 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -232,7 +232,7 @@ process_request(Data, IP, HOpts) -> "dressing' xmlns='", (?NS_HTTP_BIND)/binary, "'/>">>}; XmppDomain -> - NXmppDomain = jlib:nameprep(XmppDomain), + NXmppDomain = jid:nameprep(XmppDomain), Sid = p1_sha:sha(term_to_binary({now(), make_ref()})), case start(NXmppDomain, Sid, <<"">>, IP, HOpts) of {error, _} -> diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl index c7138981fa0..4855a757349 100644 --- a/src/ejabberd_oauth.erl +++ b/src/ejabberd_oauth.erl @@ -125,7 +125,7 @@ get_client_identity(Client, Ctx) -> {ok, {Ctx, {client, Client}}}. verify_redirection_uri(_, _, Ctx) -> {ok, Ctx}. authenticate_user({User, Server}, {password, Password} = Ctx) -> - case jlib:make_jid(User, Server, <<"">>) of + case jid:make(User, Server, <<"">>) of #jid{} = JID -> Access = ejabberd_config:get_option( @@ -173,8 +173,8 @@ associate_access_token(AccessToken, Context, AppContext) -> proplists:get_value(<<"resource_owner">>, Context, <<"">>), Scope = proplists:get_value(<<"scope">>, Context, []), Expire = proplists:get_value(<<"expiry_time">>, Context, 0), - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), R = #oauth_token{ token = AccessToken, us = {LUser, LServer}, @@ -190,8 +190,8 @@ associate_refresh_token(RefreshToken, Context, AppContext) -> check_token(User, Server, Scope, Token) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), case catch mnesia:dirty_read(oauth_token, Token) of [#oauth_token{us = {LUser, LServer}, scope = TokenScope, diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index c5e6a443627..ebf8aebac4d 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -242,7 +242,7 @@ export_users([], _Server, _Fd) -> %%%% Utilities export_user(User, Server, Fd) -> Password = ejabberd_auth:get_password_s(User, Server), - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), PasswordFormat = ejabberd_config:get_option({auth_password_format, LServer}, fun(X) -> X end, plain), Pass = case Password of {_,_,_,_} -> @@ -281,7 +281,7 @@ parse_scram_password(PassData) -> }. get_vcard(User, Server) -> - JID = jlib:make_jid(User, Server, <<>>), + JID = jid:make(User, Server, <<>>), case mod_vcard:process_sm_iq(JID, JID, #iq{type = get}) of #iq{type = result, sub_el = [_|_] = VCardEls} -> VCardEls; @@ -335,7 +335,7 @@ get_privacy(User, Server) -> %% @spec (Dir::string(), Hosts::[string()]) -> ok get_roster(User, Server) -> - JID = jlib:make_jid(User, Server, <<>>), + JID = jid:make(User, Server, <<>>), case mod_roster:get_roster(User, Server) of [_|_] = Items -> Subs = @@ -349,8 +349,8 @@ get_roster(User, Server) -> [#xmlel{name = <<"presence">>, attrs = [{<<"from">>, - jlib:jid_to_string(R#roster.jid)}, - {<<"to">>, jlib:jid_to_string(JID)}, + jid:to_string(R#roster.jid)}, + {<<"to">>, jid:to_string(JID)}, {<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, <<"subscribe">>}], children = @@ -444,7 +444,7 @@ process_el({xmlstreamelement, #xmlel{name = <<"host">>, attrs = Attrs, children = Els}}, State) -> JIDS = xml:get_attr_s(<<"jid">>, Attrs), - case jlib:string_to_jid(JIDS) of + case jid:from_string(JIDS) of #jid{lserver = S} -> case lists:member(S, ?MYHOSTS) of true -> @@ -499,7 +499,7 @@ process_user(#xmlel{name = <<"user">>, attrs = Attrs, children = Els}, _ -> Password end, - case jlib:nodeprep(Name) of + case jid:nodeprep(Name) of error -> stop("Invalid 'user': ~s", [Name]); LUser -> @@ -579,7 +579,7 @@ process_roster(El, State = #state{user = U, server = S}) -> %%%================================== %%%% Export server process_privacy(El, State = #state{user = U, server = S}) -> - JID = jlib:make_jid(U, S, <<"">>), + JID = jid:make(U, S, <<"">>), case mod_privacy:process_iq_set( [], JID, JID, #iq{type = set, sub_el = El}) of {error, Error} = Err -> @@ -605,7 +605,7 @@ process_privacy(El, State = #state{user = U, server = S}) -> %% @spec (Dir::string()) -> ok process_private(El, State = #state{user = U, server = S}) -> - JID = jlib:make_jid(U, S, <<"">>), + JID = jid:make(U, S, <<"">>), case mod_private:process_sm_iq( JID, JID, #iq{type = set, sub_el = El}) of #iq{type = result} -> @@ -617,7 +617,7 @@ process_private(El, State = #state{user = U, server = S}) -> %%%================================== %%%% Export host process_vcard(El, State = #state{user = U, server = S}) -> - JID = jlib:make_jid(U, S, <<"">>), + JID = jid:make(U, S, <<"">>), case mod_vcard:process_sm_iq( JID, JID, #iq{type = set, sub_el = El}) of #iq{type = result} -> @@ -629,9 +629,9 @@ process_vcard(El, State = #state{user = U, server = S}) -> %% @spec (Dir::string(), Host::string()) -> ok process_offline_msg(El, State = #state{user = U, server = S}) -> FromS = xml:get_attr_s(<<"from">>, El#xmlel.attrs), - case jlib:string_to_jid(FromS) of + case jid:from_string(FromS) of #jid{} = From -> - To = jlib:make_jid(U, S, <<>>), + To = jid:make(U, S, <<>>), NewEl = jlib:replace_from_to(From, To, El), case catch mod_offline:store_packet(From, To, NewEl) of {'EXIT', _} = Err -> @@ -646,9 +646,9 @@ process_offline_msg(El, State = #state{user = U, server = S}) -> %% @spec (Dir::string(), Fn::string(), Host::string()) -> ok process_presence(El, #state{user = U, server = S} = State) -> FromS = xml:get_attr_s(<<"from">>, El#xmlel.attrs), - case jlib:string_to_jid(FromS) of + case jid:from_string(FromS) of #jid{} = From -> - To = jlib:make_jid(U, S, <<>>), + To = jid:make(U, S, <<>>), NewEl = jlib:replace_from_to(From, To, El), ejabberd_router:route(From, To, NewEl), {ok, State}; diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl index f4bfbd6000c..3c7b9a765a2 100644 --- a/src/ejabberd_rdbms.erl +++ b/src/ejabberd_rdbms.erl @@ -75,7 +75,7 @@ start_odbc(Host, App) -> %% Returns {true, App} if we have configured odbc for the given host needs_odbc(Host) -> - LHost = jlib:nameprep(Host), + LHost = jid:nameprep(Host), case ejabberd_config:get_option({odbc_type, LHost}, fun(mysql) -> mysql; (pgsql) -> pgsql; diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 53ac7fb4cbf..9daa498ee77 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -99,7 +99,7 @@ register_route(Domain) -> -spec register_route(binary(), local_hint()) -> term(). register_route(Domain, LocalHint) -> - case jlib:nameprep(Domain) of + case jid:nameprep(Domain) of error -> erlang:error({invalid_domain, Domain}); LDomain -> Pid = self(), @@ -161,7 +161,7 @@ register_routes(Domains) -> -spec unregister_route(binary()) -> term(). unregister_route(Domain) -> - case jlib:nameprep(Domain) of + case jid:nameprep(Domain) of error -> erlang:error({invalid_domain, Domain}); LDomain -> Pid = self(), @@ -349,12 +349,12 @@ do_route(OrigFrom, OrigTo, OrigPacket) -> of undefined -> now(); random -> now(); - source -> jlib:jid_tolower(From); - destination -> jlib:jid_tolower(To); + source -> jid:tolower(From); + destination -> jid:tolower(To); bare_source -> - jlib:jid_remove_resource(jlib:jid_tolower(From)); + jid:remove_resource(jid:tolower(From)); bare_destination -> - jlib:jid_remove_resource(jlib:jid_tolower(To)) + jid:remove_resource(jid:tolower(To)) end, case get_component_number(LDstDomain) of undefined -> diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index 226a3492759..da4b45968d9 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -69,7 +69,7 @@ route_multicast(From, Domain, Destinations, Packet) -> end. register_route(Domain) -> - case jlib:nameprep(Domain) of + case jid:nameprep(Domain) of error -> erlang:error({invalid_domain, Domain}); LDomain -> @@ -82,7 +82,7 @@ register_route(Domain) -> end. unregister_route(Domain) -> - case jlib:nameprep(Domain) of + case jid:nameprep(Domain) of error -> erlang:error({invalid_domain, Domain}); LDomain -> @@ -209,9 +209,9 @@ code_change(_OldVsn, State, _Extra) -> do_route(From, Domain, Destinations, Packet) -> ?DEBUG("route_multicast~n\tfrom ~s~n\tdomain ~s~n\tdestinations ~p~n\tpacket ~p~n", - [jlib:jid_to_string(From), + [jid:to_string(From), Domain, - [jlib:jid_to_string(To) || To <- Destinations], + [jid:to_string(To) || To <- Destinations], Packet]), %% Try to find an appropriate multicast service diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 40179fe7dd4..a52b4a9afbd 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -311,8 +311,8 @@ do_route(From, To, Packet) -> #xmlel{name = Name, attrs = Attrs, children = Els} = Packet, NewAttrs = - jlib:replace_from_to_attrs(jlib:jid_to_string(From), - jlib:jid_to_string(To), Attrs), + jlib:replace_from_to_attrs(jid:to_string(From), + jid:to_string(To), Attrs), #jid{lserver = MyServer} = From, ejabberd_hooks:run(s2s_send_packet, MyServer, [From, To, Packet]), @@ -386,7 +386,7 @@ choose_pid(From, Pids) -> Ps -> Ps end, Pid = - lists:nth(erlang:phash(jlib:jid_remove_resource(From), + lists:nth(erlang:phash(jid:remove_resource(From), length(Pids1)), Pids1), ?DEBUG("Using ejabberd_s2s_out ~p~n", [Pid]), @@ -431,7 +431,7 @@ new_connection(MyServer, Server, From, FromTo, max_s2s_connections_number({From, To}) -> case acl:match_rule(From, max_s2s_connections, - jlib:make_jid(<<"">>, To, <<"">>)) + jid:make(<<"">>, To, <<"">>)) of Max when is_integer(Max) -> Max; _ -> ?DEFAULT_MAX_S2S_CONNECTIONS_NUMBER @@ -439,7 +439,7 @@ max_s2s_connections_number({From, To}) -> max_s2s_connections_number_per_node({From, To}) -> case acl:match_rule(From, max_s2s_connections_per_node, - jlib:make_jid(<<"">>, To, <<"">>)) + jid:make(<<"">>, To, <<"">>)) of Max when is_integer(Max) -> Max; _ -> ?DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE @@ -550,7 +550,7 @@ allow_host1(MyHost, S2SHost) -> s2s_access, fun(A) when is_atom(A) -> A end, all), - JID = jlib:make_jid(<<"">>, S2SHost, <<"">>), + JID = jid:make(<<"">>, S2SHost, <<"">>), case acl:match_rule(MyHost, Rule, JID) of deny -> false; allow -> @@ -639,7 +639,7 @@ get_cert_domains(Cert) -> true -> error end, if D /= error -> - case jlib:string_to_jid(D) of + case jid:from_string(D) of #jid{luser = <<"">>, lserver = LD, lresource = <<"">>} -> [LD]; @@ -675,7 +675,7 @@ get_cert_domains(Cert) -> when is_binary(D) -> case - jlib:string_to_jid((D)) + jid:from_string((D)) of #jid{luser = <<"">>, @@ -698,7 +698,7 @@ get_cert_domains(Cert) -> ({dNSName, D}) when is_list(D) -> case - jlib:string_to_jid(list_to_binary(D)) + jid:from_string(list_to_binary(D)) of #jid{luser = <<"">>, lserver = LD, diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index e655397b81e..1b184a274df 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -199,7 +199,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, send_text(StateData, ?STREAM_HEADER(<<" version='1.0'">>)), Auth = if StateData#state.tls_enabled -> - case jlib:nameprep(xml:get_attr_s(<<"from">>, Attrs)) of + case jid:nameprep(xml:get_attr_s(<<"from">>, Attrs)) of From when From /= <<"">>, From /= error -> {Result, Message} = ejabberd_s2s:check_peer_certificate(StateData#state.sockmod, @@ -360,7 +360,7 @@ wait_for_feature_request({xmlstreamelement, El}, ?INFO_MSG("Accepted s2s EXTERNAL authentication for ~s (TLS=~p)", [AuthDomain, StateData#state.tls_enabled]), change_shaper(StateData, <<"">>, - jlib:make_jid(<<"">>, AuthDomain, <<"">>)), + jid:make(<<"">>, AuthDomain, <<"">>)), {next_state, wait_for_stream, StateData#state{streamid = new_id(), authenticated = true}}; @@ -403,8 +403,8 @@ stream_established({xmlstreamelement, El}, StateData) -> case is_key_packet(El) of {key, To, From, Id, Key} -> ?DEBUG("GET KEY: ~p", [{To, From, Id, Key}]), - LTo = jlib:nameprep(To), - LFrom = jlib:nameprep(From), + LTo = jid:nameprep(To), + LFrom = jid:nameprep(From), case {ejabberd_s2s:allow_host(LTo, LFrom), lists:member(LTo, ejabberd_router:dirty_get_all_domains())} @@ -418,7 +418,7 @@ stream_established({xmlstreamelement, El}, StateData) -> wait_for_verification, StateData#state.connections), change_shaper(StateData, LTo, - jlib:make_jid(<<"">>, LFrom, <<"">>)), + jid:make(<<"">>, LFrom, <<"">>)), {next_state, stream_established, StateData#state{connections = Conns, timer = Timer}}; {_, false} -> @@ -430,8 +430,8 @@ stream_established({xmlstreamelement, El}, StateData) -> end; {verify, To, From, Id, Key} -> ?DEBUG("VERIFY KEY: ~p", [{To, From, Id, Key}]), - LTo = jlib:nameprep(To), - LFrom = jlib:nameprep(From), + LTo = jid:nameprep(To), + LFrom = jid:nameprep(From), Type = case ejabberd_s2s:has_key({LTo, LFrom}, Key) of true -> <<"valid">>; _ -> <<"invalid">> @@ -448,9 +448,9 @@ stream_established({xmlstreamelement, El}, StateData) -> NewEl = jlib:remove_attr(<<"xmlns">>, El), #xmlel{name = Name, attrs = Attrs} = NewEl, From_s = xml:get_attr_s(<<"from">>, Attrs), - From = jlib:string_to_jid(From_s), + From = jid:from_string(From_s), To_s = xml:get_attr_s(<<"to">>, Attrs), - To = jlib:string_to_jid(To_s), + To = jid:from_string(To_s), if (To /= error) and (From /= error) -> LFrom = From#jid.lserver, LTo = To#jid.lserver, @@ -500,8 +500,8 @@ stream_established({valid, From, To}, StateData) -> children = []}), ?INFO_MSG("Accepted s2s dialback authentication for ~s (TLS=~p)", [From, StateData#state.tls_enabled]), - LFrom = jlib:nameprep(From), - LTo = jlib:nameprep(To), + LFrom = jid:nameprep(From), + LTo = jid:nameprep(To), NSD = StateData#state{connections = (?DICT):store({LFrom, LTo}, established, StateData#state.connections)}, @@ -513,8 +513,8 @@ stream_established({invalid, From, To}, StateData) -> [{<<"from">>, To}, {<<"to">>, From}, {<<"type">>, <<"invalid">>}], children = []}), - LFrom = jlib:nameprep(From), - LTo = jlib:nameprep(To), + LFrom = jid:nameprep(From), + LTo = jid:nameprep(To), NSD = StateData#state{connections = (?DICT):erase({LFrom, LTo}, StateData#state.connections)}, diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 73aa10ff884..6d3b3e99a8c 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -999,9 +999,9 @@ bounce_element(El, Error) -> <<"result">> -> ok; _ -> Err = jlib:make_error_reply(El, Error), - From = jlib:string_to_jid(xml:get_tag_attr_s(<<"from">>, + From = jid:from_string(xml:get_tag_attr_s(<<"from">>, El)), - To = jlib:string_to_jid(xml:get_tag_attr_s(<<"to">>, + To = jid:from_string(xml:get_tag_attr_s(<<"to">>, El)), ejabberd_router:route(To, From, Err) end. diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index febede8d97e..9d9f0294e46 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -225,10 +225,10 @@ stream_established({xmlstreamelement, El}, StateData) -> %% when accept packets from any address. %% In this case, the component can send packet of %% behalf of the server users. - false -> jlib:string_to_jid(From); + false -> jid:from_string(From); %% The default is the standard behaviour in XEP-0114 _ -> - FromJID1 = jlib:string_to_jid(From), + FromJID1 = jid:from_string(From), case FromJID1 of #jid{lserver = Server} -> case lists:member(Server, StateData#state.hosts) of @@ -241,7 +241,7 @@ stream_established({xmlstreamelement, El}, StateData) -> To = xml:get_attr_s(<<"to">>, Attrs), ToJID = case To of <<"">> -> error; - _ -> jlib:string_to_jid(To) + _ -> jid:from_string(To) end, if ((Name == <<"iq">>) or (Name == <<"message">>) or (Name == <<"presence">>)) @@ -323,8 +323,8 @@ handle_info({route, From, To, Packet}, StateName, #xmlel{name = Name, attrs = Attrs, children = Els} = Packet, Attrs2 = - jlib:replace_from_to_attrs(jlib:jid_to_string(From), - jlib:jid_to_string(To), Attrs), + jlib:replace_from_to_attrs(jid:to_string(From), + jid:to_string(To), Attrs), Text = xml:element_to_binary(#xmlel{name = Name, attrs = Attrs2, children = Els}), send_text(StateData, Text); diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 772f075ec4a..c550409f8ee 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -120,7 +120,7 @@ route(From, To, Packet) -> open_session(SID, User, Server, Resource, Priority, Info) -> set_session(SID, User, Server, Resource, Priority, Info), check_for_sessions_to_replace(User, Server, Resource), - JID = jlib:make_jid(User, Server, Resource), + JID = jid:make(User, Server, Resource), ejabberd_hooks:run(sm_register_connection_hook, JID#jid.lserver, [SID, JID, Info]). @@ -133,14 +133,14 @@ open_session(SID, User, Server, Resource, Info) -> close_session(SID, User, Server, Resource) -> Mod = get_sm_backend(), - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), Info = case Mod:delete_session(LUser, LServer, LResource, SID) of {ok, #session{info = I}} -> I; {error, notfound} -> [] end, - JID = jlib:make_jid(User, Server, Resource), + JID = jid:make(User, Server, Resource), ejabberd_hooks:run(sm_remove_connection_hook, JID#jid.lserver, [SID, JID, Info]). @@ -164,13 +164,13 @@ bounce_offline_message(From, To, Packet) -> -spec disconnect_removed_user(binary(), binary()) -> ok. disconnect_removed_user(User, Server) -> - ejabberd_sm:route(jlib:make_jid(<<"">>, <<"">>, <<"">>), - jlib:make_jid(User, Server, <<"">>), + ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), + jid:make(User, Server, <<"">>), {broadcast, {exit, <<"User removed">>}}). get_user_resources(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), Mod = get_sm_backend(), Ss = Mod:get_sessions(LUser, LServer), [element(3, S#session.usr) || S <- clean_session_list(Ss)]. @@ -186,9 +186,9 @@ get_user_present_resources(LUser, LServer) -> -spec get_user_ip(binary(), binary(), binary()) -> ip(). get_user_ip(User, Server, Resource) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), Mod = get_sm_backend(), case Mod:get_sessions(LUser, LServer, LResource) of [] -> @@ -201,9 +201,9 @@ get_user_ip(User, Server, Resource) -> -spec get_user_info(binary(), binary(), binary()) -> info() | offline. get_user_info(User, Server, Resource) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), Mod = get_sm_backend(), case Mod:get_sessions(LUser, LServer, LResource) of [] -> @@ -224,7 +224,7 @@ set_presence(SID, User, Server, Resource, Priority, set_session(SID, User, Server, Resource, Priority, Info), ejabberd_hooks:run(set_presence_hook, - jlib:nameprep(Server), + jid:nameprep(Server), [User, Server, Resource, Presence]). -spec unset_presence(sid(), binary(), binary(), @@ -235,7 +235,7 @@ unset_presence(SID, User, Server, Resource, Status, set_session(SID, User, Server, Resource, undefined, Info), ejabberd_hooks:run(unset_presence_hook, - jlib:nameprep(Server), + jid:nameprep(Server), [User, Server, Resource, Status]). -spec close_session_unset_presence(sid(), binary(), binary(), @@ -245,15 +245,15 @@ close_session_unset_presence(SID, User, Server, Resource, Status) -> close_session(SID, User, Server, Resource), ejabberd_hooks:run(unset_presence_hook, - jlib:nameprep(Server), + jid:nameprep(Server), [User, Server, Resource, Status]). -spec get_session_pid(binary(), binary(), binary()) -> none | pid(). get_session_pid(User, Server, Resource) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), Mod = get_sm_backend(), case Mod:get_sessions(LUser, LServer, LResource) of [#session{sid = {_, Pid}}] -> Pid; @@ -275,7 +275,7 @@ dirty_get_my_sessions_list() -> -spec get_vh_session_list(binary()) -> [ljid()]. get_vh_session_list(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), Mod = get_sm_backend(), [S#session.usr || S <- Mod:get_sessions(LServer)]. @@ -288,7 +288,7 @@ get_all_pids() -> -spec get_vh_session_number(binary()) -> non_neg_integer(). get_vh_session_number(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), Mod = get_sm_backend(), length(Mod:get_sessions(LServer)). @@ -374,9 +374,9 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. prio(), info()) -> ok. set_session(SID, User, Server, Resource, Priority, Info) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), US = {LUser, LServer}, USR = {LUser, LServer, LResource}, Mod = get_sm_backend(), @@ -390,12 +390,12 @@ do_route(From, To, {broadcast, _} = Packet) -> <<"">> -> lists:foreach(fun(R) -> do_route(From, - jlib:jid_replace_resource(To, R), + jid:replace_resource(To, R), Packet) end, get_user_resources(To#jid.user, To#jid.server)); _ -> - {U, S, R} = jlib:jid_tolower(To), + {U, S, R} = jid:tolower(To), Mod = get_sm_backend(), case Mod:get_sessions(U, S, R) of [] -> @@ -474,7 +474,7 @@ do_route(From, To, #xmlel{} = Packet) -> PResources = get_user_present_resources(LUser, LServer), lists:foreach(fun ({_, R}) -> do_route(From, - jlib:jid_replace_resource(To, + jid:replace_resource(To, R), Packet) end, @@ -563,7 +563,7 @@ route_message(From, To, Packet, Type) -> when is_integer(Priority), Priority >= 0 -> lists:foreach(fun ({P, R}) when P == Priority; (P >= 0) and (Type == headline) -> - LResource = jlib:resourceprep(R), + LResource = jid:resourceprep(R), Mod = get_sm_backend(), case Mod:get_sessions(LUser, LServer, LResource) of @@ -619,9 +619,9 @@ clean_session_list([S1, S2 | Rest], Res) -> %% On new session, check if some existing connections need to be replace check_for_sessions_to_replace(User, Server, Resource) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), check_existing_resources(LUser, LServer, LResource), check_max_sessions(LUser, LServer). @@ -643,9 +643,9 @@ is_existing_resource(LUser, LServer, LResource) -> [] /= get_resource_sessions(LUser, LServer, LResource). get_resource_sessions(User, Server, Resource) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LResource = jlib:resourceprep(Resource), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LResource = jid:resourceprep(Resource), Mod = get_sm_backend(), [S#session.sid || S <- Mod:get_sessions(LUser, LServer, LResource)]. @@ -663,7 +663,7 @@ check_max_sessions(LUser, LServer) -> %% Defaults to infinity get_max_user_sessions(LUser, Host) -> case acl:match_rule(Host, max_user_sessions, - jlib:make_jid(LUser, Host, <<"">>)) + jid:make(LUser, Host, <<"">>)) of Max when is_integer(Max) -> Max; infinity -> infinity; diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index cfe97a73e4b..d1844b8040c 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -68,7 +68,7 @@ process_command(From, To, Packet) -> case Name of <<"message">> -> LFrom = - jlib:jid_tolower(jlib:jid_remove_resource(From)), + jid:tolower(jid:remove_resource(From)), case lists:member(LFrom, get_admin_jids()) of true -> Body = xml:get_path_s(Packet, @@ -185,9 +185,9 @@ process_large_heap(Pid, Info) -> io_lib:format("(~w) The process ~w is consuming too " "much memory:~n~p~n~s", [node(), Pid, Info, DetailedInfo])), - From = jlib:make_jid(<<"">>, Host, <<"watchdog">>), + From = jid:make(<<"">>, Host, <<"watchdog">>), lists:foreach(fun (JID) -> - send_message(From, jlib:make_jid(JID), Body) + send_message(From, jid:make(JID), Body) end, JIDs). send_message(From, To, Body) -> @@ -203,8 +203,8 @@ get_admin_jids() -> ejabberd_config:get_option( watchdog_admins, fun(JIDs) -> - [jlib:jid_tolower( - jlib:string_to_jid( + [jid:tolower( + jid:from_string( iolist_to_binary(S))) || S <- JIDs] end, []). @@ -336,7 +336,7 @@ process_remote_command(_) -> throw(unknown_command). opt_type(watchdog_admins) -> fun (JIDs) -> - [jlib:jid_tolower(jlib:string_to_jid(iolist_to_binary(S))) + [jid:tolower(jid:from_string(iolist_to_binary(S))) || S <- JIDs] end; opt_type(watchdog_large_heap) -> diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 5374cb0d100..4dc157f882f 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -95,7 +95,7 @@ is_acl_match(Host, Rules, Jid) -> get_jid(Auth, HostHTTP, Method) -> case get_auth_admin(Auth, HostHTTP, [], Method) of {ok, {User, Server}} -> - jlib:make_jid(User, Server, <<"">>); + jid:make(User, Server, <<"">>); {unauthorized, Error} -> ?ERROR_MSG("Unauthorized ~p: ~p", [Auth, Error]), throw({unauthorized, Auth}) @@ -184,7 +184,7 @@ process([<<"server">>, SHost | RPath] = Path, #request{auth = Auth, lang = Lang, host = HostHTTP, method = Method} = Request) -> - Host = jlib:nameprep(SHost), + Host = jid:nameprep(SHost), case lists:member(Host, ?MYHOSTS) of true -> case get_auth_admin(Auth, HostHTTP, Path, Method) of @@ -250,7 +250,7 @@ get_auth_admin(Auth, HostHTTP, RPath, Method) -> case Auth of {SJID, Pass} -> {HostOfRule, AccessRule} = get_acl_rule(RPath, Method), - case jlib:string_to_jid(SJID) of + case jid:from_string(SJID) of error -> {unauthorized, <<"badformed-jid">>}; #jid{user = <<"">>, server = User} -> get_auth_account(HostOfRule, AccessRule, User, HostHTTP, @@ -267,7 +267,7 @@ get_auth_account(HostOfRule, AccessRule, User, Server, case ejabberd_auth:check_password(User, Server, Pass) of true -> case is_acl_match(HostOfRule, AccessRule, - jlib:make_jid(User, Server, <<"">>)) + jid:make(User, Server, <<"">>)) of false -> {unauthorized, <<"unprivileged-account">>}; true -> {ok, {User, Server}} @@ -1128,7 +1128,7 @@ string_to_spec(<<"server_regexp">>, Val) -> {server_regexp, Val}; string_to_spec(<<"node_regexp">>, Val) -> #jid{luser = U, lserver = S, resource = <<"">>} = - jlib:string_to_jid(Val), + jid:from_string(Val), {node_regexp, U, S}; string_to_spec(<<"user_glob">>, Val) -> string_to_spec2(user_glob, Val); @@ -1136,7 +1136,7 @@ string_to_spec(<<"server_glob">>, Val) -> {server_glob, Val}; string_to_spec(<<"node_glob">>, Val) -> #jid{luser = U, lserver = S, resource = <<"">>} = - jlib:string_to_jid(Val), + jid:from_string(Val), {node_glob, U, S}; string_to_spec(<<"all">>, _) -> all; string_to_spec(<<"raw">>, Val) -> @@ -1146,7 +1146,7 @@ string_to_spec(<<"raw">>, Val) -> string_to_spec2(ACLName, Val) -> #jid{luser = U, lserver = S, resource = <<"">>} = - jlib:string_to_jid(Val), + jid:from_string(Val), case U of <<"">> -> {ACLName, S}; _ -> {ACLName, {U, S}} @@ -1362,7 +1362,7 @@ list_users_parse_query(Query, Host) -> lists:keysearch(<<"newusername">>, 1, Query), {value, {_, Password}} = lists:keysearch(<<"newuserpassword">>, 1, Query), - case jlib:string_to_jid(<>) of error -> error; @@ -1463,10 +1463,10 @@ get_lastactivity_menuitem_list(Server) -> end. us_to_list({User, Server}) -> - jlib:jid_to_string({User, Server, <<"">>}). + jid:to_string({User, Server, <<"">>}). su_to_list({Server, User}) -> - jlib:jid_to_string({User, Server, <<"">>}). + jid:to_string({User, Server, <<"">>}). %%%================================== %%%% get_stats @@ -1521,8 +1521,8 @@ list_online_users(Host, _Lang) -> SUsers). user_info(User, Server, Query, Lang) -> - LServer = jlib:nameprep(Server), - US = {jlib:nodeprep(User), LServer}, + LServer = jid:nameprep(Server), + US = {jid:nodeprep(User), LServer}, Res = user_parse_query(User, Server, Query), Resources = ejabberd_sm:get_user_resources(User, Server), diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index 8e83fb5b0b3..2580ffe6b16 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -62,7 +62,7 @@ modules() -> mod_vcard_xupdate]. export(Server, Output) -> - LServer = jlib:nameprep(iolist_to_binary(Server)), + LServer = jid:nameprep(iolist_to_binary(Server)), Modules = modules(), IO = prepare_output(Output), lists:foreach( @@ -72,7 +72,7 @@ export(Server, Output) -> close_output(Output, IO). export(Server, Output, Module) -> - LServer = jlib:nameprep(iolist_to_binary(Server)), + LServer = jid:nameprep(iolist_to_binary(Server)), IO = prepare_output(Output), lists:foreach( fun({Table, ConvertFun}) -> @@ -87,7 +87,7 @@ import_file(Server, FileName) -> {file, FileName}, {mode, read_only}]) of {ok, Fd} -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), Mods = [{Mod, gen_mod:db_type(LServer, Mod)} || Mod <- modules(), gen_mod:is_loaded(LServer, Mod)], AuthMods = case lists:member(ejabberd_auth_internal, @@ -106,7 +106,7 @@ import(Server, Output) -> import(Server, Output, [{fast, true}]). import(Server, Output, Opts) -> - LServer = jlib:nameprep(iolist_to_binary(Server)), + LServer = jid:nameprep(iolist_to_binary(Server)), Modules = modules(), IO = prepare_output(Output, disk_log), lists:foreach( @@ -116,7 +116,7 @@ import(Server, Output, Opts) -> close_output(Output, IO). import(Server, Output, Opts, Module) -> - LServer = jlib:nameprep(iolist_to_binary(Server)), + LServer = jid:nameprep(iolist_to_binary(Server)), IO = prepare_output(Output, disk_log), lists:foreach( fun({SelectQuery, ConvertFun}) -> diff --git a/src/extauth.erl b/src/extauth.erl index 766d43340c0..64220fcbec1 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -95,7 +95,7 @@ remove_user(User, Server, Password) -> [<<"removeuser3">>, User, Server, Password]). call_port(Server, Msg) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), ProcessName = get_process_name(LServer, random_instance(get_instances(LServer))), ProcessName ! {call, self(), Msg}, diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl index bfa52bb2a54..26c2a2914fb 100644 --- a/src/jd2ejd.erl +++ b/src/jd2ejd.erl @@ -42,8 +42,8 @@ import_file(File) -> User = filename:rootname(filename:basename(File)), Server = filename:basename(filename:dirname(File)), - case jlib:nodeprep(User) /= error andalso - jlib:nameprep(Server) /= error + case jid:nodeprep(User) /= error andalso + jid:nameprep(Server) /= error of true -> case file:read_file(File) of @@ -112,7 +112,7 @@ process_xdb(User, Server, xdb_data(_User, _Server, {xmlcdata, _CData}) -> ok; xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> - From = jlib:make_jid(User, Server, <<"">>), + From = jid:make(User, Server, <<"">>), case xml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_AUTH -> Password = xml:get_tag_cdata(El), @@ -129,7 +129,7 @@ xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> ok; ?NS_VCARD -> catch mod_vcard:process_sm_iq(From, - jlib:make_jid(<<"">>, Server, <<"">>), + jid:make(<<"">>, Server, <<"">>), #iq{type = set, xmlns = ?NS_VCARD, sub_el = El}), ok; @@ -139,7 +139,7 @@ xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> case xml:get_attr_s(<<"j_private_flag">>, Attrs) of <<"1">> -> catch mod_private:process_sm_iq(From, - jlib:make_jid(<<"">>, Server, + jid:make(<<"">>, Server, <<"">>), #iq{type = set, xmlns = ?NS_PRIVATE, @@ -158,13 +158,13 @@ xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> end. process_offline(Server, To, #xmlel{children = Els}) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), lists:foreach(fun (#xmlel{attrs = Attrs} = El) -> FromS = xml:get_attr_s(<<"from">>, Attrs), From = case FromS of <<"">> -> - jlib:make_jid(<<"">>, Server, <<"">>); - _ -> jlib:string_to_jid(FromS) + jid:make(<<"">>, Server, <<"">>); + _ -> jid:from_string(FromS) end, case From of error -> ok; diff --git a/src/jid.erl b/src/jid.erl new file mode 100644 index 00000000000..c09e06488db --- /dev/null +++ b/src/jid.erl @@ -0,0 +1,228 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @doc +%%% JID processing library +%%% @end +%%% Created : 24 Nov 2015 by Evgeny Khramtsov +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%------------------------------------------------------------------- +-module(jid). + +%% API +-export([start/0, + make/1, + make/3, + split/1, + from_string/1, + to_string/1, + is_nodename/1, + nodeprep/1, + nameprep/1, + resourceprep/1, + tolower/1, + remove_resource/1, + replace_resource/2]). + +-include("jlib.hrl"). + +-export_type([jid/0]). + +%%%=================================================================== +%%% API +%%%=================================================================== +-spec start() -> ok. + +start() -> + SplitPattern = binary:compile_pattern([<<"@">>, <<"/">>]), + catch ets:new(jlib, [named_table, protected, set, {keypos, 1}]), + ets:insert(jlib, {string_to_jid_pattern, SplitPattern}), + ok. + +-spec make(binary(), binary(), binary()) -> jid() | error. + +make(User, Server, Resource) -> + case nodeprep(User) of + error -> error; + LUser -> + case nameprep(Server) of + error -> error; + LServer -> + case resourceprep(Resource) of + error -> error; + LResource -> + #jid{user = User, server = Server, resource = Resource, + luser = LUser, lserver = LServer, + lresource = LResource} + end + end + end. + +-spec make({binary(), binary(), binary()}) -> jid() | error. + +make({User, Server, Resource}) -> + make(User, Server, Resource). + +%% This is the reverse of make_jid/1 +-spec split(jid()) -> {binary(), binary(), binary()} | error. + +split(#jid{user = U, server = S, resource = R}) -> + {U, S, R}; +split(_) -> + error. + +-spec from_string(binary()) -> jid() | error. + +from_string(S) -> + SplitPattern = ets:lookup_element(jlib, string_to_jid_pattern, 2), + Size = size(S), + End = Size-1, + case binary:match(S, SplitPattern) of + {0, _} -> + error; + {End, _} -> + error; + {Pos1, _} -> + case binary:at(S, Pos1) of + $/ -> + make(<<>>, + binary:part(S, 0, Pos1), + binary:part(S, Pos1+1, Size-Pos1-1)); + _ -> + Pos1N = Pos1+1, + case binary:match(S, SplitPattern, [{scope, {Pos1+1, Size-Pos1-1}}]) of + {End, _} -> + error; + {Pos1N, _} -> + error; + {Pos2, _} -> + case binary:at(S, Pos2) of + $/ -> + make(binary:part(S, 0, Pos1), + binary:part(S, Pos1+1, Pos2-Pos1-1), + binary:part(S, Pos2+1, Size-Pos2-1)); + _ -> error + end; + _ -> + make(binary:part(S, 0, Pos1), + binary:part(S, Pos1+1, Size-Pos1-1), + <<>>) + end + end; + _ -> + make(<<>>, S, <<>>) + end. + +-spec to_string(jid() | ljid()) -> binary(). + +to_string(#jid{user = User, server = Server, + resource = Resource}) -> + to_string({User, Server, Resource}); +to_string({N, S, R}) -> + Node = iolist_to_binary(N), + Server = iolist_to_binary(S), + Resource = iolist_to_binary(R), + S1 = case Node of + <<"">> -> <<"">>; + _ -> <> + end, + S2 = <>, + S3 = case Resource of + <<"">> -> S2; + _ -> <> + end, + S3. + +-spec is_nodename(binary()) -> boolean(). + +is_nodename(Node) -> + N = nodeprep(Node), + (N /= error) and (N /= <<>>). + +-define(LOWER(Char), + if Char >= $A, Char =< $Z -> Char + 32; + true -> Char + end). + +-spec nodeprep(binary()) -> binary() | error. + +nodeprep("") -> <<>>; +nodeprep(S) when byte_size(S) < 1024 -> + R = stringprep:nodeprep(S), + if byte_size(R) < 1024 -> R; + true -> error + end; +nodeprep(_) -> error. + +-spec nameprep(binary()) -> binary() | error. + +nameprep(S) when byte_size(S) < 1024 -> + R = stringprep:nameprep(S), + if byte_size(R) < 1024 -> R; + true -> error + end; +nameprep(_) -> error. + +-spec resourceprep(binary()) -> binary() | error. + +resourceprep(S) when byte_size(S) < 1024 -> + R = stringprep:resourceprep(S), + if byte_size(R) < 1024 -> R; + true -> error + end; +resourceprep(_) -> error. + +-spec tolower(jid() | ljid()) -> error | ljid(). + +tolower(#jid{luser = U, lserver = S, + lresource = R}) -> + {U, S, R}; +tolower({U, S, R}) -> + case nodeprep(U) of + error -> error; + LUser -> + case nameprep(S) of + error -> error; + LServer -> + case resourceprep(R) of + error -> error; + LResource -> {LUser, LServer, LResource} + end + end + end. + +-spec remove_resource(jid()) -> jid(); + (ljid()) -> ljid(). + +remove_resource(#jid{} = JID) -> + JID#jid{resource = <<"">>, lresource = <<"">>}; +remove_resource({U, S, _R}) -> {U, S, <<"">>}. + +-spec replace_resource(jid(), binary()) -> error | jid(). + +replace_resource(JID, Resource) -> + case resourceprep(Resource) of + error -> error; + LResource -> + JID#jid{resource = Resource, lresource = LResource} + end. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== diff --git a/src/jlib.erl b/src/jlib.erl index 52dd9b2c923..711c432e603 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -39,10 +39,7 @@ make_error_reply/2, make_error_element/2, make_correct_from_to_attrs/3, replace_from_to_attrs/3, replace_from_to/3, replace_from_attrs/2, replace_from/2, - remove_attr/2, make_jid/3, make_jid/1, split_jid/1, string_to_jid/1, - jid_to_string/1, is_nodename/1, tolower/1, nodeprep/1, - nameprep/1, resourceprep/1, jid_tolower/1, - jid_remove_resource/1, jid_replace_resource/2, + remove_attr/2, tolower/1, get_iq_namespace/1, iq_query_info/1, iq_query_or_response_info/1, is_iq_request_type/1, iq_to_xml/1, parse_xdata_submit/1, @@ -58,19 +55,16 @@ atom_to_binary/1, binary_to_atom/1, tuple_to_binary/1, l2i/1, i2l/1, i2l/2, queue_drop_while/2]). --export([start/0]). +%% The following functions are deprecated and will be removed soon +%% Use corresponding functions from jid.erl instead +-export([make_jid/3, make_jid/1, split_jid/1, string_to_jid/1, + jid_to_string/1, is_nodename/1, nodeprep/1, + nameprep/1, resourceprep/1, jid_tolower/1, + jid_remove_resource/1, jid_replace_resource/2]). -include("ejabberd.hrl"). -include("jlib.hrl"). --export_type([jid/0]). - -start() -> - SplitPattern = binary:compile_pattern([<<"@">>, <<"/">>]), - catch ets:new(jlib, [named_table, protected, set, {keypos, 1}]), - ets:insert(jlib, {string_to_jid_pattern, SplitPattern}), - ok. - %send_iq(From, To, ID, SubTags) -> % ok. @@ -173,8 +167,8 @@ replace_from_to_attrs(From, To, Attrs) -> replace_from_to(From, To, #xmlel{name = Name, attrs = Attrs, children = Els}) -> NewAttrs = - replace_from_to_attrs(jlib:jid_to_string(From), - jlib:jid_to_string(To), Attrs), + replace_from_to_attrs(jid:to_string(From), + jid:to_string(To), Attrs), #xmlel{name = Name, attrs = NewAttrs, children = Els}. -spec replace_from_attrs(binary(), [attr()]) -> [attr()]. @@ -187,7 +181,7 @@ replace_from_attrs(From, Attrs) -> replace_from(From, #xmlel{name = Name, attrs = Attrs, children = Els}) -> - NewAttrs = replace_from_attrs(jlib:jid_to_string(From), + NewAttrs = replace_from_attrs(jid:to_string(From), Attrs), #xmlel{name = Name, attrs = NewAttrs, children = Els}. @@ -201,101 +195,32 @@ remove_attr(Attr, -spec make_jid(binary(), binary(), binary()) -> jid() | error. make_jid(User, Server, Resource) -> - case nodeprep(User) of - error -> error; - LUser -> - case nameprep(Server) of - error -> error; - LServer -> - case resourceprep(Resource) of - error -> error; - LResource -> - #jid{user = User, server = Server, resource = Resource, - luser = LUser, lserver = LServer, - lresource = LResource} - end - end - end. + jid:make(User, Server, Resource). -spec make_jid({binary(), binary(), binary()}) -> jid() | error. make_jid({User, Server, Resource}) -> - make_jid(User, Server, Resource). + jid:make({User, Server, Resource}). %% This is the reverse of make_jid/1 -spec split_jid(jid()) -> {binary(), binary(), binary()} | error. -split_jid(#jid{user = U, server = S, resource = R}) -> - {U, S, R}; -split_jid(_) -> - error. +split_jid(J) -> + jid:split(J). -spec string_to_jid(binary()) -> jid() | error. string_to_jid(S) -> - SplitPattern = ets:lookup_element(jlib, string_to_jid_pattern, 2), - Size = size(S), - End = Size-1, - case binary:match(S, SplitPattern) of - {0, _} -> - error; - {End, _} -> - error; - {Pos1, _} -> - case binary:at(S, Pos1) of - $/ -> - make_jid(<<>>, - binary:part(S, 0, Pos1), - binary:part(S, Pos1+1, Size-Pos1-1)); - _ -> - Pos1N = Pos1+1, - case binary:match(S, SplitPattern, [{scope, {Pos1+1, Size-Pos1-1}}]) of - {End, _} -> - error; - {Pos1N, _} -> - error; - {Pos2, _} -> - case binary:at(S, Pos2) of - $/ -> - make_jid(binary:part(S, 0, Pos1), - binary:part(S, Pos1+1, Pos2-Pos1-1), - binary:part(S, Pos2+1, Size-Pos2-1)); - _ -> error - end; - _ -> - make_jid(binary:part(S, 0, Pos1), - binary:part(S, Pos1+1, Size-Pos1-1), - <<>>) - end - end; - _ -> - make_jid(<<>>, S, <<>>) - end. + jid:from_string(S). -spec jid_to_string(jid() | ljid()) -> binary(). -jid_to_string(#jid{user = User, server = Server, - resource = Resource}) -> - jid_to_string({User, Server, Resource}); -jid_to_string({N, S, R}) -> - Node = iolist_to_binary(N), - Server = iolist_to_binary(S), - Resource = iolist_to_binary(R), - S1 = case Node of - <<"">> -> <<"">>; - _ -> <> - end, - S2 = <>, - S3 = case Resource of - <<"">> -> S2; - _ -> <> - end, - S3. +jid_to_string(J) -> + jid:to_string(J). -spec is_nodename(binary()) -> boolean(). is_nodename(Node) -> - N = nodeprep(Node), - (N /= error) and (N /= <<>>). + jid:is_nodename(Node). %tolower_c(C) when C >= $A, C =< $Z -> % C + 32; @@ -333,66 +258,30 @@ tolower_s([]) -> []. -spec nodeprep(binary()) -> binary() | error. -nodeprep("") -> <<>>; -nodeprep(S) when byte_size(S) < 1024 -> - R = stringprep:nodeprep(S), - if byte_size(R) < 1024 -> R; - true -> error - end; -nodeprep(_) -> error. +nodeprep(S) -> jid:nodeprep(S). -spec nameprep(binary()) -> binary() | error. -nameprep(S) when byte_size(S) < 1024 -> - R = stringprep:nameprep(S), - if byte_size(R) < 1024 -> R; - true -> error - end; -nameprep(_) -> error. +nameprep(S) -> jid:nameprep(S). -spec resourceprep(binary()) -> binary() | error. -resourceprep(S) when byte_size(S) < 1024 -> - R = stringprep:resourceprep(S), - if byte_size(R) < 1024 -> R; - true -> error - end; -resourceprep(_) -> error. +resourceprep(S) -> jid:resourceprep(S). -spec jid_tolower(jid() | ljid()) -> error | ljid(). -jid_tolower(#jid{luser = U, lserver = S, - lresource = R}) -> - {U, S, R}; -jid_tolower({U, S, R}) -> - case nodeprep(U) of - error -> error; - LUser -> - case nameprep(S) of - error -> error; - LServer -> - case resourceprep(R) of - error -> error; - LResource -> {LUser, LServer, LResource} - end - end - end. +jid_tolower(J) -> + jid:tolower(J). -spec jid_remove_resource(jid()) -> jid(); (ljid()) -> ljid(). -jid_remove_resource(#jid{} = JID) -> - JID#jid{resource = <<"">>, lresource = <<"">>}; -jid_remove_resource({U, S, _R}) -> {U, S, <<"">>}. +jid_remove_resource(J) -> jid:remove_resource(J). -spec jid_replace_resource(jid(), binary()) -> error | jid(). jid_replace_resource(JID, Resource) -> - case resourceprep(Resource) of - error -> error; - LResource -> - JID#jid{resource = Resource, lresource = LResource} - end. + jid:replace_resource(JID, Resource). -spec get_iq_namespace(xmlel()) -> binary(). @@ -668,7 +557,7 @@ add_delay_info(El, From, Time, Desc) -> -> xmlel() | error. create_delay_tag(TimeStamp, FromJID, Desc) when is_tuple(FromJID) -> - From = jlib:jid_to_string(FromJID), + From = jid:to_string(FromJID), Stamp = now_to_utc_string(TimeStamp, 3), Children = case Desc of <<"">> -> []; @@ -680,7 +569,7 @@ create_delay_tag(TimeStamp, FromJID, Desc) when is_tuple(FromJID) -> {<<"stamp">>, Stamp}], children = Children}; create_delay_tag(DateTime, Host, Desc) when is_binary(Host) -> - FromJID = jlib:make_jid(<<"">>, Host, <<"">>), + FromJID = jid:make(<<"">>, Host, <<"">>), create_delay_tag(DateTime, FromJID, Desc). -type tz() :: {binary(), {integer(), integer()}} | {integer(), integer()} | utc. diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index f5480483171..f476dabfbd3 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -142,7 +142,7 @@ get_sm_commands(Acc, _From, end, Nodes = [#xmlel{name = <<"item">>, attrs = - [{<<"jid">>, jlib:jid_to_string(To)}, + [{<<"jid">>, jid:to_string(To)}, {<<"node">>, ?NS_COMMANDS}, {<<"name">>, translate:translate(Lang, <<"Commands">>)}], diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 30e2a32eb10..cebd5cea4e0 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -688,8 +688,8 @@ get_resources(User, Server) -> get_sessions(User, Server)). get_sessions(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), Sessions = mnesia:dirty_index_read(session, {LUser, LServer}, #session.us), true = is_list(Sessions), Sessions. @@ -734,8 +734,8 @@ kick_session(User, Server, Resource, ReasonText) -> ok. kick_this_session(User, Server, Resource, Reason) -> - ejabberd_sm:route(jlib:make_jid(<<"">>, <<"">>, <<"">>), - jlib:make_jid(User, Server, Resource), + ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), + jid:make(User, Server, Resource), {broadcast, {exit, Reason}}). status_num(Host, Status) -> @@ -814,8 +814,8 @@ stringize(String) -> set_presence(User, Host, Resource, Type, Show, Status, Priority) -> Pid = ejabberd_sm:get_session_pid(User, Host, Resource), - USR = jlib:jid_to_string(jlib:make_jid(User, Host, Resource)), - US = jlib:jid_to_string(jlib:make_jid(User, Host, <<>>)), + 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}], @@ -901,7 +901,7 @@ get_module_resource(Server) -> get_vcard_content(User, Server, Data) -> [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}), - JID = jlib:make_jid(User, Server, get_module_resource(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, @@ -938,7 +938,7 @@ set_vcard_content(User, Server, Data, SomeContent) -> Bin when is_binary(Bin) -> [SomeContent] end, [{_, Module, Function, _Opts}] = ets:lookup(sm_iqtable, {?NS_VCARD, Server}), - JID = jlib:make_jid(User, Server, get_module_resource(Server)), + JID = jid:make(User, Server, get_module_resource(Server)), IQ = #iq{type = get, xmlns = ?NS_VCARD}, IQr = Module:Function(JID, JID, IQ), @@ -1052,7 +1052,7 @@ get_roster(User, Server) -> make_roster_xmlrpc(Roster) -> lists:foldl( fun(Item, Res) -> - JIDS = jlib:jid_to_string(Item#roster.jid), + JIDS = jid:to_string(Item#roster.jid), Nick = Item#roster.name, Subs = atom_to_list(Item#roster.subscription), Ask = atom_to_list(Item#roster.ask), @@ -1118,7 +1118,7 @@ push_roster_item(LU, LS, U, S, Action) -> end, ejabberd_sm:get_user_resources(LU, LS)). push_roster_item(LU, LS, R, U, S, Action) -> - LJID = jlib:make_jid(LU, LS, R), + LJID = jid:make(LU, LS, R), BroadcastEl = build_broadcast(U, S, Action), ejabberd_sm:route(LJID, LJID, BroadcastEl), Item = build_roster_item(U, S, Action), @@ -1127,14 +1127,14 @@ push_roster_item(LU, LS, R, U, S, Action) -> build_roster_item(U, S, {add, Nick, Subs, Group}) -> {xmlel, <<"item">>, - [{<<"jid">>, jlib:jid_to_string(jlib:make_jid(U, S, <<>>))}, + [{<<"jid">>, jid:to_string(jid:make(U, S, <<>>))}, {<<"name">>, Nick}, {<<"subscription">>, Subs}], [{xmlel, <<"group">>, [], [{xmlcdata, Group}]}] }; build_roster_item(U, S, remove) -> {xmlel, <<"item">>, - [{<<"jid">>, jlib:jid_to_string(jlib:make_jid(U, S, <<>>))}, + [{<<"jid">>, jid:to_string(jid:make(U, S, <<>>))}, {<<"subscription">>, <<"remove">>}], [] }. @@ -1193,8 +1193,8 @@ get_last(User, Server) -> %% Cluth private_get(Username, Host, Element, Ns) -> - From = jlib:make_jid(Username, Host, <<>>), - To = jlib:make_jid(Username, Host, <<>>), + From = jid:make(Username, Host, <<>>), + To = jid:make(Username, Host, <<>>), IQ = {iq, <<>>, get, ?NS_PRIVATE, <<>>, {xmlel, <<"query">>, [{<<"xmlns">>,?NS_PRIVATE}], @@ -1216,8 +1216,8 @@ private_set(Username, Host, ElementString) -> end. private_set2(Username, Host, Xml) -> - From = jlib:make_jid(Username, Host, <<>>), - To = jlib:make_jid(Username, Host, <<>>), + From = jid:make(Username, Host, <<>>), + To = jid:make(Username, Host, <<>>), IQ = {iq, <<>>, set, ?NS_PRIVATE, <<>>, {xmlel, <<"query">>, [{<<"xmlns">>, ?NS_PRIVATE}], @@ -1261,7 +1261,7 @@ btl(B) -> binary_to_list(B). srg_get_members(Group, Host) -> Members = mod_shared_roster:get_group_explicit_users(Host,Group), - [jlib:jid_to_string(jlib:make_jid(MUser, MServer, <<>>)) + [jid:to_string(jid:make(MUser, MServer, <<>>)) || {MUser, MServer} <- Members]. srg_user_add(User, Host, Group, GroupHost) -> @@ -1292,8 +1292,8 @@ send_message(Type, From, To, Subject, Body) -> %% If the user is local and is online in several resources, %% the packet is sent to all its resources. send_packet_all_resources(FromJIDString, ToJIDString, Packet) -> - FromJID = jlib:string_to_jid(FromJIDString), - ToJID = jlib:string_to_jid(ToJIDString), + FromJID = jid:from_string(FromJIDString), + ToJID = jid:from_string(ToJIDString), ToUser = ToJID#jid.user, ToServer = ToJID#jid.server, case ToJID#jid.resource of @@ -1317,7 +1317,7 @@ send_packet_all_resources(FromJID, ToUser, ToServer, Packet) -> end. send_packet_all_resources(FromJID, ToU, ToS, ToR, Packet) -> - ToJID = jlib:make_jid(ToU, ToS, ToR), + ToJID = jid:make(ToU, ToS, ToR), ejabberd_router:route(FromJID, ToJID, Packet). build_packet(Type, Subject, Body) -> @@ -1335,8 +1335,8 @@ send_stanza_c2s(Username, Host, Resource, Stanza) -> p1_fsm:send_event(C2sPid, {xmlstreamelement, XmlEl}). privacy_set(Username, Host, QueryS) -> - From = jlib:make_jid(Username, Host, <<"">>), - To = jlib:make_jid(<<"">>, Host, <<"">>), + From = jid:make(Username, Host, <<"">>), + To = jid:make(<<"">>, Host, <<"">>), QueryEl = xml_stream:parse_element(QueryS), StanzaEl = {xmlel, <<"iq">>, [{<<"type">>, <<"set">>}], [QueryEl]}, IQ = jlib:iq_query_info(StanzaEl), @@ -1477,7 +1477,7 @@ decide_rip_jid({UName, UServer, _UResource}, Match_list) -> decide_rip_jid({UName, UServer}, Match_list) -> lists:any( fun(Match_string) -> - MJID = jlib:string_to_jid(list_to_binary(Match_string)), + MJID = jid:from_string(list_to_binary(Match_string)), MName = MJID#jid.luser, MServer = MJID#jid.lserver, Is_server = is_glob_match(UServer, MServer), diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 8049dd4f638..76d59d40965 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -691,10 +691,10 @@ announce_all(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> - Local = jlib:make_jid(<<>>, To#jid.server, <<>>), + Local = jid:make(<<>>, To#jid.server, <<>>), lists:foreach( fun({User, Server}) -> - Dest = jlib:make_jid(User, Server, <<>>), + Dest = jid:make(User, Server, <<>>), ejabberd_router:route(Local, Dest, Packet) end, ejabberd_auth:get_vh_registered_users(Host)) end. @@ -706,10 +706,10 @@ announce_all_hosts_all(From, To, Packet) -> Err = jlib:make_error_reply(Packet, ?ERR_FORBIDDEN), ejabberd_router:route(To, From, Err); allow -> - Local = jlib:make_jid(<<>>, To#jid.server, <<>>), + Local = jid:make(<<>>, To#jid.server, <<>>), lists:foreach( fun({User, Server}) -> - Dest = jlib:make_jid(User, Server, <<>>), + Dest = jid:make(User, Server, <<>>), ejabberd_router:route(Local, Dest, Packet) end, ejabberd_auth:dirty_get_registered_users()) end. @@ -740,10 +740,10 @@ announce_all_hosts_online(From, To, Packet) -> end. announce_online1(Sessions, Server, Packet) -> - Local = jlib:make_jid(<<>>, Server, <<>>), + Local = jid:make(<<>>, Server, <<>>), lists:foreach( fun({U, S, R}) -> - Dest = jlib:make_jid(U, S, R), + Dest = jid:make(U, S, R), ejabberd_router:route(Local, Dest, Packet) end, Sessions). @@ -770,7 +770,7 @@ announce_all_hosts_motd(From, To, Packet) -> end. announce_motd(Host, Packet) -> - LServer = jlib:nameprep(Host), + LServer = jid:nameprep(Host), announce_motd_update(LServer, Packet), Sessions = ejabberd_sm:get_vh_session_list(LServer), announce_online1(Sessions, LServer, Packet), @@ -922,7 +922,7 @@ send_motd(#jid{luser = LUser, lserver = LServer} = JID, mnesia) -> [#motd_users{}] -> ok; _ -> - Local = jlib:make_jid(<<>>, LServer, <<>>), + Local = jid:make(<<>>, LServer, <<>>), ejabberd_router:route(Local, JID, Packet), F = fun() -> mnesia:write(#motd_users{us = US}) @@ -940,7 +940,7 @@ send_motd(#jid{luser = LUser, lserver = LServer} = JID, riak) -> {ok, #motd_users{}} -> ok; _ -> - Local = jlib:make_jid(<<>>, LServer, <<>>), + Local = jid:make(<<>>, LServer, <<>>), ejabberd_router:route(Local, JID, Packet), {atomic, ejabberd_riak:put( #motd_users{us = US}, motd_users_schema(), @@ -963,7 +963,7 @@ send_motd(#jid{luser = LUser, lserver = LServer} = JID, odbc) when LUser /= <<>> [<<"select username from motd " "where username='">>, Username, <<"';">>]) of {selected, [<<"username">>], []} -> - Local = jlib:make_jid(<<"">>, LServer, <<"">>), + Local = jid:make(<<"">>, LServer, <<"">>), ejabberd_router:route(Local, JID, Packet), F = fun() -> odbc_queries:update_t( @@ -1038,10 +1038,10 @@ send_announcement_to_all(Host, SubjectS, BodyS) -> children = SubjectEls ++ BodyEls }, Sessions = ejabberd_sm:dirty_get_sessions_list(), - Local = jlib:make_jid(<<>>, Host, <<>>), + Local = jid:make(<<>>, Host, <<>>), lists:foreach( fun({U, S, R}) -> - Dest = jlib:make_jid(U, S, R), + Dest = jid:make(U, S, R), ejabberd_router:route(Local, Dest, Packet) end, Sessions). diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 5737129953d..18d8828839b 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -118,7 +118,7 @@ parse_blocklist_items([#xmlel{name = <<"item">>, JIDs) -> case xml:get_attr(<<"jid">>, Attrs) of {value, JID1} -> - JID = jlib:jid_tolower(jlib:string_to_jid(JID1)), + JID = jid:tolower(jid:from_string(JID1)), parse_blocklist_items(Els, [JID | JIDs]); false -> parse_blocklist_items(Els, JIDs) end; @@ -375,13 +375,13 @@ make_userlist(Name, List) -> #userlist{name = Name, list = List, needdb = NeedDb}. broadcast_list_update(LUser, LServer, Name, UserList) -> - ejabberd_sm:route(jlib:make_jid(LUser, LServer, + ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), - jlib:make_jid(LUser, LServer, <<"">>), + jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, UserList, Name}}). broadcast_blocklist_event(LUser, LServer, Event) -> - JID = jlib:make_jid(LUser, LServer, <<"">>), + JID = jid:make(LUser, LServer, <<"">>), ejabberd_sm:route(JID, JID, {broadcast, {blocking, Event}}). @@ -397,7 +397,7 @@ process_blocklist_get(LUser, LServer) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string(JID)}], + jid:to_string(JID)}], children = []} end, JIDs), diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 6d647908cfe..eb886b19a73 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -235,7 +235,7 @@ c2s_presence_in(C2SState, Delete = (Type == <<"unavailable">>) or (Type == <<"error">>), if Insert or Delete -> - LFrom = jlib:jid_tolower(From), + LFrom = jid:tolower(From), Rs = case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of @@ -269,7 +269,7 @@ c2s_presence_in(C2SState, c2s_filter_packet(InAcc, Host, C2SState, {pep_message, Feature}, To, _Packet) -> case ejabberd_c2s:get_aux_field(caps_resources, C2SState) of {ok, Rs} -> - LTo = jlib:jid_tolower(To), + LTo = jid:tolower(To), case gb_trees:lookup(LTo, Rs) of {value, Caps} -> Drop = not lists:member(Feature, get_features(Host, Caps)), @@ -417,7 +417,7 @@ feature_request(Host, From, Caps, feature_response(IQReply, Host, From, Caps, SubNodes) end, - ejabberd_local:route_iq(jlib:make_jid(<<"">>, Host, + ejabberd_local:route_iq(jid:make(<<"">>, Host, <<"">>), From, IQ, F); true -> feature_request(Host, From, Caps, Tail) @@ -449,7 +449,7 @@ feature_response(_IQResult, Host, From, Caps, feature_request(Host, From, Caps, SubNodes). caps_read_fun(Host, Node) -> - LServer = jlib:nameprep(Host), + LServer = jid:nameprep(Host), DBType = gen_mod:db_type(LServer, ?MODULE), caps_read_fun(LServer, Node, DBType). @@ -488,7 +488,7 @@ caps_read_fun(LServer, {Node, SubNode}, odbc) -> end. caps_write_fun(Host, Node, Features) -> - LServer = jlib:nameprep(Host), + LServer = jid:nameprep(Host), DBType = gen_mod:db_type(LServer, ?MODULE), caps_write_fun(LServer, Node, Features, DBType). @@ -511,7 +511,7 @@ caps_write_fun(LServer, NodePair, Features, odbc) -> end. make_my_disco_hash(Host) -> - JID = jlib:make_jid(<<"">>, Host, <<"">>), + JID = jid:make(<<"">>, Host, <<"">>), case {ejabberd_hooks:run_fold(disco_local_features, Host, empty, [JID, JID, <<"">>, <<"">>]), ejabberd_hooks:run_fold(disco_local_identity, Host, [], diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index 8fc2ca79e6a..c3ee6ad2289 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -104,7 +104,7 @@ iq_handler1(From, To, IQ) -> iq_handler(From, _To, #iq{type=set, sub_el = #xmlel{name = Operation, children = []}} = IQ, CC)-> ?DEBUG("carbons IQ received: ~p", [IQ]), - {U, S, R} = jlib:jid_tolower(From), + {U, S, R} = jid:tolower(From), Result = case Operation of <<"enable">>-> ?INFO_MSG("carbons enabled for user ~s@~s/~s", [U,S,R]), @@ -161,7 +161,7 @@ remove_connection(User, Server, Resource, _Status)-> %%% Internal %% Direction = received | sent send_copies(JID, To, Packet, Direction)-> - {U, S, R} = jlib:jid_tolower(JID), + {U, S, R} = jid:tolower(JID), PrioRes = ejabberd_sm:get_user_present_resources(U, S), {_, AvailRs} = lists:unzip(PrioRes), {MaxPrio, MaxRes} = case catch lists:max(PrioRes) of @@ -180,7 +180,7 @@ send_copies(JID, To, Packet, Direction)-> TargetJIDs = case {IsBareTo, R} of {true, MaxRes} -> OrigTo = fun(Res) -> lists:member({MaxPrio, Res}, PrioRes) end, - [ {jlib:make_jid({U, S, CCRes}), CC_Version} + [ {jid:make({U, S, CCRes}), CC_Version} || {CCRes, CC_Version} <- list(U, S), lists:member(CCRes, AvailRs), not OrigTo(CCRes) ]; {true, _} -> @@ -191,16 +191,16 @@ send_copies(JID, To, Packet, Direction)-> %% MaxRes) in order to avoid duplicates. []; {false, _} -> - [ {jlib:make_jid({U, S, CCRes}), CC_Version} + [ {jid:make({U, S, CCRes}), CC_Version} || {CCRes, CC_Version} <- list(U, S), lists:member(CCRes, AvailRs), CCRes /= R ] - %TargetJIDs = lists:delete(JID, [ jlib:make_jid({U, S, CCRes}) || CCRes <- list(U, S) ]), + %TargetJIDs = lists:delete(JID, [ jid:make({U, S, CCRes}) || CCRes <- list(U, S) ]), end, lists:map(fun({Dest,Version}) -> - {_, _, Resource} = jlib:jid_tolower(Dest), + {_, _, Resource} = jid:tolower(Dest), ?DEBUG("Sending: ~p =/= ~p", [R, Resource]), - Sender = jlib:make_jid({U, S, <<>>}), + Sender = jid:make({U, S, <<>>}), %{xmlelement, N, A, C} = Packet, New = build_forward_packet(JID, Packet, Sender, Dest, Direction, Version), ejabberd_router:route(Sender, Dest, New) @@ -211,8 +211,8 @@ build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_2) -> #xmlel{name = <<"message">>, attrs = [{<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, message_type(Packet)}, - {<<"from">>, jlib:jid_to_string(Sender)}, - {<<"to">>, jlib:jid_to_string(Dest)}], + {<<"from">>, jid:to_string(Sender)}, + {<<"to">>, jid:to_string(Dest)}], children = [ #xmlel{name = list_to_binary(atom_to_list(Direction)), attrs = [{<<"xmlns">>, ?NS_CARBONS_2}], @@ -227,8 +227,8 @@ build_forward_packet(JID, Packet, Sender, Dest, Direction, ?NS_CARBONS_1) -> #xmlel{name = <<"message">>, attrs = [{<<"xmlns">>, <<"jabber:client">>}, {<<"type">>, message_type(Packet)}, - {<<"from">>, jlib:jid_to_string(Sender)}, - {<<"to">>, jlib:jid_to_string(Dest)}], + {<<"from">>, jid:to_string(Sender)}, + {<<"to">>, jid:to_string(Dest)}], children = [ #xmlel{name = list_to_binary(atom_to_list(Direction)), attrs = [{<<"xmlns">>, ?NS_CARBONS_1}]}, @@ -259,7 +259,7 @@ complete_packet(From, #xmlel{name = <<"message">>, attrs = OrigAttrs} = Packet, Attrs = lists:keystore(<<"xmlns">>, 1, OrigAttrs, {<<"xmlns">>, <<"jabber:client">>}), case proplists:get_value(<<"from">>, Attrs) of undefined -> - Packet#xmlel{attrs = [{<<"from">>, jlib:jid_to_string(From)}|Attrs]}; + Packet#xmlel{attrs = [{<<"from">>, jid:to_string(From)}|Attrs]}; _ -> Packet#xmlel{attrs = Attrs} end; diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 3803ba1c96a..7524830df3a 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -114,7 +114,7 @@ stop(Host) -> -define(NODEJID(To, Name, Node), #xmlel{name = <<"item">>, attrs = - [{<<"jid">>, jlib:jid_to_string(To)}, + [{<<"jid">>, jid:to_string(To)}, {<<"name">>, ?T(Lang, Name)}, {<<"node">>, Node}], children = []}). @@ -292,7 +292,7 @@ adhoc_sm_items(Acc, From, #jid{lserver = LServer} = To, end, Nodes = [#xmlel{name = <<"item">>, attrs = - [{<<"jid">>, jlib:jid_to_string(To)}, + [{<<"jid">>, jid:to_string(To)}, {<<"name">>, ?T(Lang, <<"Configuration">>)}, {<<"node">>, <<"config">>}], children = []}], @@ -415,7 +415,7 @@ get_permission_level(JID) -> allow -> PermLev = get_permission_level(From), case get_local_items({PermLev, LServer}, LNode, - jlib:jid_to_string(To), Lang) + jid:to_string(To), Lang) of {result, Res} -> {result, Res}; {error, Error} -> {error, Error} @@ -437,7 +437,7 @@ get_local_items(Acc, From, #jid{lserver = LServer} = To, allow -> PermLev = get_permission_level(From), case get_local_items({PermLev, LServer}, [], - jlib:jid_to_string(To), Lang) + jid:to_string(To), Lang) of {result, Res} -> {result, Items ++ Res}; {error, _Error} -> {result, Items} @@ -1817,7 +1817,7 @@ set_form(From, Host, ?NS_ADMINL(<<"add-user">>), _Lang, AccountString = get_value(<<"accountjid">>, XData), Password = get_value(<<"password">>, XData), Password = get_value(<<"password-verify">>, XData), - AccountJID = jlib:string_to_jid(AccountString), + AccountJID = jid:from_string(AccountString), User = AccountJID#jid.luser, Server = AccountJID#jid.lserver, true = lists:member(Server, ?MYHOSTS), @@ -1831,7 +1831,7 @@ set_form(From, Host, ?NS_ADMINL(<<"delete-user">>), XData), [_ | _] = AccountStringList, ASL2 = lists:map(fun (AccountString) -> - JID = jlib:string_to_jid(AccountString), + JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse @@ -1846,7 +1846,7 @@ set_form(From, Host, ?NS_ADMINL(<<"delete-user">>), set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), - JID = jlib:string_to_jid(AccountString), + JID = jid:from_string(AccountString), LUser = JID#jid.luser, LServer = JID#jid.lserver, true = LServer == Host orelse @@ -1872,7 +1872,7 @@ set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>), set_form(From, Host, ?NS_ADMINL(<<"get-user-password">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), - JID = jlib:string_to_jid(AccountString), + JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse @@ -1892,7 +1892,7 @@ set_form(From, Host, ?NS_ADMINL(<<"change-user-password">>), _Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), Password = get_value(<<"password">>, XData), - JID = jlib:string_to_jid(AccountString), + JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse @@ -1903,7 +1903,7 @@ set_form(From, Host, set_form(From, Host, ?NS_ADMINL(<<"get-user-lastlogin">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), - JID = jlib:string_to_jid(AccountString), + JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse @@ -1938,7 +1938,7 @@ set_form(From, Host, set_form(From, Host, ?NS_ADMINL(<<"user-stats">>), Lang, XData) -> AccountString = get_value(<<"accountjid">>, XData), - JID = jlib:string_to_jid(AccountString), + JID = jid:from_string(AccountString), User = JID#jid.luser, Server = JID#jid.lserver, true = Server == Host orelse @@ -2031,7 +2031,7 @@ stop_node(From, Host, ENode, Action, XData) -> ?NS_XDATA}, {<<"type">>, <<"submit">>}], children = SubEls}]}, - To = jlib:make_jid(<<"">>, Host, <<"">>), + To = jid:make(<<"">>, Host, <<"">>), mod_announce:announce_commands(empty, From, To, Request) end, Time = timer:seconds(Delay), diff --git a/src/mod_echo.erl b/src/mod_echo.erl index cdd9a8856d7..59918b9cf93 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -167,7 +167,7 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %% Finally, the received response is printed in the ejabberd log file. do_client_version(disabled, _From, _To) -> ok; do_client_version(enabled, From, To) -> - ToS = jlib:jid_to_string(To), + ToS = jid:to_string(To), Random_resource = iolist_to_binary(integer_to_list(random:uniform(100000))), From2 = From#jid{resource = Random_resource, diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl index d12af0c99e2..742772b9afb 100644 --- a/src/mod_http_api.erl +++ b/src/mod_http_api.erl @@ -114,7 +114,7 @@ check_permissions(#request{auth = HTTPAuth, headers = Headers}, Command) Auth = case HTTPAuth of {SJID, Pass} -> - case jlib:string_to_jid(SJID) of + case jid:from_string(SJID) of #jid{user = User, server = Server} -> case ejabberd_auth:check_password(User, Server, Pass) of true -> {ok, {User, Server, Pass, Admin}}; diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 87707790685..6d19f873f4f 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -560,12 +560,12 @@ process_iq(From, end; {error, Error} -> ?DEBUG("Cannot parse request from ~s", - [jlib:jid_to_string(From)]), + [jid:to_string(From)]), IQ#iq{type = error, sub_el = [SubEl, Error]} end; deny -> ?DEBUG("Denying HTTP upload slot request from ~s", - [jlib:jid_to_string(From)]), + [jid:to_string(From)]), IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]} end; process_iq(_From, #iq{sub_el = SubEl} = IQ, _State) -> @@ -611,7 +611,7 @@ create_slot(#state{service_url = undefined, max_size = MaxSize}, Text = <<"File larger than ", (jlib:integer_to_binary(MaxSize))/binary, " Bytes.">>, ?INFO_MSG("Rejecting file ~s from ~s (too large: ~B bytes)", - [File, jlib:jid_to_string(JID), Size]), + [File, jid:to_string(JID), Size]), {error, ?ERRT_NOT_ACCEPTABLE(Lang, Text)}; create_slot(#state{service_url = undefined, jid_in_url = JIDinURL, @@ -627,7 +627,7 @@ create_slot(#state{service_url = undefined, RandStr = make_rand_string(SecretLength), FileStr = make_file_string(File), ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", - [jlib:jid_to_string(JID), File]), + [jid:to_string(JID), File]), {ok, [UserStr, RandStr, FileStr]}; deny -> {error, ?ERR_SERVICE_UNAVAILABLE}; @@ -641,7 +641,7 @@ create_slot(#state{service_url = ServiceURL}, HttpOptions = [{timeout, ?SERVICE_REQUEST_TIMEOUT}], SizeStr = jlib:integer_to_binary(Size), GetRequest = binary_to_list(ServiceURL) ++ - "?jid=" ++ ?URL_ENC(jlib:jid_to_string({U, S, <<"">>})) ++ + "?jid=" ++ ?URL_ENC(jid:to_string({U, S, <<"">>})) ++ "&name=" ++ ?URL_ENC(File) ++ "&size=" ++ ?URL_ENC(SizeStr) ++ "&content_type=" ++ ?URL_ENC(ContentType), @@ -651,32 +651,32 @@ create_slot(#state{service_url = ServiceURL}, [<<"http", _/binary>> = PutURL, <<"http", _/binary>> = GetURL] -> ?INFO_MSG("Got HTTP upload slot for ~s (file: ~s)", - [jlib:jid_to_string(JID), File]), + [jid:to_string(JID), File]), {ok, PutURL, GetURL}; Lines -> ?ERROR_MSG("Can't parse data received for ~s from <~s>: ~p", - [jlib:jid_to_string(JID), ServiceURL, Lines]), + [jid:to_string(JID), ServiceURL, Lines]), {error, ?ERR_SERVICE_UNAVAILABLE} end; {ok, {402, _Body}} -> ?INFO_MSG("Got status code 402 for ~s from <~s>", - [jlib:jid_to_string(JID), ServiceURL]), + [jid:to_string(JID), ServiceURL]), {error, ?ERR_RESOURCE_CONSTRAINT}; {ok, {403, _Body}} -> ?INFO_MSG("Got status code 403 for ~s from <~s>", - [jlib:jid_to_string(JID), ServiceURL]), + [jid:to_string(JID), ServiceURL]), {error, ?ERR_NOT_ALLOWED}; {ok, {413, _Body}} -> ?INFO_MSG("Got status code 413 for ~s from <~s>", - [jlib:jid_to_string(JID), ServiceURL]), + [jid:to_string(JID), ServiceURL]), {error, ?ERR_NOT_ACCEPTABLE}; {ok, {Code, _Body}} -> ?ERROR_MSG("Got unexpected status code for ~s from <~s>: ~B", - [jlib:jid_to_string(JID), ServiceURL, Code]), + [jid:to_string(JID), ServiceURL, Code]), {error, ?ERR_SERVICE_UNAVAILABLE}; {error, Reason} -> ?ERROR_MSG("Error requesting upload slot for ~s from <~s>: ~p", - [jlib:jid_to_string(JID), ServiceURL, Reason]), + [jid:to_string(JID), ServiceURL, Reason]), {error, ?ERR_SERVICE_UNAVAILABLE} end. @@ -959,7 +959,7 @@ thumb_el(Path, URI) -> -spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> - ServerHost = jlib:nameprep(Server), + ServerHost = jid:nameprep(Server), DocRoot = gen_mod:get_module_opt(ServerHost, ?MODULE, docroot, fun iolist_to_binary/1, <<"@HOME@/upload">>), @@ -968,7 +968,7 @@ remove_user(User, Server) -> (node) -> node end, sha1), - UserStr = make_user_string(jlib:make_jid(User, Server, <<"">>), JIDinURL), + UserStr = make_user_string(jid:make(User, Server, <<"">>), JIDinURL), UserDir = str:join([expand_home(DocRoot), UserStr], <<$/>>), case del_tree(UserDir) of ok -> diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index d7576567e59..4f656b18bcb 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -181,24 +181,24 @@ handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, NewSize = case {HardQuota, SoftQuota} of {0, 0} -> ?DEBUG("No quota specified for ~s", - [jlib:jid_to_string(JID)]), + [jid:to_string(JID)]), undefined; {0, _} -> ?WARNING_MSG("No hard quota specified for ~s", - [jlib:jid_to_string(JID)]), + [jid:to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); {_, 0} -> ?WARNING_MSG("No soft quota specified for ~s", - [jlib:jid_to_string(JID)]), + [jid:to_string(JID)]), enforce_quota(Path, Size, OldSize, HardQuota, HardQuota); _ when SoftQuota > HardQuota -> ?WARNING_MSG("Bad quota for ~s (soft: ~p, hard: ~p)", - [jlib:jid_to_string(JID), + [jid:to_string(JID), SoftQuota, HardQuota]), enforce_quota(Path, Size, OldSize, SoftQuota, SoftQuota); _ -> ?DEBUG("Enforcing quota for ~s", - [jlib:jid_to_string(JID)]), + [jid:to_string(JID)]), enforce_quota(Path, Size, OldSize, SoftQuota, HardQuota) end, NewDiskUsage = if is_integer(NewSize) -> diff --git a/src/mod_irc.erl b/src/mod_irc.erl index 31fb317076a..c3664af0fa7 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -578,7 +578,7 @@ process_irc_register(ServerHost, Host, From, _To, end. get_data(ServerHost, Host, From) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), get_data(LServer, Host, From, gen_mod:db_type(LServer, ?MODULE)). @@ -604,7 +604,7 @@ get_data(LServer, Host, From, riak) -> end; get_data(LServer, Host, From, odbc) -> SJID = - ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(jlib:jid_remove_resource(From)))), + ejabberd_odbc:escape(jid:to_string(jid:tolower(jid:remove_resource(From)))), SHost = ejabberd_odbc:escape(Host), case catch ejabberd_odbc:sql_query(LServer, [<<"select data from irc_custom where jid='">>, @@ -722,12 +722,12 @@ get_form(_ServerHost, _Host, _, _, _Lang) -> {error, ?ERR_SERVICE_UNAVAILABLE}. set_data(ServerHost, Host, From, Data) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), set_data(LServer, Host, From, data_to_binary(From, Data), gen_mod:db_type(LServer, ?MODULE)). set_data(_LServer, Host, From, Data, mnesia) -> - {LUser, LServer, _} = jlib:jid_tolower(From), + {LUser, LServer, _} = jid:tolower(From), US = {LUser, LServer}, F = fun () -> mnesia:write(#irc_custom{us_host = {US, Host}, @@ -735,14 +735,14 @@ set_data(_LServer, Host, From, Data, mnesia) -> end, mnesia:transaction(F); set_data(LServer, Host, From, Data, riak) -> - {LUser, LServer, _} = jlib:jid_tolower(From), + {LUser, LServer, _} = jid:tolower(From), US = {LUser, LServer}, {atomic, ejabberd_riak:put(#irc_custom{us_host = {US, Host}, data = Data}, irc_custom_schema())}; set_data(LServer, Host, From, Data, odbc) -> SJID = - ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(jlib:jid_remove_resource(From)))), + ejabberd_odbc:escape(jid:to_string(jid:tolower(jid:remove_resource(From)))), SHost = ejabberd_odbc:escape(Host), SData = ejabberd_odbc:encode_term(Data), F = fun () -> @@ -921,7 +921,7 @@ adhoc_join(From, To, <<"invite">>, attrs = [{<<"from">>, - jlib:jid_to_string(From)}], + jid:to_string(From)}], children = [#xmlel{name = @@ -952,7 +952,7 @@ adhoc_join(From, To, Lang, <<"Join the IRC channel in this Jabber ID: ~s">>), [RoomJID]))}]}]}, - ejabberd_router:route(jlib:string_to_jid(RoomJID), From, + ejabberd_router:route(jid:from_string(RoomJID), From, Invite), adhoc:produce_response(Request, #adhoc_response{status = @@ -1248,7 +1248,7 @@ data_to_binary(JID, Data) -> ?ERROR_MSG("failed to convert " "parameter ~p for user ~s", [Param, - jlib:jid_to_string(JID)]); + jid:to_string(JID)]); true -> ?ERROR_MSG("failed to convert " "parameter ~p", @@ -1295,7 +1295,7 @@ update_table() -> fun(#irc_custom{us_host = {_, H}}) -> H end, fun(#irc_custom{us_host = {{U, S}, H}, data = Data} = R) -> - JID = jlib:make_jid(U, S, <<"">>), + JID = jid:make(U, S, <<"">>), R#irc_custom{us_host = {{iolist_to_binary(U), iolist_to_binary(S)}, iolist_to_binary(H)}, @@ -1313,8 +1313,8 @@ export(_Server) -> case str:suffix(Host, IRCHost) of true -> SJID = ejabberd_odbc:escape( - jlib:jid_to_string( - jlib:make_jid(U, S, <<"">>))), + jid:to_string( + jid:make(U, S, <<"">>))), SIRCHost = ejabberd_odbc:escape(IRCHost), SData = ejabberd_odbc:encode_term(Data), [[<<"delete from irc_custom where jid='">>, SJID, @@ -1331,7 +1331,7 @@ export(_Server) -> import(_LServer) -> [{<<"select jid, host, data from irc_custom;">>, fun([SJID, IRCHost, SData]) -> - #jid{luser = U, lserver = S} = jlib:string_to_jid(SJID), + #jid{luser = U, lserver = S} = jid:from_string(SJID), Data = ejabberd_odbc:decode_term(SData), #irc_custom{us_host = {{U, S}, IRCHost}, data = Data} diff --git a/src/mod_irc_connection.erl b/src/mod_irc_connection.erl index cc21b0f1457..5c8597f2eab 100644 --- a/src/mod_irc_connection.erl +++ b/src/mod_irc_connection.erl @@ -306,7 +306,7 @@ handle_info({route_chan, Channel, Resource, of <<"">> -> ejabberd_router:route( - jlib:make_jid( + jid:make( iolist_to_binary([Channel, <<"%">>, StateData#state.server]), @@ -430,7 +430,7 @@ handle_info({route_chan, Channel, Resource, #xmlel{name = <<"iq">>} = El}, StateName, StateData) -> From = StateData#state.user, - To = jlib:make_jid(iolist_to_binary([Channel, <<"%">>, + To = jid:make(iolist_to_binary([Channel, <<"%">>, StateData#state.server]), StateData#state.host, StateData#state.nick), _ = case jlib:iq_query_info(El) of @@ -716,7 +716,7 @@ terminate(_Reason, _StateName, FullStateData) -> send_stanza(Chan, StateData, Stanza) -> ejabberd_router:route( - jlib:make_jid( + jid:make( iolist_to_binary([Chan, <<"%">>, StateData#state.server]), @@ -770,9 +770,9 @@ bounce_messages(Reason) -> <<"error">> -> ok; _ -> Err = jlib:make_error_reply(El, <<"502">>, Reason), - From = jlib:string_to_jid(xml:get_attr_s(<<"from">>, + From = jid:from_string(xml:get_attr_s(<<"from">>, Attrs)), - To = jlib:string_to_jid(xml:get_attr_s(<<"to">>, + To = jid:from_string(xml:get_attr_s(<<"to">>, Attrs)), ejabberd_router:route(To, From, Err) end, @@ -830,7 +830,7 @@ process_channel_list_user(StateData, Chan, User) -> {U2, <<"admin">>, <<"moderator">>}; _ -> {User1, <<"member">>, <<"participant">>} end, - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Chan, + ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, User2), @@ -860,7 +860,7 @@ process_channel_topic(StateData, Chan, String) -> Msg = ejabberd_regexp:replace(String, <<".*332[^:]*:">>, <<"">>), Msg1 = filter_message(Msg), - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Chan, + ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, <<"">>), @@ -889,7 +889,7 @@ process_channel_topic_who(StateData, Chan, String) -> _ -> String end, Msg2 = filter_message(Msg1), - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Chan, + ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, <<"">>), @@ -921,7 +921,7 @@ process_nick_in_use(StateData, String) -> % Shouldn't happen with a well behaved server StateData; Chan -> - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Chan, + ejabberd_router:route(jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]), StateData#state.host, @@ -938,7 +938,7 @@ process_num_error(StateData, String) -> <<"continue">>), lists:foreach(fun (Chan) -> ejabberd_router:route( - jlib:make_jid( + jid:make( iolist_to_binary( [Chan, <<"%">>, @@ -956,7 +956,7 @@ process_num_error(StateData, String) -> StateData. process_endofwhois(StateData, _String, Nick) -> - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Nick, + ejabberd_router:route(jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), @@ -973,7 +973,7 @@ process_whois311(StateData, String, Nick, Ident, Irchost) -> Fullname = ejabberd_regexp:replace(String, <<".*311[^:]*:">>, <<"">>), - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Nick, + ejabberd_router:route(jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), @@ -997,7 +997,7 @@ process_whois311(StateData, String, Nick, Ident, process_whois312(StateData, String, Nick, Ircserver) -> Ircserverdesc = ejabberd_regexp:replace(String, <<".*312[^:]*:">>, <<"">>), - ejabberd_router:route(jlib:make_jid(iolist_to_binary([Nick, + ejabberd_router:route(jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]), StateData#state.host, <<"">>), @@ -1019,7 +1019,7 @@ process_whois312(StateData, String, Nick, Ircserver) -> process_whois319(StateData, String, Nick) -> Chanlist = ejabberd_regexp:replace(String, <<".*319[^:]*:">>, <<"">>), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Nick, <<"!">>, StateData#state.server]), @@ -1047,7 +1047,7 @@ process_chanprivmsg(StateData, Chan, From, String) -> _ -> Msg end, Msg2 = filter_message(Msg1), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1069,7 +1069,7 @@ process_channotice(StateData, Chan, From, String) -> _ -> <<"/me NOTICE: ", Msg/binary>> end, Msg2 = filter_message(Msg1), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1091,7 +1091,7 @@ process_privmsg(StateData, _Nick, From, String) -> _ -> Msg end, Msg2 = filter_message(Msg1), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [FromUser, <<"!">>, StateData#state.server]), @@ -1113,7 +1113,7 @@ process_notice(StateData, _Nick, From, String) -> _ -> <<"/me NOTICE: ", Msg/binary>> end, Msg2 = filter_message(Msg1), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [FromUser, <<"!">>, StateData#state.server]), @@ -1141,14 +1141,14 @@ process_userinfo(StateData, _Nick, From) -> send_text(StateData, io_lib:format("NOTICE ~s :\001USERINFO xmpp:~s\001\r\n", [FromUser, - jlib:jid_to_string(StateData#state.user)])). + jid:to_string(StateData#state.user)])). process_topic(StateData, Chan, From, String) -> [FromUser | _] = str:tokens(From, <<"!">>), Msg = ejabberd_regexp:replace(String, <<".*TOPIC[^:]*:">>, <<"">>), Msg1 = filter_message(Msg), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1170,7 +1170,7 @@ process_part(StateData, Chan, From, String) -> Msg = ejabberd_regexp:replace(String, <<".*PART[^:]*:">>, <<"">>), Msg1 = filter_message(Msg), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1212,7 +1212,7 @@ process_quit(StateData, From, String) -> dict:map(fun (Chan, Ps) -> case (?SETS):is_member(FromUser, Ps) of true -> - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1261,7 +1261,7 @@ process_quit(StateData, From, String) -> process_join(StateData, Channel, From, _String) -> [FromUser | FromIdent] = str:tokens(From, <<"!">>), [Chan | _] = binary:split(Channel, <<":#">>), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1294,7 +1294,7 @@ process_join(StateData, Channel, From, _String) -> process_mode_o(StateData, Chan, _From, Nick, Affiliation, Role) -> - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1318,7 +1318,7 @@ process_kick(StateData, Chan, From, Nick, String) -> Msg = lists:last(str:tokens(String, <<":">>)), Msg2 = <>, - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1329,7 +1329,7 @@ process_kick(StateData, Chan, From, Nick, String) -> children = [#xmlel{name = <<"body">>, attrs = [], children = [{xmlcdata, Msg2}]}]}), - ejabberd_router:route(jlib:make_jid(iolist_to_binary( + ejabberd_router:route(jid:make(iolist_to_binary( [Chan, <<"%">>, StateData#state.server]), @@ -1361,7 +1361,7 @@ process_nick(StateData, From, NewNick) -> NewChans = dict:map(fun (Chan, Ps) -> case (?SETS):is_member(FromUser, Ps) of true -> - ejabberd_router:route(jlib:make_jid( + ejabberd_router:route(jid:make( iolist_to_binary( [Chan, <<"%">>, @@ -1408,7 +1408,7 @@ process_nick(StateData, From, NewNick) -> children = []}]}]}), - ejabberd_router:route(jlib:make_jid( + ejabberd_router:route(jid:make( iolist_to_binary( [Chan, <<"%">>, @@ -1456,7 +1456,7 @@ process_nick(StateData, From, NewNick) -> process_error(StateData, String) -> lists:foreach(fun (Chan) -> - ejabberd_router:route(jlib:make_jid( + ejabberd_router:route(jid:make( iolist_to_binary( [Chan, <<"%">>, diff --git a/src/mod_last.erl b/src/mod_last.erl index 8904f78ce6c..cab29c42741 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -236,8 +236,8 @@ on_presence_update(User, Server, _Resource, Status) -> store_last_info(User, Server, TimeStamp, Status). store_last_info(User, Server, TimeStamp, Status) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), store_last_info(LUser, LServer, TimeStamp, Status, DBType). @@ -276,8 +276,8 @@ get_last_info(LUser, LServer) -> end. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), remove_user(LUser, LServer, DBType). diff --git a/src/mod_mam.erl b/src/mod_mam.erl index c23e695d98f..eb72ad8a6bf 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -136,8 +136,8 @@ stop(Host) -> ok. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -199,7 +199,7 @@ user_send_packet(Pkt, C2SState, JID, Peer) -> muc_filter_message(Pkt, #state{config = Config} = MUCState, RoomJID, From, FromNick) -> if Config#config.mam -> - By = jlib:jid_to_string(RoomJID), + By = jid:to_string(RoomJID), NewPkt = strip_my_archived_tag(Pkt, By), case store_muc(MUCState, NewPkt, RoomJID, From, FromNick) of {ok, ID} -> @@ -323,10 +323,10 @@ process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> {_, _, _} = jlib:datetime_string_to_timestamp(Data), With, RSM}; ({<<"with">>, [Data|_]}, {Start, End, _, RSM}) -> - {Start, End, jlib:jid_tolower(jlib:string_to_jid(Data)), RSM}; + {Start, End, jid:tolower(jid:from_string(Data)), RSM}; ({<<"withroom">>, [Data|_]}, {Start, End, _, RSM}) -> {Start, End, - {room, jlib:jid_tolower(jlib:string_to_jid(Data))}, + {room, jid:tolower(jid:from_string(Data))}, RSM}; ({<<"withtext">>, [Data|_]}, {Start, End, _, RSM}) -> {Start, End, {text, Data}, RSM}; @@ -362,7 +362,7 @@ strip_my_archived_tag(Pkt, LServer) -> NewEls = lists:filter( fun(#xmlel{name = Tag, attrs = Attrs}) when Tag == <<"archived">>; Tag == <<"stanza-id">> -> - case catch jlib:nameprep( + case catch jid:nameprep( xml:get_attr_s( <<"by">>, Attrs)) of LServer -> @@ -380,7 +380,7 @@ should_archive_peer(C2SState, always = Always, never = Never}, Peer) -> - LPeer = jlib:jid_tolower(Peer), + LPeer = jid:tolower(Peer), case lists:member(LPeer, Always) of true -> true; @@ -423,7 +423,7 @@ store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> case should_archive_muc(MUCState, Peer) of true -> LServer = MUCState#state.server_host, - {U, S, _} = jlib:jid_tolower(RoomJID), + {U, S, _} = jid:tolower(RoomJID), store(Pkt, LServer, {U, S}, groupchat, Peer, Nick, recv, gen_mod:db_type(LServer, ?MODULE)); false -> @@ -431,7 +431,7 @@ store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> end. store(Pkt, _, {LUser, LServer}, Type, Peer, Nick, _Dir, mnesia) -> - LPeer = {PUser, PServer, _} = jlib:jid_tolower(Peer), + LPeer = {PUser, PServer, _} = jid:tolower(Peer), TS = now(), ID = jlib:integer_to_binary(now_to_usec(TS)), case mnesia:dirty_write( @@ -453,13 +453,13 @@ store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> ID = TS = jlib:integer_to_binary(TSinteger), SUser = case Type of chat -> LUser; - groupchat -> jlib:jid_to_string({LUser, LHost, <<>>}) + groupchat -> jid:to_string({LUser, LHost, <<>>}) end, - BarePeer = jlib:jid_to_string( - jlib:jid_tolower( - jlib:jid_remove_resource(Peer))), - LPeer = jlib:jid_to_string( - jlib:jid_tolower(Peer)), + BarePeer = jid:to_string( + jid:tolower( + jid:remove_resource(Peer))), + LPeer = jid:to_string( + jid:tolower(Peer)), XML = xml:element_to_binary(Pkt), Body = xml:get_subtag_cdata(Pkt, <<"body">>), case ejabberd_odbc:sql_query( @@ -576,7 +576,7 @@ select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> chat -> case With of {room, {_, _, <<"">>} = WithJID} -> - select(LServer, jlib:make_jid(WithJID), Start, End, + select(LServer, jid:make(WithJID), Start, End, WithJID, RSM, MsgType, DBType); _ -> select(LServer, From, Start, End, @@ -639,7 +639,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor, Start, End, With, RSM, MsgType, {odbc, Host}) -> User = case MsgType of chat -> LUser; - {groupchat, _Role, _MUCState} -> jlib:jid_to_string(JidRequestor) + {groupchat, _Role, _MUCState} -> jid:to_string(JidRequestor) end, {Query, CountQuery} = make_sql_query(User, LServer, Start, End, With, RSM), @@ -670,7 +670,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor, fun([TS, XML, PeerBin, Kind, Nick]) -> #xmlel{} = El = xml_stream:parse_element(XML), Now = usec_to_now(jlib:binary_to_integer(TS)), - PeerJid = jlib:jid_tolower(jlib:string_to_jid(PeerBin)), + PeerJid = jid:tolower(jid:from_string(PeerBin)), T = if Kind /= <<"">> -> jlib:binary_to_atom(Kind); true -> chat @@ -704,9 +704,9 @@ maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of <<"groupchat">> when Peer /= undefined -> Pkt2 = xml:replace_tag_attr(<<"to">>, - jlib:jid_to_string(JidRequestor), + jid:to_string(JidRequestor), Pkt), - xml:replace_tag_attr(<<"from">>, jlib:jid_to_string(Peer), + xml:replace_tag_attr(<<"from">>, jid:to_string(Peer), Pkt2); _ -> Pkt end; @@ -719,12 +719,12 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, children = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string(Peer)}]}]}]; + jid:to_string(Peer)}]}]}]; _ -> [] end, Pkt1 = Pkt#xmlel{children = Items ++ Els}, - Pkt2 = jlib:replace_from(jlib:jid_replace_resource(JidRequestor, Nick), Pkt1), + Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1), jlib:remove_attr(<<"to">>, Pkt2). is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> @@ -913,11 +913,11 @@ make_sql_query(User, _LServer, Start, End, With, RSM) -> ejabberd_odbc:escape(Txt), <<"')">>]; {_, _, <<>>} -> [<<" and bare_peer='">>, - ejabberd_odbc:escape(jlib:jid_to_string(With)), + ejabberd_odbc:escape(jid:to_string(With)), <<"'">>]; {_, _, _} -> [<<" and peer='">>, - ejabberd_odbc:escape(jlib:jid_to_string(With)), + ejabberd_odbc:escape(jid:to_string(With)), <<"'">>]; none -> [] @@ -991,9 +991,9 @@ datetime_to_now(DateTime, USecs) -> get_jids(Els) -> lists:flatmap( fun(#xmlel{name = <<"jid">>} = El) -> - J = jlib:string_to_jid(xml:get_tag_cdata(El)), - [jlib:jid_tolower(jlib:jid_remove_resource(J)), - jlib:jid_tolower(J)]; + J = jid:from_string(xml:get_tag_cdata(El)), + [jid:tolower(jid:remove_resource(J)), + jid:tolower(J)]; (_) -> [] end, Els). diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl index c3a57c9ea6b..b712def152a 100644 --- a/src/mod_metrics.erl +++ b/src/mod_metrics.erl @@ -84,9 +84,9 @@ s2s_receive_packet(_From, #jid{lserver=LServer}, _Packet) -> push(LServer, s2s_receive_packet). remove_user(_User, Server) -> - push(jlib:nameprep(Server), remove_user). + push(jid:nameprep(Server), remove_user). register_user(_User, Server) -> - push(jlib:nameprep(Server), register_user). + push(jid:nameprep(Server), register_user). %%==================================================================== %% metrics push handler diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 890687cd61a..13e07499498 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -134,7 +134,7 @@ create_room(Host, Name, From, Nick, Opts) -> gen_server:call(Proc, {create, Name, From, Nick, Opts}). store_room(ServerHost, Host, Name, Opts) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), store_room(LServer, Host, Name, Opts, gen_mod:db_type(LServer, ?MODULE)). @@ -162,7 +162,7 @@ store_room(LServer, Host, Name, Opts, odbc) -> ejabberd_odbc:sql_transaction(LServer, F). restore_room(ServerHost, Host, Name) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), restore_room(LServer, Host, Name, gen_mod:db_type(LServer, ?MODULE)). @@ -190,7 +190,7 @@ restore_room(LServer, Host, Name, odbc) -> end. forget_room(ServerHost, Host, Name) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), forget_room(LServer, Host, Name, gen_mod:db_type(LServer, ?MODULE)). @@ -216,11 +216,11 @@ forget_room(LServer, Host, Name, odbc) -> remove_room_mam(LServer, Host, Name) -> case gen_mod:is_loaded(LServer, mod_mam) of true -> - U = jlib:nodeprep(Name), - S = jlib:nameprep(Host), + U = jid:nodeprep(Name), + S = jid:nameprep(Host), DBType = gen_mod:db_type(LServer, mod_mam), if DBType == odbc -> - mod_mam:remove_user(jlib:jid_to_string({U, S, <<>>}), + mod_mam:remove_user(jid:to_string({U, S, <<>>}), LServer, DBType); true -> mod_mam:remove_user(U, S, DBType) @@ -241,12 +241,12 @@ process_iq_disco_items(Host, From, To, can_use_nick(_ServerHost, _Host, _JID, <<"">>) -> false; can_use_nick(ServerHost, Host, JID, Nick) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), can_use_nick(LServer, Host, JID, Nick, gen_mod:db_type(LServer, ?MODULE)). can_use_nick(_LServer, Host, JID, Nick, mnesia) -> - {LUser, LServer, _} = jlib:jid_tolower(JID), + {LUser, LServer, _} = jid:tolower(JID), LUS = {LUser, LServer}, case catch mnesia:dirty_select(muc_registered, [{#muc_registered{us_host = '$1', @@ -259,7 +259,7 @@ can_use_nick(_LServer, Host, JID, Nick, mnesia) -> [#muc_registered{us_host = {U, _Host}}] -> U == LUS end; can_use_nick(LServer, Host, JID, Nick, riak) -> - {LUser, LServer, _} = jlib:jid_tolower(JID), + {LUser, LServer, _} = jid:tolower(JID), LUS = {LUser, LServer}, case ejabberd_riak:get_by_index(muc_registered, muc_registered_schema(), @@ -273,7 +273,7 @@ can_use_nick(LServer, Host, JID, Nick, riak) -> end; can_use_nick(LServer, Host, JID, Nick, odbc) -> SJID = - jlib:jid_to_string(jlib:jid_tolower(jlib:jid_remove_resource(JID))), + jid:to_string(jid:tolower(jid:remove_resource(JID))), SNick = ejabberd_odbc:escape(Nick), SHost = ejabberd_odbc:escape(Host), case catch ejabberd_odbc:sql_query(LServer, @@ -463,7 +463,7 @@ do_route(Host, ServerHost, Access, HistorySize, RoomShaper, do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts) -> {_AccessRoute, AccessCreate, AccessAdmin, _AccessPersistent} = Access, - {Room, _, Nick} = jlib:jid_tolower(To), + {Room, _, Nick} = jid:tolower(To), #xmlel{name = Name, attrs = Attrs} = Packet, case Room of <<"">> -> @@ -641,7 +641,7 @@ check_user_can_create_room(ServerHost, AccessCreate, end. get_rooms(ServerHost, Host) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), get_rooms(LServer, Host, gen_mod:db_type(LServer, ?MODULE)). @@ -767,7 +767,7 @@ iq_disco_items(Host, From, Lang, none) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string({Name, Host, + jid:to_string({Name, Host, <<"">>})}, {<<"name">>, Desc}], children = []}}; @@ -791,7 +791,7 @@ iq_disco_items(Host, From, Lang, Rsm) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string({Name, Host, + jid:to_string({Name, Host, <<"">>})}, {<<"name">>, Desc}], children = []}}; @@ -868,12 +868,12 @@ iq_get_unique(From) -> randoms:get_string()]))}. get_nick(ServerHost, Host, From) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), get_nick(LServer, Host, From, gen_mod:db_type(LServer, ?MODULE)). get_nick(_LServer, Host, From, mnesia) -> - {LUser, LServer, _} = jlib:jid_tolower(From), + {LUser, LServer, _} = jid:tolower(From), LUS = {LUser, LServer}, case catch mnesia:dirty_read(muc_registered, {LUS, Host}) @@ -883,7 +883,7 @@ get_nick(_LServer, Host, From, mnesia) -> [#muc_registered{nick = Nick}] -> Nick end; get_nick(LServer, Host, From, riak) -> - {LUser, LServer, _} = jlib:jid_tolower(From), + {LUser, LServer, _} = jid:tolower(From), US = {LUser, LServer}, case ejabberd_riak:get(muc_registered, muc_registered_schema(), @@ -893,7 +893,7 @@ get_nick(LServer, Host, From, riak) -> end; get_nick(LServer, Host, From, odbc) -> SJID = - ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(jlib:jid_remove_resource(From)))), + ejabberd_odbc:escape(jid:to_string(jid:tolower(jid:remove_resource(From)))), SHost = ejabberd_odbc:escape(Host), case catch ejabberd_odbc:sql_query(LServer, [<<"select nick from muc_registered where " @@ -941,12 +941,12 @@ iq_get_register_info(ServerHost, Host, From, Lang) -> Nick)]}]. set_nick(ServerHost, Host, From, Nick) -> - LServer = jlib:nameprep(ServerHost), + LServer = jid:nameprep(ServerHost), set_nick(LServer, Host, From, Nick, gen_mod:db_type(LServer, ?MODULE)). set_nick(_LServer, Host, From, Nick, mnesia) -> - {LUser, LServer, _} = jlib:jid_tolower(From), + {LUser, LServer, _} = jid:tolower(From), LUS = {LUser, LServer}, F = fun () -> case Nick of @@ -976,7 +976,7 @@ set_nick(_LServer, Host, From, Nick, mnesia) -> end, mnesia:transaction(F); set_nick(LServer, Host, From, Nick, riak) -> - {LUser, LServer, _} = jlib:jid_tolower(From), + {LUser, LServer, _} = jid:tolower(From), LUS = {LUser, LServer}, {atomic, case Nick of @@ -1006,7 +1006,7 @@ set_nick(LServer, Host, From, Nick, riak) -> end}; set_nick(LServer, Host, From, Nick, odbc) -> JID = - jlib:jid_to_string(jlib:jid_tolower(jlib:jid_remove_resource(From))), + jid:to_string(jid:tolower(jid:remove_resource(From))), SJID = ejabberd_odbc:escape(JID), SNick = ejabberd_odbc:escape(Nick), SHost = ejabberd_odbc:escape(Host), @@ -1255,8 +1255,8 @@ export(_Server) -> case str:suffix(Host, RoomHost) of true -> SJID = ejabberd_odbc:escape( - jlib:jid_to_string( - jlib:make_jid(U, S, <<"">>))), + jid:to_string( + jid:make(U, S, <<"">>))), SNick = ejabberd_odbc:escape(Nick), SRoomHost = ejabberd_odbc:escape(RoomHost), [[<<"delete from muc_registered where jid='">>, @@ -1279,7 +1279,7 @@ import(_LServer) -> {<<"select jid, host, nick from muc_registered;">>, fun([J, RoomHost, Nick]) -> #jid{user = U, server = S} = - jlib:string_to_jid(J), + jid:from_string(J), #muc_registered{us_host = {{U, S}, RoomHost}, nick = Nick} end}]. diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index b11b5ae2c55..9df4361ca73 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -676,7 +676,7 @@ get_room_occupants(Pid) -> S = get_room_state(Pid), lists:map( fun({_LJID, Info}) -> - {jlib:jid_to_string(Info#user.jid), + {jid:to_string(Info#user.jid), Info#user.nick, atom_to_list(Info#user.role)} end, @@ -691,11 +691,11 @@ get_room_occupants_number(Room, Host) -> %% http://xmpp.org/extensions/xep-0249.html send_direct_invitation(RoomName, RoomService, Password, Reason, UsersString) -> - RoomJid = jlib:make_jid(RoomName, RoomService, <<"">>), - RoomString = jlib:jid_to_string(RoomJid), + RoomJid = jid:make(RoomName, RoomService, <<"">>), + RoomString = jid:to_string(RoomJid), XmlEl = build_invitation(Password, Reason, RoomString), UsersStrings = get_users_to_invite(RoomJid, binary_to_list(UsersString)), - [send_direct_invitation(RoomJid, jlib:string_to_jid(list_to_binary(UserStrings)), XmlEl) + [send_direct_invitation(RoomJid, jid:from_string(list_to_binary(UserStrings)), XmlEl) || UserStrings <- UsersStrings], timer:sleep(1000), ok. @@ -704,11 +704,11 @@ get_users_to_invite(RoomJid, UsersString) -> UsersStrings = string:tokens(UsersString, ":"), OccupantsTuples = get_room_occupants(RoomJid#jid.luser, RoomJid#jid.lserver), - OccupantsJids = [jlib:string_to_jid(JidString) + OccupantsJids = [jid:from_string(JidString) || {JidString, _Nick, _} <- OccupantsTuples], lists:filter( fun(UserString) -> - UserJid = jlib:string_to_jid(list_to_binary(UserString)), + UserJid = jid:from_string(list_to_binary(UserString)), %% [{"badlop@localhost/work","badlop","moderator"}] lists:all(fun(OccupantJid) -> UserJid#jid.luser /= OccupantJid#jid.luser @@ -872,7 +872,7 @@ set_room_affiliation(Name, Service, JID, AffiliationString) -> [R] -> %% Get the PID for the online room so we can get the state of the room Pid = R#muc_online_room.pid, - {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jlib:string_to_jid(JID), affiliation, Affiliation, <<"">>}, <<"">>}), + {ok, StateData} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jid:from_string(JID), affiliation, Affiliation, <<"">>}, <<"">>}), mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)), ok; [] -> diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index a5242824d00..3a03acc19ce 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -279,7 +279,7 @@ build_filename_string(TimeStamp, OutDir, RoomJID, {Fd, Fn, Fnrel}. get_room_name(RoomJID) -> - JID = jlib:string_to_jid(RoomJID), JID#jid.user. + JID = jid:from_string(RoomJID), JID#jid.user. %% calculate day before get_timestamp_daydiff(TimeStamp, Daydiff) -> @@ -999,7 +999,7 @@ get_room_info(RoomJID, Opts) -> {value, {_, SA}} -> SA; false -> <<"">> end, - #room{jid = jlib:jid_to_string(RoomJID), title = Title, + #room{jid = jid:to_string(RoomJID), title = Title, subject = Subject, subject_author = SubjectAuthor, config = Opts}. @@ -1160,7 +1160,7 @@ role_users_to_string(RoleS, Users) -> <>. get_room_occupants(RoomJIDString) -> - RoomJID = jlib:string_to_jid(RoomJIDString), + RoomJID = jid:from_string(RoomJIDString), RoomName = RoomJID#jid.luser, MucService = RoomJID#jid.lserver, StateData = get_room_state(RoomName, MucService), diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 0572bca2ea8..aca32738a45 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -107,7 +107,7 @@ init([Host, ServerHost, Access, Room, HistorySize, #state{host = Host, server_host = ServerHost, access = Access, room = Room, history = lqueue_new(HistorySize), - jid = jlib:make_jid(Room, Host, <<"">>), + jid = jid:make(Room, Host, <<"">>), just_created = true, room_shaper = Shaper}), State1 = set_opts(DefRoomOpts, State), @@ -119,7 +119,7 @@ init([Host, ServerHost, Access, Room, HistorySize, true -> ok end, ?INFO_MSG("Created MUC room ~s@~s by ~s", - [Room, Host, jlib:jid_to_string(Creator)]), + [Room, Host, jid:to_string(Creator)]), add_to_log(room_existence, created, State1), add_to_log(room_existence, started, State1), {ok, normal_state, State1}; @@ -131,7 +131,7 @@ init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts]) -> access = Access, room = Room, history = lqueue_new(HistorySize), - jid = jlib:make_jid(Room, Host, <<"">>), + jid = jid:make(Room, Host, <<"">>), room_shaper = Shaper}), add_to_log(room_existence, started, State), {ok, normal_state, State}. @@ -287,7 +287,7 @@ normal_state({route, From, <<"">>, MinInterval = (StateData#state.config)#config.voice_request_min_interval, BareFrom = - jlib:jid_remove_resource(jlib:jid_tolower(From)), + jid:remove_resource(jid:tolower(From)), NowPriority = -now_to_usec(now()), CleanPriority = NowPriority + MinInterval * @@ -533,7 +533,7 @@ normal_state({route, From, ToNick, Err = jlib:make_error_reply(Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err); _ -> @@ -544,7 +544,7 @@ normal_state({route, From, ToNick, Err = jlib:make_error_reply(Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err); ToJIDs -> @@ -558,10 +558,10 @@ normal_state({route, From, ToNick, (PmFromVisitors == moderators) and DstIsModerator -> {ok, #user{nick = FromNick}} = - (?DICT):find(jlib:jid_tolower(From), + (?DICT):find(jid:tolower(From), StateData#state.users), FromNickJID = - jlib:jid_replace_resource(StateData#state.jid, + jid:replace_resource(StateData#state.jid, FromNick), X = #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}]}, @@ -574,7 +574,7 @@ normal_state({route, From, ToNick, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end @@ -587,7 +587,7 @@ normal_state({route, From, ToNick, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err); {false, _} -> @@ -595,7 +595,7 @@ normal_state({route, From, ToNick, <<"It is not allowed to send private messages">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end, @@ -619,17 +619,17 @@ normal_state({route, From, ToNick, Err = jlib:make_error_reply(Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end; ToJID -> {ok, #user{nick = FromNick}} = - (?DICT):find(jlib:jid_tolower(FromFull), + (?DICT):find(jid:tolower(FromFull), StateData#state.users), {ToJID2, Packet2} = handle_iq_vcard(FromFull, ToJID, StanzaId, NewId, Packet), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, FromNick), ToJID2, Packet2) end; @@ -643,7 +643,7 @@ normal_state({route, From, ToNick, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end; @@ -655,7 +655,7 @@ normal_state({route, From, ToNick, "not allowed in this room">>, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, ToNick), From, Err) end @@ -698,12 +698,12 @@ handle_event({destroy, Reason}, _StateName, end}, StateData), ?INFO_MSG("Destroyed MUC room ~s with reason: ~p", - [jlib:jid_to_string(StateData#state.jid), Reason]), + [jid:to_string(StateData#state.jid), Reason]), add_to_log(room_existence, destroyed, StateData), {stop, shutdown, StateData}; handle_event(destroy, StateName, StateData) -> ?INFO_MSG("Destroyed MUC room ~s", - [jlib:jid_to_string(StateData#state.jid)]), + [jid:to_string(StateData#state.jid)]), handle_event({destroy, none}, StateName, StateData); handle_event({set_affiliations, Affiliations}, StateName, StateData) -> @@ -807,7 +807,7 @@ handle_info({captcha_failed, From}, normal_state, Err = jlib:make_error_reply(Packet, ?ERR_NOT_AUTHORIZED), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData#state{robots = Robots}; @@ -848,7 +848,7 @@ terminate(Reason, _StateName, StateData) -> Nick = Info#user.nick, case Reason of shutdown -> - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet); _ -> ok @@ -924,7 +924,7 @@ process_groupchat_message(From, {next_state, normal_state, StateData}; NewPacket1 -> NewPacket = xml:remove_subtags(NewPacket1, <<"nick">>, {<<"xmlns">>, ?NS_NICK}), - send_multiple(jlib:jid_replace_resource(StateData#state.jid, + send_multiple(jid:replace_resource(StateData#state.jid, FromNick), StateData#state.server_host, StateData#state.users, @@ -992,7 +992,7 @@ is_user_allowed_message_nonparticipant(JID, %% @doc Get information of this participant, or default values. %% If the JID is not a participant, return values for a service message. get_participant_data(From, StateData) -> - case (?DICT):find(jlib:jid_tolower(From), + case (?DICT):find(jid:tolower(From), StateData#state.users) of {ok, #user{nick = FromNick, role = Role}} -> @@ -1069,7 +1069,7 @@ process_presence(From, Nick, Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; @@ -1082,7 +1082,7 @@ process_presence(From, Nick, Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), % TODO: s/Nick/""/ From, Err), StateData; @@ -1093,7 +1093,7 @@ process_presence(From, Nick, Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; @@ -1129,14 +1129,14 @@ close_room_if_temporary_and_empty(StateData1) -> true -> ?INFO_MSG("Destroyed MUC room ~s because it's temporary " "and empty", - [jlib:jid_to_string(StateData1#state.jid)]), + [jid:to_string(StateData1#state.jid)]), add_to_log(room_existence, destroyed, StateData1), {stop, normal, StateData1}; _ -> {next_state, normal_state, StateData1} end. is_user_online(JID, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), (?DICT):is_key(LJID, StateData#state.users). %% Check if the user is occupant of the room, or at least is an admin or owner. @@ -1161,7 +1161,7 @@ is_user_online_iq(StanzaId, JID, StateData) when JID#jid.lresource == <<"">> -> try stanzaid_unpack(StanzaId) of {OriginalId, Resource} -> - JIDWithResource = jlib:jid_replace_resource(JID, + JIDWithResource = jid:replace_resource(JID, Resource), {is_user_online(JIDWithResource, StateData), OriginalId, JIDWithResource} @@ -1171,7 +1171,7 @@ is_user_online_iq(StanzaId, JID, StateData) handle_iq_vcard(FromFull, ToJID, StanzaId, NewId, Packet) -> - ToBareJID = jlib:jid_remove_resource(ToJID), + ToBareJID = jid:remove_resource(ToJID), IQ = jlib:iq_query_info(Packet), handle_iq_vcard2(FromFull, ToJID, ToBareJID, StanzaId, NewId, IQ, Packet). @@ -1253,7 +1253,7 @@ decide_fate_message(<<"error">>, Packet, From, Reason = io_lib:format("This participant is considered a ghost " "and is expulsed: ~s", - [jlib:jid_to_string(From)]), + [jid:to_string(From)]), {expulse_sender, Reason}; false -> continue_delivery end, @@ -1324,7 +1324,7 @@ set_affiliation(JID, Affiliation, StateData) -> set_affiliation(JID, Affiliation, StateData, <<"">>). set_affiliation(JID, Affiliation, StateData, Reason) -> - LJID = jlib:jid_remove_resource(jlib:jid_tolower(JID)), + LJID = jid:remove_resource(jid:tolower(JID)), Affiliations = case Affiliation of none -> (?DICT):erase(LJID, StateData#state.affiliations); @@ -1343,11 +1343,11 @@ get_affiliation(JID, StateData) -> of allow -> owner; _ -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), case (?DICT):find(LJID, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; _ -> - LJID1 = jlib:jid_remove_resource(LJID), + LJID1 = jid:remove_resource(LJID), case (?DICT):find(LJID1, StateData#state.affiliations) of {ok, Affiliation} -> Affiliation; @@ -1358,7 +1358,7 @@ get_affiliation(JID, StateData) -> of {ok, Affiliation} -> Affiliation; _ -> - LJID3 = jlib:jid_remove_resource(LJID2), + LJID3 = jid:remove_resource(LJID2), case (?DICT):find(LJID3, StateData#state.affiliations) of @@ -1386,7 +1386,7 @@ get_service_affiliation(JID, StateData) -> end. set_role(JID, Role, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> (?DICT):fold(fun (J, _, Js) -> @@ -1433,7 +1433,7 @@ set_role(JID, Role, StateData) -> StateData#state{users = Users, nicks = Nicks}. get_role(JID, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), case (?DICT):find(LJID, StateData#state.users) of {ok, #user{role = Role}} -> Role; _ -> none @@ -1483,7 +1483,7 @@ get_max_users_admin_threshold(StateData) -> 5). get_user_activity(JID, StateData) -> - case treap:lookup(jlib:jid_tolower(JID), + case treap:lookup(jid:tolower(JID), StateData#state.activity) of {ok, _P, A} -> A; @@ -1515,7 +1515,7 @@ store_user_activity(JID, UserActivity, StateData) -> fun(I) when is_number(I), I>=0 -> I end, 0) * 1000), - Key = jlib:jid_tolower(JID), + Key = jid:tolower(JID), Now = now_to_usec(now()), Activity1 = clean_treap(StateData#state.activity, {1, -Now}), @@ -1598,7 +1598,7 @@ prepare_room_queue(StateData) -> end. add_online_user(JID, Nick, Role, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), Users = (?DICT):store(LJID, #user{jid = JID, nick = Nick, role = Role}, StateData#state.users), @@ -1618,7 +1618,7 @@ remove_online_user(JID, StateData) -> remove_online_user(JID, StateData, <<"">>). remove_online_user(JID, StateData, Reason) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), {ok, #user{nick = Nick}} = (?DICT):find(LJID, StateData#state.users), add_to_log(leave, {Nick, Reason}, StateData), @@ -1667,7 +1667,7 @@ strip_status(#xmlel{name = <<"presence">>, children = FEls}. add_user_presence(JID, Presence, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), FPresence = filter_presence(Presence), Users = (?DICT):update(LJID, fun (#user{} = User) -> @@ -1677,7 +1677,7 @@ add_user_presence(JID, Presence, StateData) -> StateData#state{users = Users}. add_user_presence_un(JID, Presence, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), FPresence = filter_presence(Presence), Users = (?DICT):update(LJID, fun (#user{} = User) -> @@ -1691,8 +1691,8 @@ add_user_presence_un(JID, Presence, StateData) -> %% Return jid record. find_jids_by_nick(Nick, StateData) -> case (?DICT):find(Nick, StateData#state.nicks) of - {ok, [User]} -> [jlib:make_jid(User)]; - {ok, Users} -> [jlib:make_jid(LJID) || LJID <- Users]; + {ok, [User]} -> [jid:make(User)]; + {ok, Users} -> [jid:make(LJID) || LJID <- Users]; error -> false end. @@ -1700,7 +1700,7 @@ find_jids_by_nick(Nick, StateData) -> %% highest-priority presence. Return jid record. find_jid_by_nick(Nick, StateData) -> case (?DICT):find(Nick, StateData#state.nicks) of - {ok, [User]} -> jlib:make_jid(User); + {ok, [User]} -> jid:make(User); {ok, [FirstUser | Users]} -> #user{last_presence = FirstPresence} = (?DICT):fetch(FirstUser, StateData#state.users), @@ -1718,7 +1718,7 @@ find_jid_by_nick(Nick, StateData) -> end end, {FirstUser, FirstPresence}, Users), - jlib:make_jid(LJID); + jid:make(LJID); error -> false end. @@ -1748,7 +1748,7 @@ find_nick_by_jid(Jid, StateData) -> Nick. is_nick_change(JID, Nick, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), case Nick of <<"">> -> false; _ -> @@ -1760,8 +1760,8 @@ is_nick_change(JID, Nick, StateData) -> nick_collision(User, Nick, StateData) -> UserOfNick = find_jid_by_nick(Nick, StateData), (UserOfNick /= false andalso - jlib:jid_remove_resource(jlib:jid_tolower(UserOfNick)) - /= jlib:jid_remove_resource(jlib:jid_tolower(User))). + jid:remove_resource(jid:tolower(UserOfNick)) + /= jid:remove_resource(jid:tolower(User))). add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, @@ -1796,7 +1796,7 @@ add_new_user(From, Nick, Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, Nick), + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; {_, _, _, none} -> @@ -1813,14 +1813,14 @@ add_new_user(From, Nick, ErrText) end), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, Nick), + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; {_, true, _, _} -> ErrText = <<"That nickname is already in use by another occupant">>, Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; @@ -1828,7 +1828,7 @@ add_new_user(From, Nick, ErrText = <<"That nickname is registered by another person">>, Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; @@ -1859,14 +1859,14 @@ add_new_user(From, Nick, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; captcha_required -> SID = xml:get_attr_s(<<"id">>, Attrs), RoomJID = StateData#state.jid, - To = jlib:jid_replace_resource(RoomJID, Nick), + To = jid:replace_resource(RoomJID, Nick), Limiter = {From#jid.luser, From#jid.lserver}, case ejabberd_captcha:create_captcha(SID, RoomJID, To, Lang, Limiter, From) @@ -1885,7 +1885,7 @@ add_new_user(From, Nick, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData; @@ -1895,7 +1895,7 @@ add_new_user(From, Nick, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData @@ -1906,7 +1906,7 @@ add_new_user(From, Nick, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)), ejabberd_router:route % TODO: s/Nick/""/ - (jlib:jid_replace_resource(StateData#state.jid, + (jid:replace_resource(StateData#state.jid, Nick), From, Err), StateData @@ -2086,7 +2086,7 @@ send_update_presence(JID, Reason, StateData) -> end. send_update_presence1(JID, Reason, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> (?DICT):fold(fun (J, _, Js) -> @@ -2120,13 +2120,13 @@ send_new_presence(NJID, Reason, StateData, OldStateData) -> send_new_presence1(NJID, Reason, StateData) -> #user{nick = Nick} = - (?DICT):fetch(jlib:jid_tolower(NJID), + (?DICT):fetch(jid:tolower(NJID), StateData#state.users), LJID = find_jid_by_nick(Nick, StateData), {ok, #user{jid = RealJID, role = Role, last_presence = Presence}} = - (?DICT):find(jlib:jid_tolower(LJID), + (?DICT):find(jid:tolower(LJID), StateData#state.users), Affiliation = get_affiliation(LJID, StateData), SAffiliation = affiliation_to_list(Affiliation), @@ -2138,7 +2138,7 @@ send_new_presence1(NJID, Reason, StateData) -> of true -> [{<<"jid">>, - jlib:jid_to_string(RealJID)}, + jid:to_string(RealJID)}, {<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}]; _ -> @@ -2198,7 +2198,7 @@ send_new_presence1(NJID, Reason, StateData) -> = ItemEls} | Status3]}]), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) end, @@ -2211,14 +2211,14 @@ send_existing_presences(ToJID, StateData) -> end. send_existing_presences1(ToJID, StateData) -> - LToJID = jlib:jid_tolower(ToJID), + LToJID = jid:tolower(ToJID), {ok, #user{jid = RealToJID, role = Role}} = (?DICT):find(LToJID, StateData#state.users), lists:foreach(fun ({FromNick, _Users}) -> LJID = find_jid_by_nick(FromNick, StateData), #user{jid = FromJID, role = FromRole, last_presence = Presence} = - (?DICT):fetch(jlib:jid_tolower(LJID), + (?DICT):fetch(jid:tolower(LJID), StateData#state.users), case RealToJID of FromJID -> ok; @@ -2231,7 +2231,7 @@ send_existing_presences1(ToJID, StateData) -> of true -> [{<<"jid">>, - jlib:jid_to_string(FromJID)}, + jid:to_string(FromJID)}, {<<"affiliation">>, affiliation_to_list(FromAffiliation)}, {<<"role">>, @@ -2258,7 +2258,7 @@ send_existing_presences1(ToJID, StateData) -> children = []}]}]), - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, FromNick), RealToJID, Packet) end @@ -2269,7 +2269,7 @@ now_to_usec({MSec, Sec, USec}) -> (MSec * 1000000 + Sec) * 1000000 + USec. change_nick(JID, Nick, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), {ok, #user{nick = OldNick}} = (?DICT):find(LJID, StateData#state.users), Users = (?DICT):update(LJID, @@ -2311,7 +2311,7 @@ send_nick_changing(JID, OldNick, StateData, {ok, #user{jid = RealJID, nick = Nick, role = Role, last_presence = Presence}} = - (?DICT):find(jlib:jid_tolower(JID), + (?DICT):find(jid:tolower(JID), StateData#state.users), Affiliation = get_affiliation(JID, StateData), SAffiliation = affiliation_to_list(Affiliation), @@ -2323,7 +2323,7 @@ send_nick_changing(JID, OldNick, StateData, of true -> [{<<"jid">>, - jlib:jid_to_string(RealJID)}, + jid:to_string(RealJID)}, {<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}, {<<"nick">>, Nick}]; @@ -2338,7 +2338,7 @@ send_nick_changing(JID, OldNick, StateData, of true -> [{<<"jid">>, - jlib:jid_to_string(RealJID)}, + jid:to_string(RealJID)}, {<<"affiliation">>, SAffiliation}, {<<"role">>, SRole}]; _ -> @@ -2392,13 +2392,13 @@ send_nick_changing(JID, OldNick, StateData, = []}|Status110]}]), if SendOldUnavailable -> - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, OldNick), Info#user.jid, Packet1); true -> ok end, if SendNewAvailable -> - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet2); true -> ok @@ -2442,7 +2442,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> Address = #xmlel{name = <<"address">>, attrs = [{<<"type">>, <<"ofrom">>}, {<<"jid">>, - jlib:jid_to_string(FromJID)}], + jid:to_string(FromJID)}], children = []}, Addresses = #xmlel{name = <<"addresses">>, attrs = [{<<"xmlns">>, ?NS_ADDRESS}], @@ -2451,7 +2451,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> end, TSPacket = jlib:add_delay_info(AddrPacket, StateData#state.jid, TimeStamp), SPacket = - jlib:replace_from_to(jlib:jid_replace_resource(StateData#state.jid, + jlib:replace_from_to(jid:replace_resource(StateData#state.jid, FromNick), StateData#state.jid, TSPacket), Size = element_size(SPacket), @@ -2465,7 +2465,7 @@ send_history(JID, Shift, StateData) -> lists:foldl(fun ({Nick, Packet, HaveSubject, _TimeStamp, _Size}, B) -> - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), JID, Packet), B or HaveSubject @@ -2556,7 +2556,7 @@ items_with_affiliation(SAffiliation, StateData) -> attrs = [{<<"affiliation">>, affiliation_to_list(Affiliation)}, - {<<"jid">>, jlib:jid_to_string(JID)}], + {<<"jid">>, jid:to_string(JID)}], children = [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]}]}; @@ -2565,7 +2565,7 @@ items_with_affiliation(SAffiliation, StateData) -> attrs = [{<<"affiliation">>, affiliation_to_list(Affiliation)}, - {<<"jid">>, jlib:jid_to_string(JID)}], + {<<"jid">>, jid:to_string(JID)}], children = []} end, search_affiliation(SAffiliation, StateData)). @@ -2578,7 +2578,7 @@ user_to_item(#user{role = Role, nick = Nick, jid = JID}, [{<<"role">>, role_to_list(Role)}, {<<"affiliation">>, affiliation_to_list(Affiliation)}, {<<"nick">>, Nick}, - {<<"jid">>, jlib:jid_to_string(JID)}], + {<<"jid">>, jid:to_string(JID)}], children = []}. search_role(Role, StateData) -> @@ -2604,8 +2604,8 @@ process_admin_items_set(UJID, Items, Lang, StateData) -> {result, Res} -> ?INFO_MSG("Processing MUC admin query from ~s in " "room ~s:~n ~p", - [jlib:jid_to_string(UJID), - jlib:jid_to_string(StateData#state.jid), Res]), + [jid:to_string(UJID), + jid:to_string(StateData#state.jid), Res]), NSD = lists:foldl(process_item_change(UJID), StateData, lists:flatten(Res)), case (NSD#state.config)#config.persistent of @@ -2705,7 +2705,7 @@ find_changed_items(UJID, UAffiliation, URole, Lang, StateData, Res) -> TJID = case xml:get_attr(<<"jid">>, Attrs) of {value, S} -> - case jlib:string_to_jid(S) of + case jid:from_string(S) of error -> ErrText = iolist_to_binary( io_lib:format(translate:translate( @@ -2766,9 +2766,9 @@ find_changed_items(UJID, UAffiliation, URole, StateData) of [{OJID, _}] -> - jlib:jid_remove_resource(OJID) + jid:remove_resource(OJID) /= - jlib:jid_tolower(jlib:jid_remove_resource(UJID)); + jid:tolower(jid:remove_resource(UJID)); _ -> true end; _ -> false @@ -2782,7 +2782,7 @@ find_changed_items(UJID, UAffiliation, URole, Reason = xml:get_path_s(Item, [{elem, <<"reason">>}, cdata]), - MoreRes = [{jlib:jid_remove_resource(Jidx), + MoreRes = [{jid:remove_resource(Jidx), affiliation, SAffiliation, Reason} || Jidx <- JIDs], find_changed_items(UJID, UAffiliation, URole, @@ -2814,9 +2814,9 @@ find_changed_items(UJID, UAffiliation, URole, StateData) of [{OJID, _}] -> - jlib:jid_remove_resource(OJID) + jid:remove_resource(OJID) /= - jlib:jid_tolower(jlib:jid_remove_resource(UJID)); + jid:tolower(jid:remove_resource(UJID)); _ -> true end; _ -> false @@ -2975,7 +2975,7 @@ send_kickban_presence(UJID, JID, Reason, Code, StateData) -> send_kickban_presence(UJID, JID, Reason, Code, NewAffiliation, StateData) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> (?DICT):fold(fun (J, _, Js) -> @@ -3004,14 +3004,14 @@ send_kickban_presence(UJID, JID, Reason, Code, NewAffiliation, send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation, StateData) -> {ok, #user{jid = RealJID, nick = Nick}} = - (?DICT):find(jlib:jid_tolower(UJID), + (?DICT):find(jid:tolower(UJID), StateData#state.users), SAffiliation = affiliation_to_list(Affiliation), - BannedJIDString = jlib:jid_to_string(RealJID), + BannedJIDString = jid:to_string(RealJID), case MJID /= <<"">> of true -> {ok, #user{nick = ActorNick}} = - (?DICT):find(jlib:jid_tolower(MJID), + (?DICT):find(jid:tolower(MJID), StateData#state.users); false -> ActorNick = <<"">> @@ -3064,7 +3064,7 @@ send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation, Code}], children = []}]}]}, - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) end, @@ -3099,8 +3099,8 @@ process_iq_owner(From, set, Lang, SubEl, StateData) -> end; [#xmlel{name = <<"destroy">>} = SubEl1] -> ?INFO_MSG("Destroyed MUC room ~s by the owner ~s", - [jlib:jid_to_string(StateData#state.jid), - jlib:jid_to_string(From)]), + [jid:to_string(StateData#state.jid), + jid:to_string(From)]), add_to_log(room_existence, destroyed, StateData), destroy_room(SubEl1, StateData); Items -> @@ -3265,7 +3265,7 @@ is_password_settings_correct(XEl, StateData) -> {<<"var">>, Var}], children = [#xmlel{name = <<"value">>, attrs = [], - children = [{xmlcdata, jlib:jid_to_string(JID)}]} + children = [{xmlcdata, jid:to_string(JID)}]} || JID <- JIDList]}). get_default_room_maxusers(RoomState) -> @@ -3301,7 +3301,7 @@ get_config(Lang, StateData, From) -> translate:translate( Lang, <<"Configuration of room ~s">>), - [jlib:jid_to_string(StateData#state.jid)]))}]}, + [jid:to_string(StateData#state.jid)]))}]}, #xmlel{name = <<"field">>, attrs = [{<<"type">>, <<"hidden">>}, @@ -3799,7 +3799,7 @@ set_xoption([{<<"muc#roomconfig_captcha_whitelist">>, Vals} | Opts], Config) -> - JIDs = [jlib:string_to_jid(Val) || Val <- Vals], + JIDs = [jid:from_string(Val) || Val <- Vals], ?SET_JIDMULTI_XOPT(captcha_whitelist, JIDs); set_xoption([{<<"FORM_TYPE">>, _} | Opts], Config) -> set_xoption(Opts, Config); @@ -4051,7 +4051,7 @@ destroy_room(DEl, StateData) -> children = []}, DEl]}]}, - ejabberd_router:route(jlib:jid_replace_resource(StateData#state.jid, + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) end, @@ -4218,7 +4218,7 @@ get_mucroom_disco_items(StateData) -> #xmlel{name = <<"item">>, attrs = [{<<"jid">>, - jlib:jid_to_string({StateData#state.room, + jid:to_string({StateData#state.room, StateData#state.host, Nick})}, {<<"name">>, Nick}], @@ -4295,7 +4295,7 @@ prepare_request_form(Requester, Nick, Lang) -> [{xmlcdata, <<"participant">>}]}]}, ?STRINGXFIELD(<<"User JID">>, <<"muc#jid">>, - (jlib:jid_to_string(Requester))), + (jid:to_string(Requester))), ?STRINGXFIELD(<<"Nickname">>, <<"muc#roomnick">>, Nick), ?BOOLXFIELD(<<"Grant voice to this person?">>, @@ -4352,7 +4352,7 @@ extract_jid_from_voice_approvement(Els) -> Res -> Res end, lists:foldl(fun ({<<"muc#jid">>, [JIDStr]}, error) -> - case jlib:string_to_jid(JIDStr) of + case jid:from_string(JIDStr) of error -> error; J -> {ok, J} end; @@ -4401,7 +4401,7 @@ check_invitation(From, Els, Lang, StateData) -> _ -> throw({error, ?ERR_BAD_REQUEST}) end, JID = case - jlib:string_to_jid(xml:get_tag_attr_s(<<"to">>, + jid:from_string(xml:get_tag_attr_s(<<"to">>, InviteEl)) of error -> throw({error, ?ERR_JID_MALFORMED}); @@ -4419,7 +4419,7 @@ check_invitation(From, Els, Lang, StateData) -> Continue1 -> [Continue1] end, IEl = [#xmlel{name = <<"invite">>, - attrs = [{<<"from">>, jlib:jid_to_string(From)}], + attrs = [{<<"from">>, jid:to_string(From)}], children = [#xmlel{name = <<"reason">>, attrs = [], children = [{xmlcdata, Reason}]}] @@ -4442,8 +4442,8 @@ check_invitation(From, Els, Lang, StateData) -> translate:translate( Lang, <<"~s invites you to the room ~s">>), - [jlib:jid_to_string(From), - jlib:jid_to_string({StateData#state.room, + [jid:to_string(From), + jid:to_string({StateData#state.room, StateData#state.host, <<"">>})]), case @@ -4473,7 +4473,7 @@ check_invitation(From, Els, Lang, StateData) -> attrs = [{<<"xmlns">>, ?NS_XCONFERENCE}, {<<"jid">>, - jlib:jid_to_string({StateData#state.room, + jid:to_string({StateData#state.room, StateData#state.host, <<"">>})}], children = [{xmlcdata, Reason}]}, @@ -4506,7 +4506,7 @@ check_decline_invitation(Packet) -> (?NS_MUC_USER) = xml:get_tag_attr_s(<<"xmlns">>, XEl), DEl = xml:get_subtag(XEl, <<"decline">>), ToString = xml:get_tag_attr_s(<<"to">>, DEl), - ToJID = jlib:string_to_jid(ToString), + ToJID = jid:from_string(ToString), {true, {Packet, XEl, DEl, ToJID}}. %% Send the decline to the inviter user. @@ -4514,7 +4514,7 @@ check_decline_invitation(Packet) -> send_decline_invitation({Packet, XEl, DEl, ToJID}, RoomJID, FromJID) -> FromString = - jlib:jid_to_string(jlib:jid_remove_resource(FromJID)), + jid:to_string(jid:remove_resource(FromJID)), #xmlel{name = <<"decline">>, attrs = DAttrs, children = DEls} = DEl, @@ -4564,7 +4564,7 @@ add_to_log(Type, Data, StateData) -> %% Users number checking tab_add_online_user(JID, StateData) -> - {LUser, LServer, LResource} = jlib:jid_tolower(JID), + {LUser, LServer, LResource} = jid:tolower(JID), US = {LUser, LServer}, Room = StateData#state.room, Host = StateData#state.host, @@ -4573,7 +4573,7 @@ tab_add_online_user(JID, StateData) -> room = Room, host = Host}). tab_remove_online_user(JID, StateData) -> - {LUser, LServer, LResource} = jlib:jid_tolower(JID), + {LUser, LServer, LResource} = jid:tolower(JID), US = {LUser, LServer}, Room = StateData#state.room, Host = StateData#state.host, @@ -4582,7 +4582,7 @@ tab_remove_online_user(JID, StateData) -> room = Room, host = Host}). tab_count_user(JID) -> - {LUser, LServer, _} = jlib:jid_tolower(JID), + {LUser, LServer, _} = jid:tolower(JID), US = {LUser, LServer}, case catch ets:select(muc_online_users, [{#muc_online_users{us = US, _ = '_'}, [], [[]]}]) diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index ad7514c1ae9..1c8525f52fe 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -871,7 +871,7 @@ process_discoitems_result(From, LServiceS, Els) -> case XML of #xmlel{name = <<"item">>, attrs = Attrs} -> SJID = xml:get_attr_s(<<"jid">>, Attrs), - case jlib:string_to_jid(SJID) of + case jid:from_string(SJID) of #jid{luser = <<"">>, lresource = <<"">>} -> [SJID | Res]; @@ -1214,9 +1214,9 @@ make_reply(internal_server_error, Lang, ErrText) -> make_reply(forbidden, Lang, ErrText) -> ?ERRT_FORBIDDEN(Lang, ErrText). -stj(String) -> jlib:string_to_jid(String). +stj(String) -> jid:from_string(String). -jts(String) -> jlib:jid_to_string(String). +jts(String) -> jid:to_string(String). mod_opt_type(access) -> fun (A) when is_atom(A) -> A end; diff --git a/src/mod_offline.erl b/src/mod_offline.erl index bcd65b21b47..a9f8237072d 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -248,7 +248,7 @@ store_offline_msg(Host, {User, _}, Msgs, Len, MaxOfflineMsgs, get_max_user_messages(AccessRule, {User, Server}, Host) -> case acl:match_rule( - Host, AccessRule, jlib:make_jid(User, Server, <<"">>)) of + Host, AccessRule, jid:make(User, Server, <<"">>)) of Max when is_integer(Max) -> Max; infinity -> infinity; _ -> ?MAX_USER_MESSAGES @@ -400,8 +400,8 @@ find_x_expire(TimeStamp, [El | Els]) -> end. resend_offline_messages(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, F = fun () -> Rs = mnesia:wread({offline_msg, US}), @@ -423,8 +423,8 @@ resend_offline_messages(User, Server) -> end. pop_offline_messages(Ls, User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), pop_offline_messages(Ls, LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -504,7 +504,7 @@ pop_offline_messages(Ls, LUser, LServer, riak) -> end. remove_expired_messages(Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), remove_expired_messages(LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -529,7 +529,7 @@ remove_expired_messages(_LServer, odbc) -> {atomic, ok}; remove_expired_messages(_LServer, riak) -> {atomic, ok}. remove_old_messages(Days, Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), remove_old_messages(Days, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -568,8 +568,8 @@ remove_old_messages(_Days, _LServer, riak) -> {atomic, ok}. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -678,8 +678,8 @@ offline_msg_to_route(LServer, #offline_msg{} = R) -> jlib:add_delay_info(R#offline_msg.packet, LServer, R#offline_msg.timestamp, <<"Offline Storage">>)}; offline_msg_to_route(_LServer, #xmlel{} = 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)), + To = jid:from_string(xml:get_tag_attr_s(<<"to">>, El)), + From = jid:from_string(xml:get_tag_attr_s(<<"from">>, El)), if (To /= error) and (From /= error) -> {route, From, To, El}; true -> @@ -731,8 +731,8 @@ format_user_queue(Msgs, DBType) when DBType == mnesia; DBType == riak -> [Year, Month, Day, Hour, Minute, Second])), - SFrom = jlib:jid_to_string(From), - STo = jlib:jid_to_string(To), + SFrom = jid:to_string(From), + STo = jid:to_string(To), Attrs2 = jlib:replace_from_to_attrs(SFrom, STo, Attrs), Packet = #xmlel{name = Name, attrs = Attrs2, children = Els}, @@ -761,8 +761,8 @@ format_user_queue(Msgs, odbc) -> Msgs). user_queue(User, Server, Query, Lang) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, DBType = gen_mod:db_type(LServer, ?MODULE), Res = user_queue_parse_query(LUser, LServer, Query, @@ -893,7 +893,7 @@ user_queue_parse_query(LUser, LServer, Query, odbc) -> end. us_to_list({User, Server}) -> - jlib:jid_to_string({User, Server, <<"">>}). + jid:to_string({User, Server, <<"">>}). get_queue_length(LUser, LServer) -> get_queue_length(LUser, LServer, @@ -944,7 +944,7 @@ get_messages_subset2(Max, Length, MsgsAll, DBType) {MsgsFirstN, Msgs2} = lists:split(FirstN, MsgsAll), MsgsLastN = lists:nthtail(Length - FirstN - FirstN, Msgs2), - NoJID = jlib:make_jid(<<"...">>, <<"...">>, <<"">>), + NoJID = jid:make(<<"...">>, <<"...">>, <<"">>), IntermediateMsg = #offline_msg{timestamp = now(), from = NoJID, to = NoJID, packet = @@ -961,8 +961,8 @@ get_messages_subset2(Max, Length, MsgsAll, odbc) -> MsgsFirstN ++ [IntermediateMsg] ++ MsgsLastN. webadmin_user(Acc, User, Server, Lang) -> - QueueLen = get_queue_length(jlib:nodeprep(User), - jlib:nameprep(Server)), + QueueLen = get_queue_length(jid:nodeprep(User), + jid:nameprep(Server)), FQueueLen = [?AC(<<"queue/">>, (iolist_to_binary(integer_to_list(QueueLen))))], Acc ++ @@ -973,8 +973,8 @@ webadmin_user(Acc, User, Server, Lang) -> <<"Remove All Offline Messages">>)]. delete_all_msgs(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), delete_all_msgs(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -1014,8 +1014,8 @@ webadmin_user_parse_query(Acc, _Action, _User, _Server, %% Returns as integer the number of offline messages for a given user count_offline_messages(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), count_offline_messages(LUser, LServer, DBType). @@ -1099,9 +1099,9 @@ import(LServer) -> [{<<"select username, xml from spool;">>, fun([LUser, XML]) -> El = #xmlel{} = xml_stream:parse_element(XML), - From = #jid{} = jlib:string_to_jid( + From = #jid{} = jid:from_string( xml:get_attr_s(<<"from">>, El#xmlel.attrs)), - To = #jid{} = jlib:string_to_jid( + To = #jid{} = jid:from_string( xml:get_attr_s(<<"to">>, El#xmlel.attrs)), Stamp = xml:get_path_s(El, [{elem, <<"delay">>}, {attr, <<"stamp">>}]), diff --git a/src/mod_ping.erl b/src/mod_ping.erl index 54aa6086585..d8dc5d7ced5 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -191,7 +191,7 @@ handle_info({timeout, _TRef, {ping, JID}}, State) -> F = fun (Response) -> gen_server:cast(Pid, {iq_pong, JID, Response}) end, - From = jlib:make_jid(<<"">>, State#state.host, <<"">>), + From = jid:make(<<"">>, State#state.host, <<"">>), ejabberd_local:route_iq(From, JID, IQ, F, State#state.ping_ack_timeout), Timers = add_timer(JID, State#state.ping_interval, State#state.timers), @@ -227,7 +227,7 @@ user_send(Packet, _C2SState, JID, _From) -> %% Internal functions %%==================================================================== add_timer(JID, Interval, Timers) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), NewTimers = case (?DICT):find(LJID, Timers) of {ok, OldTRef} -> cancel_timer(OldTRef), (?DICT):erase(LJID, Timers); @@ -238,7 +238,7 @@ add_timer(JID, Interval, Timers) -> (?DICT):store(LJID, TRef, NewTimers). del_timer(JID, Timers) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), case (?DICT):find(LJID, Timers) of {ok, TRef} -> cancel_timer(TRef), (?DICT):erase(LJID, Timers); diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index 840c3aaea2c..72db36084de 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -99,14 +99,14 @@ update(Server, JID, Dir) -> in -> ?WARNING_MSG("User ~s is being flooded, ignoring received " "presence subscriptions", - [jlib:jid_to_string(JID)]); + [jid:to_string(JID)]); out -> IP = ejabberd_sm:get_user_ip(JID#jid.luser, JID#jid.lserver, JID#jid.lresource), ?WARNING_MSG("Flooder detected: ~s, on IP: ~s ignoring " "sent presence subscriptions~n", - [jlib:jid_to_string(JID), + [jid:to_string(JID), jlib:ip_to_list(IP)]) end, {stop, deny}; diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 6ab559c90ed..02ff07a1b82 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -322,7 +322,7 @@ type_to_list(Type) -> value_to_list(Type, Val) -> case Type of - jid -> jlib:jid_to_string(Val); + jid -> jid:to_string(Val); group -> Val; subscription -> case Val of @@ -581,9 +581,9 @@ process_list_set(LUser, LServer, {value, Name}, Els) -> of {atomic, conflict} -> {error, ?ERR_CONFLICT}; {atomic, ok} -> - ejabberd_sm:route(jlib:make_jid(LUser, LServer, + ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), - jlib:make_jid(LUser, LServer, <<"">>), + jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, #userlist{name = Name, list = []}, @@ -597,9 +597,9 @@ process_list_set(LUser, LServer, {value, Name}, Els) -> of {atomic, ok} -> NeedDb = is_list_needdb(List), - ejabberd_sm:route(jlib:make_jid(LUser, LServer, + ejabberd_sm:route(jid:make(LUser, LServer, <<"">>), - jlib:make_jid(LUser, LServer, <<"">>), + jid:make(LUser, LServer, <<"">>), {broadcast, {privacy_list, #userlist{name = Name, list = List, @@ -645,11 +645,11 @@ parse_items([#xmlel{name = <<"item">>, attrs = Attrs, {{value, T}, {value, V}} -> case T of <<"jid">> -> - case jlib:string_to_jid(V) of + case jid:from_string(V) of error -> false; JID -> I1#listitem{type = jid, - value = jlib:jid_tolower(JID)} + value = jid:tolower(JID)} end; <<"group">> -> I1#listitem{type = group, value = V}; <<"subscription">> -> @@ -715,8 +715,8 @@ is_list_needdb(Items) -> Items). get_user_list(Acc, User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), {Default, Items} = get_user_list(Acc, LUser, LServer, gen_mod:db_type(LServer, ?MODULE)), NeedDb = is_list_needdb(Items), @@ -772,8 +772,8 @@ get_user_list(_, LUser, LServer, odbc) -> end. get_user_lists(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), get_user_lists(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). get_user_lists(LUser, LServer, mnesia) -> @@ -869,13 +869,13 @@ check_packet(_, User, Server, {_, _} -> other end, LJID = case Dir of - in -> jlib:jid_tolower(From); - out -> jlib:jid_tolower(To) + in -> jid:tolower(From); + out -> jid:tolower(To) end, {Subscription, Groups} = case NeedDb of true -> ejabberd_hooks:run_fold(roster_get_jid_info, - jlib:nameprep(Server), + jid:nameprep(Server), {none, []}, [User, Server, LJID]); @@ -944,8 +944,8 @@ is_type_match(Type, Value, JID, Subscription, Groups) -> end. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -971,9 +971,9 @@ raw_to_item([SType, SValue, SAction, SOrder, SMatchAll, {Type, Value} = case SType of <<"n">> -> {none, none}; <<"j">> -> - case jlib:string_to_jid(SValue) of + case jid:from_string(SValue) of #jid{} = JID -> - {jid, jlib:jid_tolower(JID)} + {jid, jid:tolower(JID)} end; <<"g">> -> {group, SValue}; <<"s">> -> @@ -1013,7 +1013,7 @@ item_to_raw(#listitem{type = Type, value = Value, none -> {<<"n">>, <<"">>}; jid -> {<<"j">>, - ejabberd_odbc:escape(jlib:jid_to_string(Value))}; + ejabberd_odbc:escape(jid:to_string(Value))}; group -> {<<"g">>, ejabberd_odbc:escape(Value)}; subscription -> case Value of @@ -1164,7 +1164,7 @@ update_table() -> end. export(Server) -> - case catch ejabberd_odbc:sql_query(jlib:nameprep(Server), + case catch ejabberd_odbc:sql_query(jid:nameprep(Server), [<<"select id from privacy_list order by " "id desc limit 1;">>]) of {selected, [<<"id">>], [[I]]} -> diff --git a/src/mod_private.erl b/src/mod_private.erl index 56d4b493719..52b317a5dac 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -243,8 +243,8 @@ private_storage_schema() -> {record_info(fields, private_storage), #private_storage{}}. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(Server, ?MODULE)). diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 3c360942a4a..d1c5c32e175 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -179,15 +179,15 @@ process_iq(InitiatorJID, [{elem, <<"activate">>}]), SID = xml:get_tag_attr_s(<<"sid">>, SubEl), case catch - jlib:string_to_jid(xml:get_tag_cdata(ActivateEl)) + jid:from_string(xml:get_tag_cdata(ActivateEl)) of TargetJID when is_record(TargetJID, jid), SID /= <<"">>, byte_size(SID) =< 128, TargetJID /= InitiatorJID -> Target = - jlib:jid_to_string(jlib:jid_tolower(TargetJID)), + jid:to_string(jid:tolower(TargetJID)), Initiator = - jlib:jid_to_string(jlib:jid_tolower(InitiatorJID)), + jid:to_string(jid:tolower(InitiatorJID)), SHA1 = p1_sha:sha(<>), case mod_proxy65_sm:activate_stream(SHA1, InitiatorJID, TargetJID, ServerHost) diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 722a782c56b..2d777589eec 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -120,8 +120,8 @@ activate({P1, J1}, {P2, J2}) -> {S1, S2} when is_port(S1), is_port(S2) -> P1 ! {activate, P2, S2, J1, J2}, P2 ! {activate, P1, S1, J1, J2}, - JID1 = jlib:jid_to_string(J1), - JID2 = jlib:jid_to_string(J2), + JID1 = jid:to_string(J1), + JID2 = jid:to_string(J2), ?INFO_MSG("(~w:~w) Activated bytestream for ~s " "-> ~s", [P1, P2, JID1, JID2]), diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 2482197fe0c..089386a8981 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -393,8 +393,8 @@ send_loop(State) -> Host = State#state.host, ServerHost = State#state.server_host, DBType = State#state.db_type, - LJID = jlib:jid_tolower(JID), - BJID = jlib:jid_remove_resource(LJID), + LJID = jid:tolower(JID), + BJID = jid:remove_resource(LJID), lists:foreach( fun(PType) -> Subs = get_subscriptions_for_send_last(Host, PType, DBType, JID, LJID, BJID), @@ -416,7 +416,7 @@ send_loop(State) -> fun({U, S, R}) when S == ServerHost -> case user_resources(U, S) of [] -> %% offline - PeerJID = jlib:make_jid(U, S, R), + PeerJID = jid:make(U, S, R), self() ! {presence, User, Server, [Resource], PeerJID}; _ -> %% online % this is already handled by presence probe @@ -437,7 +437,7 @@ send_loop(State) -> {presence, User, Server, Resources, JID} -> spawn(fun() -> Host = State#state.host, - Owner = jlib:jid_remove_resource(jlib:jid_tolower(JID)), + Owner = jid:remove_resource(jid:tolower(JID)), lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, type = Type, id = Nidx, options = Options}) -> case match_option(Options, send_last_published_item, on_sub_and_presence) of true -> @@ -533,7 +533,7 @@ disco_local_items(Acc, _From, _To, _Node, _Lang) -> Acc. disco_sm_identity(empty, From, To, Node, Lang) -> disco_sm_identity([], From, To, Node, Lang); disco_sm_identity(Acc, From, To, Node, _Lang) -> - disco_identity(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From) + disco_identity(jid:tolower(jid:remove_resource(To)), Node, From) ++ Acc. disco_identity(_Host, <<>>, _From) -> @@ -582,7 +582,7 @@ disco_sm_features(empty, From, To, Node, Lang) -> disco_sm_features({result, OtherFeatures} = _Acc, From, To, Node, _Lang) -> {result, OtherFeatures ++ - disco_features(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From)}; + disco_features(jid:tolower(jid:remove_resource(To)), Node, From)}; disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. disco_features(Host, <<>>, _From) -> @@ -617,7 +617,7 @@ disco_sm_items(empty, From, To, Node, Lang) -> disco_sm_items({result, []}, From, To, Node, Lang); disco_sm_items({result, OtherItems}, From, To, Node, _Lang) -> {result, lists:usort(OtherItems ++ - disco_items(jlib:jid_tolower(jlib:jid_remove_resource(To)), Node, From))}; + disco_items(jid:tolower(jid:remove_resource(To)), Node, From))}; disco_sm_items(Acc, _From, _To, _Node, _Lang) -> Acc. -spec(disco_items/3 :: @@ -636,7 +636,7 @@ disco_items(Host, <<>>, From) -> {result, _} -> [#xmlel{name = <<"item">>, attrs = [{<<"node">>, (Node)}, - {<<"jid">>, jlib:jid_to_string(Host)} + {<<"jid">>, jid:to_string(Host)} | case get_option(Options, title) of false -> []; [Title] -> [{<<"name">>, Title}] @@ -660,7 +660,7 @@ disco_items(Host, Node, From) -> case get_allowed_items_call(Host, Nidx, From, Type, Options, Owners) of {result, Items} -> {result, [#xmlel{name = <<"item">>, - attrs = [{<<"jid">>, jlib:jid_to_string(Host)}, + attrs = [{<<"jid">>, jid:to_string(Host)}, {<<"name">>, ItemId}]} || #pubsub_item{itemid = {ItemId, _}} <- Items]}; _ -> @@ -720,8 +720,8 @@ presence(ServerHost, Presence) -> %% out_subscription(User, Server, JID, subscribed) -> - Owner = jlib:make_jid(User, Server, <<>>), - {PUser, PServer, PResource} = jlib:jid_tolower(JID), + Owner = jid:make(User, Server, <<>>), + {PUser, PServer, PResource} = jid:tolower(JID), PResources = case PResource of <<>> -> user_resources(PUser, PServer); _ -> [PResource] @@ -732,7 +732,7 @@ out_subscription(_, _, _, _) -> true. in_subscription(_, User, Server, Owner, unsubscribed, _) -> - unsubscribe_user(jlib:make_jid(User, Server, <<>>), Owner), + unsubscribe_user(jid:make(User, Server, <<>>), Owner), true; in_subscription(_, _, _, _, _, _) -> true. @@ -749,7 +749,7 @@ unsubscribe_user(Entity, Owner) -> end, [], [Entity#jid.lserver, Owner#jid.lserver]))] end). unsubscribe_user(Host, Entity, Owner) -> - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + BJID = jid:tolower(jid:remove_resource(Owner)), lists:foreach(fun (PType) -> {result, Subs} = node_action(Host, PType, get_entity_subscriptions, @@ -780,9 +780,9 @@ unsubscribe_user(Host, Entity, Owner) -> %% remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - Entity = jlib:make_jid(LUser, LServer, <<>>), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + Entity = jid:make(LUser, LServer, <<>>), Host = host(LServer), HomeTreeBase = <<"/home/", LServer/binary, "/", LUser/binary>>, spawn(fun () -> @@ -1201,7 +1201,7 @@ iq_disco_items(Host, Item, From, RSM) -> ). iq_sm(From, To, #iq{type = Type, sub_el = SubEl, xmlns = XMLNS, lang = Lang} = IQ) -> ServerHost = To#jid.lserver, - LOwner = jlib:jid_tolower(jlib:jid_remove_resource(To)), + LOwner = jid:tolower(jid:remove_resource(To)), Res = case XMLNS of ?NS_PUBSUB -> iq_pubsub(LOwner, ServerHost, From, Type, SubEl, Lang); @@ -1495,7 +1495,7 @@ get_pending_nodes(Host, Owner, Plugins) -> %% subscriptions on Host and Node.

    send_pending_auth_events(Host, Node, Owner) -> ?DEBUG("Sending pending auth events for ~s on ~s:~s", - [jlib:jid_to_string(Owner), Host, Node]), + [jid:to_string(Owner), Host, Node]), Action = fun (#pubsub_node{id = Nidx, type = Type}) -> case lists:member(<<"get-pending">>, plugin_features(Host, Type)) of true -> @@ -1510,8 +1510,8 @@ send_pending_auth_events(Host, Node, Owner) -> case transaction(Host, Node, Action, sync_dirty) of {result, {N, Subs}} -> lists:foreach(fun - ({J, pending, _SubId}) -> send_authorization_request(N, jlib:make_jid(J)); - ({J, pending}) -> send_authorization_request(N, jlib:make_jid(J)); + ({J, pending, _SubId}) -> send_authorization_request(N, jid:make(J)); + ({J, pending}) -> send_authorization_request(N, jid:make(J)); (_) -> ok end, Subs), @@ -1574,7 +1574,7 @@ send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = [#xmlel{name = <<"value">>, attrs = [], children = - [{xmlcdata, jlib:jid_to_string(Subscriber)}]}]}, + [{xmlcdata, jid:to_string(Subscriber)}]}]}, #xmlel{name = <<"field">>, attrs = [{<<"var">>, @@ -1590,7 +1590,7 @@ send_authorization_request(#pubsub_node{nodeid = {Host, Node}, type = Type, id = children = [{xmlcdata, <<"false">>}]}]}]}]}, lists:foreach(fun (Owner) -> - ejabberd_router:route(service_jid(Host), jlib:make_jid(Owner), Stanza) + ejabberd_router:route(service_jid(Host), jid:make(Owner), Stanza) end, node_owners_action(Host, Type, Nidx, O)). @@ -1635,7 +1635,7 @@ send_authorization_approval(Host, JID, SNode, Subscription) -> [{<<"subscription">>, subscription_to_string(S)}] end, Stanza = event_stanza(<<"subscription">>, - [{<<"jid">>, jlib:jid_to_string(JID)} + [{<<"jid">>, jid:to_string(JID)} | nodeAttr(SNode)] ++ SubAttrs), ejabberd_router:route(service_jid(Host), JID, Stanza). @@ -1648,8 +1648,8 @@ handle_authorization_response(Host, From, To, Packet, XFields) -> {{value, {_, [Node]}}, {value, {_, [SSubscriber]}}, {value, {_, [SAllow]}}} -> - FromLJID = jlib:jid_tolower(jlib:jid_remove_resource(From)), - Subscriber = jlib:string_to_jid(SSubscriber), + FromLJID = jid:tolower(jid:remove_resource(From)), + Subscriber = jid:from_string(SSubscriber), Allow = case SAllow of <<"1">> -> true; <<"true">> -> true; @@ -2045,7 +2045,7 @@ subscribe_node(Host, Node, From, JID, Configuration) -> [#xmlel{name = <<"pubsub">>, attrs = [{<<"xmlns">>, ?NS_PUBSUB}], children = [#xmlel{name = <<"subscription">>, - attrs = [{<<"jid">>, jlib:jid_to_string(Subscriber)} + attrs = [{<<"jid">>, jid:to_string(Subscriber)} | SubAttrs]}]}] end, case transaction(Host, Node, Action, sync_dirty) of @@ -2526,13 +2526,13 @@ dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To, Node, Message = add_message_type(Stanza, NotificationType), ejabberd_c2s:send_filtered(C2SPid, {pep_message, <>}, - service_jid(From), jlib:make_jid(To), + service_jid(From), jid:make(To), Message) end; dispatch_items(From, To, _Node, Options, Stanza) -> NotificationType = get_option(Options, notification_type, headline), Message = add_message_type(Stanza, NotificationType), - ejabberd_router:route(service_jid(From), jlib:make_jid(To), Message). + ejabberd_router:route(service_jid(From), jid:make(To), Message). %% @doc

    Return the list of affiliations as an XMPP response.

    -spec(get_affiliations/4 :: @@ -2620,7 +2620,7 @@ get_affiliations(Host, Node, JID) -> []; ({AJID, Aff}) -> [#xmlel{name = <<"affiliation">>, - attrs = [{<<"jid">>, jlib:jid_to_string(AJID)}, + attrs = [{<<"jid">>, jid:to_string(AJID)}, {<<"affiliation">>, affiliation_to_string(Aff)}]}] end, Affs), @@ -2644,17 +2644,17 @@ get_affiliations(Host, Node, JID) -> | {error, xmlel()} ). set_affiliations(Host, Node, From, EntitiesEls) -> - Owner = jlib:jid_tolower(jlib:jid_remove_resource(From)), + Owner = jid:tolower(jid:remove_resource(From)), Entities = lists:foldl(fun (_, error) -> error; (El, Acc) -> case El of #xmlel{name = <<"affiliation">>, attrs = Attrs} -> - JID = jlib:string_to_jid(xml:get_attr_s(<<"jid">>, Attrs)), + JID = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), Affiliation = string_to_affiliation(xml:get_attr_s(<<"affiliation">>, Attrs)), if (JID == error) or (Affiliation == false) -> error; - true -> [{jlib:jid_tolower(JID), Affiliation} | Acc] + true -> [{jid:tolower(JID), Affiliation} | Acc] end end end, @@ -2667,7 +2667,7 @@ set_affiliations(Host, Node, From, EntitiesEls) -> Owners = node_owners_call(Host, Type, Nidx, O), case lists:member(Owner, Owners) of true -> - OwnerJID = jlib:make_jid(Owner), + OwnerJID = jid:make(Owner), FilteredEntities = case Owners of [Owner] -> [E || E <- Entities, element(1, E) =/= OwnerJID]; _ -> Entities @@ -2676,13 +2676,13 @@ set_affiliations(Host, Node, From, EntitiesEls) -> node_call(Host, Type, set_affiliation, [Nidx, JID, Affiliation]), case Affiliation of owner -> - NewOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + NewOwner = jid:tolower(jid:remove_resource(JID)), NewOwners = [NewOwner | Owners], tree_call(Host, set_node, [N#pubsub_node{owners = NewOwners}]); none -> - OldOwner = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + OldOwner = jid:tolower(jid:remove_resource(JID)), case lists:member(OldOwner, Owners) of true -> NewOwners = Owners -- [OldOwner], @@ -2756,7 +2756,7 @@ read_sub(Host, Node, Nidx, Subscriber, SubId, Lang) -> [XdataEl] end, OptionsEl = #xmlel{name = <<"options">>, - attrs = [{<<"jid">>, jlib:jid_to_string(Subscriber)}, + attrs = [{<<"jid">>, jid:to_string(Subscriber)}, {<<"subid">>, SubId} | nodeAttr(Node)], children = Children}, @@ -2832,7 +2832,7 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> unsupported, <<"retrieve-subscriptions">>)}, Acc}; true -> - Subscriber = jlib:jid_remove_resource(JID), + Subscriber = jid:remove_resource(JID), {result, Subs} = node_action(Host, Type, get_entity_subscriptions, [Host, Subscriber]), @@ -2866,14 +2866,14 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> <<>> -> [#xmlel{name = <<"subscription">>, attrs = - [{<<"jid">>, jlib:jid_to_string(SubJID)}, + [{<<"jid">>, jid:to_string(SubJID)}, {<<"subid">>, SubId}, {<<"subscription">>, subscription_to_string(Sub)} | nodeAttr(SubsNode)]}]; SubsNode -> [#xmlel{name = <<"subscription">>, attrs = - [{<<"jid">>, jlib:jid_to_string(SubJID)}, + [{<<"jid">>, jid:to_string(SubJID)}, {<<"subid">>, SubId}, {<<"subscription">>, subscription_to_string(Sub)}]}]; _ -> @@ -2884,13 +2884,13 @@ get_subscriptions(Host, Node, JID, Plugins) when is_list(Plugins) -> <<>> -> [#xmlel{name = <<"subscription">>, attrs = - [{<<"jid">>, jlib:jid_to_string(SubJID)}, + [{<<"jid">>, jid:to_string(SubJID)}, {<<"subscription">>, subscription_to_string(Sub)} | nodeAttr(SubsNode)]}]; SubsNode -> [#xmlel{name = <<"subscription">>, attrs = - [{<<"jid">>, jlib:jid_to_string(SubJID)}, + [{<<"jid">>, jid:to_string(SubJID)}, {<<"subscription">>, subscription_to_string(Sub)}]}]; _ -> [] @@ -2930,12 +2930,12 @@ get_subscriptions(Host, Node, JID) -> ({AJID, Sub}) -> [#xmlel{name = <<"subscription">>, attrs = - [{<<"jid">>, jlib:jid_to_string(AJID)}, + [{<<"jid">>, jid:to_string(AJID)}, {<<"subscription">>, subscription_to_string(Sub)}]}]; ({AJID, Sub, SubId}) -> [#xmlel{name = <<"subscription">>, attrs = - [{<<"jid">>, jlib:jid_to_string(AJID)}, + [{<<"jid">>, jid:to_string(AJID)}, {<<"subscription">>, subscription_to_string(Sub)}, {<<"subid">>, SubId}]}] end, @@ -2974,18 +2974,18 @@ get_subscriptions_for_send_last(_Host, _PType, _, _JID, _LJID, _BJID) -> []. set_subscriptions(Host, Node, From, EntitiesEls) -> - Owner = jlib:jid_tolower(jlib:jid_remove_resource(From)), + Owner = jid:tolower(jid:remove_resource(From)), Entities = lists:foldl(fun (_, error) -> error; (El, Acc) -> case El of #xmlel{name = <<"subscription">>, attrs = Attrs} -> - JID = jlib:string_to_jid(xml:get_attr_s(<<"jid">>, Attrs)), + JID = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), Sub = string_to_subscription(xml:get_attr_s(<<"subscription">>, Attrs)), SubId = xml:get_attr_s(<<"subid">>, Attrs), if (JID == error) or (Sub == false) -> error; - true -> [{jlib:jid_tolower(JID), Sub, SubId} | Acc] + true -> [{jid:tolower(JID), Sub, SubId} | Acc] end end end, @@ -3001,10 +3001,10 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> attrs = [{<<"xmlns">>, ?NS_PUBSUB}], children = [#xmlel{name = <<"subscription">>, - attrs = [{<<"jid">>, jlib:jid_to_string(JID)}, + attrs = [{<<"jid">>, jid:to_string(JID)}, {<<"subscription">>, subscription_to_string(Sub)} | nodeAttr(Node)]}]}]}, - ejabberd_router:route(service_jid(Host), jlib:make_jid(JID), Stanza) + ejabberd_router:route(service_jid(Host), jid:make(JID), Stanza) end, Action = fun (#pubsub_node{type = Type, id = Nidx, owners = O}) -> Owners = node_owners_call(Host, Type, Nidx, O), @@ -3076,7 +3076,7 @@ get_roster_info(OwnerUser, OwnerServer, {SubscriberUser, SubscriberServer, _}, A Groups), {PresenceSubscription, RosterGroup}; get_roster_info(OwnerUser, OwnerServer, JID, AllowedGroups) -> - get_roster_info(OwnerUser, OwnerServer, jlib:jid_tolower(JID), AllowedGroups). + get_roster_info(OwnerUser, OwnerServer, jid:tolower(JID), AllowedGroups). string_to_affiliation(<<"owner">>) -> owner; string_to_affiliation(<<"publisher">>) -> publisher; @@ -3243,7 +3243,7 @@ items_event_stanza(Node, Items) -> DateTime = calendar:now_to_datetime(ModifNow), {T_string, Tz_string} = jlib:timestamp_to_iso(DateTime, utc), [#xmlel{name = <<"delay">>, attrs = [{<<"xmlns">>, ?NS_DELAY}, - {<<"from">>, jlib:jid_to_string(ModifUSR)}, + {<<"from">>, jid:to_string(ModifUSR)}, {<<"stamp">>, <>}], children = [{xmlcdata, <<>>}]}]; _ -> @@ -3445,7 +3445,7 @@ broadcast_stanza(Host, _Node, _Nidx, _Type, NodeOptions, SubsByDepth, NotifyType add_shim_headers(Stanza, subid_shim(SubIDs)) end, lists:foreach(fun(To) -> - ejabberd_router:route(From, jlib:make_jid(To), StanzaToSend) + ejabberd_router:route(From, jid:make(To), StanzaToSend) end, LJIDs) end, SubIDsByJID). @@ -3462,9 +3462,9 @@ broadcast_stanza({LUser, LServer, LResource}, Publisher, Node, Nidx, Type, NodeO %% See XEP-0163 1.1 section 4.3.1 ejabberd_c2s:broadcast(C2SPid, {pep_message, <<((Node))/binary, "+notify">>}, - _Sender = jlib:make_jid(LUser, LServer, <<"">>), + _Sender = jid:make(LUser, LServer, <<"">>), _StanzaToSend = add_extended_headers(Stanza, - _ReplyTo = extended_headers([jlib:jid_to_string(Publisher)]))); + _ReplyTo = extended_headers([jid:to_string(Publisher)]))); _ -> ?DEBUG("~p@~p has no session; can't deliver ~p to contacts", [LUser, LServer, BaseStanza]) end; @@ -3684,8 +3684,8 @@ max_items(Host, Options) -> -define(JLIST_CONFIG_FIELD(Label, Var, Opts), ?LISTXFIELD(Label, <<"pubsub#", (atom_to_binary(Var, latin1))/binary>>, - (jlib:jid_to_string(get_option(Options, Var))), - [jlib:jid_to_string(O) || O <- Opts])). + (jid:to_string(get_option(Options, Var))), + [jid:to_string(O) || O <- Opts])). -define(ALIST_CONFIG_FIELD(Label, Var, Opts), ?LISTXFIELD(Label, @@ -3910,7 +3910,7 @@ set_cached_item({_, ServerHost, _}, Nidx, ItemId, Publisher, Payload) -> set_cached_item(Host, Nidx, ItemId, Publisher, Payload) -> case is_last_item_cache_enabled(Host) of true -> mnesia:dirty_write({pubsub_last_item, Nidx, ItemId, - {now(), jlib:jid_tolower(jlib:jid_remove_resource(Publisher))}, + {now(), jid:tolower(jid:remove_resource(Publisher))}, Payload}); _ -> ok end. @@ -4206,11 +4206,11 @@ extended_error(#xmlel{name = Error, attrs = Attrs, children = SubEls}, Ext, ExtA children = lists:reverse([#xmlel{name = Ext, attrs = ExtAttrs} | SubEls])}. string_to_ljid(JID) -> - case jlib:string_to_jid(JID) of + case jid:from_string(JID) of error -> {<<>>, <<>>, <<>>}; J -> - case jlib:jid_tolower(J) of + case jid:tolower(J) of error -> {<<>>, <<>>, <<>>}; J1 -> J1 end @@ -4279,7 +4279,7 @@ extended_headers(Jids) -> || Jid <- Jids]. on_user_offline(_, JID, _) -> - {User, Server, Resource} = jlib:jid_tolower(JID), + {User, Server, Resource} = jid:tolower(JID), case user_resources(User, Server) of [] -> purge_offline({User, Server, Resource}); _ -> true diff --git a/src/mod_register.erl b/src/mod_register.erl index f9ffa9c50cf..21c58446946 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -89,19 +89,19 @@ unauthenticated_iq_register(_Acc, Server, {A, _Port} -> A; _ -> undefined end, - ResIQ = process_iq(jlib:make_jid(<<"">>, <<"">>, + ResIQ = process_iq(jid:make(<<"">>, <<"">>, <<"">>), - jlib:make_jid(<<"">>, Server, <<"">>), IQ, Address), - Res1 = jlib:replace_from_to(jlib:make_jid(<<"">>, + jid:make(<<"">>, Server, <<"">>), IQ, Address), + Res1 = jlib:replace_from_to(jid:make(<<"">>, Server, <<"">>), - jlib:make_jid(<<"">>, <<"">>, <<"">>), + jid:make(<<"">>, <<"">>, <<"">>), jlib:iq_to_xml(ResIQ)), jlib:remove_attr(<<"to">>, Res1); unauthenticated_iq_register(Acc, _Server, _IQ, _IP) -> Acc. process_iq(From, To, IQ) -> - process_iq(From, To, IQ, jlib:jid_tolower(From)). + process_iq(From, To, IQ, jid:tolower(From)). process_iq(From, To, #iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = @@ -171,9 +171,9 @@ process_iq(From, To, resource = Resource} -> ResIQ = #iq{type = result, xmlns = ?NS_REGISTER, id = ID, sub_el = []}, - ejabberd_router:route(jlib:make_jid(User, Server, + ejabberd_router:route(jid:make(User, Server, Resource), - jlib:make_jid(User, Server, + jid:make(User, Server, Resource), jlib:iq_to_xml(ResIQ)), ejabberd_auth:remove_user(User, Server), @@ -373,10 +373,10 @@ try_set_password(User, Server, Password, IQ, SubEl, end. try_register(User, Server, Password, SourceRaw, Lang) -> - case jlib:is_nodename(User) of + case jid:is_nodename(User) of false -> {error, ?ERR_BAD_REQUEST}; _ -> - JID = jlib:make_jid(User, Server, <<"">>), + JID = jid:make(User, Server, <<"">>), Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) when is_atom(A) -> A end, all), @@ -441,7 +441,7 @@ send_welcome_message(JID) -> of {<<"">>, <<"">>} -> ok; {Subj, Body} -> - ejabberd_router:route(jlib:make_jid(<<"">>, Host, + ejabberd_router:route(jid:make(<<"">>, Host, <<"">>), JID, #xmlel{name = <<"message">>, @@ -463,7 +463,7 @@ send_registration_notifications(Mod, UJID, Source) -> case gen_mod:get_module_opt( Host, Mod, registration_watchers, fun(Ss) -> - [#jid{} = jlib:string_to_jid(iolist_to_binary(S)) + [#jid{} = jid:from_string(iolist_to_binary(S)) || S <- Ss] end, []) of [] -> ok; @@ -472,13 +472,13 @@ send_registration_notifications(Mod, UJID, Source) -> iolist_to_binary(io_lib:format("[~s] The account ~s was registered from " "IP address ~s on node ~w using ~p.", [get_time_string(), - jlib:jid_to_string(UJID), + jid:to_string(UJID), ip_to_string(Source), node(), Mod])), lists:foreach( fun(JID) -> ejabberd_router:route( - jlib:make_jid(<<"">>, Host, <<"">>), + jid:make(<<"">>, Host, <<"">>), JID, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], @@ -610,7 +610,7 @@ process_xdata_submit(El) -> end. is_strong_password(Server, Password) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), case gen_mod:get_module_opt(LServer, ?MODULE, password_strength, fun(N) when is_number(N), N>=0 -> N end, 0) of @@ -673,7 +673,7 @@ transform_module_options(Opts) -> %%% may_remove_resource({_, _, _} = From) -> - jlib:jid_remove_resource(From); + jid:remove_resource(From); may_remove_resource(From) -> From. get_ip_access(Host) -> @@ -706,7 +706,7 @@ mod_opt_type(password_strength) -> fun (N) when is_number(N), N >= 0 -> N end; mod_opt_type(registration_watchers) -> fun (Ss) -> - [#jid{} = jlib:string_to_jid(iolist_to_binary(S)) + [#jid{} = jid:from_string(iolist_to_binary(S)) || S <- Ss] end; mod_opt_type(welcome_message) -> diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index 32e06f142b3..7f7cf36b632 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -100,7 +100,7 @@ process([<<"new">>], lang = Lang, host = _HTTPHost}) -> case form_new_post(Q) of {success, ok, {Username, Host, _Password}} -> - Jid = jlib:make_jid(Username, Host, <<"">>), + Jid = jid:make(Username, Host, <<"">>), mod_register:send_registration_notifications(?MODULE, Jid, Ip), Text = (?T(<<"Your Jabber account was successfully " "created.">>)), @@ -491,7 +491,7 @@ register_account(Username, Host, Password) -> Access = gen_mod:get_module_opt(Host, mod_register, access, fun(A) when is_atom(A) -> A end, all), - case jlib:make_jid(Username, Host, <<"">>) of + case jid:make(Username, Host, <<"">>) of error -> {error, invalid_jid}; JID -> case acl:match_rule(Host, Access, JID) of diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 0677605acd6..c75e128f5e8 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -396,7 +396,7 @@ get_roster(LUser, LServer, odbc) -> error -> []; R -> SJID = - jlib:jid_to_string(R#roster.jid), + jid:to_string(R#roster.jid), Groups = case dict:find(SJID, GroupsDict) of @@ -413,7 +413,7 @@ get_roster(LUser, LServer, odbc) -> item_to_xml(Item) -> Attrs1 = [{<<"jid">>, - jlib:jid_to_string(Item#roster.jid)}], + jid:to_string(Item#roster.jid)}], Attrs2 = case Item#roster.name of <<"">> -> Attrs1; Name -> [{<<"name">>, Name} | Attrs1] @@ -454,7 +454,7 @@ get_roster_by_jid_t(LUser, LServer, LJID, mnesia) -> end; get_roster_by_jid_t(LUser, LServer, LJID, odbc) -> Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), {selected, [<<"username">>, <<"jid">>, <<"nick">>, <<"subscription">>, <<"ask">>, <<"askmessage">>, @@ -509,14 +509,14 @@ process_iq_set(From, To, #iq{sub_el = SubEl, id = Id} = IQ) -> process_item_set(From, To, #xmlel{attrs = Attrs, children = Els}, Managed) -> - JID1 = jlib:string_to_jid(xml:get_attr_s(<<"jid">>, + JID1 = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), #jid{user = User, luser = LUser, lserver = LServer} = From, case JID1 of error -> ok; _ -> - LJID = jlib:jid_tolower(JID1), + LJID = jid:tolower(JID1), F = fun () -> Item = get_roster_by_jid_t(LUser, LServer, LJID), Item1 = process_item_attrs_managed(Item, Attrs, Managed), @@ -552,7 +552,7 @@ process_item_set(_From, _To, _, _Managed) -> ok. process_item_attrs(Item, [{Attr, Val} | Attrs]) -> case Attr of <<"jid">> -> - case jlib:string_to_jid(Val) of + case jid:from_string(Val) of error -> process_item_attrs(Item, Attrs); JID1 -> JID = {JID1#jid.luser, JID1#jid.lserver, @@ -595,8 +595,8 @@ process_item_els(Item, [{xmlcdata, _} | Els]) -> process_item_els(Item, []) -> Item. push_item(User, Server, From, Item) -> - ejabberd_sm:route(jlib:make_jid(<<"">>, <<"">>, <<"">>), - jlib:make_jid(User, Server, <<"">>), + ejabberd_sm:route(jid:make(<<"">>, <<"">>, <<"">>), + jid:make(User, Server, <<"">>), {broadcast, {item, Item#roster.jid, Item#roster.subscription}}), case roster_versioning_enabled(Server) of @@ -629,7 +629,7 @@ push_item(User, Server, Resource, From, Item, attrs = [{<<"xmlns">>, ?NS_ROSTER} | ExtraAttrs], children = [item_to_xml(Item)]}]}, ejabberd_router:route(From, - jlib:make_jid(User, Server, Resource), + jid:make(User, Server, Resource), jlib:iq_to_xml(ResIQ)). push_item_version(Server, User, From, Item, @@ -641,8 +641,8 @@ push_item_version(Server, User, From, Item, ejabberd_sm:get_user_resources(User, Server)). get_subscription_lists(Acc, User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), DBType = gen_mod:db_type(LServer, ?MODULE), Items = get_subscription_lists(Acc, LUser, LServer, DBType), @@ -707,7 +707,7 @@ roster_subscribe_t(_LUser, _LServer, _LJID, Item, roster_subscribe_t(LUser, LServer, LJID, Item, odbc) -> ItemVals = record_to_string(Item), Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), odbc_queries:roster_subscribe(LServer, Username, SJID, ItemVals); roster_subscribe_t(LUser, LServer, _LJID, Item, riak) -> @@ -744,7 +744,7 @@ get_roster_by_jid_with_groups_t(LUser, LServer, LJID, get_roster_by_jid_with_groups_t(LUser, LServer, LJID, odbc) -> Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), case odbc_queries:get_roster_by_jid(LServer, Username, SJID) of @@ -783,9 +783,9 @@ get_roster_by_jid_with_groups_t(LUser, LServer, LJID, riak) -> process_subscription(Direction, User, Server, JID1, Type, Reason) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), - LJID = jlib:jid_tolower(JID1), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + LJID = jid:tolower(JID1), F = fun () -> Item = get_roster_by_jid_with_groups_t(LUser, LServer, LJID), @@ -836,7 +836,7 @@ process_subscription(Direction, User, Server, JID1, subscribed -> <<"subscribed">>; unsubscribed -> <<"unsubscribed">> end, - ejabberd_router:route(jlib:make_jid(User, Server, + ejabberd_router:route(jid:make(User, Server, <<"">>), JID1, #xmlel{name = <<"presence">>, @@ -850,7 +850,7 @@ process_subscription(Direction, User, Server, JID1, ok; true -> push_item(User, Server, - jlib:make_jid(User, Server, <<"">>), Item) + jid:make(User, Server, <<"">>), Item) end, true; none -> false @@ -974,8 +974,8 @@ in_auto_reply(both, none, unsubscribe) -> unsubscribed; in_auto_reply(_, _, _) -> none. remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), send_unsubscription_to_rosteritems(LUser, LServer), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). @@ -999,7 +999,7 @@ remove_user(LUser, LServer, riak) -> %% 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, <<"">>}), + From = jid:make({LUser, LServer, <<"">>}), lists:foreach(fun (RosterItem) -> send_unsubscribing_presence(From, RosterItem) end, @@ -1017,14 +1017,14 @@ send_unsubscribing_presence(From, Item) -> _ -> false end, if IsTo -> - send_presence_type(jlib:jid_remove_resource(From), - jlib:make_jid(Item#roster.jid), + send_presence_type(jid:remove_resource(From), + jid:make(Item#roster.jid), <<"unsubscribe">>); true -> ok end, if IsFrom -> - send_presence_type(jlib:jid_remove_resource(From), - jlib:make_jid(Item#roster.jid), + send_presence_type(jid:remove_resource(From), + jid:make(Item#roster.jid), <<"unsubscribed">>); true -> ok end, @@ -1039,8 +1039,8 @@ send_presence_type(From, To, Type) -> set_items(User, Server, SubEl) -> #xmlel{children = Els} = SubEl, - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), F = fun () -> lists:foreach(fun (El) -> process_item_set_t(LUser, LServer, El) @@ -1058,7 +1058,7 @@ update_roster_t(_LUser, _LServer, _LJID, Item, mnesia:write(Item); update_roster_t(LUser, LServer, LJID, Item, odbc) -> Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), ItemVals = record_to_string(Item), ItemGroups = groups_to_string(Item), odbc_queries:update_roster(LServer, Username, SJID, ItemVals, @@ -1075,14 +1075,14 @@ del_roster_t(LUser, LServer, LJID, mnesia) -> mnesia:delete({roster, {LUser, LServer, LJID}}); del_roster_t(LUser, LServer, LJID, odbc) -> Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), odbc_queries:del_roster(LServer, Username, SJID); del_roster_t(LUser, LServer, LJID, riak) -> ejabberd_riak:delete(roster, {LUser, LServer, LJID}). process_item_set_t(LUser, LServer, #xmlel{attrs = Attrs, children = Els}) -> - JID1 = jlib:string_to_jid(xml:get_attr_s(<<"jid">>, + JID1 = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), case JID1 of error -> ok; @@ -1105,7 +1105,7 @@ process_item_set_t(_LUser, _LServer, _) -> ok. process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) -> case Attr of <<"jid">> -> - case jlib:string_to_jid(Val) of + case jid:from_string(Val) of error -> process_item_attrs_ws(Item, Attrs); JID1 -> JID = {JID1#jid.luser, JID1#jid.lserver, @@ -1140,13 +1140,13 @@ process_item_attrs_ws(Item, [{Attr, Val} | Attrs]) -> process_item_attrs_ws(Item, []) -> Item. get_in_pending_subscriptions(Ls, User, Server) -> - LServer = jlib:nameprep(Server), + LServer = jid:nameprep(Server), get_in_pending_subscriptions(Ls, User, Server, gen_mod:db_type(LServer, ?MODULE)). get_in_pending_subscriptions(Ls, User, Server, DBType) when DBType == mnesia; DBType == riak -> - JID = jlib:make_jid(User, Server, <<"">>), + JID = jid:make(User, Server, <<"">>), Result = get_roster(JID#jid.luser, JID#jid.lserver, DBType), Ls ++ lists:map(fun (R) -> Message = R#roster.askmessage, @@ -1156,8 +1156,8 @@ get_in_pending_subscriptions(Ls, User, Server, DBType) #xmlel{name = <<"presence">>, attrs = [{<<"from">>, - jlib:jid_to_string(R#roster.jid)}, - {<<"to">>, jlib:jid_to_string(JID)}, + jid:to_string(R#roster.jid)}, + {<<"to">>, jid:to_string(JID)}, {<<"type">>, <<"subscribe">>}], children = [#xmlel{name = <<"status">>, @@ -1174,7 +1174,7 @@ get_in_pending_subscriptions(Ls, User, Server, DBType) end, Result)); get_in_pending_subscriptions(Ls, User, Server, odbc) -> - JID = jlib:make_jid(User, Server, <<"">>), + JID = jid:make(User, Server, <<"">>), LUser = JID#jid.luser, LServer = JID#jid.lserver, Username = ejabberd_odbc:escape(LUser), @@ -1191,8 +1191,8 @@ get_in_pending_subscriptions(Ls, User, Server, odbc) -> #xmlel{name = <<"presence">>, attrs = [{<<"from">>, - jlib:jid_to_string(R#roster.jid)}, - {<<"to">>, jlib:jid_to_string(JID)}, + jid:to_string(R#roster.jid)}, + {<<"to">>, jid:to_string(JID)}, {<<"type">>, <<"subscribe">>}], children = [#xmlel{name = <<"status">>, @@ -1219,8 +1219,8 @@ get_in_pending_subscriptions(Ls, User, Server, odbc) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% read_subscription_and_groups(User, Server, LJID) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), read_subscription_and_groups(LUser, LServer, LJID, gen_mod:db_type(LServer, ?MODULE)). @@ -1237,7 +1237,7 @@ read_subscription_and_groups(LUser, LServer, LJID, read_subscription_and_groups(LUser, LServer, LJID, odbc) -> Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), case catch odbc_queries:get_subscription(LServer, Username, SJID) of @@ -1270,11 +1270,11 @@ read_subscription_and_groups(LUser, LServer, LJID, end. get_jid_info(_, User, Server, JID) -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), case read_subscription_and_groups(User, Server, LJID) of {Subscription, Groups} -> {Subscription, Groups}; error -> - LRJID = jlib:jid_tolower(jlib:jid_remove_resource(JID)), + LRJID = jid:tolower(jid:remove_resource(JID)), if LRJID == LJID -> {none, []}; true -> case read_subscription_and_groups(User, Server, LRJID) @@ -1290,10 +1290,10 @@ get_jid_info(_, User, Server, JID) -> raw_to_record(LServer, [User, SJID, Nick, SSubscription, SAsk, SAskMessage, _SServer, _SSubscribe, _SType]) -> - case jlib:string_to_jid(SJID) of + case jid:from_string(SJID) of error -> error; JID -> - LJID = jlib:jid_tolower(JID), + LJID = jid:tolower(JID), Subscription = case SSubscription of <<"B">> -> both; <<"T">> -> to; @@ -1319,7 +1319,7 @@ record_to_string(#roster{us = {User, _Server}, ask = Ask, askmessage = AskMessage}) -> Username = ejabberd_odbc:escape(User), SJID = - ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(JID))), + ejabberd_odbc:escape(jid:to_string(jid:tolower(JID))), Nick = ejabberd_odbc:escape(Name), SSubscription = case Subscription of both -> <<"B">>; @@ -1343,7 +1343,7 @@ groups_to_string(#roster{us = {User, _Server}, jid = JID, groups = Groups}) -> Username = ejabberd_odbc:escape(User), SJID = - ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(JID))), + ejabberd_odbc:escape(jid:to_string(jid:tolower(JID))), lists:foldl(fun (<<"">>, Acc) -> Acc; (Group, Acc) -> G = ejabberd_odbc:escape(Group), @@ -1417,8 +1417,8 @@ webadmin_page(_, Host, webadmin_page(Acc, _, _) -> Acc. user_roster(User, Server, Query, Lang) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, Items1 = get_roster(LUser, LServer), Res = user_roster_parse_query(User, Server, Items1, @@ -1504,7 +1504,7 @@ user_roster(User, Server, Query, Lang) -> <<"Add Jabber ID">>)]))]. build_contact_jid_td(RosterJID) -> - ContactJID = jlib:make_jid(RosterJID), + ContactJID = jid:make(RosterJID), JIDURI = case {ContactJID#jid.luser, ContactJID#jid.lserver} of @@ -1520,10 +1520,10 @@ build_contact_jid_td(RosterJID) -> case JIDURI of <<>> -> ?XAC(<<"td">>, [{<<"class">>, <<"valign">>}], - (jlib:jid_to_string(RosterJID))); + (jid:to_string(RosterJID))); URI when is_binary(URI) -> ?XAE(<<"td">>, [{<<"class">>, <<"valign">>}], - [?AC(JIDURI, (jlib:jid_to_string(RosterJID)))]) + [?AC(JIDURI, (jid:to_string(RosterJID)))]) end. user_roster_parse_query(User, Server, Items, Query) -> @@ -1531,7 +1531,7 @@ user_roster_parse_query(User, Server, Items, Query) -> {value, _} -> case lists:keysearch(<<"newjid">>, 1, Query) of {value, {_, SJID}} -> - case jlib:string_to_jid(SJID) of + case jid:from_string(SJID) of JID when is_record(JID, jid) -> user_roster_subscribe_jid(User, Server, JID), ok; error -> error @@ -1550,7 +1550,7 @@ user_roster_parse_query(User, Server, Items, Query) -> user_roster_subscribe_jid(User, Server, JID) -> out_subscription(User, Server, JID, subscribe), - UJID = jlib:make_jid(User, Server, <<"">>), + UJID = jid:make(User, Server, <<"">>), ejabberd_router:route(UJID, JID, #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"subscribe">>}], @@ -1565,10 +1565,10 @@ user_roster_item_parse_query(User, Server, Items, 1, Query) of {value, _} -> - JID1 = jlib:make_jid(JID), + JID1 = jid:make(JID), out_subscription(User, Server, JID1, subscribed), - UJID = jlib:make_jid(User, Server, <<"">>), + UJID = jid:make(User, Server, <<"">>), ejabberd_router:route(UJID, JID1, #xmlel{name = <<"presence">>, @@ -1583,7 +1583,7 @@ user_roster_item_parse_query(User, Server, Items, 1, Query) of {value, _} -> - UJID = jlib:make_jid(User, Server, + UJID = jid:make(User, Server, <<"">>), process_iq_set(UJID, UJID, #iq{type = set, @@ -1600,7 +1600,7 @@ user_roster_item_parse_query(User, Server, Items, attrs = [{<<"jid">>, - jlib:jid_to_string(JID)}, + jid:to_string(JID)}, {<<"subscription">>, <<"remove">>}], children @@ -1615,7 +1615,7 @@ user_roster_item_parse_query(User, Server, Items, nothing. us_to_list({User, Server}) -> - jlib:jid_to_string({User, Server, <<"">>}). + jid:to_string({User, Server, <<"">>}). webadmin_user(Acc, _User, _Server, Lang) -> Acc ++ @@ -1676,7 +1676,7 @@ is_item_of_domain(_MatchDomain, {xmlcdata, _}) -> false. is_jid_of_domain(MatchDomain, {<<"jid">>, JIDString}) -> - case jlib:string_to_jid(JIDString) of + case jid:from_string(JIDString) of JID when JID#jid.lserver == MatchDomain -> true; _ -> false end; @@ -1716,7 +1716,7 @@ export(_Server) -> fun(Host, #roster{usj = {LUser, LServer, LJID}} = R) when LServer == Host -> Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jlib:jid_to_string(LJID)), + SJID = ejabberd_odbc:escape(jid:to_string(LJID)), ItemVals = record_to_string(R), ItemGroups = groups_to_string(R), odbc_queries:update_roster_sql(Username, SJID, diff --git a/src/mod_service_log.erl b/src/mod_service_log.erl index db0f3df3b59..83c8a20ffdf 100644 --- a/src/mod_service_log.erl +++ b/src/mod_service_log.erl @@ -67,7 +67,7 @@ log_packet(From, To, lists:map( fun(S) -> B = iolist_to_binary(S), - N = jlib:nameprep(B), + N = jid:nameprep(B), if N /= error -> N end @@ -77,8 +77,8 @@ log_packet(From, To, resource = <<"">>, luser = <<"">>, lserver = Host, lresource = <<"">>}, NewAttrs = - jlib:replace_from_to_attrs(jlib:jid_to_string(From), - jlib:jid_to_string(To), Attrs), + jlib:replace_from_to_attrs(jid:to_string(From), + jid:to_string(To), Attrs), FixedPacket = #xmlel{name = Name, attrs = NewAttrs, children = Els}, lists:foreach(fun (Logger) -> @@ -100,7 +100,7 @@ mod_opt_type(loggers) -> fun (L) -> lists:map(fun (S) -> B = iolist_to_binary(S), - N = jlib:nameprep(B), + N = jid:nameprep(B), if N /= error -> N end end, L) diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 9020e5d3e26..52828245169 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -182,8 +182,8 @@ get_vcard_module(Server) -> get_rosteritem_name([], _, _) -> <<"">>; get_rosteritem_name([ModVcard], U, S) -> - From = jlib:make_jid(<<"">>, S, jlib:atom_to_binary(?MODULE)), - To = jlib:make_jid(U, S, <<"">>), + From = jid:make(<<"">>, S, jlib:atom_to_binary(?MODULE)), + To = jid:make(U, S, <<"">>), case lists:member(To#jid.lserver, ?MYHOSTS) of true -> IQ = {iq, <<"">>, get, <<"vcard-temp">>, <<"">>, @@ -246,11 +246,11 @@ process_item(RosterItem, Host) -> %% existing roster groups. [] -> mod_roster:out_subscription(UserTo, ServerTo, - jlib:make_jid(UserFrom, ServerFrom, + jid:make(UserFrom, ServerFrom, <<"">>), unsubscribe), mod_roster:in_subscription(aaaa, UserFrom, ServerFrom, - jlib:make_jid(UserTo, ServerTo, + jid:make(UserTo, ServerTo, <<"">>), unsubscribe, <<"">>), RosterItem#roster{subscription = both, ask = none}; @@ -275,8 +275,8 @@ set_new_rosteritems(UserFrom, ServerFrom, UserTo, RIFrom = build_roster_record(UserFrom, ServerFrom, UserTo, ServerTo, NameTo, GroupsFrom), set_item(UserFrom, ServerFrom, ResourceTo, RIFrom), - JIDTo = jlib:make_jid(UserTo, ServerTo, <<"">>), - JIDFrom = jlib:make_jid(UserFrom, ServerFrom, <<"">>), + JIDTo = jid:make(UserTo, ServerTo, <<"">>), + JIDFrom = jid:make(UserFrom, ServerFrom, <<"">>), RITo = build_roster_record(UserTo, ServerTo, UserFrom, ServerFrom, UserFrom, []), set_item(UserTo, ServerTo, <<"">>, RITo), @@ -305,14 +305,14 @@ set_item(User, Server, Resource, Item) -> [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_ROSTER}], children = [mod_roster:item_to_xml(Item)]}]}, - ejabberd_router:route(jlib:make_jid(User, Server, + ejabberd_router:route(jid:make(User, Server, Resource), - jlib:make_jid(<<"">>, Server, <<"">>), + jid:make(<<"">>, Server, <<"">>), jlib:iq_to_xml(ResIQ)). get_subscription_lists({F, T}, User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, DisplayedGroups = get_user_displayed_groups(US), SRUsers = lists:usort(lists:flatmap(fun (Group) -> @@ -324,10 +324,10 @@ get_subscription_lists({F, T}, User, Server) -> get_jid_info({Subscription, Groups}, User, Server, JID) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, - {U1, S1, _} = jlib:jid_tolower(JID), + {U1, S1, _} = jid:tolower(JID), US1 = {U1, S1}, DisplayedGroups = get_user_displayed_groups(US), SRUsers = lists:foldl(fun (Group, Acc1) -> @@ -357,7 +357,7 @@ in_subscription(Acc, User, Server, JID, Type, out_subscription(UserFrom, ServerFrom, JIDTo, unsubscribed) -> #jid{luser = UserTo, lserver = ServerTo} = JIDTo, - JIDFrom = jlib:make_jid(UserFrom, ServerFrom, <<"">>), + JIDFrom = jid:make(UserFrom, ServerFrom, <<"">>), mod_roster:out_subscription(UserTo, ServerTo, JIDFrom, unsubscribe), mod_roster:in_subscription(aaaa, UserFrom, ServerFrom, @@ -370,11 +370,11 @@ out_subscription(User, Server, JID, Type) -> process_subscription(Direction, User, Server, JID, _Type, Acc) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, {U1, S1, _} = - jlib:jid_tolower(jlib:jid_remove_resource(JID)), + jid:tolower(jid:remove_resource(JID)), US1 = {U1, S1}, DisplayedGroups = get_user_displayed_groups(US), SRUsers = lists:usort(lists:flatmap(fun (Group) -> @@ -657,7 +657,7 @@ get_group_explicit_users(Host, Group, odbc) -> {selected, [<<"jid">>], Rs} -> lists:map(fun ([JID]) -> {U, S, _} = - jlib:jid_tolower(jlib:string_to_jid(JID)), + jid:tolower(jid:from_string(JID)), {U, S} end, Rs); @@ -949,8 +949,8 @@ remove_user(User, Server) -> push_user_to_members(User, Server, remove). push_user_to_members(User, Server, Subscription) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), GroupsOpts = groups_with_opts(LServer), SpecialGroups = get_special_displayed_groups(GroupsOpts), @@ -1024,8 +1024,8 @@ push_item(User, Server, Item) -> attrs = [{<<"xmlns">>, ?NS_ROSTER}], children = [item_to_xml(Item)]}]}), lists:foreach(fun (Resource) -> - JID = jlib:make_jid(User, Server, Resource), - ejabberd_router:route(jlib:jid_remove_resource(JID), JID, Stanza) + JID = jid:make(User, Server, Resource), + ejabberd_router:route(jid:remove_resource(JID), JID, Stanza) end, ejabberd_sm:get_user_resources(User, Server)). @@ -1040,7 +1040,7 @@ push_roster_item(User, Server, ContactU, ContactS, item_to_xml(Item) -> Attrs1 = [{<<"jid">>, - jlib:jid_to_string(Item#roster.jid)}], + jid:to_string(Item#roster.jid)}], Attrs2 = case Item#roster.name of <<"">> -> Attrs1; Name -> [{<<"name">>, Name} | Attrs1] @@ -1298,7 +1298,7 @@ shared_roster_group_parse_query(Host, Group, Query) -> <<"@all@">> -> USs; <<"@online@">> -> USs; _ -> - case jlib:string_to_jid(SJID) + case jid:from_string(SJID) of JID when is_record(JID, @@ -1358,7 +1358,7 @@ get_opt(Opts, Opt, Default) -> end. us_to_list({User, Server}) -> - jlib:jid_to_string({User, Server, <<"">>}). + jid:to_string({User, Server, <<"">>}). split_grouphost(Host, Group) -> case str:tokens(Group, <<"@">>) of @@ -1368,8 +1368,8 @@ split_grouphost(Host, Group) -> broadcast_subscription(User, Server, ContactJid, Subscription) -> ejabberd_sm:route( - jlib:make_jid(<<"">>, Server, <<"">>), - jlib:make_jid(User, Server, <<"">>), + jid:make(<<"">>, Server, <<"">>), + jid:make(User, Server, <<"">>), {broadcast, {item, ContactJid, Subscription}}). @@ -1386,7 +1386,7 @@ displayed_groups_update(Members, DisplayedGroups, Subscription) -> end, Members). make_jid_s(U, S) -> - ejabberd_odbc:escape(jlib:jid_to_string(jlib:jid_tolower(jlib:make_jid(U, + ejabberd_odbc:escape(jid:to_string(jid:tolower(jid:make(U, S, <<"">>)))). @@ -1466,9 +1466,9 @@ export(_Server) -> when LServer == Host -> SGroup = ejabberd_odbc:escape(Group), SJID = ejabberd_odbc:escape( - jlib:jid_to_string( - jlib:jid_tolower( - jlib:make_jid(U, S, <<"">>)))), + jid:to_string( + jid:tolower( + jid:make(U, S, <<"">>)))), [[<<"delete from sr_user where jid='">>, SJID, <<"'and grp='">>, Group, <<"';">>], [<<"insert into sr_user(jid, grp) values ('">>, @@ -1485,7 +1485,7 @@ import(LServer) -> end}, {<<"select jid, grp from sr_user;">>, fun([SJID, Group]) -> - #jid{luser = U, lserver = S} = jlib:string_to_jid(SJID), + #jid{luser = U, lserver = S} = jid:from_string(SJID), #sr_user{us = {U, S}, group_host = {Group, LServer}} end}]. diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 2a3d8ee1155..9064a671100 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -159,8 +159,8 @@ process_item(RosterItem, _Host) -> end. get_subscription_lists({F, T}, User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, DisplayedGroups = get_user_displayed_groups(US), SRUsers = lists:usort(lists:flatmap(fun (Group) -> @@ -172,10 +172,10 @@ get_subscription_lists({F, T}, User, Server) -> get_jid_info({Subscription, Groups}, User, Server, JID) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, - {U1, S1, _} = jlib:jid_tolower(JID), + {U1, S1, _} = jid:tolower(JID), US1 = {U1, S1}, SRUsers = get_user_to_groups_map(US, false), case dict:find(US1, SRUsers) of @@ -197,11 +197,11 @@ out_subscription(User, Server, JID, Type) -> process_subscription(Direction, User, Server, JID, _Type, Acc) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), US = {LUser, LServer}, {U1, S1, _} = - jlib:jid_tolower(jlib:jid_remove_resource(JID)), + jid:tolower(jid:remove_resource(JID)), US1 = {U1, S1}, DisplayedGroups = get_user_displayed_groups(US), SRUsers = lists:usort(lists:flatmap(fun (Group) -> @@ -417,7 +417,7 @@ search_group_info(State, Group) -> UID}, L) -> PUID = - jlib:nodeprep(UID), + jid:nodeprep(UID), case PUID of diff --git a/src/mod_sip.erl b/src/mod_sip.erl index 1e4044b1520..c8c95337947 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -160,8 +160,8 @@ locate(_SIPMsg) -> ok. find(#uri{user = User, host = Host}) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Host), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Host), if LUser == <<"">> -> to_me; true -> @@ -192,7 +192,7 @@ action(#sip{method = <<"REGISTER">>, type = request, hdrs = Hdrs, true -> register; false -> - {auth, jlib:nameprep(ToURI#uri.host)} + {auth, jid:nameprep(ToURI#uri.host)} end; false -> deny @@ -223,7 +223,7 @@ action(#sip{method = Method, hdrs = Hdrs, type = request} = Req, SIPSock) -> true -> find(ToURI); false -> - LServer = jlib:nameprep(FromURI#uri.host), + LServer = jid:nameprep(FromURI#uri.host), {relay, LServer} end; false -> @@ -250,8 +250,8 @@ check_auth(#sip{method = Method, hdrs = Hdrs, body = Body}, AuthHdr, _SIPSock) - from end, {_, #uri{user = User, host = Host}, _} = esip:get_hdr(Issuer, Hdrs), - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Host), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Host), case lists:filter( fun({_, Params}) -> Username = esip:get_param(<<"username">>, Params), @@ -299,7 +299,7 @@ make_response(Req, Resp) -> esip:make_response(Req, Resp, esip:make_tag()). at_my_host(#uri{host = Host}) -> - is_my_host(jlib:nameprep(Host)). + is_my_host(jid:nameprep(Host)). is_my_host(LServer) -> gen_mod:is_loaded(LServer, ?MODULE). diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index a0dff125625..53b16fd7ea3 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -249,8 +249,8 @@ connect(#sip{hdrs = Hdrs} = Req, Opts) -> {_, ToURI, _} = esip:get_hdr('to', Hdrs), case mod_sip:at_my_host(ToURI) of true -> - LUser = jlib:nodeprep(ToURI#uri.user), - LServer = jlib:nameprep(ToURI#uri.host), + LUser = jid:nodeprep(ToURI#uri.user), + LServer = jid:nameprep(ToURI#uri.host), case mod_sip_registrar:find_sockets(LUser, LServer) of [_|_] = SIPSocks -> {ok, SIPSocks}; @@ -412,7 +412,7 @@ choose_best_response(#state{responses = Responses} = State) -> %% Just compare host part only. cmp_uri(#uri{host = H1}, #uri{host = H2}) -> - jlib:nameprep(H1) == jlib:nameprep(H2). + jid:nameprep(H1) == jid:nameprep(H2). is_my_route(URI, URIs) -> lists:any(fun(U) -> cmp_uri(URI, U) end, URIs). @@ -441,20 +441,20 @@ prepare_request(LServer, #sip{hdrs = Hdrs} = Req) -> Hdrs3 = lists:filter( fun({'proxy-authorization', {_, Params}}) -> Realm = esip:unquote(esip:get_param(<<"realm">>, Params)), - not mod_sip:is_my_host(jlib:nameprep(Realm)); + not mod_sip:is_my_host(jid:nameprep(Realm)); (_) -> true end, Hdrs2), Req#sip{hdrs = Hdrs3}. safe_nodeprep(S) -> - case jlib:nodeprep(S) of + case jid:nodeprep(S) of error -> S; S1 -> S1 end. safe_nameprep(S) -> - case jlib:nameprep(S) of + case jid:nameprep(S) of error -> S; S1 -> S1 end. diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl index f6b3103b78a..4bc68f60715 100644 --- a/src/mod_sip_registrar.erl +++ b/src/mod_sip_registrar.erl @@ -65,8 +65,8 @@ start_link() -> request(#sip{hdrs = Hdrs} = Req, SIPSock) -> {_, #uri{user = U, host = S}, _} = esip:get_hdr('to', Hdrs), - LUser = jlib:nodeprep(U), - LServer = jlib:nameprep(S), + LUser = jid:nodeprep(U), + LServer = jid:nameprep(S), {PeerIP, _} = SIPSock#sip_socket.peer, US = {LUser, LServer}, CallID = esip:get_hdr('call-id', Hdrs), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index ed6bff11fb0..f82a0625b1a 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -261,7 +261,7 @@ set_vcard(User, LServer, VCARD) -> <<"">> -> EMail2; _ -> EMail1 end, - LUser = jlib:nodeprep(User), + LUser = jid:nodeprep(User), LFN = string2lower(FN), LFamily = string2lower(Family), LGiven = string2lower(Given), @@ -404,7 +404,7 @@ string2lower(String) -> [{xmlcdata, <<(translate:translate(Lang, <<"Search users in ">>))/binary, - (jlib:jid_to_string(JID))/binary>>}]}, + (jid:to_string(JID))/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, @@ -607,7 +607,7 @@ search_result(Lang, JID, ServerHost, Data) -> [{xmlcdata, <<(translate:translate(Lang, <<"Search Results for ">>))/binary, - (jlib:jid_to_string(JID))/binary>>}]}, + (jid:to_string(JID))/binary>>}]}, #xmlel{name = <<"reported">>, attrs = [], children = [?TLFIELD(<<"text-single">>, <<"Jabber ID">>, @@ -916,8 +916,8 @@ reindex_vcards() -> mnesia:transaction(F). remove_user(User, Server) -> - LUser = jlib:nodeprep(User), - LServer = jlib:nameprep(Server), + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), remove_user(LUser, LServer, gen_mod:db_type(LServer, ?MODULE)). diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 3f6b41a70b9..92105fdb918 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -422,7 +422,7 @@ ldap_attribute_to_vcard(_, _) -> none. [{xmlcdata, <<(translate:translate(Lang, <<"Search users in ">>))/binary, - (jlib:jid_to_string(JID))/binary>>}]}, + (jid:to_string(JID))/binary>>}]}, #xmlel{name = <<"instructions">>, attrs = [], children = [{xmlcdata, @@ -600,7 +600,7 @@ search_result(Lang, JID, State, Data) -> [{xmlcdata, <<(translate:translate(Lang, <<"Search Results for ">>))/binary, - (jlib:jid_to_string(JID))/binary>>}]}, + (jid:to_string(JID))/binary>>}]}, #xmlel{name = <<"reported">>, attrs = [], children = [?TLFIELD(<<"text-single">>, <<"Jabber ID">>, diff --git a/src/node_flat.erl b/src/node_flat.erl index 6388dfc5a63..a003642f888 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -116,7 +116,7 @@ features() -> %% checked. This parameter depends on the value of the %% access_createnode ACL value in ejabberd config file.

    create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> - LOwner = jlib:jid_tolower(Owner), + LOwner = jid:tolower(Owner), Allowed = case LOwner of {<<"">>, Host, <<"">>} -> true; % pubsub service always allowed @@ -126,7 +126,7 @@ create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> {result, Allowed}. create_node(Nidx, Owner) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + OwnerKey = jid:tolower(jid:remove_resource(Owner)), set_state(#pubsub_state{stateid = {OwnerKey, Nidx}, affiliation = owner}), {result, {default, broadcast}}. @@ -178,9 +178,9 @@ delete_node(Nodes) -> %%

    In the default plugin module, the record is unchanged.

    subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + SubKey = jid:tolower(Subscriber), + GenKey = jid:remove_resource(SubKey), + Authorized = jid:tolower(jid:remove_resource(Sender)) == GenKey, GenState = get_state(Nidx, GenKey), SubState = case SubKey of GenKey -> GenState; @@ -238,9 +238,9 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, %% @doc

    Unsubscribe the Subscriber from the Node.

    unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + SubKey = jid:tolower(Subscriber), + GenKey = jid:remove_resource(SubKey), + Authorized = jid:tolower(jid:remove_resource(Sender)) == GenKey, GenState = get_state(Nidx, GenKey), SubState = case SubKey of GenKey -> GenState; @@ -340,8 +340,8 @@ delete_subscriptions(SubKey, Nidx, Subscriptions, SubState) -> %%

    %%

    In the default plugin module, the record is unchanged.

    publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Publisher), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), SubState = case SubKey of GenKey -> GenState; @@ -406,8 +406,8 @@ remove_extra_items(Nidx, MaxItems, ItemIds) -> %%

    Default plugin: The user performing the deletion must be the node owner %% or a publisher, or PublishModel being open.

    delete_item(Nidx, Publisher, PublishModel, ItemId) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Publisher), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), #pubsub_state{affiliation = Affiliation, items = Items} = GenState, Allowed = Affiliation == publisher orelse @@ -451,8 +451,8 @@ delete_item(Nidx, Publisher, PublishModel, ItemId) -> end. purge_node(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), case GenState of #pubsub_state{affiliation = owner} -> @@ -478,8 +478,8 @@ purge_node(Nidx, Owner) -> %% that will be added to the affiliation stored in the main %% pubsub_state table.

    get_entity_affiliations(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), NodeTree = mod_pubsub:tree(Host), Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> @@ -497,14 +497,14 @@ get_node_affiliations(Nidx) -> {result, lists:map(Tr, States)}. get_affiliation(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), #pubsub_state{affiliation = Affiliation} = get_state(Nidx, GenKey), {result, Affiliation}. set_affiliation(Nidx, Owner, Affiliation) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), case {Affiliation, GenState#pubsub_state.subscriptions} of {none, []} -> del_state(Nidx, GenKey); @@ -519,8 +519,8 @@ set_affiliation(Nidx, Owner, Affiliation) -> %% that will be added to the affiliation stored in the main %% pubsub_state table.

    get_entity_subscriptions(Host, Owner) -> - {U, D, _} = SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + {U, D, _} = SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), States = case SubKey of GenKey -> mnesia:match_object(#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); @@ -562,12 +562,12 @@ get_node_subscriptions(Nidx) -> {result, lists:flatmap(Tr, States)}. get_subscriptions(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), + SubKey = jid:tolower(Owner), SubState = get_state(Nidx, SubKey), {result, SubState#pubsub_state.subscriptions}. set_subscriptions(Nidx, Owner, Subscription, SubId) -> - SubKey = jlib:jid_tolower(Owner), + SubKey = jid:tolower(Owner), SubState = get_state(Nidx, SubKey), case {SubId, SubState#pubsub_state.subscriptions} of {_, []} -> @@ -620,7 +620,7 @@ unsub_with_subid(Nidx, SubId, #pubsub_state{stateid = {Entity, _}} = SubState) - %% @doc

    Returns a list of Owner's nodes on Host with pending %% subscriptions.

    get_pending_nodes(Host, Owner) -> - GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), + GenKey = jid:remove_resource(jid:tolower(Owner)), States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, affiliation = owner, _ = '_'}), @@ -702,8 +702,8 @@ get_items(Nidx, _From, _RSM) -> {result, {lists:reverse(lists:keysort(#pubsub_item.modification, Items)), none}}. get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(JID), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), SubState = get_state(Nidx, SubKey), Affiliation = GenState#pubsub_state.affiliation, @@ -746,8 +746,8 @@ get_item(Nidx, ItemId) -> end. get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(JID), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), Affiliation = GenState#pubsub_state.affiliation, Subscriptions = GenState#pubsub_state.subscriptions, diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 68492cdc43d..37e3282a96a 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -73,7 +73,7 @@ create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). create_node(Nidx, Owner) -> - {_U, _S, _R} = OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + {_U, _S, _R} = OwnerKey = jid:tolower(jid:remove_resource(Owner)), State = #pubsub_state{stateid = {OwnerKey, Nidx}, affiliation = owner}, catch ejabberd_odbc:sql_query_t([<<"insert into pubsub_state(nodeid, jid, affiliation, subscriptions) " "values(">>, state_to_raw(Nidx, State), <<");">>]), @@ -96,9 +96,9 @@ delete_node(Nodes) -> subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, PresenceSubscription, RosterGroup, Options) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + SubKey = jid:tolower(Subscriber), + GenKey = jid:remove_resource(SubKey), + Authorized = jid:tolower(jid:remove_resource(Sender)) == GenKey, {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), Whitelisted = lists:member(Affiliation, [member, publisher, owner]), PendingSubscription = lists:any(fun @@ -145,9 +145,9 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, end. unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> - SubKey = jlib:jid_tolower(Subscriber), - GenKey = jlib:jid_remove_resource(SubKey), - Authorized = jlib:jid_tolower(jlib:jid_remove_resource(Sender)) == GenKey, + SubKey = jid:tolower(Subscriber), + GenKey = jid:remove_resource(SubKey), + Authorized = jid:tolower(jid:remove_resource(Sender)) == GenKey, {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, SubKey), SubIdExists = case SubId of <<>> -> false; @@ -207,8 +207,8 @@ delete_subscription(SubKey, Nidx, {Subscription, SubId}, Affiliation, Subscripti end. publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Publisher), + GenKey = jid:remove_resource(SubKey), {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), Subscribed = case PublishModel of subscribers -> node_flat:is_subscribed(Subscriptions); @@ -245,8 +245,8 @@ remove_extra_items(Nidx, MaxItems, ItemIds) -> {result, {NewItems, OldItems}}. delete_item(Nidx, Publisher, PublishModel, ItemId) -> - SubKey = jlib:jid_tolower(Publisher), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Publisher), + GenKey = jid:remove_resource(SubKey), {result, Affiliation} = get_affiliation(Nidx, GenKey), Allowed = Affiliation == publisher orelse Affiliation == owner orelse @@ -265,8 +265,8 @@ delete_item(Nidx, Publisher, PublishModel, ItemId) -> end. purge_node(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), GenState = get_state(Nidx, GenKey), case GenState of #pubsub_state{affiliation = owner} -> @@ -282,8 +282,8 @@ purge_node(Nidx, Owner) -> end. get_entity_affiliations(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), H = encode_host(Host), J = encode_jid(GenKey), Reply = case catch @@ -312,8 +312,8 @@ get_node_affiliations(Nidx) -> {result, Reply}. get_affiliation(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), J = encode_jid(GenKey), Reply = case catch ejabberd_odbc:sql_query_t([<<"select affiliation from pubsub_state " @@ -327,8 +327,8 @@ get_affiliation(Nidx, Owner) -> {result, Reply}. set_affiliation(Nidx, Owner, Affiliation) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), {_, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey), case {Affiliation, Subscriptions} of {none, []} -> del_state(Nidx, GenKey); @@ -336,8 +336,8 @@ set_affiliation(Nidx, Owner, Affiliation) -> end. get_entity_subscriptions(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), H = encode_host(Host), SJ = encode_jid(SubKey), GJ = encode_jid(GenKey), @@ -385,8 +385,8 @@ get_entity_subscriptions(Host, Owner) -> } ). get_entity_subscriptions_for_send_last(Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), H = encode_host(Host), SJ = encode_jid(SubKey), GJ = encode_jid(GenKey), @@ -449,7 +449,7 @@ get_node_subscriptions(Nidx) -> {result, Reply}. get_subscriptions(Nidx, Owner) -> - SubKey = jlib:jid_tolower(Owner), + SubKey = jid:tolower(Owner), J = encode_jid(SubKey), Reply = case catch ejabberd_odbc:sql_query_t([<<"select subscriptions from pubsub_state where " @@ -463,7 +463,7 @@ get_subscriptions(Nidx, Owner) -> {result, Reply}. set_subscriptions(Nidx, Owner, Subscription, SubId) -> - SubKey = jlib:jid_tolower(Owner), + SubKey = jid:tolower(Owner), SubState = get_state_without_itemids(Nidx, SubKey), case {SubId, SubState#pubsub_state.subscriptions} of {_, []} -> @@ -514,7 +514,7 @@ unsub_with_subid(Nidx, SubId, SubState) -> end. get_pending_nodes(Host, Owner) -> - GenKey = jlib:jid_remove_resource(jlib:jid_tolower(Owner)), + GenKey = jid:remove_resource(jid:tolower(Owner)), States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, affiliation = owner, _ = '_'}), Nidxxs = [Nidx || #pubsub_state{stateid = {_, Nidx}} <- States], @@ -719,8 +719,8 @@ get_items(Nidx, _From, end. get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId, RSM) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(JID), + GenKey = jid:remove_resource(SubKey), {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), Whitelisted = node_flat:can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> @@ -777,8 +777,8 @@ get_item(Nidx, ItemId) -> end. get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, _SubId) -> - SubKey = jlib:jid_tolower(JID), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(JID), + GenKey = jid:remove_resource(SubKey), {Affiliation, Subscriptions} = select_affiliation_subscriptions(Nidx, GenKey, SubKey), Whitelisted = node_flat:can_fetch_item(Affiliation, Subscriptions), if %%SubId == "", ?? -> @@ -939,7 +939,7 @@ update_subscription(Nidx, JID, Subscription) -> -> ljid() ). decode_jid(SJID) -> - jlib:jid_tolower(jlib:string_to_jid(SJID)). + jid:tolower(jid:from_string(SJID)). -spec(decode_affiliation/1 :: ( Arg :: binary()) @@ -979,7 +979,7 @@ decode_subscriptions(Subscriptions) -> -> binary() ). encode_jid(JID) -> - ejabberd_odbc:escape(jlib:jid_to_string(JID)). + ejabberd_odbc:escape(jid:to_string(JID)). -spec(encode_host/1 :: ( Host :: host()) diff --git a/src/node_hometree.erl b/src/node_hometree.erl index e291887f14f..da29116aa1b 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -69,7 +69,7 @@ features() -> %%

    This function also check that node can be created as a children of its %% parent node

    create_node_permission(Host, ServerHost, Node, _ParentNode, Owner, Access) -> - LOwner = jlib:jid_tolower(Owner), + LOwner = jid:tolower(Owner), {User, Server, _Resource} = LOwner, Allowed = case LOwner of {<<"">>, Host, <<"">>} -> diff --git a/src/node_pep.erl b/src/node_pep.erl index 15877b07331..972a7386670 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -94,7 +94,7 @@ features() -> <<"subscribe">>]. create_node_permission(Host, ServerHost, _Node, _ParentNode, Owner, Access) -> - LOwner = jlib:jid_tolower(Owner), + LOwner = jid:tolower(Owner), {User, Server, _Resource} = LOwner, Allowed = case LOwner of {<<"">>, Host, <<"">>} -> @@ -143,9 +143,9 @@ purge_node(Nidx, Owner) -> node_flat:purge_node(Nidx, Owner). get_entity_affiliations(Host, Owner) -> - {_, D, _} = SubKey = jlib:jid_tolower(Owner), - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + {_, D, _} = SubKey = jid:tolower(Owner), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), States = mnesia:match_object(#pubsub_state{stateid = {GenKey, '_'}, _ = '_'}), NodeTree = mod_pubsub:tree(Host), Reply = lists:foldl(fun (#pubsub_state{stateid = {_, N}, affiliation = A}, Acc) -> @@ -168,8 +168,8 @@ set_affiliation(Nidx, Owner, Affiliation) -> node_flat:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(Host, Owner) -> - {U, D, _} = SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + {U, D, _} = SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), States = case SubKey of GenKey -> mnesia:match_object(#pubsub_state{stateid = {{U, D, '_'}, '_'}, _ = '_'}); diff --git a/src/node_pep_odbc.erl b/src/node_pep_odbc.erl index 8df25c9b1e0..a15b548d537 100644 --- a/src/node_pep_odbc.erl +++ b/src/node_pep_odbc.erl @@ -100,7 +100,7 @@ purge_node(Nidx, Owner) -> node_flat_odbc:purge_node(Nidx, Owner). get_entity_affiliations(_Host, Owner) -> - OwnerKey = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + OwnerKey = jid:tolower(jid:remove_resource(Owner)), node_flat_odbc:get_entity_affiliations(OwnerKey, Owner). get_node_affiliations(Nidx) -> @@ -113,8 +113,8 @@ set_affiliation(Nidx, Owner, Affiliation) -> node_flat_odbc:set_affiliation(Nidx, Owner, Affiliation). get_entity_subscriptions(_Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), Host = node_flat_odbc:encode_host(element(2, SubKey)), SJ = node_flat_odbc:encode_jid(SubKey), GJ = node_flat_odbc:encode_jid(GenKey), @@ -148,8 +148,8 @@ get_entity_subscriptions(_Host, Owner) -> {result, Reply}. get_entity_subscriptions_for_send_last(_Host, Owner) -> - SubKey = jlib:jid_tolower(Owner), - GenKey = jlib:jid_remove_resource(SubKey), + SubKey = jid:tolower(Owner), + GenKey = jid:remove_resource(SubKey), Host = node_flat_odbc:encode_host(element(2, SubKey)), SJ = node_flat_odbc:encode_jid(SubKey), GJ = node_flat_odbc:encode_jid(GenKey), diff --git a/src/nodetree_dag.erl b/src/nodetree_dag.erl index b2d4fade06a..6ca7802395f 100644 --- a/src/nodetree_dag.erl +++ b/src/nodetree_dag.erl @@ -51,7 +51,7 @@ set_node(#pubsub_node{nodeid = {Key, _}, owners = Owners, options = Options} = N end. create_node(Key, Node, Type, Owner, Options, Parents) -> - OwnerJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + OwnerJID = jid:tolower(jid:remove_resource(Owner)), case find_node(Key, Node) of false -> Nidx = pubsub_index:new(node), diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl index e34eabf307a..b45d82cca82 100644 --- a/src/nodetree_tree.erl +++ b/src/nodetree_tree.erl @@ -148,7 +148,7 @@ get_subnodes_tree(Host, Node) -> end. create_node(Host, Node, Type, Owner, Options, Parents) -> - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + BJID = jid:tolower(jid:remove_resource(Owner)), case catch mnesia:read({pubsub_node, {Host, Node}}) of [] -> ParentExists = case Host of diff --git a/src/nodetree_tree_odbc.erl b/src/nodetree_tree_odbc.erl index 038dc472cdc..e28ea71ae35 100644 --- a/src/nodetree_tree_odbc.erl +++ b/src/nodetree_tree_odbc.erl @@ -211,7 +211,7 @@ get_subnodes_tree(Host, Node) -> end. create_node(Host, Node, Type, Owner, Options, Parents) -> - BJID = jlib:jid_tolower(jlib:jid_remove_resource(Owner)), + BJID = jid:tolower(jid:remove_resource(Owner)), case nodeidx(Host, Node) of {error, ?ERR_ITEM_NOT_FOUND} -> ParentExists = case Host of diff --git a/src/scram.erl b/src/scram.erl index 3069be4666c..b9605375489 100644 --- a/src/scram.erl +++ b/src/scram.erl @@ -36,7 +36,7 @@ -spec salted_password(binary(), binary(), non_neg_integer()) -> binary(). salted_password(Password, Salt, IterationCount) -> - hi(jlib:resourceprep(Password), Salt, IterationCount). + hi(jid:resourceprep(Password), Salt, IterationCount). -spec client_key(binary()) -> binary(). From 87fb5132be7436c6d78ba989e977e36bd04abc6c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 24 Nov 2015 20:24:43 +0300 Subject: [PATCH 366/695] Make JID related functions from jlib.erl deprecated --- rebar.config.script | 2 +- src/jlib.erl | 12 ++++++++++++ tools/xmpp_codec.erl | 6 +++--- tools/xmpp_codec.spec | 6 +++--- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index 9e213b86364..dd005d455fd 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -187,7 +187,7 @@ Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++ ++ TestConfig ++ "-include " ++ filename:join([Cwd, "tools"])}, {xref_warnings, false}, - {xref_checks, []}, + {xref_checks, [deprecated_function_calls]}, {xref_queries, [{"(XC - UC) || (XU - X - B - " ++ string:join(CfgXrefs, " - ") ++ ")", []}]}, diff --git a/src/jlib.erl b/src/jlib.erl index 711c432e603..edeb6cd0189 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -62,6 +62,18 @@ nameprep/1, resourceprep/1, jid_tolower/1, jid_remove_resource/1, jid_replace_resource/2]). +-deprecated([{make_jid, '_'}, + {split_jid, 1}, + {string_to_jid, 1}, + {jid_to_string, 1}, + {is_nodename, 1}, + {nodeprep, 1}, + {nameprep, 1}, + {resourceprep, 1}, + {jid_tolower, 1}, + {jid_remove_resource, 1}, + {jid_replace_resource, 2}]). + -include("ejabberd.hrl"). -include("jlib.hrl"). diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 987eb7c4135..3adceabc4d4 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -2533,15 +2533,15 @@ dec_bool(<<"true">>) -> true; dec_bool(<<"1">>) -> true. resourceprep(R) -> - case jlib:resourceprep(R) of + case jid:resourceprep(R) of error -> erlang:error(badarg); R1 -> R1 end. -enc_jid(J) -> jlib:jid_to_string(J). +enc_jid(J) -> jid:to_string(J). dec_jid(Val) -> - case jlib:string_to_jid(Val) of + case jid:from_string(Val) of error -> erlang:error(badarg); J -> J end. diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 38508ce6c42..8d087c8b637 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2421,7 +2421,7 @@ enc_utc(Val) -> jlib:now_to_utc_string(Val). dec_jid(Val) -> - case jlib:string_to_jid(Val) of + case jid:from_string(Val) of error -> erlang:error(badarg); J -> @@ -2429,10 +2429,10 @@ dec_jid(Val) -> end. enc_jid(J) -> - jlib:jid_to_string(J). + jid:to_string(J). resourceprep(R) -> - case jlib:resourceprep(R) of + case jid:resourceprep(R) of error -> erlang:error(badarg); R1 -> From fee2530b1c2571a2c24e109d7c142889764eca9f Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 25 Nov 2015 00:05:24 +0100 Subject: [PATCH 367/695] Always use occupant JID as 'from' for room subject When sending the room subject to a new participant, always use the occupant JID that corresponds to the subject author as the 'from' address. It was already done this way when the subject was sent as part of the room history. --- src/mod_muc_room.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index aca32738a45..bc712b359af 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2475,14 +2475,15 @@ send_history(JID, Shift, StateData) -> lqueue_to_list(StateData#state.history))). send_subject(_JID, #state{subject_author = <<"">>}) -> ok; -send_subject(JID, StateData) -> +send_subject(JID, #state{subject_author = Nick} = StateData) -> Subject = StateData#state.subject, Packet = #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"groupchat">>}], children = [#xmlel{name = <<"subject">>, attrs = [], children = [{xmlcdata, Subject}]}]}, - ejabberd_router:route(StateData#state.jid, JID, Packet). + ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), JID, + Packet). check_subject(Packet) -> case xml:get_subtag(Packet, <<"subject">>) of From 44f5e411c52c89b7d544eefa7ced637a56e9648d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 25 Nov 2015 08:58:22 +0100 Subject: [PATCH 368/695] mod_offline: Support discarding chat states XEP-0160 says that standalone chat state notifications should not be stored offline. By default, mod_offline discards them now. Closes #842. --- src/jlib.erl | 21 +++++++++++++++++++++ src/mod_client_state.erl | 18 ++++-------------- src/mod_offline.erl | 12 +++++++++--- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index edeb6cd0189..321781216a4 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -43,6 +43,7 @@ get_iq_namespace/1, iq_query_info/1, iq_query_or_response_info/1, is_iq_request_type/1, iq_to_xml/1, parse_xdata_submit/1, + is_standalone_chat_state/1, add_delay_info/3, add_delay_info/4, timestamp_to_iso/1, timestamp_to_iso/2, now_to_utc_string/1, now_to_local_string/1, @@ -527,6 +528,26 @@ rsm_encode_count(Count, Arr) -> children = [{xmlcdata, i2l(Count)}]} | Arr]. +-spec is_standalone_chat_state(xmlel()) -> boolean(). + +is_standalone_chat_state(#xmlel{name = <<"message">>} = El) -> + ChatStates = [<<"active">>, <<"inactive">>, <<"gone">>, <<"composing">>, + <<"paused">>], + Stripped = + lists:foldl(fun(ChatState, AccEl) -> + xml:remove_subtags(AccEl, ChatState, + {<<"xmlns">>, ?NS_CHATSTATES}) + end, El, ChatStates), + case Stripped of + #xmlel{children = [#xmlel{name = <<"thread">>}]} -> + true; + #xmlel{children = []} -> + true; + _ -> + false + end; +is_standalone_chat_state(_El) -> false. + -spec add_delay_info(xmlel(), jid() | ljid() | binary(), erlang:timestamp()) -> xmlel(). diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 4934db3bc2c..e89ec6883d0 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -91,22 +91,12 @@ filter_presence(_Action, #xmlel{name = <<"presence">>, attrs = Attrs}) -> filter_presence(Action, _Stanza) -> Action. filter_chat_states(_Action, #xmlel{name = <<"message">>} = Stanza) -> - %% All XEP-0085 chat states except for : - ChatStates = [<<"active">>, <<"inactive">>, <<"composing">>, <<"paused">>], - Stripped = - lists:foldl(fun(ChatState, AccStanza) -> - xml:remove_subtags(AccStanza, ChatState, - {<<"xmlns">>, ?NS_CHATSTATES}) - end, Stanza, ChatStates), - case Stripped of - #xmlel{children = [#xmlel{name = <<"thread">>}]} -> + case jlib:is_standalone_chat_state(Stanza) of + true -> ?DEBUG("Got standalone chat state notification", []), {stop, drop}; - #xmlel{children = []} -> - ?DEBUG("Got standalone chat state notification", []), - {stop, drop}; - _ -> - ?DEBUG("Got message with chat state notification", []), + false -> + ?DEBUG("Got message stanza", []), {stop, send} end; filter_chat_states(Action, _Stanza) -> Action. diff --git a/src/mod_offline.erl b/src/mod_offline.erl index a9f8237072d..c41770d3201 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -286,10 +286,14 @@ need_to_store(LServer, Packet) -> and (Type /= <<"headline">>) -> case gen_mod:get_module_opt( LServer, ?MODULE, store_empty_body, - fun(V) when is_boolean(V) -> V end, - true) of + fun(V) when is_boolean(V) -> V; + (unless_chat_state) -> unless_chat_state + end, + unless_chat_state) of false -> xml:get_subtag(Packet, <<"body">>) /= false; + unless_chat_state -> + not jlib:is_standalone_chat_state(Packet); true -> true end; @@ -1129,6 +1133,8 @@ mod_opt_type(access_max_user_messages) -> fun (A) -> A end; mod_opt_type(db_type) -> fun gen_mod:v_db/1; mod_opt_type(store_empty_body) -> - fun (V) when is_boolean(V) -> V end; + fun (V) when is_boolean(V) -> V; + (unless_chat_state) -> unless_chat_state + end; mod_opt_type(_) -> [access_max_user_messages, db_type, store_empty_body]. From 9cc5a5d467ed7f4fc2dba33f454dedb49de9d21d Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sat, 28 Nov 2015 17:38:10 +0300 Subject: [PATCH 369/695] Simplify external components configuration --- src/ejabberd_service.erl | 103 +++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index 9d9f0294e46..f80675c8ef0 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -53,8 +53,8 @@ {socket :: ejabberd_socket:socket_state(), sockmod = ejabberd_socket :: ejabberd_socket | ejabberd_frontend_socket, streamid = <<"">> :: binary(), - hosts = [] :: [binary()], - password = <<"">> :: binary(), + host_opts = dict:new() :: ?TDICT, + host = <<"">> :: binary(), access :: atom(), check_from = true :: boolean()}). @@ -126,18 +126,21 @@ init([{SockMod, Socket}, Opts]) -> {value, {_, A}} -> A; _ -> all end, - %% This should be improved probably - {Hosts, HostOpts} = case lists:keyfind(hosts, 1, Opts) of - {_, HOpts} -> - {[H || {H, _} <- HOpts], - lists:flatten( - [O || {_, O} <- HOpts])}; - _ -> - {[], []} - end, - Password = gen_mod:get_opt(password, HostOpts, - fun iolist_to_binary/1, - p1_sha:sha(crypto:rand_bytes(20))), + HostOpts = case lists:keyfind(hosts, 1, Opts) of + {hosts, HOpts} -> + lists:foldl( + fun({H, Os}, D) -> + P = proplists:get_value( + password, Os, + p1_sha:sha(crypto:rand_bytes(20))), + dict:store(H, P, D) + end, dict:new(), HOpts); + false -> + Pass = proplists:get_value( + password, Opts, + p1_sha:sha(crypto:rand_bytes(20))), + dict:from_list([{global, Pass}]) + end, Shaper = case lists:keysearch(shaper_rule, 1, Opts) of {value, {_, S}} -> S; _ -> none @@ -151,7 +154,7 @@ init([{SockMod, Socket}, Opts]) -> SockMod:change_shaper(Socket, Shaper), {ok, wait_for_stream, #state{socket = Socket, sockmod = SockMod, - streamid = new_id(), hosts = Hosts, password = Password, + streamid = new_id(), host_opts = HostOpts, access = Access, check_from = CheckFrom}}. %%---------------------------------------------------------------------- @@ -166,10 +169,33 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, case xml:get_attr_s(<<"xmlns">>, Attrs) of <<"jabber:component:accept">> -> To = xml:get_attr_s(<<"to">>, Attrs), - Header = io_lib:format(?STREAM_HEADER, - [StateData#state.streamid, xml:crypt(To)]), - send_text(StateData, Header), - {next_state, wait_for_handshake, StateData}; + Host = jid:nameprep(To), + if Host == error -> + Header = io_lib:format(?STREAM_HEADER, + [<<"none">>, ?MYNAME]), + send_text(StateData, + <<(list_to_binary(Header))/binary, + (?INVALID_XML_ERR)/binary, + (?STREAM_TRAILER)/binary>>), + {stop, normal, StateData}; + true -> + Header = io_lib:format(?STREAM_HEADER, + [StateData#state.streamid, xml:crypt(To)]), + send_text(StateData, Header), + HostOpts = case dict:is_key(Host, StateData#state.host_opts) of + true -> + StateData#state.host_opts; + false -> + case dict:find(global, StateData#state.host_opts) of + {ok, GlobalPass} -> + dict:from_list([{Host, GlobalPass}]); + error -> + StateData#state.host_opts + end + end, + {next_state, wait_for_handshake, + StateData#state{host = Host, host_opts = HostOpts}} + end; _ -> send_text(StateData, ?INVALID_HEADER_ERR), {stop, normal, StateData} @@ -188,21 +214,26 @@ wait_for_handshake({xmlstreamelement, El}, StateData) -> #xmlel{name = Name, children = Els} = El, case {Name, xml:get_cdata(Els)} of {<<"handshake">>, Digest} -> - case p1_sha:sha(<<(StateData#state.streamid)/binary, - (StateData#state.password)/binary>>) - of - Digest -> - send_text(StateData, <<"">>), - lists:foreach(fun (H) -> - ejabberd_router:register_route(H), - ?INFO_MSG("Route registered for service ~p~n", - [H]) - end, - StateData#state.hosts), - {next_state, stream_established, StateData}; - _ -> - send_text(StateData, ?INVALID_HANDSHAKE_ERR), - {stop, normal, StateData} + case dict:find(StateData#state.host, StateData#state.host_opts) of + {ok, Password} -> + case p1_sha:sha(<<(StateData#state.streamid)/binary, + Password/binary>>) of + Digest -> + send_text(StateData, <<"">>), + lists:foreach( + fun (H) -> + ejabberd_router:register_route(H), + ?INFO_MSG("Route registered for service ~p~n", + [H]) + end, dict:fetch_keys(StateData#state.host_opts)), + {next_state, stream_established, StateData}; + _ -> + send_text(StateData, ?INVALID_HANDSHAKE_ERR), + {stop, normal, StateData} + end; + _ -> + send_text(StateData, ?INVALID_HANDSHAKE_ERR), + {stop, normal, StateData} end; _ -> {next_state, wait_for_handshake, StateData} end; @@ -231,7 +262,7 @@ stream_established({xmlstreamelement, El}, StateData) -> FromJID1 = jid:from_string(From), case FromJID1 of #jid{lserver = Server} -> - case lists:member(Server, StateData#state.hosts) of + case dict:is_key(Server, StateData#state.host_opts) of true -> FromJID1; false -> error end; @@ -349,7 +380,7 @@ terminate(Reason, StateName, StateData) -> lists:foreach(fun (H) -> ejabberd_router:unregister_route(H) end, - StateData#state.hosts); + dict:fetch_keys(StateData#state.host_opts)); _ -> ok end, (StateData#state.sockmod):close(StateData#state.socket), From 9eeee67da71d4dfba99fefb2389d2f3647516891 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 30 Nov 2015 11:35:53 +0100 Subject: [PATCH 370/695] Webadmin console visual refresh (thanks to Marek Foss) (EJAB-1142) --- src/ejabberd_web_admin.erl | 480 +++++++++++++++++++++---------------- src/mod_muc_log.erl | 2 +- 2 files changed, 273 insertions(+), 209 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 4dc157f882f..ba6dfa112ab 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -343,7 +343,7 @@ make_xhtml(Els, Host, Node, Lang, JID) -> [?XE(<<"p">>, [?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>), ?C(<<" (c) 2002-2015 ">>), - ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne">>)] + ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne, leader in messaging and push solutions">>)] )])])])]}}. direction(ltr) -> [{<<"dir">>, <<"ltr">>}]; @@ -376,217 +376,281 @@ additions_js() -> css(Host) -> Base = get_base_path(Host, cluster), - <<"\nhtml,body {\n background: white;\n " - " margin: 0;\n padding: 0;\n height: " - "100%;\n}\n\n#container {\n padding: " - "0;\n margin: 0;\n min-height: 100%;\n " - " height: 100%;\n margin-bottom: -30px;\n}\n\n" - "html>body #container {\n height: auto;\n}\n\n" - "#header h1 {\n width: 100%;\n height: " - "55px;\n padding: 0;\n margin: 0;\n " - " background: transparent url(\"", - Base/binary, - "logo-fill.png\");\n}\n\n#header h1 a " - "{\n position: absolute;\n top: 0;\n " - " left: 0;\n width: 100%;\n height: " - "55px;\n padding: 0;\n margin: 0;\n " - " background: transparent url(\"", - Base/binary, - "logo.png\") no-repeat;\n display: block;\n " - " text-indent: -700em;\n}\n\n#clearcopyright " - "{\n display: block;\n width: 100%;\n " - " height: 30px;\n}\n\n#copyrightouter " - "{\n display: table;\n width: 100%;\n " - " height: 30px;\n}\n\n#copyright {\n " - " display: table-cell;\n vertical-align: " - "bottom;\n width: 100%;\n height: 30px;\n}\n\n" - "#copyright p {\n margin-left: 0;\n " - " margin-right: 0;\n margin-top: 5px;\n " - " margin-bottom: 0;\n padding-left: " - "0;\n padding-right: 0;\n padding-top: " - "1px;\n padding-bottom: 1px;\n width: " - "100%;\n color: #ffffff;\n background-color: " - "#fe8a00;\n font-family: Verdana, Arial, " - "Helvetica, sans-serif; \n font-size: " - "7pt;\n font-weight: bold;\n text-align: " - "center;\n}\n\n#navigation ul {\n position: " - "absolute;\n top: 65px;\n left: 0;\n " - " padding: 0 1px 1px 1px;\n margin: " - "0;\n font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 8pt;\n font-weigh" - "t: bold;\n border-top: 1px solid #d47911;\n " - " width: 17em;\n}\n\n#navigation ul li " - "{\n list-style: none;\n margin: 0;\n " - " text-align: left;\n display: inline;\n}\n\n" - "#navigation ul li a {\n margin: 0;\n " - " display: block;\n padding: 3px 6px " - "3px 9px;\n border-left: 1em solid #ffc78c;\n " - " border-right: 1px solid #d47911;\n " - " border-bottom: 1px solid #d47911;\n " - " background: #ffe3c9;\n text-decoration: " - "none;\n}\n\n#navigation ul li a:link " - "{\n color: #844;\n}\n\n#navigation " - "ul li a:visited {\n color: #766;\n}\n\n#navig" - "ation ul li a:hover {\n border-color: " - "#fc8800;\n color: #FFF;\n background: " - "#332;\n}\n\nul li #navhead a, ul li " - "#navheadsub a, ul li #navheadsubsub " - "a {\n text-align: center;\n border-top: " - "1px solid #d47911;\n border-bottom: " - "2px solid #d47911;\n background: #FED6A6;\n}\n\n" - "#navheadsub, #navitemsub {\n border-left: " - "7px solid white;\n margin-left: 2px;\n}\n\n#" - "navheadsubsub, #navitemsubsub {\n border-lef" - "t: 14px solid white;\n margin-left: " - "4px;\n}\n\n#lastactivity li {\n font-weight: " - "bold;\n border: 1px solid #d6760e;\n " - " background-color: #fff2e8;\n padding: " - "2px;\n margin-bottom: -1px;\n}\n\ntd.copy " - "{\n color: #ffffff;\n background-color: " - "#fe8a00;\n font-family: Verdana, Arial, " - "Helvetica, sans-serif; \n font-size: " - "7pt;\n font-weight: bold;\n text-align: " - "center;\n}\n\ninput {\n font-family: " - "Verdana, Arial, Helvetica, sans-serif; " - "\n font-size: 10pt;\n border: 1px " - "solid #d6760e;\n color: #723202;\n " - " background-color: #fff2e8;\n vertical-align" - ": middle;\n margin-bottom: 0px;\n " - "padding: 0.1em;\n}\n\ninput[type=submit] " - "{\n font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 8pt;\n font-weigh" - "t: bold;\n color: #ffffff;\n background-col" - "or: #fe8a00;\n border: 1px solid #d6760e;\n}\n\n" - "textarea {\n font-family: Verdana, " - "Arial, Helvetica, sans-serif; \n font-size: " - "10pt;\n border: 1px solid #d6760e;\n " - " color: #723202;\n background-color: " - "#fff2e8;\n}\n\nselect {\n border: 1px " - "solid #d6760e;\n color: #723202;\n " - " background-color: #fff2e8;\n vertical-align" - ": middle;\n margin-bottom: 0px; \n " - " padding: 0.1em;\n}\n\nthead {\n color: " - "#000000;\n background-color: #ffffff;\n " - " font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 10pt;\n " - "font-weight: bold;\n}\n\ntr.head {\n " - " color: #ffffff;\n background-color: " - "#3b547a;\n font-family: Verdana, Arial, " - "Helvetica, sans-serif; \n font-size: " - "9pt;\n font-weight: bold;\n text-align: " - "center;\n}\n\ntr.oddraw {\n color: " - "#412c75;\n background-color: #ccd4df;\n " - " font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 9pt;\n font-weigh" - "t: normal;\n text-align: center;\n}\n\ntr.ev" - "enraw {\n color: #412c75;\n background-colo" - "r: #dbe0e8;\n font-family: Verdana, " - "Arial, Helvetica, sans-serif; \n font-size: " - "9pt;\n font-weight: normal;\n text-align: " - "center;\n}\n\ntd.leftheader {\n color: " - "#412c75;\n background-color: #ccccc1;\n " - " font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 9pt;\n font-weigh" - "t: bold;\n padding-left: 5px;\n padding-top" - ": 2px;\n padding-bottom: 2px;\n margin-top: " - "0px;\n margin-bottom: 0px;\n}\n\ntd.leftcont" - "ent {\n color: #000044;\n background-color: " - "#e6e6df;\n font-family: Verdana, Arial, " - "Helvetica, sans-serif; \n font-size: " - "7pt;\n font-weight: normal;\n padding-left: " - "5px;\n padding-right: 5px;\n padding-top: " - "2px;\n padding-bottom: 2px;\n margin-top: " - "0px;\n margin-bottom: 0px;\n}\n\ntd.rightcon" - "tent {\n color: #000044;\n font-family: " - "Verdana, Arial, Helvetica, sans-serif; " - "\n font-size: 10pt;\n font-weight: " - "normal;\n text-align: justify;\n padding-le" - "ft: 10px;\n padding-right: 10px;\n " - " padding-bottom: 5px;\n}\n\n\nh1 {\n " - " color: #000044;\n font-family: Verdana, " - "Arial, Helvetica, sans-serif; \n font-size: " - "14pt;\n font-weight: bold;\n text-align: " - "center;\n padding-top: 2px;\n padding-botto" - "m: 2px;\n margin-top: 0px;\n margin-bottom: " - "0px;\n}\n\nh2 {\n color: #000044;\n " - " font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 12pt;\n " - "font-weight: bold;\n text-align: center;\n " - " padding-top: 2px;\n padding-bottom: " - "2px;\n margin-top: 0px;\n margin-bottom: " - "0px;\n}\n\nh3 {\n color: #000044;\n " - " font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 10pt;\n " - "font-weight: bold;\n " - " padding-top: 20px;\n padding-bottom: " - "2px;\n margin-top: 0px;\n margin-bottom: " - "0px;\n}\n\n#content a:link {\n color: " - "#990000; \n font-family: Verdana, Arial, " - "Helvetica, sans-serif; \n font-size: " - "10pt;\n font-weight: bold;\n text-decoratio" - "n: underline;\n}\n#content a:visited " - "{\n color: #990000; \n font-family: " - "Verdana, Arial, Helvetica, sans-serif; " - "\n font-size: 10pt;\n font-weight: " - "bold;\n text-decoration: underline;\n}\n#con" - "tent a:hover {\n color: #cc6600; \n " - " font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 10pt;\n " - "font-weight: bold;\n text-decoration: " - "underline;\n}\n\n\n#content ul li {\n " - " list-style-type: disc;\n font-size: " - "10pt;\n /*font-size: 7pt;*/\n padding-left: " - "10px;\n}\n\n#content ul.nolistyle>li " - "{\n list-style-type: none;\n}\n\n#content " - "li.big {\n font-size: 10pt;\n}\n\n#content " - "{\n font-family: Verdana, Arial, Helvetica, " - "sans-serif; \n font-size: 10pt;\n " - "padding-left: 17em;\n padding-top: " - "5px;\n}\n\ndiv.guidelink {\n text-align: " - "right;\n padding-right: 1em;\n}\n\ntable.wit" - "htextareas>tbody>tr>td {\n vertical-align: " - "top;\n}\n\np.result {\n border: 1px;\n " - " border-style: dashed;\n border-color: " - "#FE8A02;\n padding: 1em;\n margin-right: " - "1em;\n background: #FFE3C9;\n}\n\n*.alignrig" - "ht {\n font-size: 10pt;\n text-align: " - "right;\n}\n\n#copyright a:link {\n color: " - "#ffffff;\n text-decoration: none;\n}\n" - "#copyright a:visited {\n color: #ffffff;\n " - "text-decoration: none;\n}\n#copyright a:hover" - " {\n color: #ffffff;\n text-decoration: " - "underline;\n}\n">>. + <<"html,body {\n" + " margin: 0;\n" + " padding: 0;\n" + " height: 100%;\n" + " background: #f9f9f9;\n" + " font-family: sans-serif;\n" + "}\n" + "a {\n" + " text-decoration: none;\n" + " color: #3eaffa;\n" + "}\n" + "a:hover,\n" + "a:active {\n" + " text-decoration: underline;\n" + "}\n" + "#container {\n" + " position: relative;\n" + " padding: 0;\n" + " margin: 0 auto;\n" + " max-width: 1280px;\n" + " min-height: 100%;\n" + " height: 100%;\n" + " margin-bottom: -30px;\n" + " z-index: 1;\n" + "}\n" + "html>body #container {\n" + " height: auto;\n" + "}\n" + "#header h1 {\n" + " width: 100%;\n" + " height: 50px;\n" + " padding: 0;\n" + " margin: 0;\n" + " background-color: #49cbc1;\n" + "}\n" + "#header h1 a {\n" + " position: absolute;\n" + " top: 0;\n" + " left: 0;\n" + " width: 100%;\n" + " height: 50px;\n" + " padding: 0;\n" + " margin: 0;\n" + " background: url('",Base/binary,"logo.png') 10px center no-repeat transparent;\n" + " background-size: auto 25px;\n" + " display: block;\n" + " text-indent: -9999px;\n" + "}\n" + "#clearcopyright {\n" + " display: block;\n" + " width: 100%;\n" + " height: 30px;\n" + "}\n" + "#copyrightouter {\n" + " position: relative;\n" + " display: table;\n" + " width: 100%;\n" + " height: 30px;\n" + " z-index: 2;\n" + "}\n" + "#copyright {\n" + " display: table-cell;\n" + " vertical-align: bottom;\n" + " width: 100%;\n" + " height: 30px;\n" + "}\n" + "#copyright a {\n" + " font-weight: bold;\n" + " color: #fff;\n" + "}\n" + "#copyright p {\n" + " margin-left: 0;\n" + " margin-right: 0;\n" + " margin-top: 5px;\n" + " margin-bottom: 0;\n" + " padding-left: 0;\n" + " padding-right: 0;\n" + " padding-top: 5px;\n" + " padding-bottom: 5px;\n" + " width: 100%;\n" + " color: #fff;\n" + " background-color: #30353E;\n" + " font-size: 0.75em;\n" + " text-align: center;\n" + "}\n" + "#navigation ul {\n" + " position: absolute;\n" + " top: 75px;\n" + " left: 0;\n" + " padding: 0;\n" + " margin: 0;\n" + " width: 17em;\n" + " background: #fff;\n" + "}\n" + "#navigation ul li {\n" + " list-style: none;\n" + " margin: 0;\n" + "\n" + " border-bottom: 1px solid #f9f9f9;\n" + " text-align: left;\n" + "}\n" + "#navigation ul li a {\n" + " margin: 0;\n" + " display: inline-block;\n" + " padding: 10px;\n" + " color: #333;\n" + "}\n" + "ul li #navhead a, ul li #navheadsub a, ul li #navheadsubsub a {\n" + " font-size: 1.5em;\n" + " color: inherit;\n" + "}\n" + "#navitemsub {\n" + " border-left: 0.5em solid #424a55;\n" + "}\n" + "#navitemsubsub {\n" + " border-left: 2em solid #424a55;\n" + "}\n" + "#navheadsub,\n" + "#navheadsubsub {\n" + " padding-left: 0.5em;\n" + "}\n" + "#navhead,\n" + "#navheadsub,\n" + "#navheadsubsub {\n" + " border-top: 3px solid #49cbc1;\n" + " background: #424a55;\n" + " color: #fff;\n" + "}\n" + "#lastactivity li {\n" + " padding: 2px;\n" + " margin-bottom: -1px;\n" + "}\n" + "thead tr td {\n" + " background: #3eaffa;\n" + " color: #fff;\n" + "}\n" + "td.copy {\n" + " text-align: center;\n" + "}\n" + "tr.head {\n" + " color: #fff;\n" + " background-color: #3b547a;\n" + " text-align: center;\n" + "}\n" + "tr.oddraw {\n" + " color: #412c75;\n" + " background-color: #ccd4df;\n" + " text-align: center;\n" + "}\n" + "tr.evenraw {\n" + " color: #412c75;\n" + " background-color: #dbe0e8;\n" + " text-align: center;\n" + "}\n" + "td.leftheader {\n" + " color: #412c75;\n" + " background-color: #ccccc1;\n" + " padding-left: 5px;\n" + " padding-top: 2px;\n" + " padding-bottom: 2px;\n" + " margin-top: 0px;\n" + " margin-bottom: 0px;\n" + "}\n" + "td.leftcontent {\n" + " color: #000044;\n" + " background-color: #e6e6df;\n" + " padding-left: 5px;\n" + " padding-right: 5px;\n" + " padding-top: 2px;\n" + " padding-bottom: 2px;\n" + " margin-top: 0px;\n" + " margin-bottom: 0px;\n" + "}\n" + "td.rightcontent {\n" + " color: #000044;\n" + " text-align: justify;\n" + " padding-left: 10px;\n" + " padding-right: 10px;\n" + " padding-bottom: 5px;\n" + "}\n" + "\n" + "h1 {\n" + " color: #000044;\n" + " padding-top: 2px;\n" + " padding-bottom: 2px;\n" + " margin-top: 0px;\n" + " margin-bottom: 0px;\n" + "}\n" + "h2 {\n" + " color: #000044;\n" + " text-align: center;\n" + " padding-top: 2px;\n" + " padding-bottom: 2px;\n" + " margin-top: 0px;\n" + " margin-bottom: 0px;\n" + "}\n" + "h3 {\n" + " color: #000044;\n" + " text-align: left;\n" + " padding-top: 20px;\n" + " padding-bottom: 2px;\n" + " margin-top: 0px;\n" + " margin-bottom: 0px;\n" + "}\n" + "#content ul {\n" + " padding-left: 1.1em;\n" + " margin-top: 1em;\n" + "}\n" + "#content ul li {\n" + " list-style-type: disc;\n" + " padding: 5px;\n" + "}\n" + "#content ul.nolistyle>li {\n" + " list-style-type: none;\n" + "}\n" + "#content {\n" + " padding-left: 19em;\n" + " padding-top: 25px;\n" + "}\n" + "div.guidelink,\n" + "p[dir=ltr] {\n" + " display: inline-block;\n" + " float: right;\n" + "\n" + " margin: 0;\n" + " margin-right: 1em;\n" + "}\n" + "div.guidelink a,\n" + "p[dir=ltr] a {\n" + " display: inline-block;\n" + " border-radius: 3px;\n" + " padding: 3px;\n" + "\n" + " background: #3eaffa;\n" + "\n" + " text-transform: uppercase;\n" + " font-size: 0.75em;\n" + " color: #fff;\n" + "}\n" + "table {\n" + " margin-top: 1em;\n" + "}\n" + "table tr td {\n" + " padding: 0.5em;\n" + "}\n" + "table tr:nth-child(odd) {\n" + " background: #fff;\n" + "}\n" + "table.withtextareas>tbody>tr>td {\n" + " vertical-align: top;\n" + "}\n" + "textarea {\n" + " margin-bottom: 1em;\n" + "}\n" + "input,\n" + "select {\n" + " font-size: 1em;\n" + "}\n" + "p.result {\n" + " border: 1px;\n" + " border-style: dashed;\n" + " border-color: #FE8A02;\n" + " padding: 1em;\n" + " margin-right: 1em;\n" + " background: #FFE3C9;\n" + "}\n" + "*.alignright {\n" + " text-align: right;\n" + "}">>. favicon() -> - jlib:decode_base64(<<"AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAA" - "AEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJf+cAAI" - "PsAAGC8gAVhecAAIr8ACiR7wBBmOcAUKPsAFun8ABhqeo" - "AgLryAJLB8ACz1PcAv9r7AMvi+gAAAAAAAgICARMhICAk" - "JCQkQkFCQgICN2d2cSMgJCRevdvVQkICAlqYh5MgICQkX" - "rRCQkJCMgI7kiAjICAUFF2swkFBQRQUXazCQUFBAgI7ki" - "AgICAkJF60QkJCQgICOpiHkyAgJCRevdvlQkICAjdndnM" - "gICQkJCRCQkJCAgICARAgICAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAA">>). + jlib:decode_base64(<<"AAABAAEAEBAAAAEAIAAoBQAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAA1AwMAQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMARQUEA+oFAwCOBAQAaAQEAGkEBABpBAQAaQQEAGoFAgBcBAAAOQAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAEIHBgX/BwYF/wcGBf8HBgX/BwYF/wcGBf8HBgX/BwYF/wUFA/wEBAHOBQICXgAAAAAAAAAAAAAAAAAAAAADAwBCBwYF/wcGBf8HBgX/BwYF/wcGBf8HBgX/BwYF/wcGBf8HBgX/BwYF/wcGBf8DAwCUAAAABwAAAAAAAAAAAwMAQgcGBf8HBgX/BwYF/wcGBf8FBQPMBAAAaAQAAD8DAwNOAwMDlgUFA/QHBgX/BwYF/wQEAHkAAAAAAAAAAAMDAEIHBgX/BwYF/wcGBf8EBAGeAAAACAAAAAAAAAASAAAABQAAAAAFBQGxBwYF/wcGBf8FBAPvAAAAKAAAAAADAwBCBwYF/wcGBf8EBAHPAAAADQAAACEFBQGuBQQD8AUEAeEFBQGuBQQB9QcGBf8HBgX/BwYF/wQEAH8AAAAAAwMAQgcGBf8HBgX/BgQAbwAAAAADAwOXBQQB3gUFAdgFBQHZBQQB3QUFAdYFBAHhBQUD/gcGBf8EBAK8AAAAAAMDAEIHBgX/BwYF/wQAAD0AAAAAAAAABQAAAAEAAAABAAAAAQAAAAEAAAAFAAAAEQUFArwKBgX/BQMDxQAAAAADAwBCBwYF/wcGBf8DAwBKAAAAAwYDAFAGAwBVBgMAVAYDAFQFAgJZAAAALwAAAAAFBQGuCgYF/wUDA8QAAAAAAAAAKwUEA/QHBgX/AwMDlgAAAAAFAwOIBwYF/wcGBf8HBgX/BQQB5wAAADMAAAAWBQUD5wcGBf8EBAGbAAAAAAAAAAYFBAG9BwYF/wUFA/EDAABAAAAAAAMDA1QDAwOYBQUAhQAAACQAAAAABAQBnQcGBf8HBgX/AwMATQAAAAAAAAAAAwAAQwUFA/oHBgX/BQQB5QYDA1UAAAAAAAAAAAAAAAAAAAAXAwMAlwcGBf8HBgX/BQUBtQAAAAcAAAAAAAAAAAAAAAAEBABzBQUD/gcGBf8HBgX/BQMDyQQEAZwGBAGqBQQB5AcGBf8HBgX/BAQB0QAAACEAAAAAAAAAAAAAAAAAAAAAAAAAAAUFAmQFBAHlBwYF/wcGBf8HBgX/BwYF/wcGBf8FBQP+BQUBsAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwUFA40FBAHrBwYF/wUFA/4FAwPGBgMAUgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==">>). logo() -> - jlib:decode_base64(<<"iVBORw0KGgoAAAANSUhEUgAAAVcAAAA3CAMAAACPbPnEA" - "AAAAXNSR0IArs4c6QAAAEtQTFRFcTIA1XcE/YsA/40E/p" - "IH/JYc/5kg/54i/KIu/6U6/apE/61H/61P/bFX/7Vh/bd" - "a/rpq/L5s/8J2/cJ8/8qI/86Y/9aj/9mt/+bJ7EGiPwAA" - "AZRJREFUeNrt28lug0AQhGHajrPv+/s/aVwpDlgE0gQ3t" - "qO/DhxihMg33VJ7JmmCVKSJlVJ4bZQ93Jl/zjJv+8tzcM" - "UVV1xxLXIlRfPAZptYrbf5YeW618PWyvG8w/g9ZwquuJ6" - "Y6+bbdY0rrifhSmrmgUulVXbVDq3H39Zy6Cf9+8c7JNM/" - "mXeY8+SMRmuIK6644oprkSupmQdulLhQdup1qJKmrmWmV" - "pb5NN9LUyddu7nnLYkrrrjiimuVK6mZB+6VuFbiXJk8v/" - "bnv0PVa+Yd5tdr/x7vCfqbgPsfV1xxxRXXKldSMw+8KPG" - "gxJWyU7WZE538p0vOr/lOm/q7dPf+bOVKvVXiUcEVV1xx" - "xbXMldTMA29KPCtxp7T6XpvxE6/9nm/l987mnG9l5u/8j" - "O4Ot9uTEq8KrrjiiiuuZa6kZh74UFpli3sO61btMfyHyW" - "Gv/RMs7wB67ne32/BdwRVXXHHFtcyV1MwDn0qrbHHvyPT" - "/Dsarla/R/1GpQydYPhf0bqC/A7jz7YkrrrjiimuVK6nI" - "F5dWoNvcLcs/AAAAAElFTkSuQmCC">>). + jlib:decode_base64(<<"iVBORw0KGgoAAAANSUhEUgAAA64AAADICAYAAADoQ7yoAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AABAAElEQVR4Ae19CbgdVZVu1c0EGclMBsgNDUHRACKgQpjs0D6FqK0tCCqE9mt8HezXdjO07XvdBAdsIXwP+zUI2D4GWxB8ditBWwFBQoBWEAjYCjTk3oQMZCBzbpKb5Nb717nnhDucc24Ne+3au+rf37fuuadq1xr+tavOXnuvvSsMWIiA5whEUTQMJgytmjEYn/uCINwRhkHkuWlU3zME0BZDFLY7z/yWRl36Og1qvIYIEAEiQATKjID8dor97CuVuRWU0HY0/OGgRXvxp0m5G+cmlhAemqyMANrVNNDdTdpfG87PB8lACovHCMCH9LXH/qPqRIAIEAEikC8C+B0dBVoI2gyqV9pwUM6PyldTSicCCghUGzc+4pbOWxXUIMsSIoAWN2x7FD0ft+VV680vIVTem0xfe+9CGkAEiAARIAI5I7ALg/zJ+kzss+fsMoo3hcAazLKuS9b6e9SWK9cMN6UL+ZQPATSg2T0aVMJ/Ny0uH2L+Wkxf++s7ak4EiAARIAIOIICMs/R99k34GWaf3QEvUoW0CKAFj8WoTcayDdfzRkjrgzJfh5TguRkbHy5/g8GrB42IvvbASVSRCBABIkAE3EUgilrSB6213lal1z/WXSOpGRFohAAWcme/AWo3wvLNjcTwOBGoh0BH9xrHWgPK+LlxQT0ZPOYGAvS1G36gFkSACBABIuAvAq8lX1LVoG8lM69Bi79IUPNSIrAcmzA1aNEpD2+YV0ogaXQqBFanbGX1L5PtnJZy84FUntC/iL7Wx5gSiAARIAJEoLgIbDSSodazB7WC2WrFbS4FtAzrWqWrb7as5utKCthUNEzCA3iB2bYn3PgQ1vBVVp70dVYEeT0RIAJEgAiUHQFzGZK9el+tZceV9nuCQHsUXdmr6Zr7MssTCKhmjggoPYClFXPWNUe/1hNNX9dDhceIABEgAkSACMRDwPxsa63T3/ZYTQPmDdeQ4KerCCitCVx5oasGUy83EFiLdwBPUlPlzc+osSbjxAjQ14kh4wVEgAgQASJABHohsDUIFvU6YOzLmNOx1jUUdoON8SQjImAaAexKNi4IWk2z7ea392J8LtThTa5FQGBXEJylZ8euS8H7Zj3+5JwEAfo6CVqsWyYEMN8hu3oeXaUZ+BwNkoyRkdVP+b8n4WuwvQ/t6PF9G/5fAXoF9HIYhpvwyUIEiIDvCGAjVTwsjtMxQx5D0SFBEG5m4KqDMLmaQSDaZ4ZPHS7DMDDEQgQaI4B0lAmNz2Y+Ix1AFkcQoK8dcQTVyA0BBKhHQPhskASpspSmFqxOxP9Jy5S4F0DuRtR9uQ+9iIB2eVwerEcEiED+CCzFYJaMYCmWMeDNwFURYLJ2GoE9cgOwEIGcEBhziGzxHoZBV04KUKw1BOhra1BTUGwEEDAehsqSVfL+6ufhsS82W1EGCIVO7ckW+r2O74+AHpVPBLLynYUIEAFHEZgWBONtzIbakOEoxFSLCBABIkAEiAARIALFRwCBoCzZrwWp8nmk41ZLYC1LeoQC6P8qPipBrHwikF0nx1mIABFwA4HJQbDXhiYMXG2gTBmpEdBroEwVTu0UXkgEiAARIALOI4BgbwSU/BhINoP7Q1ALyNcigbbQn4G6YJvMxn4X9K8IYmUNLQsRIAIlQMDnh1gJ3FNyE8MwwkLUZToo7P+eDl9yJQJEgAgQASKQDwII6FpAZ4PuggYyKymfZ4OK1N8TW+aC7gS9AVu/W7W5SDbCNBYiQAT6IsCbvC8i/O4UAgcHwY06CkU/0OFLrkSACBABIkAE7CKAwO0Y0HWQKmtBHwTJLKvMuBa9iI2fBonNrwOD60HvKLrRtI8IlBUBBq5l9bwndmPHhrtkX32zZdWWMJzZbpYnuREBIkAEiAARsIsAgrSTQT+G1N+CrgRNtauBU9LE9itALwKT+0HvcUo7KkMEiEBmBBi4ZoaQDFQRCMOuziC4xKyMSNKmWIgAESACRIAIeIkAgrIzQQ9B+V+BPgwKvTRER2nBYh7oP4DRw6CzdMSQKxEgArYRYOBqG3HKS4zAhDC8oy0ItiS+sO4Fa5eE4eHP1D3Fg0SACBABIkAEHEYAQdiHQE9ARdlhV9Z5sjRHQDalegSYPQk6p3lVniUCRMB1BBi4uu4h6ldB4IggmLg+MxYrwGHqmZnZkAERIAJEgAgQAYsIIOiSDZeehcifgE6xKLooot4HQx4Ahs+B/qgoRtEOIlA2BBi4ls3jvtobhvsmY897rHddks6E9diduLUlDIMo3fW8iggQASJABIiAXQQQZE0D3QupD4LeZVd6IaUdD6t+DkzvA00vpIU0iggUGAEGrgV2bhFNGx2GZ8Cus/clM+6SMJx8PIPWZKCxNhEgAkSACOSDAIKqwaDLIf0l0Hn5aFFoqZ+Adb8HxlcI1oW2lMYRgQIhwMC1QM4siymYeH14CP7A3rMxfdroPa/tOH8ZSKregU8WIkAEiAARIALOI4BA6jQo+RxoEWik8wr7q6Bgez3oeWB+ur9mUHMiUB4EOMpUHl8XzlIJYGGUpP0E+NHpOQgT4RxTggvncRpEBIgAESguAvgdwxvgghtAFxXXSictk/e+Pgb8/wWff4X+w0YntaRSRIAIBD07+4SDCHiLAH5ounoQg1ZvPUnFiQARIALlQwBBk8yyPg9i0Jqf+z8N0cvgC86+5ucDSiYCTRFg4NoUHp4kAkSACBABIkAEiIAOAgiSQtCXwP1R0DQdKeSaAIGpqCuvz/lfIPaREwDHqkTABgK8KW2gTBlEgAgQASJABIgAEeiBAAKjSfj6M9DXQIN6nOK/+SIgvvgKSHYfnpyvKpROBIhATwQYuPZEg/8TASJABIgAESACREAZAQREZ0KEpAbznaLKWGdgP1d8BF+dlYEHLyUCRMAgAgxcDYJJVkSACBABIkAEiAARaIYAAqG/w/lfgKY0q8dzTiBwKLR4GD77e5C8zYCFCBCBHBFg4Joj+BRNBIgAESACRIAIlAMBBD7ybtbbYe2XQex/+eN28dU1oDvEh/6oTU2JQPEQ4IOzeD6lRUSACBABIkAEiIBDCCDgGQ51fgSa75BaVCUZArLj84+rvkx2JWsTASJgBAEGrkZgJBMiQASIABEgAkSACPRHAIHOOByV946f0/8sj3iGwIeg7y/g0/Ge6U11iUAhEGDgWgg30ggiQASIABEgAkTANQQQ4EyHTo+D3ueabtQnNQLvxZWPw7eHpebAC4kAEUiFAAPXVLDxIiJABIgAESACRIAINEYAgc0xOPskSD5ZioXA22HOk/DxO4plFq0hAm4jwMDVbf9QOyJABIgAESACRMAzBKoBjcy0clbOM98lUFdm05fA1+9McA2rEgEikAGBQuyOhoeGbFF+MEhe5i0PkqmgCdXv+AhmgdaAdoB2gjaAVoFWVv/fGoZhF/5nIQKlQAD3jAxaCQ1qYvBe3hdN0PH0VAPf74c5XfS3p05toDZ93QAY5cPA/XCI+DlI1rayFBsB8fHP4fNT8PxcUWxTaZ0rCKC9Sdwj1LcfJ7/l+9EWI1d0Na2Hl4ErHDYWQMwBXQD6IOgQUKYSRXtx/eAl+HMv6KeglezEAQVHC9qA7NA4H3TpviA4bnCwd0sQDAHta636cRHu6Z+EYVDKAYnqQ03uiz8AnQyS++WYbqzwX8wCPlITuAYvgJ4GPQZ6FrSW9wdQcLDAZ8Oglrwfcjbo3VWSGYFWUNPS7W+0kmBwO/48BVoK+jXoNdCWIv8Ywj7vCn3tnsvgExk0fxA0zT3t1DTqBOdtoO2gXaARoNGgUSAv+5nQO0mRyZIH4ftT8YzcmORC1m2OADCVvt500NEg+T2TiShJvR8Dkj6OkPRR5LfqG8BfPgtRYLsEpbIJ2HEg6cOJ/Ql+yyu4rMA1vwM9V6Xf43MdcJIfei+LROvOFzhPHnxngv4SdC7IVlkGQdeC/h1OlgcyS94IoC1gOOku3M0yaBGnnA/f3Renos91qveIrLn5OOhiUCtIuVQGC74DIbeBXgXOhRokaI+iBTOC4CYdEOVxMnpQ1oGVqt+PALOPgD4Fkh84zSLPxO+BfgBaAZ8XYlSXvq7bZArp67qWGjqI+1ECtkdAMlhYpCLZai+BpNNbI/m+AbQdzwEJXOsWYCLZcBLEHgaSgKMnzcR36ZwXpTwDQ84CHoIXS0IE0FZk0FUC0wz9mMrA69nwwcMJxedevfp7Lv24izGV9tkhBiblGhtVwekBnP8h6CHQGmCW6fe8I4qm4WZf1Vhm5jMzoWN7Zi5qDDANDifO6Yqi5/HpQOncDCXOA8mNxZIDAsB+9t5ULWET2lAlpSIHrfVEAorhIGmTjtwj0WPQZQ6oEB0RCWZgi1LZBr7pOmy4cBpoYWcUyTMp7yI+nwuSwUVvC30dqxkVwtdajRQIDgFJymgRyh4Y8Qjoi6B3gVQmOcB3NOiPQbeAcBsWosjM61CtdlY0vsBK6fdsw2M+YAX7R4Hmg9pAeRfpS4ouktWauEjgqmxAa2KlbFwAo8WJi5SNz8h+n/yAuwmgDSflIGN3FM3L5rR1uDxdoJCDuY1Fdg/ozEWvoi0bHupXL4aE1saGuH/GpWAGWMoPwq3qXssmQJ6Lkp7sXaGvEzveW19rNE6gF4LuToyiWxfsgDrfAZ0Lkplj6wVyjwZ9AfQsyOdyD5RXCfatO0VBILCp/J7tVffwakhwr98HpQaDztvpxuBzAy/skuNXgiTdP1axFbg6MzMCcGbJ7CrQkXUSl8dCKbdKg06H6LYoqszCzstNjZIIRttoxTT3/dnMnYTL18g6PS8LMJDZ1UXI4+iCAQ9hOLfVcUMkpR/3iMwsyqBD8Wa81fHv7gzPk5lVyJL0m0vVZWYTIM/FF8ThKDL4GPsHL5vYAlxNX/vuxGthQNzlK67ZKv2uBaCpSMP7LOgBkGxiab1A7sugG0EnQPhJoG+DfEy7/ST0/gcQSxUB/B4MAy2QcAiHKr9n+mk6svS4HavL3CgwXQL2xdAGmcDBvcNVU4Gz2nyQMLgOhE5cl8zEnpiVo6nrcw9cAcasrd0ds5cxPKW9PssUblU+Q2RR+P3Y2AlmROcZZk52ggA6dOsRAJkBY0prFG2UH2hvCtrV8P0YyYfC0pFwfECnHqyV2AWDDnsxLiWptwxg66HU6xhSrYHVldVBivt117n0kmzyi7RV/OBVslMmmmRcKF70tffuxL16Doz4G88Mkc78XaD3IEh8F+hbIJk0cKZAn2dAMlgnG819DvSKM8rFU0Rmq2zuyRJPK8u1gMG0fVEkabu7QTdVwiGrOsxAN/J16UPlVoDBiTK7CgUkYPewTYQSmz1dm4jIDciq4NwCVzhyLNIdZaTvZazalwDQ41IZN7o3iipT63M8NsQ51ZcHwfUyV2qujLgJwZP765S7U0kWwe6duEl9Hcnv4bbKPXJTNYCd3+ME/60h0D3rJgGrdCplpLMApZKdsr4awKZaN1MAEPqbQF/3x8TDI+jHTIfad4Iw7u5Fkdmu74OOQVB4MejXrmsNHXeAZAPAY0DzQegWeFGkTdyJNnK4F9oaVhJ2z5IlTWC7alAQSDZOjmX6BVG0YZZtBYDB7GrA+vRw7+McQa97IqIa68y1jWdNnv3AtfsHWzrkm4Z6N8Nag63RZ2Us6fEo2tKGBstOWiOY4h5H8IahVsOzjOKj5f8YV4U86qHtnIfehaSSGLY9D2v6yqwEsLdzkKc3LvD5XDi8C0cLErD2tg+vC5aOyybYiXW67q056qut5nf6WhNde7zhR3mYSRA43p7UTJJ+hKuPQxB4Aci32csAOsu7KWWQ4GiQzMSuBLlexkHB71fbiuu6GtEPtk6sTUqhj99qhKkRJjtfNsImBhNgUJuYe6EYAWtfoyuxzkNRtFU2iGzte1b7u9XAFQbO3tXdOStgh7ynq8aII6WTdmXPo/w/GQJrguC9ldsj2WUxao+41MWUVbSXidW0+XtjGOF5lYpnMcizXdZO4NletrIPHbFA0qfHvtmdQvRQJaQvPgzocEbIfo9KtDcAfV3QZv012HWqB7b9VvRE0PfHoBc90LepirBhH+jbqHQU6O9AkoLqcnkflPu6ywoa0Q2TUtiP4VbwWo+A1cFlf5Iy3Km+ThO/bQuBQQEn5uq1ktGSLdsWRfuxMV0QPhIEHfVqmT5mLXCtNugXdAIR07AY43ddFL0pIxLcpCQFpLgDFqS4LMYlknzcIav2nSnVh916/9Pmk0I6Un7gkE1TpkBGMBqLH9HK2uVNGJL3fKlEUp9X6mNvgMqghftp+6nM63kRfV00X+Pe/RA87PrAtAR0XwKdgEDvyZ4tsgj/w6ZO0Fdhy2zQLxy36XK0GQ/XNsZDFbadKBlD2I8BA5Mul7VXa2kHDFqxqYOk4qvJ0NI9O9+WC7ClRRcW+0tWh3pRD1zhx7Ey9eh+g9bCepx0SqU9l2iGwQyW6NEeY4ZTPS4dZ9c7avsY2sWoyot6Svmw64U2ApkNj7k4E95LS7Nf8LAvc6kMWuBNV9HcEqBAX2NmrAi+hg2yrvUukMvrWh+Gfu9EYPd1EGKK4hbY9ypIniEXgTY4amltvethjuqXTi3MsmLUeTEuftqPjKGDVAYPsD3rQmDQVu4Zqor1siRIvagGrnjAS7C2iYs9K35Ex3zr3eoeLZCATlVbduS+0ynuD9nIa5vZzadUQVNmPgEPvU2SPlvu578yyg6yl7UyfDY66BgFlYrg61uAi6vrWuVn8/MI5M4GvabgP2dZwt7vQrl3gB50VElZ7yqptIUo+J1ulaV/WOejEgzqgDRJMp2M9f3Aa9gbWOqDoL2Es6w6HorDVS1w3d6d635/HCXKU2c0djarpA6XID2uPF5NY2l1hO7xNNcW+5rKMJdkKMwutp20rjcC8myU3IM16AexFBsBf32NBvpR+EZef+NiaYNSpyCAu8lF5WzoBNtlxvWDoL8HddmQmVDGB9GGPpbwGueqw4b5UKrNv6V/kj0fymtpMhdgMGsfskgml3OpT2b8sjAwH7gidWANtsAe6XyuexbYslwrqcO7JWVqWhYuvNZfBJA6v5gjdAP674Uo2nPegLVYoUAISO7BRFnvPKtARtGUugj452u0SxlU+WZdc/I/KGvLZC3rb/JXJV8NgEEX6CvQQpYDrctXm7rSb0RbGlH3jAcHq6nBt3ugah0V18mmiIg3sxX4bz44vOxHenQ2W1282mjgioB1+CaMck1xagtsF2GvjFOtQuNX3+HMRevLrJMM6mBO0aPUmjy9NRTvRt7h+gYoeQJUQNmVrsDLHLQooGv7meSdr2UW7/B+ZuR7IIL4LyJQkx2Dt+SrilvSgccj0OhdoGfc0iyQda7+pZbi9U+yA75fqcF9Pb/3gb5Hkn6vZpN6GrgntdbN+sYCVwRhY9Eh3wliiY/A08BN1gGzFB0BZCLIWggO6iR19AjszL12UdKrWN93BGTQYvtC362g/nEQcN/X+J1+Oyz56zjWWKwjmy5dhADtGxZleiUK2KyFwmeBHnJM8S+gTcl6XC+K9O+xnnUvFukiY9DnMuOa1NqjD4fFLM8zmzQ1gsYuNBK4olG3QqNN/uW7G8MxCyNs2rRzQRYGvNZxBCRoxf3BtRBp/XQoXiWwhcFrWvi8vW7k1VG0WmaUWAqPgPO+vhkuwMsRnCk7ock8BGb/4oxGjioCjHZAtXNB9zqkorQlL9YiF6d/37YlDIc+k6YNLMWGkfgh6sICBwffT5vGIr+vyRy4Vht1m98w5K398JuiaCOD17zdoCT/dQatBpAdg+CVM3AGgPSMxVTsArmGvy+eeS2dum76Gn2cT8GeM9PZpHKVbEB0FgKyn6twLyBTYCW7LV8I+ieHzDsDbeszDunTTxXoJ/sNFOT5G0raeOIiSyDfjbc/JL6QF6ghkClwRaOeCM0K0qjVMI7JeDyC1zfPi1mZ1TxBQFJLpnufXuMK2DIrwwEeV7xhT48prQheH7Mnj5LyQ8AtX6OPIzNjX88Pj36S38SRMxGIPd3vDA80RQCYyaZNf4FKNzataPfktWhjQ+2KjCcNerWi5svxartea/01YTizPbGWUdQyCEsgmU2aGDnVC1IHrjIKgY2l16tqVzrm47Cuq5MbNhXE7yuwezBTS0w7UwZ4Ns41zZX8XEdgyulc6+y6j0zp55SvL4JVspmOC0VSXj+E4Ot3LijjsQ6yVtmVFGuMawcXu4Ylgtax2Hq3IJNSa5eE4eSFaTBeEwSvoQ/H4hgC6QJXrNnjKISWJ4fIhk0yk83iMQKYaV14OHcPVvLg+Id4jyhB6zRbWeu8m5vZOe0jU8rl72s8Y9DNCb5oyqKMfCTVVXYO/nVGPqW/HBhGAOES0E8dAeOL1bbmhjrYPRgvOt1U2fPbDY0yaLHnhjCcekYaBq9H0d3cTDMNcvrXpApcsWbvOY5CaDpn8/ooClL5RlMr8o6HwN4omoP74+p4tVkrHQLreY+kA87zq4ZhM7sOvgPbcy/GUz93X58PPY+Mp6tqrf3gfiECrodVpZSIObDEhGLwCdBTDph9BHS4wAE9Kiqgf7/B/7eDiHuD08LwoCvS4IrX/pw33SGfpLGhyNckDo5kJgkO5c5aqq1CHhvtr6mKIHMVBGT3OTB+XIU5mfZAQIbO2h7tcYD/lgaB3XgHNgf2yuHufHyNGbAQ+H7JEYz/BoHWDx3RpTBqANMOGCMZHCsdMOpL1TaXqyoyy4j+vcevvMECxiC4DBuAt8C/S9OA2RFF0/DaH5d2oE5jRqGvSRS47oii2Q7PJMnLt28DfRh0NAhtL5A11UKywYKQ/D8ahHszOA10FWgZyMEyAxuSrFvooGJUqQkCM/Aj6G6Kzd5G90jf+2MmTJT76AZQO8jR0op1jxuk48HSFIF9cvYBkKTHHQuSqH8EqK/fez4Xl+C8o0UG9jhoUd859HV9XBIf/SiueEfiq8xf8CN0wOU5zKKAALB9E2xl5lVSsfMs8p7gj+WpwIYomocfAGdmfvtjceDZdg3OSf/kJJD8nkl/X/osI8LwYLg0vDkMgwjfkxcMWG0PglXJL7R1xQEMEJxX7K/9ltfiHPmU33a4snJeYhyHf8uhnWpB3vs2DAk5VhZDnxNB2WIFNFbwmAZauAt/3CobZDvyUpbXsCOvni/arzQNansUXamnb2rOco/MAaW+R3BtC2g26G6QYwWJ2dGa4aZ9KfzgzwWOGZtAnT1tqHweaFQWbHD9RNCCzijajE/Hirld2OnrIIBzS+HrOPcDsHjGgcaOn8BoTBx9bdaBTsNBZ4BkbeZ3QT8BPQV6GYT4J9oNQnJe9DsQkpCiH4O+DfocSH5HEk2Y2LANOv0FKO/yrA1b68mQTDH5JXWrVDRaBJ2kzaTuv9Szt9Ex2VDTLQwq2kg/eB7IxG/5le7FOIkQb23ku7rHdYOIJIrvlA7UXJDaww+8W0GONOBNUKWcaXG6bc5s4PoAduGDoxwpnXKPyIPO/D3SPcgzZ6dTgczrz9d9aGU86GkwsxB+z/QD1wg28JU2Lh0JR4p0bJYasZW+7u11AFtYX/e2tP832H62Aw1cgr8T+mtn/wj0kIH9s0D/ByQBfdYYZyt4PAj6W5DMDDlRoMt9oLzLB/IAAynCLg1M3gonTLSNAxq1DPA7UirhpQycD9PAAXyngRyciBgQ/lbBI1bHVlIIjsh9XWtHO/Q9OgxHjEUqwMOgLjFAo4B3O2geeMuUu6Qf51gkLe6/fpyjAhQdA4F3BkFuo6VvqbdNUoFxjwyVe2Sxyj2CHRnBdylycqRhzuxwIpV4+nHlfkVOJX0IG8mEsq5nIQjZTuYL+G4GXRF2/26cX5FqXkwCjjIIP/2FBBcUoCp9bcGJf2pBxkAiLse9lutvCrqQk0F/A0VfAT0C+jzo3aCss1+jweNs0LUgjBlFGPeNPgLKyhfsMpXP4urlmThkv9h624MDrsTowSHZVc/CobI2VX7DBqHdfw60IQu3xNdikH+XE3uTdEgf7qS3Up7DPYltiXEB8F0NuhBVJbX4hhiXOFVl4MAVDxOE/PfnpzU25u4OWGcCaHmAWiuQ1wH6HASOQHdB1ojlVI48N4p2zM5JOMUOgADeaTwHa1tbB6imeLrSmcUOemMkYLV2j0BWOwJYWVtyrEqklAixlodKmplwTXUjivtSr+tJhDMqdw9e3DcEDQDfZA1NjkX2AijNe33pa2VfI3iSoOojOTZoEf0foJvz0gEYzAL9APKxwWzwD6AjFXUZBN7ngH4EWgm5V4CGKspryBqPM/kZ+/OGFeyc+DDst5YeLinC6LtcZ8e0hlIuqQZq8humNiHVUDpOvIr3+hpJ3WkmpOm5SuCOPlxlYu6ZplUNnkSb3wOSnZcPQuNfYpC1KqsBA1c49K4cHXp+GI4DrvY64/XQhvwOdNLm4dzMShhdr5L6sa0lm1lQB9SYAOwCkOMuwrvvqQYuS40ZlJAR7o8XR+MPLssxiJEJ4OV5/wAnRC5L9U0yMisPR8ywptyIIov46rWQfz3+HbE115n3/TJoIe2voIW+fsux6r6WjXoOfkue9f9kFFJmnNJtLpNBXQRMo0DyDP0t6E9AsnmbzYLXZgbyPPkt9DjXpuCaLOD+IP7/Xu17Dp8yA3aeLbkAPMe+y3YJlGT88w5b9taTsxZpyX+Q66ZUe2/DIyf1Lsj1bEp6DD7Ygz7cGbjupMo0SFIGlus3DVzzc+iGduBwEMC8zzIeTcVBn3bpKaJSDh30qUEUtS9oqiBPWkdgYxTNn2pd6gGBGKE7GO/3yy9wOaAJ/sGtIZ2O6fnNvh52udZGTT3tzP9/ean6eJldz28crQcI0KPjkO6Z98t6HLb47yTI2pj3TImSvfR1b2DVfX1Rb3nWv92I+8nqIDWCRFnDKnZLto5sWmg7YO0L8lE4IHuM/Az0tr4nLXz/K8jYZEFOIxFW2uDvsenREfktATw7DEefgbaee5wEBR5q5Ajd4xXTkRY8FANVzvThnsHNPwgdi2W6tmfj3jRw7cjFoV1XheGkmWjQKrnd2eDqvhq6SQd9pv07btxNmFnIex2ICQiLwQPrInAD3W7fmEq8IpOcuc2yNrIZOq1Grl1LPmkncmt0/HMj3QpyPPVL1bXth+9vhoyj7T8XxbKh8mxs+numbb8Cf/q6Lqg6vkaQ1Apx8pq8vMpKCF5oUzhsHgd5PwXdCTrUpuwYsj6AOs9Bx0tj1DVWBc+xDWAm6ZN5lVNh8xHawkfmkhp6oO/ysLZ9cfjLPT89l+BdsmgGy+SctbTgOHhU6mD/IEzQHb8jCK6JfY3lig1/6NvgUNw5x1nW59gwHCRBofMFDa4dIxND1gWBpOxZKpK0vVbWnLA4gMDGIPjvkqBqt0g2wjhJK8lvYnMgg5HmJmkn+Tz4ZlxQzFnXyhqYSfC7c4MVPZsD9HsFvb4R63setPK/PBvXXW5FlLoQ+ro5xGq+/gzk5ply/kXcPzub227uLDrtJ4Lbs6D/Zo6rcU6SOiu7zMprd0YY596AIfwgA9K/bnBa+7C0QWmLakX25UDAdoiagLqM3eu7vBYEj9ZVVfXgxiXVjClnJ+fE/FFYhoSPs+V/10rDwBVzFz+yp2zlh1qycF+0J9OAJKQ5HIrdVRHALDHALSaLCUiHDLBfFkuuCGC2FTtI3GRXh7V44Ek2ghtpJQPZLg++ziDAToE2i8y6hl+2KVFfloxSb8Y+WJZ3Wkxp2FSkDk/GrLvdQT1R9uDr/J91pa/jNTsVX6sGCwPY9RLO3ztAHWOnEQTKppMyCDbDGFNdRp8G+19D77friunF/e96fbP7RbUt4nfZ8trWzQ+41nfpwCthsLa11a5bN90WhhPPsCszvTT0OWRm/Nj0HHSurBu4ikPtTZ8f+KGWf7wsEzG7hAURt9lRXjrmy//RjixKaYQABisuknF/e2X9PWE41ZsHXg2XYd3r1E+qfbfzOUIGd+RGKUCRuctx2MBiKlZueFQw6y6DenioW1wrI3fkRivrw3Q8QV/Hx9WsrxEQyezjUfHlG6/5VXQSu4xz7cMQdsp6VhlwvQXk2wD4MdBZgtcz8ale4I8HIcRygHfArD+AnScf+Gbwn+pbEAxyHIiV9F3GzRuolu3zGFi9267MHddgplUGjLwquA9kQnGmS0rXDVztOdTTH+o6HhyP1+ZstfY+pCmXcta1jhMsHtpvdW3rSoxWTr7QonlGReHB9wwYWhy1q3RqZYTe8yLPx8l4r12wz1dDZK3MKqvLKfbc7idW9HVyvxn19dzk8o1d8Qo4fd8YtwaMEAhJf++fQQsaVPHh8Ego+e+w5UOWlM1z1lWlTaLvstgSdhCzzsm+C14cPLY1CE63h8NqzLSOWmhPnllJ6MO14z23mM90o/QLXO05VCZYJ2Mmwd9OWV8XYmfNK+wEr7LsY/nX+srndzsIdGJ0fpIdUZCytj0MZzg3WpnUfBm1w4KODye9Ln19o53a9GqkvlKWT+xHenA+77VLrXadCw8Lgon20mlk9/U1c+qo4fAh+jqdc4z6+v3pdDBylcy2Ip7QKwj0BoH7naA/1ZNijbN0gH4Em/5EWyL88hhkPKwtpwF/421yA97Ri+jD0trWVVvC8FAn+y7vDoL/2QBzhcOrloXhdO9mWvsCMRwbb+7F63L6Hs/je7/A1Y5Dt8PW3dIp25eH0ZoyJXjF2Pk9mjK6eVfWuvbzn75cSni9e9TaAhByn0zNM33NqI3YQm8xZt8s3BuitnRqd8w2aoBVZgcd7V16cCN8sBcANjGzmGq0x7NBPfq6UdMZ+Hh2XyMAwnYFwakDy1KpsRpcVVMWq0GrPHc/rWJBPkyHQOz3YZsNm67Nx8TgFNg3zKRsrDe5wSS/xrxkMG7QtMbnczyDdHl0nC+3o4H04Q47wY4sfSlDkT2H+OYqfUnNJfQOfOBQ3CUWHDp4emE6ZXXwnRyGF6KDrry2axQkbzinjnge0kQAPyRTre22fRDe8VWswZ3DcG+s0fRPL94b/qnXV2++rL8GI/2SPliYAnva8YN3jR2Dxp/uzxpn+jpbmzDi6/dCh+HZ9Eh99V24N1RnW6HZdaBPpNbQ3QtlFvn/Irg7S1NF+OdR8M/jeXww5L7PmG1IFccA4rnG+DVlNBjvaXVzXwbsen+UvYy5LdKHU1+73tQVhk8ivrl+bRC0G2abiF2vwHVHELwTDVu5bPxwGA6XUcZCF6THvQsdNeWyk5s0KSPclz0een8keUr6Rda1DpW1oYUrndZm34x0ai3jvyLAeuaFloVaEYcfvIV2Bi1kUK/zeCtGZRJCX2eCr3KxEV+/P7seqTmorslGUCeblf11au3cv1BmXn8IO2cpq/ptZf6N2Btrm3j2niJ3i36R1NghD+vLSScBc6CXprsy6VXShzu8kH245dizJM902V6BK9Yh/W1S1ySrL46cuDjZNZ7Wxq6aT2M7UF3tp7VG0VI7zyJdQ7zhvi0IvqKvrKTZzPhjfTn5SJiJ2Tc7KcNGOrWWQZphMaXWsmkQN8baJl3r/8y+dUkl0tdJEatfP7OvjQUH9fVreHQpZvP+q+HZjCcQzJ0MFrdmZOPD5TLfgu1ZIs15lzsgA2Ou1ouxtrk3CP5GX3sJZ1acpi8nvQSMdHw2/dVxr6z04dTXYMfVxnS9OWG4fWsQXGaab1x+bwWuSBMeGgQXxL0weT3ZnmOGxc1Zkmto+opzw3DzRtUNaQZD5bd/0LTe5NcAAaTaTLSSJrzzkqKlCPdFFBkJF8mjXb+s9Gi2QQb2wnZ9TPKTMBKbdOkvoxD79lkaVU+LJX2dFrn+16X3NYIdSRF+T3+eVo6ozbbCLsmG/DeQnQQhK3A1FXIUzsrMq6QPGy94LqMrF/yrccYDMzwZNo0YuNoANdC/xzDuuQPUMnD69RvCcA4mNR0tuN8PtbI51bqr0Ifb4ygKRtSaEIY3rzHCKTmTA4FrB3Yz0c37HnosHBklV9HvK/CO18XIB1+iZ0XHl/R4k3NPBJBK/w796e01SBWdcEdPuYX8Hxv24LVbV+nbdrDiYJxJ7WWkesb5Jjm6ygvDbWfr6zZNdhfOa93iAObR1wMAlPB0Jl+fAmEYs7deZPbuPkWp3wTvqYr8XWQta12vVFRMbaChic6YIMy+cVgbflw0p6O79Zd49QgLv+lN0BrgFAKtE2S6R7fIJF3rIl0ZbnDH4vxcdhk+ELhiPeaFelDI6PLIF/X4u80Zvx5/qDe7NOY4fzYicdtPA2mHx/LFA9XJfn6YhU59di1NcGgNgkXyiNctsruwD+n0m67BwB7GD4tfpoThhnbVwTzBsNI9OcFNNOlrs37J5OvZZnWJze1JzOJhLNR8wQydZGF90jxnLzheA/vfqaTpY+C7U4l3M7aZ22hoZXOuzsvwG+b0RkTA4aPNgDZzbuslZZmkOxy7DOexUdOBwBUOW2DGaX25yCjMjI/0PVqq75hdQgddKe9f5gB3vL1UeOZkLOZJlNdGyGYtEx7OyTz7YrEOHGuGLayTeFteqYAxMZVhrclfjVm5ENWQv2hh/c9uC52UpO6gr5MiFq9+al8fHY+/8Voqz/lqWum3jGvrD0OZPb8TOBifWMNAg6R+/jIHKEy0UaX+fQ0NGYKecEvtm6ufu9T7cJgCDGbe6ar9GnohJeADGnyb8ey+uXGTj8PcdrOK6c91tQdB9H7MCh6cnkchrsQ9o1W2y0zgFVrcyRcIWFkbMaJUa8ClXbUGwS0IXm/STcHe/QmIUukoig3ZyzaZbcW4SHmKzLq+FkXLjlBdM97ycSDq2HORvtZp5al9bSIoSGOS1vPoy1BmRhqFCnSNZFp8CSRYmC4/A8NzTDMdgF+2Noq9OfT69zXNt8tvmNOzrejDtUxQX986SGadoxoqZfjEcshX2qOoHQ+dVlv2VgLXtiCYrtdxHCPGPGTLoHLK2SczgY510IrliZVBcIzxIdxeEElmwsSf9DpUhi9h2LUxim7D8+dSPXM7zwPvz+nxz8JZ4tX912Xh4Ou1GMn8PHR/XE//0a0YMG1xp0NFXzvo62xBQTqDtuCyZ9Jd2vgqzDLKMkbJ7FrWuFZpzmCyJPoqZklNB1MSuNoumdro2iAYr9e/r0FxuKypdrpgHc4U3dkzeb533uE0CErKIc3hM2Ct+FveW/FKXzwMgg/1PsxvfiEw5hBZ51q2WRubPsKv31m68jZjHbjjI5ZKAOD583WwVgxcJ8j94VAA0xPIN/DOu8NKsba1p9XyP9b+P4nZ9kCvUyXdlAiZTJUUPxGZc6GvXfI1ApvRaBBTcmgUv0RAhX1NzBbwlHzNk81yJbeeCADjV9FuMNcTzOx5XPn/yZA5BrK3ppGDB+Bxaa6Lf82qLfgNk7bndNmIe/0wVQ1Xt4dha1l/y5/YBGxl5MxGaREh6Dh+0IYwytBCQLoDHZO1uJMv5sSC4FO6OAz5hi5/d7mjB7BCVobolcr9kUcHNYZJB/1djErFrILZkA2qs0OVN4E45Hf6Wq8hp/L1LD19mnLmjGhTeJw/+WwOGqaedd0RBMrtvMv52VbxFyYftAd1rs+hXbghEvuVIGfwAVvKVAJX/NEdiLBlTanlDHl7qc1XNn5QEIzREyEbtkx9Wo+/45zx0AMCyg+9gzHw7FqR1KK9v3BNK5v64LfnRl15O/Um+RIpTl876Ou3JXKhucovmWNFTjkg8LscZKZuqxh0V8xmEiSG350DHolFIv9mUuKLEl0w4weJqhesMjpY1iZfWrBgORyhnkpQMA85ac7qdzmpVhGUwj2iu7nBWqTaFPtl1QM1g+FBcNtAdbKdXyEbNDlWZBfpqaVMLao5AvNkyuu6N/63mqx8P+lrB32dehYrY1v6fcbreXm+COQRuKZuq0NVsarszfGqqghDzKHpxYZY1WEjmdIhspHLW7D052kZnrVRZMY11N10xoYZlIG1XOcSBR0EMBV4iO60zSAvUm100O3mOjEIHpR553KVFuVg3X00ZXfhFbpq7tRlH5c7fe2grw+P6z2D9SLwesUgP7Kyj0AegWu6toqddJEqdpweRJuwrtOPvTmwJHKrHg477wEOcm+Xt+B1UW8EgWw8p15asMr8cN1OuboNFFBBYH+6BxvRGxCBd6imCYv4KcppsgOa6EKFTsX3RcG+fQtcMLK3DqNu6P29nN+QyrZMz/JBc/R4J+FMXwtajvk6j67PCmyyo/uoS9IsWTcNAi93N+U0l6a+Jm1bjXRnwcI7U1tk80JkzY1UDeD3L7VpjquyMLt/rQ3dWrCjz14bgiiDCPiKgP49srrUKSaVdoF1rpgaUwxghimOtqZt2RM6017J6+IisOd9cWvq1qOvdfEV7ol9nTYYyGLKyiwX89r8EcDAwx5ogcklqyWPthrDQPnZ9qKEWOPKoowARuSstAdJFWYpBAKTKu8sLIQppTOitXQW1zNYN4rbo7i5Vj1rYh1zMJiOpbfRStj4rAwp0/Q1Wo1jvs4jGJBFgSz+IyBv8rJZ8mirNu3TlqU88xz9VNsAH/ijkVqZhGHg6kNroI4FRkASeZ54s8AGxjZNdxOJ2GpYqljZzMHKehBLBlFMQwTo64bQ5Hsij2CAgWu+Pjcl3YvAFTv/TR1ryuK6fKY+Wvdw6Q62ls7iegYjh/6JesdNH2tZFwQOvibCtJnkRwTSI4DcB2y8rVWkHzNnhxZ3n/gi/yqPTS9ygqiyJR72i2ApPgL0taM+ZuDqqGM8UMuLwFUfRy5z0sfYHwnHW1K1pRWCdBdvW7Kk9GJ2LfNldzffXDUBeft690hlPJTLL9AokEb4oG9tg/oSASLgLQIMXL11Xe6KM3CtuKA1d0dQAXcQQJ7wFBvatEDQUL4OxwbU2jIOPi6KgkKlfiOQcWJdYjuyEvTuEUkjDLjLJEBA4/24gMFCBIgAEbCAQB6BK7NrLDjWgggrm9D0sGNkj//5LxFwEgFM8qy1oVgLciBt34A27CqhjMrSmeK8RwrvHxsXBK0uOFJ3V2GZcY1wv7MgcD3MMRQUU8Qds5Tq0NclagNRFEmWC8ZGrZeDrEukQA0EdJeO9te4BW2Wz6j+uPCIQwg8b0mXQs3QWcLMUTGdSwr2AmTlXeCcciN/kOAO3V2Fk/sbowk/S35V3CsqWwtwfwHA5cJUAn0dt91mq+eCr6sW5LUXnEMQZPNlya+2khLZB+OuPt/5NQECellzCZQoeNWjguAEPRNlci5cKfwZuOqhbJnz6JssC6Q4Ywjs4ruUjWFpjhEejpvMcevLSSZeojw6P30Vyf078uQv1VNiUOWHbiD+9PVACJk574KvzViSmkse6cmpleWF/RHAzKcMPszuf0b1yH68P5ZLijJArLdPiSj15ocyqFaYS5G+ayVrjrsKF6LJyEjE+H8thClVI9YEwcGu/MLr77y9U3GUypNWEUUhcq+Oc0lbfb+7ZG1+uujOtIf3xrGMvo6DUvY6Lvg6uxWZOLjys5bJiJJf/AHYP8wyBpW1YJZlFkdcGEbYTWSZnkE79FiTcz8EWv4zCLb2O8oDniGw6SqkCesOKFlG5JAgGKub2jFyQ1yT8Au1fnfcyqnqdbw71WXFuijU9XdysPSfjes/kVyr4l2BuWfNAYtYafj0tZ125YKv7VjaUApThRtC482Jz+egKQPXjKBjA5gxGVk0uTz8YJOTpTmFTQMUs6e2B7U3p7ScGwRbeEf43K7WwJmt1/tsQT3d8eLss+sdN3ds+ENxeU3Frr+6OTrR1XF1KWo95HOe4NpUhP6zcdeCovozrl1PRtE03F+KZUKsdcr0taILqqxd8bW+pU0lYM9BFl8RQJrwOdD9zBz0Zzc9I+joX9yZkUWTy0edi7d6lPu97NhQFSMDioPQu9prDmhB1BMhSNhSO8BPnxCQSdaphfwhRIN0J5jDPbJTNc1kWhBFS12L26zeCGjJn7QqMI4w9WfjuNaivcIqDqw968xSH6AaEa/DR1/3dIvK/874WsW62EyxfwmLjwggaJ0Evb+Vk+7xnmM5KeeDWEw+rNfTUzaZ7tAdg9VT3gjntiA4XLkT+1RNUexJEQTYGWZF7QA/fUFAklcHT8KC/c2+aBxbT4zc4BeiNXb9xBXlN2D42iSXIbBSTKmXJNmjz0yiT9HqDgmCz7poEwYsFJ+N8pjfcKSLdtvSCTfVF/RkyX0erorLn76Oi1S6ei75Op0FRq4ahQCIm7IZgdIeE/hM1rTKPiJWNp+pYxkXUdYBJckhrBl5OEn95HU7PpL8muJcMTwIPqFrzeDnavwrgevQIPhR7QA/fUBg8zLsXTQIQesGH7RNquPvg+AduiM3mw7kysfVDTkgsTZ5icuvf71tX+l/rBxHlkbRqOlBcIiL1mJIQfnZuF1xTYiLiPbQKYoGY4haM7VIhO3vIbHpv/R1U3iynXTM19mMyXz10Zk5kIE1BBC0ToQwCXpOtSa0vyDOuPbHJNERTD4oT/LsuDKRQgWr3BkEX9I1acSPa/wrgSv+/KZ2gJ8uI9DZDu2ODcNxx9cWKbusbVrdELQqb36wH4F/sqI/Wjf1OKSNyqhu6cq0IPi4q0ZjJlh5lHbE5a7arq3XRqwVk5cC6ZUdy5K825q+1vOEa77WszQWZwausWDKvxKCVtl051egOTlrsy1n+d6LR5rDRt3IdRqW/pRzydcDUTR2uurkA4Ydgr0HsqcwyBwEePn6UuVWeQn4YyktS0IEMPteKa/i77NhOKz4GOK1KDBaeRZq0PequMb+wJDrCtmgSa+jLZw3Il12ws2xlSpIRTyE/rerpmBG8FkspQgqD0oVJSdhffOaOWE4VfsZrKJ9FqbIffv2+CwMBrw22X1OXw8IaOoKrvk6tSFmLmTgagZHFS4IVtEHD/4QJP2QU1SEJGeKJYQsmRCQvUqiaNlYtSwf6SUcJgPRCzPp6eHFxwTB/9RVe7VsQnsg/qn0x5AGuWUdpE5Sk7zzN2E48kU19mRcGASQ+3wuHizKJd5Oo72UCMM9a6Noy0zVUaWWmzDrekuRZ9N7YYovG6JoFgbOnEwTrugahh1vwO+6o4md34UsNK3ylLYoap2huo5dsJzxg0SI0teJ4Ipb2Ulfx1Vep957dNgGGASLbgPvt2vxLzBfJFwEI0HyW4QkIOfKy85p5KFCBweB3B836ak+9mr04b5cpj4cHjqDMZutnDk2WPx2oFQC18rOwlG0BEdPP3DG6D+dL8jumUnStoyKJzNvEOgMgvt1lZVNrUZiGW2q8h1cpXiDSsjeDv7Fe71RI7R3BsHPEbg6XfCQVPb7DKQY7ZhdpsE9YKq9dhhtavTKpA2Lvk6K2MD1XfX1wJqr1TgZAeZI7FGBiWjj5V/A8ZcgzEewFAgBBq4GnIlsvh+DjWLgKruzlKsPtyII/pdeJmLN6ZO+XftPPitrXOWf0arOlA758ltEDgsRaITA8ig6b2qjk8aOr2vHAIokzCcueCT1GvVJzCDWBZOvK8ta1x1RNFt/1i0W6E0rwe93Nq1g5ORmGTgsRZFZdsxgK27KJDBukPWtXUkBpa+TIta8vsu+bq656lnE8jqTBAiG5Tnyf1W1J/M8EHglD6FFk4nAdY3uOldBbJz04eQeL37BbtvI1L1a11CZbBraK2P3QOD6VBA8pCt85qUYZWzVlUHu3iKAta3I0bnXgv6p15Bineur29UVlLGr129XF+OAAGzY8oIDagyoAvLH/lPf79MPiaKNcwdUpgAVgOWv9M1ouTGNDPo6DWqNr3HZ1421tnJG1lBqlavAuJBvHNACzHG+q5Vm5x03W0E9rHPdGgTKg8Qy67pccVZXAZeULF8Pgtv1Z1srk017eqp4IHA9F+8DxZSvclnfhpEIprAoo+wje7S9q2VeXr/MuCO1jDDselP9oSfaTb+g6IM8b2J2HbOtfhRrfm95SJZU+AFKOi0xAzdvppU1za2SEpa80NfJMWtwhfO+bqC3pcPv15KDIGcTeP+VFn/ytY4A04QNQo50u0UG2TVgVZmos9OlbaCB9uGOKJqGzKkLtOVg5f41fWX06iQhr+qGvhXMfpftn15PvKOrWR3IzTUE5D2eh6unG4jVa7CcO9u7bzGW9hU7+K1psyMnBylYzI+UHRuz68aMw3uKlHfNE1Xld27Vt4wp7Roj+B04Kq9hF6NXbcF9njojjL420HA88bUBS9OywOvPoilpLx7oOrR/6WcpZ9ENpAXPG0LgJUN8yAYIHBUED6ZaK5YYvRXPJr7EowswifNbfXXFU6t/2FdOr8AVU6H/1LeC+e8ym7Rhnnm+5OgrAhi1sZQyuueGrBhhI6FfSsa9fpmKzdrWWhgZ1Lekr4Q3guDf9NNL+krN9h1rr5/UTxcWHadhScWGWdm0dfNqZFX82ygrqu2/NosY+joLet3X+uLr7Jam5oDuVvDp1FfHu/AiVFsdryprOYwAZ1xNOgdviEAfZJlJlvV5yaaLb55X/5zfR9uj6Er022UHbuWyGnvSzOnX9eoVuM4Mw/Y1ymp0s59wP0YbsWSQpewIIHd8PlJGW+3gcGj294WG4b71QfCAJX0vj6LOE+3IsiNlYxTNnYxXHtmRZlAKUkjh93sMcmzCatDLRUsZ3gu/I6vCgt9lhHZVto0A6esmbXPgU175emBzNGvM12SOWVf0z4OPg/ZoyiFvdQQsDeyr2+GMgEFB8Hk7yoy+F7FOoVKG0WeXV9ldZwe/kX9WT06vwFUq7A0CWdhvoWxfj84ZsrJYyooA3os6sRWLu+3YL+mDw42MPiPN9XI7OouU8OmiPPgewAN8jMfpayOC4C/t+F1+59YVJs1I7nNssWgpbXEldhPuP0Kb1G/0dVLEuuv76Ot0lhq56hg8208ywqkBEwSvshHaZQ1O87D7CEiC11Puq+mXhsiqeSL1WpJEpsrmwms2FWZvHywBGR8ElpaxYaogmPCLenD3C1xbg+AfZcxav0jS2OrdRZtZ0MetIBJwA6BzKC3TUjlI0qaMlIlh+MprRjjFYSIPvu148K1BvOxxgb9PCYJNYo2vZQrWR6+1sjmXIDQJa+DW3e0rVgf0xnb5du/zIz56QHaGf+jrFOB56usUlpq8ZL5JZvV4IXiV91AXd+18PaOLc+wJ+I8z5qb9id2Fu6wN6CBMDtY9Z9oE6/zw5g/M/Oy1s9xHrBt0CV5pF9Wzs1/git1r9mB9iqWUOHHoG9hglDsN13NOYY9FUYvdG0Di44lG03uR3H+2Pf/Io2LkTm9nXqv+LkK+DPx+oT2/T8J+AFu9DV7XRNFwbG+6294P3QqshwnbTfmHvo6PpO++jm+p8Zqyg7yNJf+SLfKIce3JUBuBR7UFlJX/hCC4rd/iSTUwKgPRz6ux12aMPtybmHiQiM1OkfnwCXc1ktU/cEVNbGFmMbVkMvoHq7s489rIRQU7jlH5dUGw394NIPh1NBy5SYvuhDB8GAM8Fot0//dh5jVqtSg0s6hqh9ayvzOr3ZDB8DBcvdzKxg41FUajY7vOux88GWTBQMVOu4MVEz5cQ83EJ30dD8Ui+DqepSq15Bb5MxXOPZhiQAerwCprzP+9x2H+6z4CHGzQ8hH2K9kVBNdose/PV4JX/14JWuvDjbOyGVMNta7LMNvaVfvW97Nu4CrvdG23lhInKkkYs2m/9+mQYgpLQwSkg7MNMzDyUiR7RWZbZ96pIW+k1VlXsaCSaNsGHOdp2GOaJ/ScaD94MW1Ff34YeDmn/1HNI/KD9+ZmDO55kWkNv88CGptsTCO9hXob1rCPfPGt72b+o6+b41gkXze3VPXsVcBxqKoEMEfwin568BHQ/9OWRf5GEJAJwaeNcCKTughMDoKv2nlLRE28bOuyDhN1fiz9wnNpGnbRtTwAXZlt/VYNsXqfdQNXqYhOx5/Uu0DvmAw8TpR0yFY9GeScFwLwzDf9CgAAHYZJREFU62zI3iTzhnbL4PMb5cln1cP+rOsBjWVX7kUHvjn4D/SbC7XW2w1e7ABxCmZd260O7Ild45CZsgsbtrr9fIR+86FsDq9vmHS6oGS60NeNES2arxtbqn4Gb5YILlGXAgHVmddP4l+VwVwbNpRIxuPwl50tZ0oEai9Tu98SYXHWVaTL1E0l1pEBXmcLnu8yQbLK/mj51ksG6rM3DFxlc4qV1l77UfPdgRmlBbUj/PQfAUylXwkrctjSfQ1+qMffp4kgbiDVXSGb6I5X5cgsXGR/LKCJUnJqexTdig9Lu8gOoIzSaazRPleJdRO2lWGANvjcvecj1sBsi6LHoLylXcJ7wiRrW83PttYk0Nc1JKqfBfZ1H0ttfv0i7msrfUQEQ/thmATKXwc1TMezaTxl1UXgkbpHedAoAjOC4Mv21rrWVK/c6njt3X7pG7tVsAkTZhAXQ6n77SsmffaZdwwkt2HgKhe+bnUjkl6q3hRFO6WDZneJVC8V+CUrAvDf8C1R1IZGdl1WXumun6geVB4ehs9gh+H2dPplvUpm4QLEC5VZrqzMMl8PPabJIlykUF+amZnjDOaE4fb1VtfH9AKk9nx0YtACLj8ROYj7oYzKrGcvy+t+mTSn7mFDB+nrt4Asuq/fstT6f62QeJEtqQheI9CXIO8M0HJbciknEQIPJqrNyukQwHu737SU8dBfwZbrqhMQTsQ6eL7Pxm951/BcBuYFnf2x+uxNA1f5wX4jCG7oD7aNI8NbIQX94M5bAaaVkchmVkGHsaArQW2gnkVmve4GzW52fdnOAQ+ZFdo5Jgha87F9Fd7nOPQZG7JHBMHJNuQ0kXE7dp+VdtjapI7aKcgdhln1uyFglRNPXzVLezPG+phrELzmVCrPRxm0WJjXxnaQPRaz67Jx1NP5pYS/do+p9zM3cyR9XR5fN2sHyue+hntqtLKMXuwRvC7FgeNA3+51gl/yRuBF+Mb4mv28jXJV/swwvGNFbspVJiBkzH8RKJdYB3JH7erOmHohv9/y9iVheHisPnvTwFX8OCUIrrI/jd6zBQ2R2RtZ2yVB44D69rzSxP+QOXZPd+cMb3aozBy29uErs14XgF6IIulHljuAhf1zcQNEwOOmPjhZ/CrLQlacZkugpNXnN8BTs3K0tMO2KNrzPOBvrR3V/IScUaBFkLEbN6bcA+UqmLXAoMWxORt9dRBEGDeoPB+t/OhB1kSQpBJtwuy6dHpzKvLLdOSnrQinr8vjaysNqq6QQ3H0K3XPKB5EgLQDJP2sD4KWKYpKwhoZ+pV3z8os9Jmgd4Nk35VrQE+Bil7uKrqBrtmHTuvMnHW6HPIl1sFgdIRJT/0COTIhJ5MO2xCwnq4vsZEE2SJr5h81Opvq+EYEIzDOlSKjEshKUyzI8YaM2aDF6YzeLmv8SlOA0XDQlXLHuVE2ymyv3YI2s84N46ta7JQZ2Hkgo4M9wg90IrbFkwDZo/Jqm1aDWIU1vQ4BIdkfraZtBU/x+1wM4rXh05GyVzVFuB6G9HVerjfra1gxJi9LBpC7D+ePr9f2bByDbOn7fAyU1/P9Zcj+Y9CgZvbi/CyQPHfxU1S4Im3AyBsDO7B8Rxmd1mZ+8u3ccqd+y/c9Bt+Zz+Tsvscd68NtnKvSVl7L70HW4L7b04YTElAPM2UweMnDUDp+Bop/72tKgiMAktm289zqyIrb1qgFKAPhs6N7sEOUcK3IA1DulVSjeLhOfC3XCx9Pi17gKu1itXOoVIaRpGMnA3CpZmJxnfh9HshBv6+QGd9cCn2NFmG1mPc11Hc1cBVknwSFuTTuqlCRD5IAcilIOziUjJGHQPNBQ5PYjfqngF4FFan8PAkGzeoycG2GTv1z7j3fK01b4pITQaniHVwnk0tzQCkn43ClWkn+fI//cETnB+/g3Ks71Vm/IcU42o46N4N+DFqBtJc9+BywwA/SkT8G9NcghVRHebfgEd4t+wMuPTu68kOCjMhA0pgkXefjSMQ9t2cFHHOkSLrB5hFhOLUjL4VWYcRumtObE0ka9eAl+PMA6CVQO0iKPBBxi1f2aj8Sn+8EzQXlmAoK6cbKa9h59ki1VCDcM3Kfy3ICV8sWKLYUJL5/DoRXlAbynOwEyT0ua+uOAMl6bcf9vh4qTm4ZaMt8VFIp9LUKrA2Y6vgaPhwDgXJPuFr+HP2YW1xQDljJc/NCkKTlv82QTsjMrKT83ovPH8DWtWn5Qj/pm8gu9vKbVYTyaeDxPROGSOB6MPaeMMGrAY+Z0LW9wTkvD6/FUhg0KHnwOFoO9OEehYK/Acm9I323nr/lU/Bd+utnofbpg/GPm2UN1JqW+Lc8fuAK9p2I+If480Lkdqj8W5Agsx0kReJuScGQB1wryEJpuwHB6xUWBGUSgYf/HDD4GijHPPdMJuDivSfZ2pCpmabtAHNGswo8lwMCuoGrGIQ5zrn4gSj0a4BycFwdkbum29iQqY7gA4fo6wNQKP+j42s8ol0PXLG5Z3AyggLpwzhTgJsMZMr+Ee8FvQd0JChuWY6KT1bpAdiGF1eYKdBrAjhJJ/5wMxxz4yJ91UOBjZHBdwau6fz4JrIJxwWBDKqwqCFQCcDHoa1vTioiUeAqzDEasQijEZcnFVTu+k+MDsM5teDZKSjwwD9xd667gpqCY/01YTh5oSlumfhgJh+9jp357c6WSfuCXqwfuApwfD5qN59N52u/mzmuBfR1XKTS1tPztQeBq4D2OxAGY80EMWm90Ow64Dge548CoZ9fIfkuEwTS35EZbemUyucrsAN7GOoV6PI+cJeMEncnmAY2/w7gdMnA1eLVYOAaD6d6tVYgrRajIOfWO8djJhDYd1oYDlmahlPiwFWEYAHz5plBcEgageW8ZiVGF2fMc8127P57N4IrhRRp25bKq28OO9621Gby8CPaivO5rbdtpls5z9kJXAXb17EfwPTCpFi71Fo23Yag9XMuaURfa3lD19eeBK4C7u0IZP5UC+Wi8YVf/zds+oLHduEtlOETpvRn4JoNyTcQ6+BVaIx1ssFY5+r1V2Gi6fo6J2IdShW4Bm6vd41luN1KMiX+K3dmXbHxAoY+NxXjhlwRhGFrunas3AiQTjgHQ7+PK4sh+1gI2AtcRR3+4MVySoJKK7BGuXVmggusVaWvTUOt72uPAlcB9zMIZv7FNMpF5Ae/ToJdkpIs+3L4Vh6Hn083qTQD14xoYjMkLB7dLSkELKYQWIV3rx8ma+ZTl5ZUV4bhPjhSHhAssRCQzJVpkkLjRMFTvSBBq2QhtWLZtZtlCF7ujtXy57upHbXSRADLKcY7vLuDpukKvFeAZ6tsHOVkoa9NusVtX5u0NAGvbyMgOzVB/dJWReAnj13ZpNPH8lUflS60ztjoFbHOOJl6YjGBwNolWYNW0SJd4IoL8YDYsBfrL0yYUg4eo850wU68a3Qhpi0KkPogS2h2YwfhwOlnyrAwvA+7LFzmgu+pg0UEwrALGQ1DGLxmxVwQbMUYUCC7kLpZ6GtDfvHA14YsTchGtkuQ11gck/C6slZ/wEPDn0af+kEP9S68yvDLZkw9YfUPSzYEJGidekY2Ht1Xpw5c5fKhYfgMooazTShSfB47JuZtI374xmKa/Oq89cguX4LWHbm+9iaJDVD05p1BcFWSa1i3AAggMwXB6yDZ1pwlDQISyEyWoNXpwamKZfR1Ggf3uMYjX/fQ2uK/8rqtn+E3nB3ogUF/fuAqztX4mnMaUaEDCCB4XY0vTi5VOaCk0/+swz4/ZoJWMTNT4CoM0Kt4GC8D/LD8z+I2AquC4FG3NYyjnXRwRqPZ5feu1jha9q0zMgyv58xrX1RK8B2zcdPwnMWL1tpLYK1BE9dtQdA6yIugtWY1fV1DIuGnh75OaKGh6oeBjwSv3r0b3pD9cdmo7l4cV4kE9V5E3fsT1GfVHBBA8NoOsZPcH0XNAZymIrfilaCHGt2cNnPgKvoeFIaL4Ux5txeLqwjgFS1Yi3Wcq+rF02ttOzqz8rJiL58dMvPKNa/xPF2oWmEYTQ3DmeuCwMcUthxcsR67hB86Fvd5Vw7Cs4mkrxPi57GvE1pqqPo7wOdhBK9InmJpgMD+BsddPXwtgiJ3l0K4iloOesFPGzZg4y/ZXYUlDgK7LwnDQ66IUzNJHSOBqwjEFNhSfBydRHi56k57Kk97ka54AvL0PS7rsRPZ1JnozHr9gJc1rxzk8bgZZlAdb5WXUUeud26K4Q688mby8U2reHCSvo7jpGL4Oo6lhuucAH5LEbzOMMy3KOwmeGTIK9D1Po/0Lb2qGITuwEuLByGAbS89GM0BODYMD76jeZV0Z40FriIeoxFyE47bnU6Xgl+1Cpm6+RVspDU3P+mZJZ+PzuyFmbk4wqA6yDOJ94kjDrGoBp6RN0McN7Wrjznu81Gfq3/Kv6P0dVOfFcrXTS3VOXkU2D6B4FVmYFl6I/C23l+d/nY5nhP+ZZY4DakF5eCzSciiwqty7rEgzTMRlflovP4zlBR4lWI0cBUNoezmgzEBi7Q4rFFi6UZA1mXOlH3+cyuYprw4N+GpBVdCu+loU4UbkYRNG+Q+4ahd6sbh7YXw/TNrkW60ic/Iqg8r9/nMgt7n9HWvO7W4vu5lpp0vWD4fLEHweoodcd5IeY8nmv4YzzzV5SPohw/xBAsv1RwThjKhwj1+DnivA5swjUOzDmUHVbViPHCtaIodFpEqNZajETW/7bos7xRXBEky0+NR2b4kCA7G5iyV3dw80juBqrhPZNQOw61XJbiKVQuAgKQbjcczEhvb3VAAczKYsHlZ9T5vz8DE6Uvp65p7iu/rmqUWP5G1GPwSwetfWpTprCjgIH3aTzqr4FuKdeBfdZ9hG9xVlaGit+TyP8MIoI+6GCwncd1r8OEwHGF0E6ZGrtIJXKvSOBohQEhzbv1WFZLcPvCU/EFuwpMLxg0w+gwvN2dJbmuA6Px6XMYHXwrs4l8Sbo1f115NbGwnGxccXdLOBdJFxx1flvucvi6Pr+09QSqSZFbtRgRtPwSNsSzbNXEy+zXLNaXq6PNVBDz6WXgYHN+om9mDN/2xwJcbZJ5xRxDcVj40trbDZuw9WgngrZivGriKBVVjRpc3Le4gpLrmv6HQTGzl7f77JHdjllU2qbZ3A1i5y2IIgc2VBx+qlm32FfaGLfj1OzYGTBmqtNyY4WLVS+H7V5ARIc/iksy+7sAsa+WHrnBLAAZqKPT1QAjxfAYEPoZrf4Pg9V0ZeHh7KeyWzapu9sCAl6CjtWc9NuX8jg4m66V/j9VOLDUERoWh7NEwUzVPtibMjU8MPh8yE+2gw6Y66oGrGAOjtktaHP69zKZx+cradw3sRhkuLy52ogxzFv/KbS47kGGWNUT2ZHkL7JfZ19EYuZPOfZGLjExin6rwehnYQQtQfvfe6h86DSZehwAsZPZ1En4B2p3WNbVylXnl07ABE2ZZ7f7QpVZZ40L6WgNV8uxG4A/w8R8I4r4MOqgsoMDWj8LWX4CmeGAzlo6Fnbb0xFP3n3Rkbb9Hh6/fXOHbdtmZCFYUON7pEt9L/y2XwWcB12rBA2YUOuWPj/T+naKNYJMgbNRMabyNauR2PIpCLNbvmpSbAn0Fy+tYB2PEJp/G31cb177jXpmFIOZXw4PgENd0S6/Pvgfg8wvh836Dku0wWOf9DiuxYcAMK2sv0uPS+0pAcSIAenpU78M+f7sEPr/DZwO0dKevtZBtzBeYS0pt0TeQfA02LsB992BjJPw+Az8iWaUye/nnnlhyN/zxKdu6vhpFbRjRaDUsF1t0cMa1GaZon5jwDm4CXdqsnj/nOjGhMvTsvP1uZca1p1Ng8HZMpx+PY8f267n2rOjn/1dhbSZMdDBoFTwx0o9pbwdexVGZeUHAKgM2DFobNXVg8woWDkimwkkIYD3vZO2XNHAsAxkyD3bVvfURpJ3fCIv0x2VwZIgC3/QaxbkSGD1THbU9zV/fC/bBJZIKDnvuiGN3GevQ12X0uhWbZfb15+g8fx/kw0xkIlBg0ym44GmQL0HrKuj6PxIZaajyiCA42RCrKpu22/Dc2mCWZ/G4AaN9oM/BMrjA5/WvErAGWPY4TLKl6Hc8fOZswx+/y97F0B8TY36UdVF0dz54dz0PubP9QMk9LQW7rigSDH0qi6Bs7IlDzLq2mTVu71z3PJlcI2DSui+KHjOLjRa3PW3gPCe5lbxCEAB29LVyUwDGY0BlKjth7A2gQ5WhVWcPGw4D5dSHgeR0ZS8uO1UdnCYCVkTRwnSq971qNd6uyJIGASA5GDTfo5jnVugrkycs9RAAOLP2+Ncpl4enl05dbzxAABJ1yy45eiUodvBSr33w2FsICJaCaQVZ/ONgkQDrxCgKki9FQDr7G1G02YxNu+a/hVox/gMuw0AL3PO99MsqHSMvn4cutg76Ws8rwLZsgavcn1Lk0fFN0FQ9dHU4Q+dpoG+AOkC+lat0UEnGdU3mwU9pPkvZl0sGe93aAFLaswSGjpXKwPM8KGU9I7cuUD4cBFjSKV9Y6QY55s5udTqlUz0fJLnrXhfMvCrN3lW61TK6Jy9IZ1FEABhPBF3ZaSzYA7d0RYLVOSAjDzuMSGaYXaw8PQo/sw+sxfdynxkK9MEpWRG5vM8V7+8aa+BMX9fAMPAJPMsauNbu8N34RzrNhlNIDTinDwvoiEHQ6Hsg/Mx5WX4CrZMP4vbBwdTXralnq9Fj9Ciz0BRe6nzQNoDrbNCt+cU9lWD1PPrXgLcBYmu+zoT0qNKUJBVYRiC8SQeOCz9sWgDKWHphxNG4uOAbrgcnShqKPAAlmGgDKZaKzyXjQOQZCVb7wgG+KZYRVNL2vR9U6ovFQN+B1XDQXJD4RCuQFb7S2ZUBisI9CwfC2JXzgj2Ivs7gEOBX9sAVEBwov8d/XwQ5M9AMXY4HfQUkuvlcXofy4zM0VZVLoZP0Z5OURSqKkGk/BOCUsSAJIhcrBrJt4C/LuKT/5l1/yZlRoH7e63MA4EoK2tmgy0Cn9zlt8usyMPsRCLufBr/DQmTsjVLsAmyHwcKvYSuVywdowbJB0ArQr0BPgZ6U78Co1K+wAQZOFvhV7m/ZdXE66GjQu0GzQMeAZFfNQ6qEj15F/Cy0FfQ66Deg34F+D1oF2gqfd+HTSoEd0qG6ECT3/TtBffWWe/Z7oFugV92Nn3CuVAWYya08GfR20LuqFNfvK1H/JZDg+muQ7E5q1eeQxxITAfo6JlA9qgGzMuwq3MPiWP/KM11eKfNz0GOg5/A83Y9P1QJf4CUTwQmgE0GyeeT7QDobzIOxxSK7050JDJ+wKDO+KAw4Y7Hqf8dWmTfVf2+SqD/4Bvz5e9hQ+H5wfODs1mzyfJ8BDx3SoM9e68PV+y3fAn96vU7Zm8C1b1OBMyXYkofb8SDpkEmn/DBQ7YGHzm3lxhMHSql9iiPl3aprQL8FvQp6GbQNzix9AFbFdSjwkB+sGnUBG2uBCuSyEAEiQASIABFQQQC/cwxcB0Z2G6osBUkQ+yyoDbQSfYG9+ExcqphPxIWyQZT022qB6tvwv0rWDvjmWa4AVhL4OV/gG4l/ZJB7J0h2wN0F3aUDzUIEnEPA28DVOSSpEBEgAkSACBABIuA8AgxcU7tIBrBXgdpBK0CYsKvMEMggtwQ6QkNAEqD2JRkQL0v5JgK/L5TFWNpJBGwiwMDVJtqURQSIABEgAkSACOSKAAPXXOEvuvB7YOCnELh6nY5ZdCfRPn8RKGJ6hr/eoOZEgAgQASJABIgAESACPiLwIJS+mEGrj66jzr4gwMDVF09RTyJABIgAESACRIAIEAEXEZCN7D6GoDXVGmAXDaJORMBFBBi4uugV6kQEiAARIAJEgAgQASLgAwKywec5CFplcyMWIkAEFBFg4KoILlkTASJABIgAESACRIAIFBaBlbDsjxC0biyshTSMCDiEAANXh5xBVYgAESACRIAIEAEiQAS8QOA/oeWpCFoleGUhAkTAAgIMXC2ATBFEgAgQASJABIgAESAChUHgSVhyGoJWeT0QCxEgApYQYOBqCWiKIQJEgAgQASJABIgAEfAegQdgwVwErZu9t4QGEAHPEGDg6pnDqC4RIAJEgAgQASJABIhALgjcDqkfRdC6KxfpFEoESo4AA9eSNwCaTwSIABEgAkSACBABIjAgAv+AgPVPQfsHrMkKRIAIqCAwWIUrmRIBIkAEiAARIAJEgAgQAf8RkNnVv0DA+h3/TaEFRMBvBBi4+u0/ak8EiAARIAJEgAgQASKgg8BLYHsegtYXddiTKxEgAkkQYKpwErRYlwgQASJABIgAESACRKAMCHwXRp7IoLUMrqaNviDAGVdfPEU9iQARIAJEgAgQASJABLQR6ICAzyNglY2YWIgAEXAIAQauDjmDqhABIkAEiAARIAJEgAjkhsDvIPkTCFrlk4UIEAHHEGCqsGMOoTpEgAgQASJABIgAESACVhHYC2nfAJ3EoNUq7hRGBBIhwBnXRHCxMhEgAkSACBABIkAEiECBEHgUtlyGgPX3BbKJphCBQiLAGddCupVGEQEiQASIABEgAkSACDRBYC3OXYiA9f0MWpugxFNEwCEEGLg65AyqQgSIABEgAkSACBABIqCKwH5w/ybobQhY71GVROZEgAgYRYCpwkbhJDMiQASIABEgAkSACBABRxH4KfT6WwSsLziqH9UiAkSgCQIMXJuAw1NEgAgQASJABIgAESACXiPQBe3/FXQtAtbnvLaEyhOBkiPAwLXkDYDmEwEiQASIABEgAkSggAjsg013g76OgPWlAtpHk4hA6RBg4Fo6l9NgIkAEiAARIAJEgAgUFoE9sOx20HUIWNsKayUNIwIlRICBawmdTpOJABEgAkSACBABIlAwBCQN+C7Q3QhY1xfMNppDBIgAEGDgymZABIgAESACRIAIEAEi4CMCq6D090DfRbD6nz4aQJ2JABGIjwAD1/hYsSYRIAJEgAgQASJABIhAvgjsgHjZbElmVx9FwCqbL7EQASJQAgQYuJbAyTSRCBABIkAEiAARIAKeItAJvf8D9AjoUfkfwaocYyECRKBkCDBwLZnDaS4RIAJEgAgQASJABBxGQHYDfgYkQaoEq08gUN2FTxYiQARKjgAD15I3AJpPBIgAESACRIAIEIEcEOiAzP8CvdyHXkKgKunALESACBCBXggwcO0FB78QASJABIgAESACREANgf3gLAHbzuqn/F+kNZqSwru9B0kA2vP7NnxfCZJg9XUEqBE+WYgAESACsRBg4BoLJlYiAkSACBABIkAEiEAsBPai1jLQr0GvguRdou1CCNS24JOFCBABIkAEUiDAwDUFaLyECBABIkAEiAARIAJVBGTG9CnQ/aDHQc8iQN2DTxYiQASIABEwiAADV4NgkhURIAJEgAgQASJQGgSWwNI7QYsRqG4ojdU0lAgQASJABIgAESACRIAIEAEiQAR0EYiiaAwobdmGC/8RdIyuluROBIgAESACRIAIEAEiQASIABEgAqVFAEFnmsB1J677Bmh8aYGj4USACBABIkAEiAARIAJEgAgQASJgB4EUgesduGayHe0ohQgQASJABIgAESACRIAIEAEiQARKj0CCwPUl1D2j9IARACJABIgAESACRIAIEAEiQASIABGwi0DMwPWfUW+4Xc0ojQgQASJABIgAESACRIAIEAEiQASIABAYIHDdhfMXEigiQASIABEgAkSACBABIkAEiAARIAK5IdAkcF2Hc+/NTTEKJgJEgAgQASJABIgAESACRIAIEAEiIAg0CFxX4fgsIkQEiAARIAJEgAgQASJABIgAESACRCB3BOoErqtx7IjcFaMCRIAIEAEiQASIABEgAkSACBABIkAEBIE+gesWfJ9NZIgAESACRIAIEAEiQASIABEgAkSACDiDQI/AdT/+/4AzilERIkAEiAARIAJEgAgQASJABIgAESACgkCPwPXviQgRIAJEgAgQASJABIgAESACRIAIEAHnEKgGrk/hc5BzylEhIkAEiAARIAJEgAgQASJABIgAESACCFhHgo4lEkSACBABIkAEiAARIAJEgAgQASJABIgAESACRIAIEAFjCPx/2P3JeG4VmJoAAAAASUVORK5CYII=">>). logo_fill() -> jlib:decode_base64(<<"iVBORw0KGgoAAAANSUhEUgAAAAYAAAA3BAMAAADdxCZzA" diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 3a03acc19ce..8f940d318cd 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -305,7 +305,7 @@ write_last_lines(F, Images_dir, _FileFormat) -> fw(F, <<"
    \"Powered">>, + "rd.png\" alt=\"Powered by ejabberd - robust, scalable and extensible XMPP server\"/>">>, [Images_dir]), fw(F, <<" Date: Tue, 1 Dec 2015 14:05:54 +0300 Subject: [PATCH 371/695] Fix archive preference retreiving (#848) --- src/mod_mam.erl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index eb72ad8a6bf..87ff8e5e16a 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -310,6 +310,24 @@ process_iq(#jid{luser = LUser, lserver = LServer}, catch _:_ -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]} end; +process_iq(#jid{luser = LUser, lserver = LServer}, + #jid{lserver = LServer}, + #iq{type = get, sub_el = #xmlel{name = <<"prefs">>}} = IQ) -> + Prefs = get_prefs(LUser, LServer), + Default = jlib:atom_to_binary(Prefs#archive_prefs.default), + JFun = fun(L) -> + [#xmlel{name = <<"jid">>, + children = [{xmlcdata, jid:to_string(J)}]} + || J <- L] + end, + Always = #xmlel{name = <<"always">>, + children = JFun(Prefs#archive_prefs.always)}, + Never = #xmlel{name = <<"never">>, + children = JFun(Prefs#archive_prefs.never)}, + IQ#iq{type = result, + sub_el = [#xmlel{name = <<"prefs">>, + attrs = [{<<"default">>, Default}], + children = [Always, Never]}]}; process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. From e5ae35c66b54e770e3b5ac37007b9decf13c3a44 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Tue, 1 Dec 2015 19:17:51 +0100 Subject: [PATCH 372/695] Update cache_tab app name --- mix.exs | 6 +++--- rebar.config.script | 2 +- src/ejabberd_app.erl | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mix.exs b/mix.exs index fcc2973fa92..e8e34c47e57 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.09.0", + version: "15.11.0", elixir: "~> 1.0", elixirc_paths: ["lib"], compile_path: ".", @@ -18,7 +18,7 @@ defmodule Ejabberd.Mixfile do [mod: {:ejabberd_app, []}, applications: [:ssl], included_applications: [:p1_logger, :p1_yaml, :p1_tls, :p1_xml, - :p1_stringprep, :p1_zlib, :p1_cache_tab, + :p1_stringprep, :p1_zlib, :cache_tab, :mnesia, :p1_utils, :p1_iconv, :esip, :p1_stun, :p1_mysql, :p1_pgsql, :eredis, :oauth2, :xmlrpc]] end @@ -36,7 +36,7 @@ defmodule Ejabberd.Mixfile do {:p1_tls, git: "https://github.com/processone/tls"}, {:p1_stringprep, git: "https://github.com/processone/stringprep"}, {:p1_zlib, git: "https://github.com/processone/zlib"}, - {:p1_cache_tab, git: "https://github.com/processone/cache_tab"}, + {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.1"}, {:p1_utils, git: "https://github.com/processone/p1_utils"}, {:p1_iconv, git: "https://github.com/processone/eiconv"}, {:esip, git: "https://github.com/processone/p1_sip"}, diff --git a/rebar.config.script b/rebar.config.script index dd005d455fd..e47890036d1 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -52,7 +52,7 @@ SrcDirs = lists:foldl( Acc end, [], Cfg), -Deps = [{p1_cache_tab, ".*", {git, "https://github.com/processone/cache_tab"}}, +Deps = [{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.1"}}}, {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}}, {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 6e392150479..7d94a6276ad 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -257,7 +257,7 @@ start_apps() -> ejabberd:start_app(p1_xml), ejabberd:start_app(p1_stringprep), ejabberd:start_app(p1_zlib), - ejabberd:start_app(p1_cache_tab). + ejabberd:start_app(cache_tab). opt_type(net_ticktime) -> fun (P) when is_integer(P), P > 0 -> P end; From ff22782752f24ff0f93bdb81b0ba91b917a740c3 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 2 Dec 2015 01:50:30 +0100 Subject: [PATCH 373/695] List in Service Disco non-empty rooms and provide Node for empty (EJAB-343) --- src/mod_muc.erl | 46 +++++++++++++++++--------------------------- src/mod_muc_room.erl | 16 ++++++++++++--- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 13e07499498..b4038dbc8d8 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -232,11 +232,12 @@ remove_room_mam(LServer, Host, Name) -> process_iq_disco_items(Host, From, To, #iq{lang = Lang} = IQ) -> Rsm = jlib:rsm_decode(IQ), + DiscoNode = xml:get_tag_attr_s(<<"node">>, IQ#iq.sub_el), Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_ITEMS}], - children = iq_disco_items(Host, From, Lang, Rsm)}]}, + children = iq_disco_items(Host, From, Lang, DiscoNode, Rsm)}]}, ejabberd_router:route(To, From, jlib:iq_to_xml(Res)). can_use_nick(_ServerHost, _Host, _JID, <<"">>) -> false; @@ -752,37 +753,28 @@ iq_disco_info(ServerHost, Lang) -> [] end. -iq_disco_items(Host, From, Lang, none) -> - lists:zf(fun (#muc_online_room{name_host = - {Name, _Host}, - pid = Pid}) -> - case catch gen_fsm:sync_send_all_state_event(Pid, - {get_disco_item, - From, Lang}, - 100) - of - {item, Desc} -> - flush(), - {true, - #xmlel{name = <<"item">>, +iq_disco_items(Host, From, Lang, <<>>, none) -> + XmlEmpty = #xmlel{name = <<"item">>, attrs = - [{<<"jid">>, - jid:to_string({Name, Host, - <<"">>})}, - {<<"name">>, Desc}], - children = []}}; - _ -> false - end - end, get_vh_rooms(Host)); -iq_disco_items(Host, From, Lang, Rsm) -> + [{<<"jid">>, <<"conference.localhost">>}, + {<<"node">>, <<"emptyrooms">>}, + {<<"name">>, translate:translate(Lang, <<"Empty Rooms">>)}], + children = []}, + Query = {get_disco_item, only_non_empty, From, Lang}, + [XmlEmpty | iq_disco_items_list(Host, get_vh_rooms(Host), Query)]; +iq_disco_items(Host, From, Lang, <<"emptyrooms">>, none) -> + iq_disco_items_list(Host, get_vh_rooms(Host), {get_disco_item, 0, From, Lang}); +iq_disco_items(Host, From, Lang, _DiscoNode, Rsm) -> {Rooms, RsmO} = get_vh_rooms(Host, Rsm), RsmOut = jlib:rsm_encode(RsmO), + iq_disco_items_list(Host, Rooms, {get_disco_item, all, From, Lang}) ++ RsmOut. + +iq_disco_items_list(Host, Rooms, Query) -> lists:zf(fun (#muc_online_room{name_host = {Name, _Host}, pid = Pid}) -> case catch gen_fsm:sync_send_all_state_event(Pid, - {get_disco_item, - From, Lang}, + Query, 100) of {item, Desc} -> @@ -797,9 +789,7 @@ iq_disco_items(Host, From, Lang, Rsm) -> children = []}}; _ -> false end - end, - Rooms) - ++ RsmOut. + end, Rooms). get_vh_rooms(Host, #rsm_in{max=M, direction=Direction, id=I, index=Index})-> AllRooms = lists:sort(get_vh_rooms(Host)), diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index bc712b359af..9f31907c3da 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -712,10 +712,20 @@ handle_event({set_affiliations, Affiliations}, handle_event(_Event, StateName, StateData) -> {next_state, StateName, StateData}. -handle_sync_event({get_disco_item, JID, Lang}, _From, StateName, StateData) -> - Reply = get_roomdesc_reply(JID, StateData, - get_roomdesc_tail(StateData, Lang)), +handle_sync_event({get_disco_item, Filter, JID, Lang}, _From, StateName, StateData) -> + Len = ?DICT:fold(fun(_, _, Acc) -> Acc + 1 end, 0, + StateData#state.users), + Reply = case (Filter == all) or (Filter == Len) or ((Filter /= 0) and (Len /= 0)) of + true -> + get_roomdesc_reply(JID, StateData, + get_roomdesc_tail(StateData, Lang)); + false -> + false + end, {reply, Reply, StateName, StateData}; +%% This clause is only for backwards compatibility +handle_sync_event({get_disco_item, JID, Lang}, From, StateName, StateData) -> + handle_sync_event({get_disco_item, any, JID, Lang}, From, StateName, StateData); handle_sync_event(get_config, _From, StateName, StateData) -> {reply, {ok, StateData#state.config}, StateName, From 086fbc6a500ab3dd2c73ca852373c49434b8b0c7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 2 Dec 2015 02:32:14 +0100 Subject: [PATCH 374/695] Only filter rooms in Service Disco when more than 100 (EJAB-343) --- src/mod_muc.erl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index b4038dbc8d8..867f8d387b4 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -82,6 +82,8 @@ -define(PROCNAME, ejabberd_mod_muc). +-define(MAX_ROOMS_DISCOITEMS, 100). + %%==================================================================== %% API %%==================================================================== @@ -754,6 +756,14 @@ iq_disco_info(ServerHost, Lang) -> end. iq_disco_items(Host, From, Lang, <<>>, none) -> + Rooms = get_vh_rooms(Host), + case erlang:length(Rooms) < ?MAX_ROOMS_DISCOITEMS of + true -> + iq_disco_items_list(Host, Rooms, {get_disco_item, all, From, Lang}); + false -> + iq_disco_items(Host, From, Lang, <<"nonemptyrooms">>, none) + end; +iq_disco_items(Host, From, Lang, <<"nonemptyrooms">>, none) -> XmlEmpty = #xmlel{name = <<"item">>, attrs = [{<<"jid">>, <<"conference.localhost">>}, From e412438aba993255029af680cf558aa245861f5c Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 2 Dec 2015 12:07:29 +0100 Subject: [PATCH 375/695] When user joins logged room, he must be warned (EJAB-726) --- src/mod_muc_room.erl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 9f31907c3da..cb85f2963a1 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2193,6 +2193,15 @@ send_new_presence1(NJID, Reason, StateData) -> | Status2]; false -> Status2 end, + Status4 = case (StateData#state.config)#config.logging of + true -> + [#xmlel{name = <<"status">>, + attrs = + [{<<"code">>, <<"170">>}], + children = []} + | Status3]; + false -> Status3 + end, Packet = xml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = @@ -2207,7 +2216,7 @@ send_new_presence1(NJID, Reason, StateData) -> children = ItemEls} - | Status3]}]), + | Status4]}]), ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) From c3888cb0caf124bc921a38e8d54a9c0986b624eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 2 Dec 2015 12:39:34 +0100 Subject: [PATCH 376/695] Don't forget copying files that were compiled during `make install` --- Makefile.in | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Makefile.in b/Makefile.in index 79ac69c4cd6..6f5b1c78c52 100644 --- a/Makefile.in +++ b/Makefile.in @@ -123,12 +123,12 @@ TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(call TO_DEST_SINGLE,$(subst /, , FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path))) FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w)))) -DEPS_FILES:=$(call FILES_WILDCARD,deps/*/ebin/*.beam deps/*/ebin/*.app deps/*/priv/* deps/*/priv/lib/* deps/*/priv/bin/* deps/*/include/*.hrl deps/*/lib/*/ebin/*.beam deps/*/lib/*/ebin/*.app) -DEPS_FILES_FILTERED:=$(filter-out %/epam deps/elixir/ebin/elixir.app,$(DEPS_FILES)) -DEPS_DIRS:=$(sort deps/ $(wildcard deps/*) $(dir $(DEPS_FILES))) +DEPS_FILES=$(call FILES_WILDCARD,deps/*/ebin/*.beam deps/*/ebin/*.app deps/*/priv/* deps/*/priv/lib/* deps/*/priv/bin/* deps/*/include/*.hrl deps/*/lib/*/ebin/*.beam deps/*/lib/*/ebin/*.app) +DEPS_FILES_FILTERED=$(filter-out %/epam deps/elixir/ebin/elixir.app,$(DEPS_FILES)) +DEPS_DIRS=$(sort deps/ $(wildcard deps/*) $(dir $(DEPS_FILES))) -MAIN_FILES:=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/*.app priv/msgs/*.msg priv/lib/* include/*.hrl)) -MAIN_DIRS:=$(sort $(dir $(MAIN_FILES))) +MAIN_FILES=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/*.app priv/msgs/*.msg priv/lib/* include/*.hrl)) +MAIN_DIRS=$(sort $(dir $(MAIN_FILES))) define COPY_template $(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; $$(INSTALL) -m 644 $(1) $(call TO_DEST,$(1)) @@ -142,7 +142,10 @@ $(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))): $(call TO_DEST,deps/p1_pam/priv/bin/epam): $(LIBDIR)/%: deps/% $(call TO_DEST,deps/p1_pam/priv/bin/) $(INSTALL) -m 750 $(O_USER) $< $@ -copy-files: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES)) +copy-files: + $(MAKE) copy-files-sub + +copy-files-sub: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES)) install: all copy-files # From f9e12d900c13ce3394b7b798a955d0e838170b11 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 2 Dec 2015 17:10:23 +0100 Subject: [PATCH 377/695] No need for a top menu link as there's a top page link --- src/ejabberd_web_admin.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index ba6dfa112ab..9a6aea3afef 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -2889,7 +2889,7 @@ make_server_menu(HostMenu, NodeMenu, Lang, JID) -> Fixed2 = [Tuple || Tuple <- Fixed, is_allowed_path(BasePath, Tuple, JID)], - {Base, <<"ejabberd">>, Fixed2}. + {Base, <<"">>, Fixed2}. get_menu_items_hook({hostnode, Host, Node}, Lang) -> ejabberd_hooks:run_fold(webadmin_menu_hostnode, Host, From ba916c316240ab1b82eecdc4728ebf0dc3cb7908 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 2 Dec 2015 19:25:10 +0100 Subject: [PATCH 378/695] XEP-0198: Fix stanza counting corner case issue Don't forget to count outgoing stanzas that are processed while the ejabberd_c2s process is already waiting for stream resumption. --- src/ejabberd_c2s.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index f552964180a..b80abfabe03 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1299,8 +1299,8 @@ session_established2(El, StateData) -> fsm_next_state(session_established, NewState). wait_for_resume({xmlstreamelement, _El} = Event, StateData) -> - session_established(Event, StateData), - fsm_next_state(wait_for_resume, StateData); + Result = session_established(Event, StateData), + fsm_next_state(wait_for_resume, element(3, Result)); wait_for_resume(timeout, StateData) -> ?DEBUG("Timed out waiting for resumption of stream for ~s", [jid:to_string(StateData#state.jid)]), From daad71bc7eacc4f29b77bbed3e162cf1ca838abe Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 4 Dec 2015 13:14:39 +0100 Subject: [PATCH 379/695] trusted_proxies option not parsed correctly (#860) --- src/ejabberd_http.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 9856777710c..b764ee3670d 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -481,7 +481,8 @@ analyze_ip_xff({IPLast, Port}, XFF, Host) -> [jlib:ip_to_list(IPLast)], TrustedProxies = ejabberd_config:get_option( {trusted_proxies, Host}, - fun(TPs) -> + fun(all) -> all; + (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end, []), IPClient = case is_ipchain_trusted(ProxiesIPs, @@ -879,5 +880,6 @@ transform_listen_option(Opt, Opts) -> [Opt|Opts]. opt_type(trusted_proxies) -> - fun (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end; + fun (all) -> all; + (TPs) -> [iolist_to_binary(TP) || TP <- TPs] end; opt_type(_) -> [trusted_proxies]. From 5c329a769904c05b21173a7e3d7bd0d95fe5d66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 4 Dec 2015 15:08:43 +0100 Subject: [PATCH 380/695] Remove now() - part 1 --- src/cyrsasl_anonymous.erl | 10 +++++----- src/ejabberd.erl | 2 +- src/ejabberd_captcha.erl | 3 +-- src/ejabberd_odbc.erl | 8 +++++--- src/gen_iq_handler.erl | 4 ++-- src/mod_admin_extra.erl | 6 ++---- src/mod_configure2.erl | 3 +-- src/mod_muc_room.erl | 23 +++++++++-------------- src/mod_multicast.erl | 8 +++----- src/mod_pres_counter.erl | 3 +-- src/mod_roster.erl | 6 +++--- 11 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/cyrsasl_anonymous.erl b/src/cyrsasl_anonymous.erl index af403645ab2..adbde246d4b 100644 --- a/src/cyrsasl_anonymous.erl +++ b/src/cyrsasl_anonymous.erl @@ -43,11 +43,11 @@ stop() -> ok. mech_new(Host, _GetPassword, _CheckPassword, _CheckPasswordDigest) -> {ok, #state{server = Host}}. -mech_step(#state{server = Server}, _ClientIn) -> - User = iolist_to_binary([randoms:get_string() - | [jlib:integer_to_binary(X) - || X <- tuple_to_list(now())]]), +mech_step(#state{server = Server} = S, ClientIn) -> + User = iolist_to_binary([randoms:get_string(), + randoms:get_string(), + randoms:get_string()]), case ejabberd_auth:is_user_exists(User, Server) of - true -> {error, <<"not-authorized">>}; + true -> mech_step(S, ClientIn); false -> {ok, [{username, User}, {auth_module, ejabberd_auth_anonymous}]} end. diff --git a/src/ejabberd.erl b/src/ejabberd.erl index 14404cd4c31..3191e9817a5 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -105,7 +105,7 @@ start_app([], _Type, _StartFlag) -> ok. check_app_modules(App, StartFlag) -> - {A, B, C} = now(), + {A, B, C} = p1_time_compat:timestamp(), random:seed(A, B, C), sleep(5000), case application:get_key(App, modules) of diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 6006b28513c..4d906f3248e 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -661,8 +661,7 @@ clean_treap(Treap, CleanPriority) -> end. now_priority() -> - {MSec, Sec, USec} = now(), - -((MSec * 1000000 + Sec) * 1000000 + USec). + -p1_time_compat:system_time(micro_seconds). opt_type(captcha_cmd) -> fun (FileName) -> diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index f86dcca2e08..123f0d558c1 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -153,7 +153,8 @@ sql_call(Host, Msg) -> case ejabberd_odbc_sup:get_random_pid(Host) of none -> {error, <<"Unknown Host">>}; Pid -> - (?GEN_FSM):sync_send_event(Pid,{sql_cmd, Msg, now()}, + (?GEN_FSM):sync_send_event(Pid,{sql_cmd, Msg, + p1_time_compat:monotonic_time(milli_seconds)}, ?TRANSACTION_TIMEOUT) end; _State -> nested_op(Msg) @@ -161,7 +162,8 @@ sql_call(Host, Msg) -> keep_alive(PID) -> (?GEN_FSM):sync_send_event(PID, - {sql_cmd, {sql_query, ?KEEPALIVE_QUERY}, now()}, + {sql_cmd, {sql_query, ?KEEPALIVE_QUERY}, + p1_time_compat:monotonic_time(milli_seconds)}, ?KEEPALIVE_TIMEOUT). -spec sql_query_t(sql_query()) -> sql_query_result(). @@ -373,7 +375,7 @@ print_state(State) -> State. %%%---------------------------------------------------------------------- run_sql_cmd(Command, From, State, Timestamp) -> - case timer:now_diff(now(), Timestamp) div 1000 of + case p1_time_compat:monotonic_time(milli_seconds) - Timestamp of Age when Age < (?TRANSACTION_TIMEOUT) -> put(?NESTING_KEY, ?TOP_LEVEL_TXN), put(?STATE_KEY, State), diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index 2b712aadc42..fa2a97737eb 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -113,7 +113,8 @@ handle(Host, Module, Function, Opts, From, To, IQ) -> {one_queue, Pid} -> Pid ! {process_iq, From, To, IQ}; {queues, Pids} -> - Pid = lists:nth(erlang:phash(now(), length(Pids)), Pids), + Pid = lists:nth(erlang:phash(p1_time_compat:unique_integer(), + length(Pids)), Pids), Pid ! {process_iq, From, To, IQ}; parallel -> spawn(?MODULE, process_iq, @@ -179,4 +180,3 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- - diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index cebd5cea4e0..ee0e9d0921e 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -554,8 +554,7 @@ num_active_users(Host, Days) -> %% Code based on ejabberd/src/web/ejabberd_web_admin.erl list_last_activity(Host, Integral, Days) -> - {MegaSecs, Secs, _MicroSecs} = now(), - TimeStamp = MegaSecs * 1000000 + Secs, + TimeStamp = p1_time_compat:system_time(seconds), TS = TimeStamp - Days * 86400, case catch mnesia:dirty_select( last_activity, [{{last_activity, {'_', Host}, '$1', '_'}, @@ -620,8 +619,7 @@ delete_old_users(Days, Users) -> SecOlder = Days*24*60*60, %% Get current time - {MegaSecs, Secs, _MicroSecs} = now(), - TimeStamp_now = MegaSecs * 1000000 + Secs, + TimeStamp_now = p1_time_compat:system_time(seconds), %% For a user, remove if required and answer true F = fun({LUser, LServer}) -> diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index efe665d2305..109df2455fa 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -186,8 +186,7 @@ process_get(#xmlel{name = <<"last">>, attrs = Attrs}) -> {'EXIT', _Reason} -> {error, ?ERR_INTERNAL_SERVER_ERROR}; Vals -> - {MegaSecs, Secs, _MicroSecs} = now(), - TimeStamp = MegaSecs * 1000000 + Secs, + TimeStamp = p1_time_compat:system_time(seconds), Str = list_to_binary( [[jlib:integer_to_binary(TimeStamp - V), <<" ">>] || V <- Vals]), diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index cb85f2963a1..38fed6eab2c 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -149,7 +149,7 @@ normal_state({route, From, <<"">>, case xml:get_attr_s(<<"type">>, Attrs) of <<"groupchat">> -> Activity = get_user_activity(From, StateData), - Now = now_to_usec(now()), + Now = p1_time_compat:system_time(micro_seconds), MinMessageInterval = trunc(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, min_message_interval, fun(MMI) when is_number(MMI) -> MMI end, 0) @@ -288,7 +288,7 @@ normal_state({route, From, <<"">>, (StateData#state.config)#config.voice_request_min_interval, BareFrom = jid:remove_resource(jid:tolower(From)), - NowPriority = -now_to_usec(now()), + NowPriority = -p1_time_compat:system_time(micro_seconds), CleanPriority = NowPriority + MinInterval * 1000000, @@ -472,7 +472,7 @@ normal_state({route, From, Nick, #xmlel{name = <<"presence">>} = Packet}, StateData) -> Activity = get_user_activity(From, StateData), - Now = now_to_usec(now()), + Now = p1_time_compat:system_time(micro_seconds), MinPresenceInterval = trunc(gen_mod:get_module_opt(StateData#state.server_host, mod_muc, min_presence_interval, @@ -1526,7 +1526,7 @@ store_user_activity(JID, UserActivity, StateData) -> 0) * 1000), Key = jid:tolower(JID), - Now = now_to_usec(now()), + Now = p1_time_compat:system_time(micro_seconds), Activity1 = clean_treap(StateData#state.activity, {1, -Now}), Activity = case treap:lookup(Key, Activity1) of @@ -1997,9 +1997,8 @@ count_stanza_shift(Nick, Els, StateData) -> Shift1 = case Seconds of false -> 0; _ -> - Sec = - calendar:datetime_to_gregorian_seconds(calendar:now_to_universal_time(now())) - - Seconds, + Sec = calendar:datetime_to_gregorian_seconds(calendar:universal_time()) + - Seconds, count_seconds_shift(Sec, HL) end, MaxStanzas = extract_history(Els, <<"maxstanzas">>), @@ -2284,9 +2283,6 @@ send_existing_presences1(ToJID, StateData) -> end, (?DICT):to_list(StateData#state.nicks)). -now_to_usec({MSec, Sec, USec}) -> - (MSec * 1000000 + Sec) * 1000000 + USec. - change_nick(JID, Nick, StateData) -> LJID = jid:tolower(JID), {ok, #user{nick = OldNick}} = (?DICT):find(LJID, @@ -2454,7 +2450,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> false -> false; _ -> true end, - TimeStamp = now(), + TimeStamp = p1_time_compat:timestamp(), AddrPacket = case (StateData#state.config)#config.anonymous of true -> Packet; false -> @@ -4518,7 +4514,7 @@ handle_roommessage_from_nonparticipant(Packet, Lang, %% Check in the packet is a decline. %% If so, also returns the splitted packet. -%% This function must be catched, +%% This function must be catched, %% because it crashes when the packet is not a decline message. check_decline_invitation(Packet) -> #xmlel{name = <<"message">>} = Packet, @@ -4546,7 +4542,7 @@ send_decline_invitation({Packet, XEl, DEl, ToJID}, Packet2 = replace_subelement(Packet, XEl2), ejabberd_router:route(RoomJID, ToJID, Packet2). -%% Given an element and a new subelement, +%% Given an element and a new subelement, %% replace the instance of the subelement in element with the new subelement. replace_subelement(#xmlel{name = Name, attrs = Attrs, children = SubEls}, @@ -4630,4 +4626,3 @@ has_body_or_subject(Packet) -> (#xmlel{name = <<"subject">>}) -> false; (_) -> true end, Packet#xmlel.children). - diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 1c8525f52fe..bc166b81d35 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -937,8 +937,7 @@ create_cache() -> {attributes, record_info(fields, multicastc)}]). add_response(RServer, Response) -> - Secs = - calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(now())), + Secs = calendar:datetime_to_gregorian_seconds(calendar:local_time()), mnesia:dirty_write(#multicastc{rserver = RServer, response = Response, ts = Secs}). @@ -949,8 +948,7 @@ search_server_on_cache(RServer, _LServerS, Maxmins) -> case look_server(RServer) of not_cached -> not_cached; {cached, Response, Ts} -> - Now = - calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(now())), + Now = calendar:datetime_to_gregorian_seconds(calendar:local_time()), case is_obsolete(Response, Ts, Now, Maxmins) of false -> {cached, Response}; true -> {obsolete, Response} @@ -978,7 +976,7 @@ purge() -> Maxmins_positive = (?MAXTIME_CACHE_POSITIVE), Maxmins_negative = (?MAXTIME_CACHE_NEGATIVE), Now = - calendar:datetime_to_gregorian_seconds(calendar:now_to_datetime(now())), + calendar:datetime_to_gregorian_seconds(calendar:local_time()), purge(Now, {Maxmins_positive, Maxmins_negative}). purge(Now, Maxmins) -> diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index 72db36084de..9834c4360a9 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -78,8 +78,7 @@ update(Server, JID, Dir) -> TimeInterval = gen_mod:get_module_opt(Server, ?MODULE, interval, fun(I) when is_integer(I), I>0 -> I end, 60), - {MegaSecs, Secs, _MicroSecs} = now(), - TimeStamp = MegaSecs * 1000000 + Secs, + TimeStamp = p1_time_compat:system_time(seconds), case read(Dir) of undefined -> write(Dir, diff --git a/src/mod_roster.erl b/src/mod_roster.erl index c75e128f5e8..eb987a2df21 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -223,7 +223,7 @@ write_roster_version_t(LUser, LServer) -> write_roster_version(LUser, LServer, true). write_roster_version(LUser, LServer, InTransaction) -> - Ver = p1_sha:sha(term_to_binary(now())), + Ver = p1_sha:sha(term_to_binary(p1_time_compat:unique_integer())), write_roster_version(LUser, LServer, InTransaction, Ver, gen_mod:db_type(LServer, ?MODULE)), Ver. @@ -256,7 +256,7 @@ write_roster_version(LUser, LServer, _InTransaction, Ver, ejabberd_riak:put(#roster_version{us = US, version = Ver}, roster_version_schema()). -%% Load roster from DB only if neccesary. +%% 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 @@ -1391,7 +1391,7 @@ update_roster_table() -> end. %% Convert roster table to support virtual host -%% Convert roster table: xattrs fields become +%% Convert roster table: xattrs fields become update_roster_version_table() -> Fields = record_info(fields, roster_version), case mnesia:table_info(roster_version, attributes) of From 0a846d03bf4c1a07a1b2bfcff9e81c0785533598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Sun, 6 Dec 2015 15:58:46 +0100 Subject: [PATCH 381/695] More now() removal --- src/ejabberd_config.erl | 3 +-- src/ejabberd_odbc_sup.erl | 2 +- src/mod_caps.erl | 2 +- src/mod_offline.erl | 15 +++++++-------- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 6e738581121..75d56509ec4 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -69,8 +69,7 @@ start() -> State0 = read_file(Config), State = validate_opts(State0), %% This start time is used by mod_last: - {MegaSecs, Secs, _} = now(), - UnixTime = MegaSecs*1000000 + Secs, + UnixTime = p1_time_compat:system_time(seconds), SharedKey = case erlang:get_cookie() of nocookie -> p1_sha:sha(randoms:get_string()); diff --git a/src/ejabberd_odbc_sup.erl b/src/ejabberd_odbc_sup.erl index fa44853487c..de2ffead85d 100644 --- a/src/ejabberd_odbc_sup.erl +++ b/src/ejabberd_odbc_sup.erl @@ -102,7 +102,7 @@ get_pids(Host) -> get_random_pid(Host) -> case get_pids(Host) of [] -> none; - Pids -> lists:nth(erlang:phash(now(), length(Pids)), Pids) + Pids -> lists:nth(erlang:phash(p1_time_compat:unique_integer(), length(Pids)), Pids) end. add_pid(Host, Pid) -> diff --git a/src/mod_caps.erl b/src/mod_caps.erl index eb886b19a73..f2eeb490361 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -648,7 +648,7 @@ gb_trees_fold_iter(F, Acc, Iter) -> end. now_ts() -> - {MegaSecs, Secs, _} = now(), MegaSecs * 1000000 + Secs. + {MegaSecs, Secs, _} = p1_time_compat:system_time(seconds). is_valid_node(Node) -> case str:tokens(Node, <<"#">>) of diff --git a/src/mod_offline.erl b/src/mod_offline.erl index c41770d3201..dca3996f4ec 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -309,7 +309,7 @@ store_packet(From, To, Packet) -> case check_event(From, To, Packet) of true -> #jid{luser = LUser, lserver = LServer} = To, - TimeStamp = now(), + TimeStamp = p1_time_compat:timestamp(), #xmlel{children = Els} = Packet, Expire = find_x_expire(TimeStamp, Els), gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) ! @@ -441,7 +441,7 @@ pop_offline_messages(Ls, LUser, LServer, mnesia) -> end, case mnesia:transaction(F) of {atomic, Rs} -> - TS = now(), + TS = p1_time_compat:timestamp(), Ls ++ lists:map(fun (R) -> offline_msg_to_route(LServer, R) @@ -487,7 +487,7 @@ pop_offline_messages(Ls, LUser, LServer, riak) -> fun(#offline_msg{timestamp = T}) -> ok = ejabberd_riak:delete(offline_msg, T) end, Rs), - TS = now(), + TS = p1_time_compat:timestamp(), Ls ++ lists:map( fun (R) -> offline_msg_to_route(LServer, R) @@ -513,7 +513,7 @@ remove_expired_messages(Server) -> gen_mod:db_type(LServer, ?MODULE)). remove_expired_messages(_LServer, mnesia) -> - TimeStamp = now(), + TimeStamp = p1_time_compat:timestamp(), F = fun () -> mnesia:write_lock_table(offline_msg), mnesia:foldl(fun (Rec, _Acc) -> @@ -538,8 +538,7 @@ remove_old_messages(Days, Server) -> gen_mod:db_type(LServer, ?MODULE)). remove_old_messages(Days, _LServer, mnesia) -> - {MegaSecs, Secs, _MicroSecs} = now(), - S = MegaSecs * 1000000 + Secs - 60 * 60 * 24 * Days, + S = p1_time_compat:system_time(seconds) - 60 * 60 * 24 * Days, MegaSecs1 = S div 1000000, Secs1 = S rem 1000000, TimeStamp = {MegaSecs1, Secs1, 0}, @@ -949,7 +948,7 @@ get_messages_subset2(Max, Length, MsgsAll, DBType) MsgsLastN = lists:nthtail(Length - FirstN - FirstN, Msgs2), NoJID = jid:make(<<"...">>, <<"...">>, <<"">>), - IntermediateMsg = #offline_msg{timestamp = now(), + IntermediateMsg = #offline_msg{timestamp = p1_time_compat:timestamp(), from = NoJID, to = NoJID, packet = #xmlel{name = <<"...">>, attrs = [], @@ -1113,7 +1112,7 @@ import(LServer) -> {_, _, _} = Now -> Now; undefined -> - now() + p1_time_compat:timestamp() end, Expire = find_x_expire(TS, El#xmlel.children), #offline_msg{us = {LUser, LServer}, From b9f751e0997dede2ee1e61612117d52757ad208a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 7 Dec 2015 10:26:51 +0100 Subject: [PATCH 382/695] Fix bug in last commit --- src/mod_caps.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_caps.erl b/src/mod_caps.erl index f2eeb490361..ac4499a35c4 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -648,7 +648,7 @@ gb_trees_fold_iter(F, Acc, Iter) -> end. now_ts() -> - {MegaSecs, Secs, _} = p1_time_compat:system_time(seconds). + p1_time_compat:system_time(seconds). is_valid_node(Node) -> case str:tokens(Node, <<"#">>) of From 29db302808f94697689d3010b3b589f9a00333b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 7 Dec 2015 16:08:57 +0100 Subject: [PATCH 383/695] More now() replacements --- src/adhoc.erl | 2 +- src/ejabberd_auth_anonymous.erl | 2 +- src/ejabberd_auth_external.erl | 3 +-- src/ejabberd_c2s.erl | 16 ++++++---------- src/ejabberd_http_bind.erl | 11 +++-------- src/ejabberd_riak_sup.erl | 2 +- src/ejabberd_router.erl | 4 ++-- src/ejabberd_s2s.erl | 9 +++++---- src/ejabberd_s2s_out.erl | 5 ++--- src/ejabberd_web_admin.erl | 3 +-- src/extauth.erl | 3 +-- src/mod_fail2ban.erl | 11 +++-------- src/mod_last.erl | 6 +++--- src/mod_mam.erl | 6 +++--- src/mod_muc.erl | 2 +- src/mod_muc_admin.erl | 2 +- src/mod_muc_log.erl | 8 ++++---- src/mod_register.erl | 3 +-- src/mod_sip_proxy.erl | 6 ++---- src/mod_sip_registrar.erl | 4 ++-- src/mod_time.erl | 5 ++--- src/randoms.erl | 2 +- src/shaper.erl | 9 +++------ 23 files changed, 50 insertions(+), 74 deletions(-) diff --git a/src/adhoc.erl b/src/adhoc.erl index a68b54d8926..f2bd2dbeee4 100644 --- a/src/adhoc.erl +++ b/src/adhoc.erl @@ -121,7 +121,7 @@ produce_response( }) -> SessionID = if is_binary(ProvidedSessionID), ProvidedSessionID /= <<"">> -> ProvidedSessionID; - true -> jlib:now_to_utc_string(now()) + true -> jlib:now_to_utc_string(p1_time_compat:timestamp()) end, case Actions of [] -> diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index 7a1d8fe84f0..ab04534f2ec 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -56,7 +56,7 @@ %% Create the anonymous table if at least one virtual host has anonymous features enabled %% Register to login / logout events -record(anonymous, {us = {<<"">>, <<"">>} :: {binary(), binary()}, - sid = {now(), self()} :: ejabberd_sm:sid()}). + sid = {p1_time_compat:timestamp(), self()} :: ejabberd_sm:sid()}). start(Host) -> %% TODO: Check cluster mode diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index cc3a781cef4..393bf1e021d 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -270,8 +270,7 @@ set_password_internal(User, Server, Password) -> Password). is_fresh_enough(TimeStampLast, CacheTime) -> - {MegaSecs, Secs, _MicroSecs} = now(), - Now = MegaSecs * 1000000 + Secs, + Now = p1_time_compat:system_time(seconds), TimeStampLast + CacheTime > Now. %% @spec (User, Server) -> online | never | mod_last_required | TimeStamp::integer() diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b80abfabe03..fbea2a8e347 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -326,7 +326,7 @@ init([{SockMod, Socket}, Opts]) -> xml_socket = XMLSocket, zlib = Zlib, tls = TLS, tls_required = StartTLSRequired, tls_enabled = TLSEnabled, tls_options = TLSOpts, - sid = {now(), self()}, streamid = new_id(), + sid = {p1_time_compat:timestamp(), self()}, streamid = new_id(), access = Access, shaper = Shaper, ip = IP, mgmt_state = StreamMgmtState, mgmt_max_queue = MaxAckQueue, @@ -1011,9 +1011,7 @@ resource_conflict_action(U, S, R) -> acceptnew -> {accept_resource, R}; closenew -> closenew; setresource -> - Rnew = iolist_to_binary([randoms:get_string() - | [jlib:integer_to_binary(X) - || X <- tuple_to_list(now())]]), + Rnew = iolist_to_binary([randoms:get_string(),randoms:get_string(),randoms:get_string()]), {accept_resource, Rnew} end. @@ -1041,9 +1039,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> R = case jid:resourceprep(R1) of error -> error; <<"">> -> - iolist_to_binary([randoms:get_string() - | [jlib:integer_to_binary(X) - || X <- tuple_to_list(now())]]); + iolist_to_binary([randoms:get_string(),randoms:get_string(),randoms:get_string()]); Resource -> Resource end, case R of @@ -2047,7 +2043,7 @@ presence_update(From, Packet, StateData) -> FromUnavail = (StateData#state.pres_last == undefined), ?DEBUG("from unavail = ~p~n", [FromUnavail]), NewStateData = StateData#state{pres_last = Packet, - pres_timestamp = now()}, + pres_timestamp = p1_time_compat:timestamp()}, NewState = if FromUnavail -> ejabberd_hooks:run(user_available_hook, NewStateData#state.server, @@ -2791,7 +2787,7 @@ mgmt_queue_add(StateData, El) -> Num -> Num + 1 end, - NewQueue = queue:in({NewNum, now(), El}, StateData#state.mgmt_queue), + NewQueue = queue:in({NewNum, p1_time_compat:timestamp(), El}, StateData#state.mgmt_queue), NewState = StateData#state{mgmt_queue = NewQueue, mgmt_stanzas_out = NewNum}, check_queue_length(NewState). @@ -3003,7 +2999,7 @@ csi_queue_add(#state{csi_queue = Queue} = StateData, Stanza) -> true -> csi_queue_add(csi_queue_flush(StateData), Stanza); false -> From = xml:get_tag_attr_s(<<"from">>, Stanza), - NewQueue = lists:keystore(From, 1, Queue, {From, now(), Stanza}), + NewQueue = lists:keystore(From, 1, Queue, {From, p1_time_compat:timestamp(), Stanza}), StateData#state{csi_queue = NewQueue} end. diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index a3098779f39..194b099d72a 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -233,7 +233,7 @@ process_request(Data, IP, HOpts) -> (?NS_HTTP_BIND)/binary, "'/>">>}; XmppDomain -> NXmppDomain = jid:nameprep(XmppDomain), - Sid = p1_sha:sha(term_to_binary({now(), make_ref()})), + Sid = p1_sha:sha(term_to_binary({p1_time_compat:monotonic_time(), make_ref()})), case start(NXmppDomain, Sid, <<"">>, IP, HOpts) of {error, _} -> {500, ?HEADER, @@ -448,7 +448,7 @@ handle_sync_event(#http_put{payload_size = shaper_timer = NewShaperTimer}); %% HTTP GET: send packets to the client handle_sync_event({http_get, Rid, Wait, Hold}, From, StateName, StateData) -> - TNow = tnow(), + TNow = p1_time_compat:system_time(micro_seconds), if (Hold > 0) and ((StateData#state.output == []) or (StateData#state.rid < Rid)) and ((TNow - StateData#state.ctime) < (Wait*1000*1000)) and @@ -606,7 +606,7 @@ process_http_put(#http_put{rid = Rid, attrs = Attrs, end end end, - TNow = tnow(), + TNow = p1_time_compat:system_time(micro_seconds), LastPoll = if Payload == [] -> TNow; true -> 0 end, @@ -1185,11 +1185,6 @@ get_max_pause({Host, _}) -> ?MAX_PAUSE); get_max_pause(_) -> ?MAX_PAUSE. -%% Current time as integer -tnow() -> - {TMegSec, TSec, TMSec} = now(), - (TMegSec * 1000000 + TSec) * 1000000 + TMSec. - check_default_xmlns(#xmlel{name = Name, attrs = Attrs, children = Els} = El) -> diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index a971a4a3276..78d6fc6e778 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -141,7 +141,7 @@ get_pids() -> [ejabberd_riak:get_proc(I) || I <- lists:seq(1, get_pool_size())]. get_random_pid() -> - get_random_pid(now()). + get_random_pid(p1_time_compat:monotonic_time()). get_random_pid(Term) -> I = erlang:phash2(Term, get_pool_size()) + 1, diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 9daa498ee77..81fedfe0fd4 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -347,8 +347,8 @@ do_route(OrigFrom, OrigTo, OrigPacket) -> ejabberd_config:get_local_option({domain_balancing, LDstDomain}, fun(D) when is_atom(D) -> D end) of - undefined -> now(); - random -> now(); + undefined -> p1_time_compat:monotonic_time(); + random -> p1_time_compat:monotonic_time(); source -> jid:tolower(From); destination -> jid:tolower(To); bare_source -> diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index a52b4a9afbd..0e51ec0448d 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -81,7 +81,7 @@ -record(state, {}). -record(temporarily_blocked, {host = <<"">> :: binary(), - timestamp = now() :: erlang:timestamp()}). + timestamp :: integer()}). -type temporarily_blocked() :: #temporarily_blocked{}. @@ -114,9 +114,9 @@ external_host_overloaded(Host) -> "seconds", [Host, ?S2S_OVERLOAD_BLOCK_PERIOD]), mnesia:transaction(fun () -> + Time = p1_time_compat:monotonic_time(), mnesia:write(#temporarily_blocked{host = Host, - timestamp = - now()}) + timestamp = Time}) end). -spec is_temporarly_blocked(binary()) -> boolean(). @@ -125,7 +125,8 @@ is_temporarly_blocked(Host) -> case mnesia:dirty_read(temporarily_blocked, Host) of [] -> false; [#temporarily_blocked{timestamp = T} = Entry] -> - case timer:now_diff(now(), T) of + Diff = p1_time_compat:monotonic_time() - T, + case p1_time_compat:convert_time_unit(Diff, native, micro_seconds) of N when N > (?S2S_OVERLOAD_BLOCK_PERIOD) * 1000 * 1000 -> mnesia:dirty_delete_object(Entry), false; _ -> true diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 6d3b3e99a8c..6bf928282c5 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -1097,8 +1097,7 @@ get_addr_port(Server) -> ?DEBUG("srv lookup of '~s': ~p~n", [Server, HEnt#hostent.h_addr_list]), AddrList = HEnt#hostent.h_addr_list, - {A1, A2, A3} = now(), - random:seed(A1, A2, A3), + random:seed(p1_time_compat:monotonic_time()), case catch lists:map(fun ({Priority, Weight, Port, Host}) -> N = case Weight of @@ -1273,7 +1272,7 @@ wait_before_reconnect(StateData) -> cancel_timer(StateData#state.timer), Delay = case StateData#state.delay_to_retry of undefined_delay -> - {_, _, MicroSecs} = now(), MicroSecs rem 14000 + 1000; + {_, _, MicroSecs} = p1_time_compat:timestamp(), MicroSecs rem 14000 + 1000; D1 -> lists:min([D1 * 2, get_max_retry_delay()]) end, Timer = erlang:start_timer(Delay, self(), []), diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 9a6aea3afef..c4a191eb0b5 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1722,8 +1722,7 @@ user_parse_query1(Action, User, Server, Query) -> end. list_last_activity(Host, Lang, Integral, Period) -> - {MegaSecs, Secs, _MicroSecs} = now(), - TimeStamp = MegaSecs * 1000000 + Secs, + TimeStamp = p1_time_compat:system_time(seconds), case Period of <<"all">> -> TS = 0, Days = infinity; <<"year">> -> TS = TimeStamp - 366 * 86400, Days = 366; diff --git a/src/extauth.erl b/src/extauth.erl index 64220fcbec1..9b84741dcac 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -102,8 +102,7 @@ call_port(Server, Msg) -> receive {eauth, Result} -> Result end. random_instance(MaxNum) -> - {A1, A2, A3} = now(), - random:seed(A1, A2, A3), + random:seed(p1_time_compat:monotonic_time()), random:uniform(MaxNum) - 1. get_instances(Server) -> diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index abfd1273fba..523cbb3f94f 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -65,7 +65,7 @@ c2s_auth_result(false, _User, LServer, {Addr, _Port}) -> LServer, ?MODULE, c2s_max_auth_failures, fun(I) when is_integer(I), I > 0 -> I end, ?C2S_MAX_AUTH_FAILURES), - UnbanTS = unban_timestamp(BanLifetime), + UnbanTS = p1_time_compat:system_time(seconds) + BanLifetime, case ets:lookup(failed_auth, Addr) of [{Addr, N, _, _}] -> ets:insert(failed_auth, {Addr, N+1, UnbanTS, MaxFailures}); @@ -79,7 +79,7 @@ c2s_auth_result(true, _User, _Server, _AddrPort) -> check_bl_c2s(_Acc, Addr, Lang) -> case ets:lookup(failed_auth, Addr) of [{Addr, N, TS, MaxFailures}] when N >= MaxFailures -> - case TS > now() of + case TS > p1_time_compat:system_time(seconds) of true -> IP = jlib:ip_to_list(Addr), UnbanDate = format_date( @@ -139,7 +139,7 @@ handle_cast(_Msg, State) -> handle_info(clean, State) -> ?DEBUG("cleaning ~p ETS table", [failed_auth]), - Now = now(), + Now = p1_time_compat:system_time(seconds), ets:select_delete( failed_auth, ets:fun2ms(fun({_, _, UnbanTS, _}) -> UnbanTS =< Now end)), @@ -171,11 +171,6 @@ is_whitelisted(Host, Addr) -> none), acl:match_rule(Host, Access, Addr) == allow. -unban_timestamp(BanLifetime) -> - {MegaSecs, MSecs, USecs} = now(), - UnbanSecs = MegaSecs * 1000000 + MSecs + BanLifetime, - {UnbanSecs div 1000000, UnbanSecs rem 1000000, USecs}. - is_loaded_at_other_hosts(Host) -> lists:any( fun(VHost) when VHost == Host -> diff --git a/src/mod_last.erl b/src/mod_last.erl index cab29c42741..6cd598a187f 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -112,7 +112,7 @@ get_node_uptime() -> undefined -> trunc(element(1, erlang:statistics(wall_clock)) / 1000); Now -> - now_to_seconds(now()) - Now + p1_time_compat:system_time(seconds) - Now end. now_to_seconds({MegaSecs, Secs, _MicroSecs}) -> @@ -210,7 +210,7 @@ get_last_iq(IQ, SubEl, LUser, LServer) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_SERVICE_UNAVAILABLE]}; {ok, TimeStamp, Status} -> - TimeStamp2 = now_to_seconds(now()), + TimeStamp2 = p1_time_compat:system_time(seconds), Sec = TimeStamp2 - TimeStamp, IQ#iq{type = result, sub_el = @@ -232,7 +232,7 @@ get_last_iq(IQ, SubEl, LUser, LServer) -> end. on_presence_update(User, Server, _Resource, Status) -> - TimeStamp = now_to_seconds(now()), + TimeStamp = p1_time_compat:system_time(seconds), store_last_info(User, Server, TimeStamp, Status). store_last_info(User, Server, TimeStamp, Status) -> diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 87ff8e5e16a..c0756b6ebec 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -45,7 +45,7 @@ -record(archive_msg, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', id = <<>> :: binary() | '_', - timestamp = now() :: erlang:timestamp() | '_' | '$1', + timestamp = p1_time_compat:timestamp() :: erlang:timestamp() | '_' | '$1', peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', packet = #xmlel{} :: xmlel() | '_', @@ -450,7 +450,7 @@ store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> store(Pkt, _, {LUser, LServer}, Type, Peer, Nick, _Dir, mnesia) -> LPeer = {PUser, PServer, _} = jid:tolower(Peer), - TS = now(), + TS = p1_time_compat:timestamp(), ID = jlib:integer_to_binary(now_to_usec(TS)), case mnesia:dirty_write( #archive_msg{us = {LUser, LServer}, @@ -467,7 +467,7 @@ store(Pkt, _, {LUser, LServer}, Type, Peer, Nick, _Dir, mnesia) -> Err end; store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> - TSinteger = now_to_usec(now()), + TSinteger = p1_time_compat:system_time(micro_seconds), ID = TS = jlib:integer_to_binary(TSinteger), SUser = case Type of chat -> LUser; diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 867f8d387b4..385bf54b0bc 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -864,7 +864,7 @@ flush() -> receive _ -> flush() after 0 -> ok end. iq_get_unique(From) -> {xmlcdata, - p1_sha:sha(term_to_binary([From, now(), + p1_sha:sha(term_to_binary([From, p1_time_compat:timestamp(), randoms:get_string()]))}. get_nick(ServerHost, Host, From) -> diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 9df4361ca73..97ae3c6ec09 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -608,7 +608,7 @@ decide_room({_Room_name, _Host, Room_pid}, Last_allowed) -> Num_users = length(?DICT:to_list(Room_users)), History = (S#state.history)#lqueue.queue, - Ts_now = calendar:now_to_universal_time(now()), + Ts_now = calendar:universal_time(), Ts_uptime = uptime_seconds(), {Has_hist, Last} = case queue:is_empty(History) of true -> diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 8f940d318cd..996ac83a588 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -348,7 +348,7 @@ add_message_to_log(Nick1, Message, RoomJID, Opts, Room = get_room_info(RoomJID, Opts), Nick = htmlize(Nick1, FileFormat), Nick2 = htmlize_nick(Nick1, FileFormat), - Now = now(), + Now = p1_time_compat:timestamp(), TimeStamp = case Timezone of local -> calendar:now_to_local_time(Now); universal -> calendar:now_to_universal_time(Now) @@ -902,7 +902,7 @@ put_header_script(F) -> put_room_config(_F, _RoomConfig, _Lang, plaintext) -> ok; put_room_config(F, RoomConfig, Lang, _FileFormat) -> - {_, Now2, _} = now(), + {_, Now2, _} = p1_time_compat:timestamp(), fw(F, <<"
    ">>), fw(F, <<"
    - {_, Now2, _} = now(), + {_, Now2, _} = p1_time_compat:timestamp(), %% htmlize %% The default behaviour is to ignore the nofollow spam prevention on links %% (NoFollow=false) @@ -1190,7 +1190,7 @@ get_proc_name(Host) -> gen_mod:get_module_proc(Host, ?PROCNAME). calc_hour_offset(TimeHere) -> - TimeZero = calendar:now_to_universal_time(now()), + TimeZero = calendar:universal_time(), TimeHereHour = calendar:datetime_to_gregorian_seconds(TimeHere) div 3600, diff --git a/src/mod_register.erl b/src/mod_register.erl index 21c58446946..da0b805e73d 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -509,8 +509,7 @@ check_timeout(Source) -> infinity end, 600), if is_integer(Timeout) -> - {MSec, Sec, _USec} = now(), - Priority = -(MSec * 1000000 + Sec), + Priority = -p1_time_compat:system_time(seconds), CleanPriority = Priority + Timeout, F = fun () -> Treap = case mnesia:read(mod_register_ip, treap, write) diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index 53b16fd7ea3..bf297bc88d8 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -299,8 +299,7 @@ add_record_route_and_set_uri(URI, LServer, #sip{hdrs = Hdrs} = Req) -> case need_record_route(LServer) of true -> RR_URI = get_configured_record_route(LServer), - {MSecs, Secs, _} = now(), - TS = list_to_binary(integer_to_list(MSecs*1000000 + Secs)), + TS = list_to_binary(integer_to_list(p1_time_compat:system_time(seconds))), Sign = make_sign(TS, Hdrs), User = <>, NewRR_URI = RR_URI#uri{user = User}, @@ -341,8 +340,7 @@ is_signed_by_me(TS_Sign, Hdrs) -> try [TSBin, Sign] = str:tokens(TS_Sign, <<"-">>), TS = list_to_integer(binary_to_list(TSBin)), - {MSecs, Secs, _} = now(), - NowTS = MSecs*1000000 + Secs, + NowTS = p1_time_compat:system_time(seconds), true = (NowTS - TS) =< ?SIGN_LIFETIME, Sign == make_sign(TSBin, Hdrs) catch _:_ -> diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl index 4bc68f60715..44091ed391d 100644 --- a/src/mod_sip_registrar.erl +++ b/src/mod_sip_registrar.erl @@ -48,7 +48,7 @@ socket = #sip_socket{} :: #sip_socket{}, call_id = <<"">> :: binary(), cseq = 0 :: non_neg_integer(), - timestamp = now() :: erlang:timestamp(), + timestamp = p1_time_compat:timestamp() :: erlang:timestamp(), contact :: {binary(), #uri{}, [{binary(), binary()}]}, flow_tref :: reference(), reg_tref = make_ref() :: reference(), @@ -242,7 +242,7 @@ register_session(US, SIPSocket, CallID, CSeq, IsOutboundSupported, socket = SIPSocket, call_id = CallID, cseq = CSeq, - timestamp = now(), + timestamp = p1_time_compat:timestamp(), contact = Contact, expires = Expires} end, ContactsWithExpires), diff --git a/src/mod_time.erl b/src/mod_time.erl index e1146840093..4c2e6e567d6 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -56,9 +56,8 @@ process_local_iq(_From, _To, set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> - Now = now(), - Now_universal = calendar:now_to_universal_time(Now), - Now_local = calendar:now_to_local_time(Now), + Now_universal = calendar:universal_time(), + Now_local = calendar:universal_time_to_local_time(Now_universal), {UTC, UTC_diff} = jlib:timestamp_to_iso(Now_universal, utc), Seconds_diff = diff --git a/src/randoms.erl b/src/randoms.erl index 950f29fc338..b2e95b256c8 100644 --- a/src/randoms.erl +++ b/src/randoms.erl @@ -35,7 +35,7 @@ start() -> register(random_generator, spawn(randoms, init, [])). init() -> - {A1, A2, A3} = now(), random:seed(A1, A2, A3), loop(). + random:seed(p1_time_compat:monotonic_time()), loop(). loop() -> receive diff --git a/src/shaper.erl b/src/shaper.erl index c8140703c35..a2fd09dfa63 100644 --- a/src/shaper.erl +++ b/src/shaper.erl @@ -107,7 +107,7 @@ new(Name) -> new1(none) -> none; new1(MaxRate) -> #maxrate{maxrate = MaxRate, lastrate = 0.0, - lasttime = now_to_usec(now())}. + lasttime = p1_time_compat:system_time(micro_seconds)}. -spec update(shaper(), integer()) -> {shaper(), integer()}. @@ -115,7 +115,7 @@ update(none, _Size) -> {none, 0}; update(#maxrate{} = State, Size) -> MinInterv = 1000 * Size / (2 * State#maxrate.maxrate - State#maxrate.lastrate), - Interv = (now_to_usec(now()) - State#maxrate.lasttime) / + Interv = (p1_time_compat:system_time(micro_seconds) - State#maxrate.lasttime) / 1000, ?DEBUG("State: ~p, Size=~p~nM=~p, I=~p~n", [State, Size, MinInterv, Interv]), @@ -123,7 +123,7 @@ update(#maxrate{} = State, Size) -> 1 + trunc(MinInterv - Interv); true -> 0 end, - NextNow = now_to_usec(now()) + Pause * 1000, + NextNow = p1_time_compat:system_time(micro_seconds) + Pause * 1000, {State#maxrate{lastrate = (State#maxrate.lastrate + 1000000 * Size / (NextNow - State#maxrate.lasttime)) @@ -141,8 +141,5 @@ transform_options({OptName, Name, none}, Opts) when OptName == shaper -> transform_options(Opt, Opts) -> [Opt|Opts]. -now_to_usec({MSec, Sec, USec}) -> - (MSec * 1000000 + Sec) * 1000000 + USec. - opt_type(shaper) -> fun (V) -> V end; opt_type(_) -> [shaper]. From 5ac10d6555f3005306594acf5c393e2e821b66f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 7 Dec 2015 16:16:11 +0100 Subject: [PATCH 384/695] Remove now() in pubsub code --- src/mod_pubsub.erl | 6 +++--- src/node_flat.erl | 2 +- src/node_flat_odbc.erl | 4 ++-- src/pubsub_migrate.erl | 2 +- src/pubsub_subscription.erl | 2 +- src/pubsub_subscription_odbc.erl | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 089386a8981..a429eb4e03f 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3141,7 +3141,7 @@ sub_option_can_deliver(nodes, _, {subscription_type, items}) -> false; sub_option_can_deliver(_, _, {subscription_depth, all}) -> true; sub_option_can_deliver(_, Depth, {subscription_depth, D}) -> Depth =< D; sub_option_can_deliver(_, _, {deliver, false}) -> false; -sub_option_can_deliver(_, _, {expire, When}) -> now() < When; +sub_option_can_deliver(_, _, {expire, When}) -> p1_time_compat:timestamp() < When; sub_option_can_deliver(_, _, _) -> true. -spec(presence_can_deliver/2 :: @@ -3910,7 +3910,7 @@ set_cached_item({_, ServerHost, _}, Nidx, ItemId, Publisher, Payload) -> set_cached_item(Host, Nidx, ItemId, Publisher, Payload) -> case is_last_item_cache_enabled(Host) of true -> mnesia:dirty_write({pubsub_last_item, Nidx, ItemId, - {now(), jid:tolower(jid:remove_resource(Publisher))}, + {p1_time_compat:timestamp(), jid:tolower(jid:remove_resource(Publisher))}, Payload}); _ -> ok end. @@ -4218,7 +4218,7 @@ string_to_ljid(JID) -> -spec(uniqid/0 :: () -> mod_pubsub:itemId()). uniqid() -> - {T1, T2, T3} = now(), + {T1, T2, T3} = p1_time_compat:timestamp(), iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). nodeAttr(Node) -> [{<<"node">>, Node}]. diff --git a/src/node_flat.erl b/src/node_flat.erl index a003642f888..d73b2be0c5a 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -362,7 +362,7 @@ publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> {error, ?ERR_FORBIDDEN}; true -> if MaxItems > 0 -> - Now = now(), + Now = p1_time_compat:timestamp(), PubId = {Now, SubKey}, Item = case get_item(Nidx, ItemId) of {result, OldItem} -> diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 37e3282a96a..b8af0da0b57 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -223,9 +223,9 @@ publish_item(Nidx, Publisher, PublishModel, MaxItems, ItemId, Payload) -> {error, ?ERR_FORBIDDEN}; true -> if MaxItems > 0 -> - PubId = {now(), SubKey}, + PubId = {p1_time_compat:timestamp(), SubKey}, set_item(#pubsub_item{itemid = {ItemId, Nidx}, - creation = {now(), GenKey}, + creation = {p1_time_compat:timestamp(), GenKey}, modification = PubId, payload = Payload}), Items = [ItemId | itemids(Nidx, GenKey) -- [ItemId]], diff --git a/src/pubsub_migrate.erl b/src/pubsub_migrate.erl index 35282d9735d..7ac54ffec48 100644 --- a/src/pubsub_migrate.erl +++ b/src/pubsub_migrate.erl @@ -157,7 +157,7 @@ update_node_database(Host, ServerHost) -> {unknown, Publisher}, M = - {now(), + {p1_time_compat:timestamp(), Publisher}, mnesia:write(#pubsub_item{itemid = diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index df1560005c7..51bd9a0ffcf 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -202,7 +202,7 @@ write_subscription(_JID, _NodeId, SubID, Options) -> -spec(make_subid/0 :: () -> SubId::mod_pubsub:subId()). make_subid() -> - {T1, T2, T3} = now(), + {T1, T2, T3} = p1_time_compat:timestamp(), iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). %% diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index 6c99b155dd5..382ac006afe 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -165,7 +165,7 @@ create_table() -> ok. -spec(make_subid/0 :: () -> mod_pubsub:subId()). make_subid() -> - {T1, T2, T3} = now(), + {T1, T2, T3} = p1_time_compat:timestamp(), iolist_to_binary(io_lib:fwrite("~.16B~.16B~.16B", [T1, T2, T3])). %% From d0df7be7220920d746047ed5cd4d700e0321c662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 7 Dec 2015 16:37:40 +0100 Subject: [PATCH 385/695] Fix randoms.erl on R17 that don't have random:seed(integer()) --- src/randoms.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/randoms.erl b/src/randoms.erl index b2e95b256c8..4068fa79d7c 100644 --- a/src/randoms.erl +++ b/src/randoms.erl @@ -35,7 +35,7 @@ start() -> register(random_generator, spawn(randoms, init, [])). init() -> - random:seed(p1_time_compat:monotonic_time()), loop(). + random:seed(p1_time_compat:timestamp()), loop(). loop() -> receive From 95a9100623e6af7abadf5c6f1a16fab4432dc240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 7 Dec 2015 16:48:29 +0100 Subject: [PATCH 386/695] Fix more places where random:seed is used --- src/ejabberd_s2s_out.erl | 2 +- src/extauth.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 6bf928282c5..a5f7280555d 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -1097,7 +1097,7 @@ get_addr_port(Server) -> ?DEBUG("srv lookup of '~s': ~p~n", [Server, HEnt#hostent.h_addr_list]), AddrList = HEnt#hostent.h_addr_list, - random:seed(p1_time_compat:monotonic_time()), + random:seed(p1_time_compat:timestamp()), case catch lists:map(fun ({Priority, Weight, Port, Host}) -> N = case Weight of diff --git a/src/extauth.erl b/src/extauth.erl index 9b84741dcac..1d312624653 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -102,7 +102,7 @@ call_port(Server, Msg) -> receive {eauth, Result} -> Result end. random_instance(MaxNum) -> - random:seed(p1_time_compat:monotonic_time()), + random:seed(p1_time_compat:timestamp()), random:uniform(MaxNum) - 1. get_instances(Server) -> From 3e57850da7bf4fce4961085fa53f1e271d1300b2 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Dec 2015 18:30:52 +0100 Subject: [PATCH 387/695] If mod_register access_from is 'none', then don't advertise IBR (#857) --- src/mod_register.erl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mod_register.erl b/src/mod_register.erl index da0b805e73d..5628dbf8c32 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -72,8 +72,11 @@ stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_REGISTER). -stream_feature_register(Acc, _Host) -> - case lists:keymember(<<"mechanisms">>, 2, Acc) of +stream_feature_register(Acc, Host) -> + AF = gen_mod:get_module_opt(Host, ?MODULE, access_from, + fun(A) when is_atom(A) -> A end, + all), + case (AF /= none) and lists:keymember(<<"mechanisms">>, 2, Acc) of true -> [#xmlel{name = <<"register">>, attrs = [{<<"xmlns">>, ?NS_FEATURE_IQREGISTER}], From 5ce0b062ffb804bb81ec4e68bd0f9656a5ce3f3e Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Dec 2015 00:10:00 +0100 Subject: [PATCH 388/695] mod_mam: Honor Message Processing Hints (XEP-0334) --- src/mod_mam.erl | 52 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index c0756b6ebec..1481c48d2df 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -361,17 +361,26 @@ process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> end. should_archive(#xmlel{name = <<"message">>} = Pkt) -> - case {xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs), - xml:get_subtag_cdata(Pkt, <<"body">>)} of - {<<"error">>, _} -> - false; - {<<"groupchat">>, _} -> + case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of + <<"error">> -> false; - {_, <<>>} -> - %% Empty body + <<"groupchat">> -> false; _ -> - true + case check_store_hint(Pkt) of + store -> + true; + no_store -> + false; + none -> + case xml:get_subtag_cdata(Pkt, <<"body">>) of + <<>> -> + %% Empty body + false; + _ -> + true + end + end end; should_archive(#xmlel{}) -> false. @@ -426,6 +435,33 @@ should_archive_muc(_MUCState, _Peer) -> %% TODO true. +check_store_hint(Pkt) -> + case has_store_hint(Pkt) of + true -> + store; + false -> + case has_no_store_hint(Pkt) of + true -> + no_store; + false -> + none + end + end. + +has_store_hint(Message) -> + xml:get_subtag_with_xmlns(Message, <<"store">>, ?NS_HINTS) + /= false. + +has_no_store_hint(Message) -> + xml:get_subtag_with_xmlns(Message, <<"no-store">>, ?NS_HINTS) + /= false orelse + xml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS) + /= false orelse + xml:get_subtag_with_xmlns(Message, <<"no-permanent-store">>, ?NS_HINTS) + /= false orelse + xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS) + /= false. + store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> Prefs = get_prefs(LUser, LServer), case should_archive_peer(C2SState, Prefs, Peer) of From 7a69dab5963b13953c5fb08fdb2b39635c1c8992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 8 Dec 2015 11:25:26 +0100 Subject: [PATCH 389/695] Add ability to disable timeout for ejabberdctl command --- ejabberdctl.template | 3 +- src/ejabberd_ctl.erl | 67 +++++++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index bd791cedab1..5fbcf94ee17 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -48,6 +48,7 @@ while [ $# -ne 0 ] ; do shift case $PARAM in --) break ;; + --no-timeout) EJABBERD_NO_TIMEOUT="--no-timeout" ;; --node) ERLANG_NODE_ARG=$1 ; shift ;; --config-dir) ETC_DIR="$1" ; shift ;; --config) EJABBERD_CONFIG_PATH="$1" ; shift ;; @@ -418,7 +419,7 @@ ctlexec() -hidden \ -pa $EJABBERD_EBIN_PATH \ $KERNEL_OPTS \ - -s ejabberd_ctl -extra $ERLANG_NODE $COMMAND" + -s ejabberd_ctl -extra $ERLANG_NODE $EJABBERD_NO_TIMEOUT $COMMAND" } # stop epmd if there is no other running node diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index ec916b32b54..b0a1069d972 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -63,37 +63,40 @@ %%----------------------------- start() -> - case init:get_plain_arguments() of - [SNode | Args] -> - SNode1 = case string:tokens(SNode, "@") of - [_Node, _Server] -> - SNode; - _ -> - case net_kernel:longnames() of - true -> - lists:flatten([SNode, "@", inet_db:gethostname(), - ".", inet_db:res_option(domain)]); - false -> - lists:flatten([SNode, "@", inet_db:gethostname()]); - _ -> - SNode - end - end, - Node = list_to_atom(SNode1), - Status = case rpc:call(Node, ?MODULE, process, [Args], 60000) of - {badrpc, Reason} -> - print("Failed RPC connection to the node ~p: ~p~n", - [Node, Reason]), - %% TODO: show minimal start help - ?STATUS_BADRPC; - S -> - S - end, - halt(Status); - _ -> - print_usage(), - halt(?STATUS_USAGE) - end. + [SNode, Timeout, Args] = case init:get_plain_arguments() of + [SNode2, "--no-timeout" | Args2] -> + [SNode2, infinity, Args2]; + [SNode3 | Args3] -> + [SNode3, 10000, Args3]; + _ -> + print_usage(), + halt(?STATUS_USAGE) + end, + SNode1 = case string:tokens(SNode, "@") of + [_Node, _Server] -> + SNode; + _ -> + case net_kernel:longnames() of + true -> + lists:flatten([SNode, "@", inet_db:gethostname(), + ".", inet_db:res_option(domain)]); + false -> + lists:flatten([SNode, "@", inet_db:gethostname()]); + _ -> + SNode + end + end, + Node = list_to_atom(SNode1), + Status = case rpc:call(Node, ?MODULE, process, [Args], Timeout) of + {badrpc, Reason} -> + print("Failed RPC connection to the node ~p: ~p~n", + [Node, Reason]), + %% TODO: show minimal start help + ?STATUS_BADRPC; + S -> + S + end, + halt(Status). init() -> ets:new(ejabberd_ctl_cmds, [named_table, set, public]), @@ -470,7 +473,7 @@ print_usage(HelpMode, MaxC, ShCode) -> get_list_ctls(), print( - ["Usage: ", ?B("ejabberdctl"), " [--node ", ?U("nodename"), "] [--auth ", + ["Usage: ", ?B("ejabberdctl"), " [--no-timeout] [--node ", ?U("nodename"), "] [--auth ", ?U("user"), " ", ?U("host"), " ", ?U("password"), "] ", ?U("command"), " [", ?U("options"), "]\n" "\n" From 67f93b0d6053a41e65d0480af584877fb12847fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 8 Dec 2015 11:28:03 +0100 Subject: [PATCH 390/695] Don't keep 10 sec timeout that i used for testing... --- src/ejabberd_ctl.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index b0a1069d972..a8d15c169f0 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -67,7 +67,7 @@ start() -> [SNode2, "--no-timeout" | Args2] -> [SNode2, infinity, Args2]; [SNode3 | Args3] -> - [SNode3, 10000, Args3]; + [SNode3, 60000, Args3]; _ -> print_usage(), halt(?STATUS_USAGE) From c2f6bf03431b372e0e451203a74812c74e1c0856 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Tue, 8 Dec 2015 21:24:39 +0300 Subject: [PATCH 391/695] Improve muc#roomconfig_presencebroadcast support --- src/mod_muc_room.erl | 74 +++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 38fed6eab2c..dd7f78163ff 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2085,16 +2085,16 @@ presence_broadcast_allowed(JID, StateData) -> Role = get_role(JID, StateData), lists:member(Role, (StateData#state.config)#config.presence_broadcast). -send_update_presence(JID, StateData) -> - send_update_presence(JID, <<"">>, StateData). +send_update_presence(JID, StateData, OldStateData) -> + send_update_presence(JID, <<"">>, StateData, OldStateData). -send_update_presence(JID, Reason, StateData) -> +send_update_presence(JID, Reason, StateData, OldStateData) -> case is_room_overcrowded(StateData) of true -> ok; - false -> send_update_presence1(JID, Reason, StateData) + false -> send_update_presence1(JID, Reason, StateData, OldStateData) end. -send_update_presence1(JID, Reason, StateData) -> +send_update_presence1(JID, Reason, StateData, OldStateData) -> LJID = jid:tolower(JID), LJIDs = case LJID of {U, S, <<"">>} -> @@ -2112,7 +2112,7 @@ send_update_presence1(JID, Reason, StateData) -> end end, lists:foreach(fun (J) -> - send_new_presence(J, Reason, StateData, StateData) + send_new_presence(J, Reason, StateData, OldStateData) end, LJIDs). @@ -2120,27 +2120,47 @@ send_new_presence(NJID, StateData, OldStateData) -> send_new_presence(NJID, <<"">>, StateData, OldStateData). send_new_presence(NJID, Reason, StateData, OldStateData) -> - case is_room_overcrowded(StateData) orelse - not (presence_broadcast_allowed(NJID, StateData) orelse - presence_broadcast_allowed(NJID, OldStateData)) of + case is_room_overcrowded(StateData) of true -> ok; - false -> send_new_presence1(NJID, Reason, StateData) + false -> send_new_presence1(NJID, Reason, StateData, OldStateData) end. -send_new_presence1(NJID, Reason, StateData) -> - #user{nick = Nick} = - (?DICT):fetch(jid:tolower(NJID), - StateData#state.users), +send_new_presence1(NJID, Reason, StateData, OldStateData) -> + LNJID = jid:tolower(NJID), + #user{nick = Nick} = (?DICT):fetch(LNJID, StateData#state.users), LJID = find_jid_by_nick(Nick, StateData), {ok, - #user{jid = RealJID, role = Role, - last_presence = Presence}} = + #user{jid = RealJID, role = Role0, + last_presence = Presence0} = UserInfo} = (?DICT):find(jid:tolower(LJID), StateData#state.users), + {Role1, Presence1} = + case presence_broadcast_allowed(NJID, StateData) of + true -> {Role0, Presence0}; + false -> + {none, + #xmlel{name = <<"presence">>, + attrs = [{<<"type">>, <<"unavailable">>}], + children = []} + } + end, Affiliation = get_affiliation(LJID, StateData), SAffiliation = affiliation_to_list(Affiliation), - SRole = role_to_list(Role), - lists:foreach(fun ({_LJID, Info}) -> + UserList = + case not (presence_broadcast_allowed(NJID, StateData) orelse + presence_broadcast_allowed(NJID, OldStateData)) of + true -> + [{LNJID, UserInfo}]; + false -> + (?DICT):to_list(StateData#state.users) + end, + lists:foreach(fun ({LUJID, Info}) -> + {Role, Presence} = + if + LNJID == LUJID -> {Role0, Presence0}; + true -> {Role1, Presence1} + end, + SRole = role_to_list(Role), ItemAttrs = case Info#user.role == moderator orelse (StateData#state.config)#config.anonymous == false @@ -2220,7 +2240,7 @@ send_new_presence1(NJID, Reason, StateData) -> Nick), Info#user.jid, Packet) end, - (?DICT):to_list(StateData#state.users)). + UserList). send_existing_presences(ToJID, StateData) -> case is_room_overcrowded(StateData) of @@ -2238,8 +2258,12 @@ send_existing_presences1(ToJID, StateData) -> last_presence = Presence} = (?DICT):fetch(jid:tolower(LJID), StateData#state.users), - case RealToJID of - FromJID -> ok; + PresenceBroadcast = + lists:member( + FromRole, (StateData#state.config)#config.presence_broadcast), + case {RealToJID, PresenceBroadcast} of + {FromJID, _} -> ok; + {_, false} -> ok; _ -> FromAffiliation = get_affiliation(LJID, StateData), @@ -2666,7 +2690,7 @@ process_item_change(E, SD, UJID) -> set_role(JID, none, SD1); _ -> SD1 = set_affiliation(JID, none, SD), - send_update_presence(JID, SD1), + send_update_presence(JID, SD1, SD), SD1 end; {JID, affiliation, outcast, Reason} -> @@ -2684,12 +2708,12 @@ process_item_change(E, SD, UJID) -> when (A == admin) or (A == owner) -> SD1 = set_affiliation(JID, A, SD, Reason), SD2 = set_role(JID, moderator, SD1), - send_update_presence(JID, Reason, SD2), + send_update_presence(JID, Reason, SD2, SD), SD2; {JID, affiliation, member, Reason} -> SD1 = set_affiliation(JID, member, SD, Reason), SD2 = set_role(JID, participant, SD1), - send_update_presence(JID, Reason, SD2), + send_update_presence(JID, Reason, SD2, SD), SD2; {JID, role, Role, Reason} -> SD1 = set_role(JID, Role, SD), @@ -2698,7 +2722,7 @@ process_item_change(E, SD, UJID) -> SD1; {JID, affiliation, A, _Reason} -> SD1 = set_affiliation(JID, A, SD), - send_update_presence(JID, SD1), + send_update_presence(JID, SD1, SD), SD1 end of From 90fd7f3780a4de44887c9a05342cda3457bdbb00 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Dec 2015 21:46:36 +0100 Subject: [PATCH 392/695] mod_offline: Honor hint Ignore the "store_empty_body" option for messages that have a hint as described in XEP-0334, version 0.2. --- src/mod_offline.erl | 73 ++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/src/mod_offline.erl b/src/mod_offline.erl index dca3996f4ec..253fe788cc1 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -284,18 +284,25 @@ need_to_store(LServer, Packet) -> Type = xml:get_tag_attr_s(<<"type">>, Packet), if (Type /= <<"error">>) and (Type /= <<"groupchat">>) and (Type /= <<"headline">>) -> - case gen_mod:get_module_opt( - LServer, ?MODULE, store_empty_body, - fun(V) when is_boolean(V) -> V; - (unless_chat_state) -> unless_chat_state - end, - unless_chat_state) of - false -> - xml:get_subtag(Packet, <<"body">>) /= false; - unless_chat_state -> - not jlib:is_standalone_chat_state(Packet); - true -> - true + case check_store_hint(Packet) of + store -> + true; + no_store -> + false; + none -> + case gen_mod:get_module_opt( + LServer, ?MODULE, store_empty_body, + fun(V) when is_boolean(V) -> V; + (unless_chat_state) -> unless_chat_state + end, + unless_chat_state) of + false -> + xml:get_subtag(Packet, <<"body">>) /= false; + unless_chat_state -> + not jlib:is_standalone_chat_state(Packet); + true -> + true + end end; true -> false @@ -304,26 +311,38 @@ need_to_store(LServer, Packet) -> store_packet(From, To, Packet) -> case need_to_store(To#jid.lserver, Packet) of true -> - case has_no_store_hint(Packet) of - false -> - case check_event(From, To, Packet) of - true -> - #jid{luser = LUser, lserver = LServer} = To, - TimeStamp = p1_time_compat:timestamp(), - #xmlel{children = Els} = Packet, - Expire = find_x_expire(TimeStamp, Els), - gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) ! - #offline_msg{us = {LUser, LServer}, - timestamp = TimeStamp, expire = Expire, - from = From, to = To, packet = Packet}, - stop; - _ -> ok - end; + case check_event(From, To, Packet) of + true -> + #jid{luser = LUser, lserver = LServer} = To, + TimeStamp = p1_time_compat:timestamp(), + #xmlel{children = Els} = Packet, + Expire = find_x_expire(TimeStamp, Els), + gen_mod:get_module_proc(To#jid.lserver, ?PROCNAME) ! + #offline_msg{us = {LUser, LServer}, + timestamp = TimeStamp, expire = Expire, + from = From, to = To, packet = Packet}, + stop; _ -> ok end; false -> ok end. +check_store_hint(Packet) -> + case has_store_hint(Packet) of + true -> + store; + false -> + case has_no_store_hint(Packet) of + true -> + no_store; + false -> + none + end + end. + +has_store_hint(Packet) -> + xml:get_subtag_with_xmlns(Packet, <<"store">>, ?NS_HINTS) =/= false. + has_no_store_hint(Packet) -> xml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) =/= false orelse From 59ba09826b5c9e74fc4c7279ceba084cb4cd39a7 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Dec 2015 21:58:54 +0100 Subject: [PATCH 393/695] mod_offline: Fix outdated comments --- src/mod_offline.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 253fe788cc1..0532f9eb8bb 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -348,7 +348,7 @@ has_no_store_hint(Packet) -> orelse xml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) =/= false. -%% Check if the packet has any content about XEP-0022 or XEP-0085 +%% Check if the packet has any content about XEP-0022 check_event(From, To, Packet) -> #xmlel{name = Name, attrs = Attrs, children = Els} = Packet, @@ -392,7 +392,7 @@ check_event(From, To, Packet) -> end end. -%% Check if the packet has subelements about XEP-0022, XEP-0085 or other +%% Check if the packet has subelements about XEP-0022 find_x_event([]) -> false; find_x_event([{xmlcdata, _} | Els]) -> find_x_event(Els); From 14609dbfa2a85ef0abc40b0720acfa2e6e26026c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Dec 2015 22:15:55 +0100 Subject: [PATCH 394/695] mod_mam: Remove unused code --- src/mod_mam.erl | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 1481c48d2df..0e1dbf30844 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -227,8 +227,6 @@ process_iq_v0_2(#jid{lserver = LServer} = From, [{<<"end">>, [xml:get_tag_cdata(El)]}]; (#xmlel{name = <<"with">>} = El) -> [{<<"with">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"withroom">>} = El) -> - [{<<"withroom">>, [xml:get_tag_cdata(El)]}]; (#xmlel{name = <<"withtext">>} = El) -> [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; (#xmlel{name = <<"set">>}) -> @@ -342,10 +340,6 @@ process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> With, RSM}; ({<<"with">>, [Data|_]}, {Start, End, _, RSM}) -> {Start, End, jid:tolower(jid:from_string(Data)), RSM}; - ({<<"withroom">>, [Data|_]}, {Start, End, _, RSM}) -> - {Start, End, - {room, jid:tolower(jid:from_string(Data))}, - RSM}; ({<<"withtext">>, [Data|_]}, {Start, End, _, RSM}) -> {Start, End, {text, Data}, RSM}; ({<<"set">>, El}, {Start, End, With, _}) -> @@ -628,14 +622,7 @@ select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType, DBType) - select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> case MsgType of chat -> - case With of - {room, {_, _, <<"">>} = WithJID} -> - select(LServer, jid:make(WithJID), Start, End, - WithJID, RSM, MsgType, DBType); - _ -> - select(LServer, From, Start, End, - With, RSM, MsgType, DBType) - end; + select(LServer, From, Start, End, With, RSM, MsgType, DBType); {groupchat, _Role, _MUCState} -> select(LServer, To, Start, End, With, RSM, MsgType, DBType) end. From 325c17f277fa8c4f5c33a6e26acbfcd9d25197f9 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Dec 2015 22:21:39 +0100 Subject: [PATCH 395/695] mod_mam: Update record field type --- src/mod_mam.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 0e1dbf30844..cfc1e213f78 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -46,7 +46,7 @@ {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', id = <<>> :: binary() | '_', timestamp = p1_time_compat:timestamp() :: erlang:timestamp() | '_' | '$1', - peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', + peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3' | undefined, bare_peer = {<<"">>, <<"">>, <<"">>} :: ljid() | '_' | '$3', packet = #xmlel{} :: xmlel() | '_', nick = <<"">> :: binary(), From 07baf2d9732c442ab21cc618266da8bca4864e0a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 8 Dec 2015 22:48:04 +0100 Subject: [PATCH 396/695] Don't let "reopen_log" rotate files (EJAB-1243) Make sure the "reopen_log" command really just reopens log files without also rotating them. For rotating log files, the new "rotate_log" command can be used. --- src/ejabberd_admin.erl | 9 ++++++++- src/ejabberd_logger.erl | 11 ++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 49042f4d5ab..ab758fb3610 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -28,7 +28,7 @@ -export([start/0, stop/0, %% Server - status/0, reopen_log/0, + status/0, reopen_log/0, rotate_log/0, set_loglevel/1, stop_kindly/2, send_service_message_all_mucs/2, registered_vhosts/0, @@ -88,6 +88,10 @@ commands() -> desc = "Reopen the log files", module = ?MODULE, function = reopen_log, args = [], result = {res, rescode}}, + #ejabberd_commands{name = rotate_log, tags = [logs, server], + desc = "Rotate the log files", + module = ?MODULE, function = rotate_log, + args = [], result = {res, rescode}}, #ejabberd_commands{name = stop_kindly, tags = [server], desc = "Inform users and rooms, wait, and stop the server", longdesc = "Provide the delay in seconds, and the " @@ -276,6 +280,9 @@ reopen_log() -> ejabberd_hooks:run(reopen_log_hook, []), ejabberd_logger:reopen_log(). +rotate_log() -> + ejabberd_hooks:run(rotate_log_hook, []), + ejabberd_logger:rotate_log(). set_loglevel(LogLevel) -> {module, Module} = ejabberd_logger:set(LogLevel), diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 6f2457831ce..3545abe848e 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -27,7 +27,7 @@ -behaviour(ejabberd_config). %% API --export([start/0, reopen_log/0, get/0, set/1, get_log_path/0, opt_type/1]). +-export([start/0, reopen_log/0, rotate_log/0, get/0, set/1, get_log_path/0, opt_type/1]). -include("ejabberd.hrl"). @@ -36,6 +36,7 @@ -spec start() -> ok. -spec get_log_path() -> string(). -spec reopen_log() -> ok. +-spec rotate_log() -> ok. -spec get() -> {loglevel(), atom(), string()}. -spec set(loglevel() | {loglevel(), list()}) -> {module, module()}. @@ -128,6 +129,10 @@ start() -> ok. reopen_log() -> + %% Lager detects external log rotation automatically. + ok. + +rotate_log() -> lager_crash_log ! rotate, lists:foreach( fun({lager_file_backend, File}) -> @@ -191,6 +196,10 @@ reopen_log() -> p1_logger_h:reopen_log(), reopen_sasl_log(). +rotate_log() -> + %% Not implemented. + ok. + get() -> p1_loglevel:get(). From be4d687a8650e549ae3c1417b766ee36ded1245c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 9 Dec 2015 09:46:45 +0100 Subject: [PATCH 397/695] Fix problem with handling of old db entries in mod_mam --- src/mod_mam.erl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index cfc1e213f78..89b8ddadd4a 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -712,9 +712,10 @@ select(LServer, #jid{luser = LUser} = JidRequestor, #xmlel{} = El = xml_stream:parse_element(XML), Now = usec_to_now(jlib:binary_to_integer(TS)), PeerJid = jid:tolower(jid:from_string(PeerBin)), - T = if Kind /= <<"">> -> - jlib:binary_to_atom(Kind); - true -> chat + T = case Kind of + <<"">> -> chat; + null -> chat; + _ -> jlib:binary_to_atom(Kind) end, {TS, jlib:binary_to_integer(TS), msg_to_el(#archive_msg{timestamp = Now, From 4c47ee63f295cedd2febb5cfcd9de7bc4e9fccab Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 9 Dec 2015 12:52:30 +0300 Subject: [PATCH 398/695] Do not forget to include xmlns in mam prefs response (#859) --- src/mod_mam.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 89b8ddadd4a..3df2011546d 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -324,7 +324,8 @@ process_iq(#jid{luser = LUser, lserver = LServer}, children = JFun(Prefs#archive_prefs.never)}, IQ#iq{type = result, sub_el = [#xmlel{name = <<"prefs">>, - attrs = [{<<"default">>, Default}], + attrs = [{<<"xmlns">>, IQ#iq.xmlns}, + {<<"default">>, Default}], children = [Always, Never]}]}; process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. From e09afe367f242e3e3cb33d70d1e3e6c8d8fed7ba Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 9 Dec 2015 22:28:44 +0100 Subject: [PATCH 399/695] Document XEP-0334 support --- src/mod_mam.erl | 1 + src/mod_muc_log.erl | 2 ++ src/mod_offline.erl | 1 + 3 files changed, 4 insertions(+) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 3df2011546d..b1801fd3244 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -26,6 +26,7 @@ -module(mod_mam). -protocol({xep, 313, '0.4'}). +-protocol({xep, 334, '0.2'}). -behaviour(gen_mod). diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 996ac83a588..49adf034b41 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -25,6 +25,8 @@ -module(mod_muc_log). +-protocol({xep, 334, '0.2'}). + -behaviour(ejabberd_config). -author('badlop@process-one.net'). diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 0532f9eb8bb..73039b55b05 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -30,6 +30,7 @@ -protocol({xep, 22, '1.4'}). -protocol({xep, 23, '1.3'}). -protocol({xep, 160, '1.0'}). +-protocol({xep, 334, '0.2'}). -define(GEN_SERVER, p1_server). -behaviour(?GEN_SERVER). From 469e93f37b0205b8c501cfbe4606c272b4ba55a3 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 9 Dec 2015 22:44:45 +0100 Subject: [PATCH 400/695] mod_mam: Don't store resent messages Make sure messages that were resent by the stream management code aren't stored in MAM. --- src/mod_mam.erl | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index b1801fd3244..7e2051057b6 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -363,18 +363,23 @@ should_archive(#xmlel{name = <<"message">>} = Pkt) -> <<"groupchat">> -> false; _ -> - case check_store_hint(Pkt) of - store -> - true; - no_store -> + case is_resent(Pkt) of + true -> false; - none -> - case xml:get_subtag_cdata(Pkt, <<"body">>) of - <<>> -> - %% Empty body + false -> + case check_store_hint(Pkt) of + store -> + true; + no_store -> false; - _ -> - true + none -> + case xml:get_subtag_cdata(Pkt, <<"body">>) of + <<>> -> + %% Empty body + false; + _ -> + true + end end end end; @@ -458,6 +463,14 @@ has_no_store_hint(Message) -> xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS) /= false. +is_resent(Pkt) -> + case xml:get_subtag_cdata(Pkt, <<"delay">>) of + <<>> -> + false; + Desc -> + binary:match(Desc, <<"Resent">>) =/= nomatch + end. + store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> Prefs = get_prefs(LUser, LServer), case should_archive_peer(C2SState, Prefs, Peer) of From 10c920ef13501605ec95d6b637db9a8c06ab0676 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 26 Nov 2015 12:37:18 +0100 Subject: [PATCH 401/695] Don't force max_items_node to MAXITEMS if not defined --- src/mod_pubsub.erl | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index a429eb4e03f..13fe0cc367b 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -2376,7 +2376,10 @@ purge_node(Host, Node, Owner) -> ). get_items(Host, Node, From, SubId, SMaxItems, ItemIds, RSM) -> MaxItems = if SMaxItems == <<>> -> - get_max_items_node(Host); + case get_max_items_node(Host) of + undefined -> ?MAXITEMS; + Max -> Max + end; true -> case catch jlib:binary_to_integer(SMaxItems) of {'EXIT', _} -> {error, ?ERR_BAD_REQUEST}; @@ -3823,8 +3826,12 @@ add_opt(Key, Value, Opts) -> -define(SET_INTEGER_XOPT(Opt, Val, Min, Max), case catch jlib:binary_to_integer(Val) of - IVal when is_integer(IVal), IVal >= Min, IVal =< Max -> - set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); + IVal when is_integer(IVal), IVal >= Min -> + if (Max =:= undefined) orelse (IVal =< Max) -> + set_xoption(Host, Opts, add_opt(Opt, IVal, NewOpts)); + true -> + {error, ?ERR_NOT_ACCEPTABLE} + end; _ -> {error, ?ERR_NOT_ACCEPTABLE} end). @@ -3896,7 +3903,7 @@ set_xoption(Host, [_ | Opts], NewOpts) -> get_max_items_node({_, ServerHost, _}) -> get_max_items_node(ServerHost); get_max_items_node(Host) -> - config(serverhost(Host), max_items_node, ?MAXITEMS). + config(serverhost(Host), max_items_node, undefined). %%%% last item cache handling From c4943cffe83fda5ce791133ca94bb6f0bbac4cbe Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 30 Nov 2015 14:57:21 +0100 Subject: [PATCH 402/695] Follow pubsub configuration when using virtual nodetree --- src/mod_pubsub.erl | 3 ++- src/nodetree_virtual.erl | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 13fe0cc367b..deaed10fc3d 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -83,7 +83,8 @@ -export([subscription_to_string/1, affiliation_to_string/1, string_to_subscription/1, string_to_affiliation/1, extended_error/2, extended_error/3, service_jid/1, - tree/1, tree/2, plugin/2, config/3, host/1, serverhost/1]). + tree/1, tree/2, plugin/2, plugins/1, config/3, + host/1, serverhost/1]). %% API and gen_server callbacks -export([start_link/2, start/2, stop/1, init/1, diff --git a/src/nodetree_virtual.erl b/src/nodetree_virtual.erl index d56be860fc1..9797ad8db64 100644 --- a/src/nodetree_virtual.erl +++ b/src/nodetree_virtual.erl @@ -65,10 +65,11 @@ get_node(Host, Node) -> get_node(Nidx) -> {Host, Node} = nodeid(Nidx), - Record = #pubsub_node{nodeid = Node, id = Nidx}, - Module = jlib:binary_to_atom(<<"node_", (Record#pubsub_node.type)/binary>>), - Record#pubsub_node{owners = [{<<"">>, Host, <<"">>}], - options = Module:options()}. + [Type|_] = mod_pubsub:plugins(Host), + Module = mod_pubsub:plugin(Host, Type), + #pubsub_node{nodeid = Node, id = Nidx, type = Type, + owners = [{<<"">>, Host, <<"">>}], + options = Module:options()}. get_nodes(Host, _From) -> get_nodes(Host). From 86a8606fd1bca5816f322129a6ac7aba5d2cc057 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Mon, 30 Nov 2015 15:20:38 +0100 Subject: [PATCH 403/695] Virtual nodetree is not attached to any backend --- src/mod_pubsub.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index deaed10fc3d..116b99cae9a 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3978,6 +3978,8 @@ tree(Host) -> Tree -> Tree end. +tree(_Host, <<"virtual">>) -> + nodetree_virtual; % special case, virtual does not use any backend tree(Host, Name) -> case gen_mod:db_type(serverhost(Host), ?MODULE) of mnesia -> jlib:binary_to_atom(<<"nodetree_", Name/binary>>); From 6357ea1d5d336ffbd10df22b1fa571d7e3e0d059 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 10 Nov 2015 16:28:57 +0100 Subject: [PATCH 404/695] Limit number of subscriptions per node and allow custom default node configuration --- src/mod_pubsub.erl | 52 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 116b99cae9a..a47a03942e6 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -192,6 +192,8 @@ ignore_pep_from_offline = true, last_item_cache = false, max_items_node = ?MAXITEMS, + max_subscriptions_node = undefined, + default_node_config = [], nodetree = <<"nodetree_", (?STDTREE)/binary>>, plugins = [?STDNODE], db_type @@ -206,6 +208,8 @@ ignore_pep_from_offline :: boolean(), last_item_cache :: boolean(), max_items_node :: non_neg_integer(), + max_subscriptions_node :: non_neg_integer()|undefined, + default_node_config :: [{atom(), binary()|boolean()|integer()|atom()}], nodetree :: binary(), plugins :: [binary(),...], db_type :: atom() @@ -259,6 +263,10 @@ init([ServerHost, Opts]) -> fun(A) when is_boolean(A) -> A end, false), MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, fun(A) when is_integer(A) andalso A >= 0 -> A end, ?MAXITEMS), + MaxSubsNode = gen_mod:get_opt(max_subscriptions_node, Opts, + fun(A) when is_integer(A) andalso A >= 0 -> A end, undefined), + DefaultNodeCfg = gen_mod:get_opt(default_node_config, Opts, + fun(A) when is_list(A) -> filter_node_options(A) end, []), pubsub_index:init(Host, ServerHost, Opts), ets:new(gen_mod:get_module_proc(ServerHost, config), [set, named_table]), {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts), @@ -270,6 +278,8 @@ init([ServerHost, Opts]) -> ets:insert(gen_mod:get_module_proc(ServerHost, config), {plugins, Plugins}), ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, LastItemCache}), ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, MaxItemsNode}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_subscriptions_node, MaxSubsNode}), + ets:insert(gen_mod:get_module_proc(ServerHost, config), {default_node_config, DefaultNodeCfg}), ets:insert(gen_mod:get_module_proc(ServerHost, config), {pep_mapping, PepMapping}), ets:insert(gen_mod:get_module_proc(ServerHost, config), {ignore_pep_from_offline, PepOffline}), ets:insert(gen_mod:get_module_proc(ServerHost, config), {host, Host}), @@ -2013,6 +2023,21 @@ subscribe_node(Host, Node, From, JID, Configuration) -> AccessModel = get_option(Options, access_model), SendLast = get_option(Options, send_last_published_item), AllowedGroups = get_option(Options, roster_groups_allowed, []), + CanSubscribe = case get_max_subscriptions_node(Host) of + Max when is_integer(Max) -> + case node_call(Host, Type, get_node_subscriptions, [Nidx]) of + {result, NodeSubs} -> + SubsNum = lists:foldl( + fun ({_, subscribed, _}, Acc) -> Acc+1; + (_, Acc) -> Acc + end, 0, NodeSubs), + SubsNum < Max; + _ -> + true + end; + _ -> + true + end, if not SubscribeFeature -> {error, extended_error(?ERR_FEATURE_NOT_IMPLEMENTED, unsupported, <<"subscribe">>)}; @@ -2025,6 +2050,10 @@ subscribe_node(Host, Node, From, JID, Configuration) -> SubOpts == invalid -> {error, extended_error(?ERR_BAD_REQUEST, <<"invalid-options">>)}; + not CanSubscribe -> + %% fallback to closest XEP compatible result, assume we are not allowed to subscribe + {error, + extended_error(?ERR_NOT_ALLOWED, <<"closed-node">>)}; true -> Owners = node_owners_call(Host, Type, Nidx, O), {PS, RG} = get_presence_and_roster_permissions(Host, Subscriber, @@ -3604,6 +3633,12 @@ get_option(Options, Var, Def) -> end. node_options(Host, Type) -> + case config(serverhost(Host), default_node_config) of + undefined -> node_plugin_options(Host, Type); + [] -> node_plugin_options(Host, Type); + Config -> Config + end. +node_plugin_options(Host, Type) -> Module = plugin(Host, Type), case catch Module:options() of {'EXIT', {undef, _}} -> @@ -3612,6 +3647,11 @@ node_options(Host, Type) -> Result -> Result end. +filter_node_options(Options) -> + lists:foldl(fun({Key, Val}, Acc) -> + DefaultValue = proplists:get_value(Key, Options, Val), + [{Key, DefaultValue}|Acc] + end, [], node_flat:options()). node_owners_action(Host, Type, Nidx, []) -> case gen_mod:db_type(serverhost(Host), ?MODULE) of @@ -3906,6 +3946,11 @@ get_max_items_node({_, ServerHost, _}) -> get_max_items_node(Host) -> config(serverhost(Host), max_items_node, undefined). +get_max_subscriptions_node({_, ServerHost, _}) -> + get_max_subscriptions_node(ServerHost); +get_max_subscriptions_node(Host) -> + config(serverhost(Host), max_subscriptions_node, undefined). + %%%% last item cache handling is_last_item_cache_enabled({_, ServerHost, _}) -> @@ -4382,6 +4427,10 @@ mod_opt_type(last_item_cache) -> fun (A) when is_boolean(A) -> A end; mod_opt_type(max_items_node) -> fun (A) when is_integer(A) andalso A >= 0 -> A end; +mod_opt_type(max_subscriptions_node) -> + fun (A) when is_integer(A) andalso A >= 0 -> A end; +mod_opt_type(default_node_config) -> + fun (A) when is_list(A) -> A end; mod_opt_type(nodetree) -> fun (A) when is_binary(A) -> A end; mod_opt_type(pep_mapping) -> @@ -4391,4 +4440,5 @@ mod_opt_type(plugins) -> mod_opt_type(_) -> [access_createnode, db_type, host, ignore_pep_from_offline, iqdisc, last_item_cache, - max_items_node, nodetree, pep_mapping, plugins]. + max_items_node, nodetree, pep_mapping, plugins, + max_subscriptions_node, default_node_config]. From 1a32f20c07d27daa096ee2693b6540d16c595807 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 9 Dec 2015 16:57:43 +0100 Subject: [PATCH 405/695] Disable use of multi-subscribe and subscription-option on standard plugins --- src/node_flat.erl | 37 ++++++++++++++++++------------ src/node_flat_odbc.erl | 39 ++++++++++++++++++++------------ src/pubsub_subscription.erl | 1 + src/pubsub_subscription_odbc.erl | 1 + test/ejabberd_SUITE.erl | 9 -------- 5 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/node_flat.erl b/src/node_flat.erl index d73b2be0c5a..29c89d337fc 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -51,7 +51,7 @@ path_to_node/1, can_fetch_item/2, is_subscribed/1]). init(_Host, _ServerHost, _Opts) -> - pubsub_subscription:init(), + %%pubsub_subscription:init(), mnesia:create_table(pubsub_state, [{disc_copies, [node()]}, {type, ordered_set}, @@ -97,7 +97,6 @@ features() -> <<"instant-nodes">>, <<"manage-subscriptions">>, <<"modify-affiliations">>, - <<"multi-subscribe">>, <<"outcast-affiliation">>, <<"persistent-items">>, <<"publish">>, @@ -108,8 +107,8 @@ features() -> <<"retrieve-items">>, <<"retrieve-subscriptions">>, <<"subscribe">>, - <<"subscription-notifications">>, - <<"subscription-options">>]. + <<"subscription-notifications">>]. +%%<<"subscription-options">> %% @doc Checks if the current user has the permission to create the requested node %%

    In flat node, any unused node name is allowed. The access parameter is also @@ -177,7 +176,7 @@ delete_node(Nodes) -> %%

    %%

    In the default plugin module, the record is unchanged.

    subscribe_node(Nidx, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> + SendLast, PresenceSubscription, RosterGroup, _Options) -> SubKey = jid:tolower(Subscriber), GenKey = jid:remove_resource(SubKey), Authorized = jid:tolower(jid:remove_resource(Sender)) == GenKey, @@ -219,13 +218,20 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, %% % Requesting entity is anonymous %% {error, ?ERR_FORBIDDEN}; true -> - SubId = pubsub_subscription:add_subscription(Subscriber, Nidx, Options), - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed + %%SubId = pubsub_subscription:add_subscription(Subscriber, Nidx, Options), + {NewSub, SubId} = case Subscriptions of + [{subscribed, Id}|_] -> + {subscribed, Id}; + [] -> + Id = pubsub_subscription:make_subid(), + Sub = case AccessModel of + authorize -> pending; + _ -> subscribed + end, + set_state(SubState#pubsub_state{subscriptions = + [{Sub, Id} | Subscriptions]}), + {Sub, Id} end, - set_state(SubState#pubsub_state{subscriptions = - [{NewSub, SubId} | Subscriptions]}), case {NewSub, SendLast} of {subscribed, never} -> {result, {default, subscribed, SubId}}; @@ -301,7 +307,7 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> delete_subscriptions(SubKey, Nidx, Subscriptions, SubState) -> NewSubs = lists:foldl(fun ({Subscription, SubId}, Acc) -> - pubsub_subscription:delete_subscription(SubKey, Nidx, SubId), + %%pubsub_subscription:delete_subscription(SubKey, Nidx, SubId), Acc -- [{Subscription, SubId}] end, SubState#pubsub_state.subscriptions, Subscriptions), case {SubState#pubsub_state.affiliation, NewSubs} of @@ -601,14 +607,15 @@ replace_subscription(_, [], Acc) -> Acc; replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). -new_subscription(Nidx, Owner, Sub, SubState) -> - SubId = pubsub_subscription:add_subscription(Owner, Nidx, []), +new_subscription(_Nidx, _Owner, Sub, SubState) -> + %%SubId = pubsub_subscription:add_subscription(Owner, Nidx, []), + SubId = pubsub_subscription:make_subid(), Subs = SubState#pubsub_state.subscriptions, set_state(SubState#pubsub_state{subscriptions = [{Sub, SubId} | Subs]}), {Sub, SubId}. unsub_with_subid(Nidx, SubId, #pubsub_state{stateid = {Entity, _}} = SubState) -> - pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, Nidx, SubId), + %%pubsub_subscription:delete_subscription(SubState#pubsub_state.stateid, Nidx, SubId), NewSubs = [{S, Sid} || {S, Sid} <- SubState#pubsub_state.subscriptions, SubId =/= Sid], diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index b8af0da0b57..c922a901169 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -57,7 +57,7 @@ encode_host/1]). init(_Host, _ServerHost, _Opts) -> - pubsub_subscription_odbc:init(), + %%pubsub_subscription_odbc:init(), ok. terminate(_Host, _ServerHost) -> @@ -95,7 +95,7 @@ delete_node(Nodes) -> {result, {default, broadcast, Reply}}. subscribe_node(Nidx, Sender, Subscriber, AccessModel, - SendLast, PresenceSubscription, RosterGroup, Options) -> + SendLast, PresenceSubscription, RosterGroup, _Options) -> SubKey = jid:tolower(Subscriber), GenKey = jid:remove_resource(SubKey), Authorized = jid:tolower(jid:remove_resource(Sender)) == GenKey, @@ -131,16 +131,26 @@ subscribe_node(Nidx, Sender, Subscriber, AccessModel, %% % Requesting entity is anonymous %% {error, ?ERR_FORBIDDEN}; true -> - {result, SubId} = pubsub_subscription_odbc:subscribe_node(Subscriber, Nidx, Options), - NewSub = case AccessModel of - authorize -> pending; - _ -> subscribed + %%{result, SubId} = pubsub_subscription_odbc:subscribe_node(Subscriber, Nidx, Options), + {NewSub, SubId} = case Subscriptions of + [{subscribed, Id}|_] -> + {subscribed, Id}; + [] -> + Id = pubsub_subscription_odbc:make_subid(), + Sub = case AccessModel of + authorize -> pending; + _ -> subscribed + end, + update_subscription(Nidx, SubKey, [{Sub, Id} | Subscriptions]), + {Sub, Id} end, - update_subscription(Nidx, SubKey, [{NewSub, SubId} | Subscriptions]), case {NewSub, SendLast} of - {subscribed, never} -> {result, {default, subscribed, SubId}}; - {subscribed, _} -> {result, {default, subscribed, SubId, send_last}}; - {_, _} -> {result, {default, pending, SubId}} + {subscribed, never} -> + {result, {default, subscribed, SubId}}; + {subscribed, _} -> + {result, {default, subscribed, SubId, send_last}}; + {_, _} -> + {result, {default, pending, SubId}} end end. @@ -200,7 +210,7 @@ unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> delete_subscription(SubKey, Nidx, {Subscription, SubId}, Affiliation, Subscriptions) -> NewSubs = Subscriptions -- [{Subscription, SubId}], - pubsub_subscription_odbc:unsubscribe_node(SubKey, Nidx, SubId), + %%pubsub_subscription_odbc:unsubscribe_node(SubKey, Nidx, SubId), case {Affiliation, NewSubs} of {none, []} -> del_state(Nidx, SubKey); _ -> update_subscription(Nidx, SubKey, NewSubs) @@ -497,14 +507,15 @@ replace_subscription(_, [], Acc) -> Acc; replace_subscription({Sub, SubId}, [{_, SubId} | T], Acc) -> replace_subscription({Sub, SubId}, T, [{Sub, SubId} | Acc]). -new_subscription(Nidx, Owner, Subscription, SubState) -> - {result, SubId} = pubsub_subscription_odbc:subscribe_node(Owner, Nidx, []), +new_subscription(_Nidx, _Owner, Subscription, SubState) -> + %%{result, SubId} = pubsub_subscription_odbc:subscribe_node(Owner, Nidx, []), + SubId = pubsub_subscription_odbc:make_subid(), Subscriptions = [{Subscription, SubId} | SubState#pubsub_state.subscriptions], set_state(SubState#pubsub_state{subscriptions = Subscriptions}), {Subscription, SubId}. unsub_with_subid(Nidx, SubId, SubState) -> - pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, Nidx, SubId), + %%pubsub_subscription_odbc:unsubscribe_node(SubState#pubsub_state.stateid, Nidx, SubId), NewSubs = [{S, Sid} || {S, Sid} <- SubState#pubsub_state.subscriptions, SubId =/= Sid], diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index 51bd9a0ffcf..67f8575a72f 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -27,6 +27,7 @@ %% API -export([init/0, subscribe_node/3, unsubscribe_node/3, get_subscription/3, set_subscription/4, + make_subid/0, get_options_xform/2, parse_options_xform/1]). % Internal function also exported for use in transactional bloc from pubsub plugins diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index 382ac006afe..87296b620aa 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -27,6 +27,7 @@ %% API -export([init/0, subscribe_node/3, unsubscribe_node/3, get_subscription/3, set_subscription/4, + make_subid/0, get_options_xform/2, parse_options_xform/1]). -include("pubsub.hrl"). diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index a220ed37e19..11ed6f74385 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -839,15 +839,6 @@ pubsub(Config) -> [#pubsub_affiliation{node = Node, type = owner}]}]} = send_recv(Config, #iq{type = get, to = pubsub_jid(Config), sub_els = [#pubsub{affiliations = []}]}), - %% Get subscription options - true = lists:member(?PUBSUB("subscription-options"), Features), - #iq{type = result, sub_els = [#pubsub{options = #pubsub_options{ - node = Node}}]} = - send_recv(Config, - #iq{type = get, to = pubsub_jid(Config), - sub_els = [#pubsub{options = #pubsub_options{ - node = Node, - jid = my_jid(Config)}}]}), %% Fetching published items from node "presence" #iq{type = result, sub_els = [#pubsub{items = #pubsub_items{ From 3bdd5d0d2526bb31135c7ab17a43ba3891758137 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 9 Dec 2015 10:06:57 +0100 Subject: [PATCH 406/695] Remove receiver's supervisor --- src/ejabberd_receiver.erl | 5 ++--- src/ejabberd_sup.erl | 9 --------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 71ae8e40931..55ebdbed441 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -76,9 +76,8 @@ start(Socket, SockMod, Shaper) -> non_neg_integer() | infinity) -> undefined | pid(). start(Socket, SockMod, Shaper, MaxStanzaSize) -> - {ok, Pid} = - supervisor:start_child(ejabberd_receiver_sup, - [Socket, SockMod, Shaper, MaxStanzaSize]), + {ok, Pid} = ?GEN_SERVER:start(ejabberd_receiver, + [Socket, SockMod, Shaper, MaxStanzaSize], []), Pid. -spec change_shaper(pid(), shaper:shaper()) -> ok. diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index e8d3ce8302a..e6b30a3d6bc 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -97,14 +97,6 @@ init([]) -> infinity, supervisor, [ejabberd_listener]}, - ReceiverSupervisor = - {ejabberd_receiver_sup, - {ejabberd_tmp_sup, start_link, - [ejabberd_receiver_sup, ejabberd_receiver]}, - permanent, - infinity, - supervisor, - [ejabberd_tmp_sup]}, S2SInSupervisor = {ejabberd_s2s_in_sup, {ejabberd_tmp_sup, start_link, @@ -162,7 +154,6 @@ init([]) -> S2S, Local, Captcha, - ReceiverSupervisor, S2SInSupervisor, S2SOutSupervisor, ServiceSupervisor, From 8ee5f9fb6f311d3a7ab1512b4cf9f3de8ba74ff6 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 9 Dec 2015 15:40:20 +0100 Subject: [PATCH 407/695] Remove http supervisors --- src/ejabberd_http.erl | 5 +++-- src/ejabberd_http_bind.erl | 6 +++--- src/ejabberd_http_ws.erl | 2 +- src/ejabberd_sup.erl | 9 --------- src/mod_http_bind.erl | 18 +++++------------- 5 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index b764ee3670d..7225e74cfda 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -84,8 +84,9 @@ "">>). start(SockData, Opts) -> - supervisor:start_child(ejabberd_http_sup, - [SockData, Opts]). + {ok, + proc_lib:spawn(ejabberd_http, init, + [SockData, Opts])}. start_link(SockData, Opts) -> {ok, diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index 194b099d72a..e7239772661 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -152,9 +152,9 @@ start(XMPPDomain, Sid, Key, IP, HOpts) -> ?DEBUG("Starting session", []), - SupervisorProc = gen_mod:get_module_proc(XMPPDomain, ?PROCNAME_MHB), - case catch supervisor:start_child(SupervisorProc, - [Sid, Key, IP, HOpts]) + case catch gen_fsm:start(?MODULE, + [Sid, Key, IP, HOpts], + ?FSMOPTS) of {ok, Pid} -> {ok, Pid}; _ -> check_bind_module(XMPPDomain), diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index 65a80b0046d..ed88c03d9d9 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -75,7 +75,7 @@ -export_type([ws_socket/0]). start(WS) -> - supervisor:start_child(ejabberd_wsloop_sup, [WS]). + gen_fsm:start(?MODULE, [WS], ?FSMOPTS). start_link(WS) -> gen_fsm:start_link(?MODULE, [WS], ?FSMOPTS). diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index e6b30a3d6bc..9e635220268 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -121,14 +121,6 @@ init([]) -> infinity, supervisor, [ejabberd_tmp_sup]}, - HTTPSupervisor = - {ejabberd_http_sup, - {ejabberd_tmp_sup, start_link, - [ejabberd_http_sup, ejabberd_http]}, - permanent, - infinity, - supervisor, - [ejabberd_tmp_sup]}, FrontendSocketSupervisor = {ejabberd_frontend_socket_sup, {ejabberd_tmp_sup, start_link, @@ -157,7 +149,6 @@ init([]) -> S2SInSupervisor, S2SOutSupervisor, ServiceSupervisor, - HTTPSupervisor, IQSupervisor, FrontendSocketSupervisor, Listener]}}. diff --git a/src/mod_http_bind.erl b/src/mod_http_bind.erl index fbf43e80fe8..fd871705fd8 100644 --- a/src/mod_http_bind.erl +++ b/src/mod_http_bind.erl @@ -81,19 +81,11 @@ process(_Path, _Request) -> %%%---------------------------------------------------------------------- %%% BEHAVIOUR CALLBACKS %%%---------------------------------------------------------------------- -start(Host, _Opts) -> - setup_database(), - Proc = gen_mod:get_module_proc(Host, ?PROCNAME_MHB), - ChildSpec = {Proc, - {ejabberd_tmp_sup, start_link, - [Proc, ejabberd_http_bind]}, - permanent, infinity, supervisor, [ejabberd_tmp_sup]}, - supervisor:start_child(ejabberd_sup, ChildSpec). - -stop(Host) -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME_MHB), - supervisor:terminate_child(ejabberd_sup, Proc), - supervisor:delete_child(ejabberd_sup, Proc). +start(_Host, _Opts) -> + setup_database(). + +stop(_Host) -> + ok. setup_database() -> migrate_database(), From e3005f68e7a44e6787a4132a5248ed728c688037 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 11 Dec 2015 15:33:22 +0100 Subject: [PATCH 408/695] Remove undefined macro injected in 3bdd5d0d --- src/ejabberd_receiver.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 55ebdbed441..9c3702424c1 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -76,8 +76,8 @@ start(Socket, SockMod, Shaper) -> non_neg_integer() | infinity) -> undefined | pid(). start(Socket, SockMod, Shaper, MaxStanzaSize) -> - {ok, Pid} = ?GEN_SERVER:start(ejabberd_receiver, - [Socket, SockMod, Shaper, MaxStanzaSize], []), + {ok, Pid} = gen_server:start(ejabberd_receiver, + [Socket, SockMod, Shaper, MaxStanzaSize], []), Pid. -spec change_shaper(pid(), shaper:shaper()) -> ok. From aaa718741ec999e4bb2b09d1576d92afff29c0cf Mon Sep 17 00:00:00 2001 From: Pablo Polvorin Date: Wed, 13 Nov 2013 14:30:29 -0300 Subject: [PATCH 409/695] Use BLOB instead of TEXT on mysql in stanza storage Mysql 'utf8' do not support 4-bytes UTF8 chars. Characters like 'KISS MARK' (U+1F48B) causes mysql to cut the string at that point. There is utf8mb4 encoding available on newer mysql versions that do support 4-bytes utf8. But for storing stanzas, that doesn't need to be indexed or searched or inspected in any way, it was easier to use BLOB (the bytes stored are utf8 encoded anyway, like all XMPP), and avoids the need to redefine indexes (as allowed size is shorter on utf8mb4) or having mixed utf8 and utf8mb4 encodings on the same table. --- sql/mysql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysql.sql b/sql/mysql.sql index 21e7b9b5277..eaa1077882c 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -77,7 +77,7 @@ CREATE INDEX i_sr_user_grp ON sr_user(grp); CREATE TABLE spool ( username varchar(250) NOT NULL, - xml text NOT NULL, + xml BLOB NOT NULL, seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB CHARACTER SET utf8; From 7d1c75d0e817db0e04fe1133e06ba35cd367d76e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 8 Dec 2015 15:56:43 +0300 Subject: [PATCH 410/695] Use UTF8MB4 character set in MySQL tables --- sql/mysql.sql | 142 +++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/sql/mysql.sql b/sql/mysql.sql index eaa1077882c..e546fc88671 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -17,10 +17,10 @@ -- CREATE TABLE users ( - username varchar(250) PRIMARY KEY, + username varchar(191) PRIMARY KEY, password text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- To support SCRAM auth: -- ALTER TABLE users ADD COLUMN serverkey text NOT NULL DEFAULT ''; @@ -28,15 +28,15 @@ CREATE TABLE users ( -- ALTER TABLE users ADD COLUMN iterationcount integer NOT NULL DEFAULT 0; CREATE TABLE last ( - username varchar(250) PRIMARY KEY, + username varchar(191) PRIMARY KEY, seconds text NOT NULL, state text NOT NULl -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE rosterusers ( - username varchar(250) NOT NULL, - jid varchar(250) NOT NULL, + username varchar(191) NOT NULL, + jid varchar(191) NOT NULL, nick text NOT NULL, subscription character(1) NOT NULL, ask character(1) NOT NULL, @@ -45,58 +45,58 @@ CREATE TABLE rosterusers ( subscribe text NOT NULL, type text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE UNIQUE INDEX i_rosteru_user_jid ON rosterusers(username(75), jid(75)); CREATE INDEX i_rosteru_username ON rosterusers(username); CREATE INDEX i_rosteru_jid ON rosterusers(jid); CREATE TABLE rostergroups ( - username varchar(250) NOT NULL, - jid varchar(250) NOT NULL, + username varchar(191) NOT NULL, + jid varchar(191) NOT NULL, grp text NOT NULL -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX pk_rosterg_user_jid ON rostergroups(username(75), jid(75)); CREATE TABLE sr_group ( - name varchar(250) NOT NULL, + name varchar(191) NOT NULL, opts text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE sr_user ( - jid varchar(250) NOT NULL, - grp varchar(250) NOT NULL, + jid varchar(191) NOT NULL, + grp varchar(191) NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE UNIQUE INDEX i_sr_user_jid_group ON sr_user(jid(75), grp(75)); CREATE INDEX i_sr_user_jid ON sr_user(jid); CREATE INDEX i_sr_user_grp ON sr_user(grp); CREATE TABLE spool ( - username varchar(250) NOT NULL, + username varchar(191) NOT NULL, xml BLOB NOT NULL, seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_despool USING BTREE ON spool(username); CREATE INDEX i_spool_created_at USING BTREE ON spool(created_at); CREATE TABLE archive ( - username varchar(250) NOT NULL, + username varchar(191) NOT NULL, timestamp BIGINT UNSIGNED NOT NULL, - peer varchar(250) NOT NULL, - bare_peer varchar(250) NOT NULL, + peer varchar(191) NOT NULL, + bare_peer varchar(191) NOT NULL, xml text NOT NULL, txt text, id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, kind varchar(10), - nick varchar(250), + nick varchar(191), created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE FULLTEXT INDEX i_text ON archive(txt); CREATE INDEX i_username USING BTREE ON archive(username); @@ -105,51 +105,51 @@ CREATE INDEX i_peer USING BTREE ON archive(peer); CREATE INDEX i_bare_peer USING BTREE ON archive(bare_peer); CREATE TABLE archive_prefs ( - username varchar(250) NOT NULL PRIMARY KEY, + username varchar(191) NOT NULL PRIMARY KEY, def text NOT NULL, always text NOT NULL, never text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE vcard ( - username varchar(250) PRIMARY KEY, + username varchar(191) PRIMARY KEY, vcard mediumtext NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE vcard_xupdate ( - username varchar(250) PRIMARY KEY, + username varchar(191) PRIMARY KEY, hash text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE vcard_search ( - username varchar(250) NOT NULL, - lusername varchar(250) PRIMARY KEY, + username varchar(191) NOT NULL, + lusername varchar(191) PRIMARY KEY, fn text NOT NULL, - lfn varchar(250) NOT NULL, + lfn varchar(191) NOT NULL, family text NOT NULL, - lfamily varchar(250) NOT NULL, + lfamily varchar(191) NOT NULL, given text NOT NULL, - lgiven varchar(250) NOT NULL, + lgiven varchar(191) NOT NULL, middle text NOT NULL, - lmiddle varchar(250) NOT NULL, + lmiddle varchar(191) NOT NULL, nickname text NOT NULL, - lnickname varchar(250) NOT NULL, + lnickname varchar(191) NOT NULL, bday text NOT NULL, - lbday varchar(250) NOT NULL, + lbday varchar(191) NOT NULL, ctry text NOT NULL, - lctry varchar(250) NOT NULL, + lctry varchar(191) NOT NULL, locality text NOT NULL, - llocality varchar(250) NOT NULL, + llocality varchar(191) NOT NULL, email text NOT NULL, - lemail varchar(250) NOT NULL, + lemail varchar(191) NOT NULL, orgname text NOT NULL, - lorgname varchar(250) NOT NULL, + lorgname varchar(191) NOT NULL, orgunit text NOT NULL, - lorgunit varchar(250) NOT NULL -) ENGINE=InnoDB CHARACTER SET utf8; + lorgunit varchar(191) NOT NULL +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_vcard_search_lfn ON vcard_search(lfn); CREATE INDEX i_vcard_search_lfamily ON vcard_search(lfamily); @@ -164,16 +164,16 @@ CREATE INDEX i_vcard_search_lorgname ON vcard_search(lorgname); CREATE INDEX i_vcard_search_lorgunit ON vcard_search(lorgunit); CREATE TABLE privacy_default_list ( - username varchar(250) PRIMARY KEY, - name varchar(250) NOT NULL -) ENGINE=InnoDB CHARACTER SET utf8; + username varchar(191) PRIMARY KEY, + name varchar(191) NOT NULL +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE privacy_list ( - username varchar(250) NOT NULL, - name varchar(250) NOT NULL, + username varchar(191) NOT NULL, + name varchar(191) NOT NULL, id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_privacy_list_username USING BTREE ON privacy_list(username); CREATE UNIQUE INDEX i_privacy_list_username_name USING BTREE ON privacy_list (username(75), name(75)); @@ -189,25 +189,25 @@ CREATE TABLE privacy_list_data ( match_message boolean NOT NULL, match_presence_in boolean NOT NULL, match_presence_out boolean NOT NULL -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_privacy_list_data_id ON privacy_list_data(id); CREATE TABLE private_storage ( - username varchar(250) NOT NULL, - namespace varchar(250) NOT NULL, + username varchar(191) NOT NULL, + namespace varchar(191) NOT NULL, data text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_private_storage_username USING BTREE ON private_storage(username); CREATE UNIQUE INDEX i_private_storage_username_namespace USING BTREE ON private_storage(username(75), namespace(75)); -- Not tested in mysql CREATE TABLE roster_version ( - username varchar(250) PRIMARY KEY, + username varchar(191) PRIMARY KEY, version text NOT NULL -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- To update from 1.x: -- ALTER TABLE rosterusers ADD COLUMN askmessage text AFTER ask; @@ -220,7 +220,7 @@ CREATE TABLE pubsub_node ( parent text, type text, nodeid bigint auto_increment primary key -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_pubsub_node_parent ON pubsub_node(parent(120)); CREATE UNIQUE INDEX i_pubsub_node_tuple ON pubsub_node(host(20), node(120)); @@ -228,14 +228,14 @@ CREATE TABLE pubsub_node_option ( nodeid bigint, name text, val text -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_pubsub_node_option_nodeid ON pubsub_node_option(nodeid); ALTER TABLE `pubsub_node_option` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE; CREATE TABLE pubsub_node_owner ( nodeid bigint, owner text -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_pubsub_node_owner_nodeid ON pubsub_node_owner(nodeid); ALTER TABLE `pubsub_node_owner` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE; @@ -245,7 +245,7 @@ CREATE TABLE pubsub_state ( affiliation character(1), subscriptions text, stateid bigint auto_increment primary key -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_pubsub_state_jid ON pubsub_state(jid(60)); CREATE UNIQUE INDEX i_pubsub_state_tuple ON pubsub_state(nodeid, jid(60)); ALTER TABLE `pubsub_state` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE; @@ -257,7 +257,7 @@ CREATE TABLE pubsub_item ( creation text, modification text, payload text -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36)); CREATE UNIQUE INDEX i_pubsub_item_tuple ON pubsub_item(nodeid, itemid(36)); ALTER TABLE `pubsub_item` ADD FOREIGN KEY (`nodeid`) REFERENCES `pubsub_node` (`nodeid`) ON DELETE CASCADE; @@ -266,7 +266,7 @@ CREATE TABLE pubsub_subscription_opt ( subid text, opt_name varchar(32), opt_value text -); +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE UNIQUE INDEX i_pubsub_subscription_opt ON pubsub_subscription_opt(subid(32), opt_name(32)); CREATE TABLE muc_room ( @@ -274,7 +274,7 @@ CREATE TABLE muc_room ( host text NOT NULL, opts text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE UNIQUE INDEX i_muc_room_name_host USING BTREE ON muc_room(name(75), host(75)); @@ -283,7 +283,7 @@ CREATE TABLE muc_registered ( host text NOT NULL, nick text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_muc_registered_nick USING BTREE ON muc_registered(nick(75)); CREATE UNIQUE INDEX i_muc_registered_jid_host USING BTREE ON muc_registered(jid(75), host(75)); @@ -293,22 +293,22 @@ CREATE TABLE irc_custom ( host text NOT NULL, data text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE UNIQUE INDEX i_irc_custom_jid_host USING BTREE ON irc_custom(jid(75), host(75)); CREATE TABLE motd ( - username varchar(250) PRIMARY KEY, + username varchar(191) PRIMARY KEY, xml text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE caps_features ( - node varchar(250) NOT NULL, - subnode varchar(250) NOT NULL, + node varchar(191) NOT NULL, + subnode varchar(191) NOT NULL, feature text, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE INDEX i_caps_features_node_subnode ON caps_features(node(75), subnode(75)); @@ -316,11 +316,11 @@ CREATE TABLE sm ( usec bigint NOT NULL, pid text NOT NULL, node text NOT NULL, - username varchar(250) NOT NULL, - resource varchar(250) NOT NULL, + username varchar(191) NOT NULL, + resource varchar(191) NOT NULL, priority text NOT NULL, info text NOT NULL -) ENGINE=InnoDB CHARACTER SET utf8; +) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE UNIQUE INDEX i_sid ON sm(usec, pid(75)); CREATE INDEX i_node ON sm(node(75)); From 6052f7bfa888b3f375278a465a9b09aac363a963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 14 Dec 2015 10:21:23 +0100 Subject: [PATCH 411/695] Fix pubsub test error --- src/node_flat.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_flat.erl b/src/node_flat.erl index 29c89d337fc..80a4189f26e 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -51,7 +51,7 @@ path_to_node/1, can_fetch_item/2, is_subscribed/1]). init(_Host, _ServerHost, _Opts) -> - %%pubsub_subscription:init(), + pubsub_subscription:init(), mnesia:create_table(pubsub_state, [{disc_copies, [node()]}, {type, ordered_set}, From a8683d5bcf67d5981c53220c615fb2fff02863a7 Mon Sep 17 00:00:00 2001 From: GreenLunar Date: Mon, 14 Dec 2015 14:39:18 +0200 Subject: [PATCH 412/695] Update hebrew translation Minor corrections, enhancements, and refinements --- priv/msgs/he.po | 164 +++++++++++++++++++----------------------------- 1 file changed, 66 insertions(+), 98 deletions(-) diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 71cac1f8033..b2b78882691 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -9,9 +9,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Language: Hebrew\n" -"X-Poedit-Language: Hebrew (עברית)\n" -"X-Generator: Poedit 1.5.4\n" +"X-Language: he\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Source-Language: en\n" @@ -36,21 +34,17 @@ msgstr "נבעט/ה" msgid "Too many unacked stanzas" msgstr "יותר מדי סטנזות בלי אישורי קבלה" -# תמליל -# כפי שעינייך רואות #: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 msgid "Enter the text you see" -msgstr "הזן את הטקסט אותו הינך רואה" +msgstr "הזן את הכיתוב שאתה רואה" -# כדי שלא לחסומן #: ejabberd_captcha.erl:154 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s" -# בקר את עמוד #: ejabberd_captcha.erl:199 msgid "If you don't see the CAPTCHA image here, visit the web page." -msgstr "במידה ואינך רואה תמונת CAPTCHA כאן, בקר בעמוד הרשת." +msgstr "אם אינך רואה תמונת CAPTCHA כאן, בקר בעמוד רשת." #: ejabberd_captcha.erl:234 msgid "CAPTCHA web page" @@ -58,7 +52,7 @@ msgstr "עמוד רשת CAPTCHA" #: ejabberd_captcha.erl:400 msgid "The CAPTCHA is valid." -msgstr "‏CAPTCHA הינה בתוקף." +msgstr "‏CAPTCHA הינה תקפה." #: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 #: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 @@ -66,9 +60,8 @@ msgid "User" msgstr "משתמש" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "שרת:" +msgstr "שרת" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 @@ -78,7 +71,7 @@ msgstr "סיסמה" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "קבל" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -154,8 +147,7 @@ msgstr "מארחים מדומים" msgid "Users" msgstr "משתמשים" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 mod_configure.erl:524 msgid "Online Users" msgstr "משתמשים מקוונים" @@ -187,8 +179,7 @@ msgstr "הצג טבלה רגילה" msgid "Show Integral Table" msgstr "הצג טבלה אינטגרלית" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 -#: mod_muc_admin.erl:247 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 mod_muc_admin.erl:247 msgid "Statistics" msgstr "סטטיסטיקה" @@ -270,8 +261,7 @@ msgstr "משתמש ~s" msgid "Connected Resources:" msgstr "משאבים מחוברים:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 -#: mod_register_web.erl:475 +#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 mod_register_web.erl:475 msgid "Password:" msgstr "סיסמה:" @@ -390,7 +380,6 @@ msgstr "אישור" msgid "Restore binary backup immediately:" msgstr "שחזר גיבוי בינארי לאלתר:" -# לאחר אתחול בא של #: ejabberd_web_admin.erl:1927 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" @@ -411,7 +400,7 @@ msgstr "יבא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):" #: ejabberd_web_admin.erl:1970 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" -msgstr "יצא מידע של כל המשתמשים שבתוך בשרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):" +msgstr "יצא מידע של כל המשתמשים שבתוך שרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):" #: ejabberd_web_admin.erl:1982 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" @@ -419,7 +408,7 @@ msgstr "יצא מידע של כל המשתמשים שבתוך מארח לתוך #: ejabberd_web_admin.erl:1998 msgid "Export all tables as SQL queries to a file:" -msgstr "יצא את כל טבלאות בתור שאילתות SQL לתוך קובץ:" +msgstr "יצא את כל הטבלאות בתור שאילתות SQL לתוך קובץ:" #: ejabberd_web_admin.erl:2014 msgid "Import user data from jabberd14 spool file:" @@ -449,7 +438,6 @@ msgstr "זמן פעילות:" msgid "CPU Time:" msgstr "זמן מחשב (CPU):" -# זיכרון דברים (דיני חוזים) #: ejabberd_web_admin.erl:2129 msgid "Transactions Committed:" msgstr "טרנזקציות שבוצעו:" @@ -551,7 +539,6 @@ msgstr "בשורות" msgid "Send announcement to all users" msgstr "שלח בשורה לכל המשתמשים" -# אצל כל #: mod_announce.erl:666 msgid "Send announcement to all users on all hosts" msgstr "שלח בשורה לכל המשתמשים בכל המארחים" @@ -601,7 +588,6 @@ msgstr "התחל מודולים" msgid "Stop Modules" msgstr "הפסק מודולים" -# שחזור #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" msgstr "שחזר" @@ -662,7 +648,6 @@ msgstr "השג מספר של משתמשים רשומים" msgid "Get Number of Online Users" msgstr "השג מספר של משתמשים מקוונים" -# הנהלת #: mod_configure.erl:320 mod_configure.erl:523 msgid "User Management" msgstr "ניהול משתמשים" @@ -699,7 +684,6 @@ msgstr "תצורת טבלאות מסד נתונים אצל " msgid "Choose storage type of tables" msgstr "בחר טיפוס אחסון של טבלאות" -# Typo: Disk (unsure) #: mod_configure.erl:1017 mod_configure.erl:1019 msgid "Disc only copy" msgstr "העתק של תקליטור בלבד" @@ -865,7 +849,7 @@ msgstr "כתובת IP זו רשומה ברשימה שחורה בתוך ~s" #: mod_irc.erl:431 msgid "IRC Transport" -msgstr "מוביל IRC" +msgstr "טרנספורט IRC" #: mod_irc.erl:468 msgid "ejabberd IRC module" @@ -873,7 +857,7 @@ msgstr "מודול IRC של ejabberd" #: mod_irc.erl:636 msgid "You need an x:data capable client to configure mod_irc settings" -msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר הגדרות של mod_irc" +msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר הגדרות mod_irc" #: mod_irc.erl:645 msgid "Registration in mod_irc for " @@ -894,21 +878,24 @@ msgstr "שם משתמש IRC" #: mod_irc.erl:674 msgid "" "If you want to specify different ports, passwords, encodings for IRC " -"servers, fill this list with values in format '{\"irc server\", \"encoding" -"\", port, \"password\"}'. By default this service use \"~s\" encoding, port " -"~p, empty password." +"servers, fill this list with values in format '{\"irc server\", " +"\"encoding\", port, \"password\"}'. By default this service use \"~s\" " +"encoding, port ~p, empty password." msgstr "" "אם ברצונך לציין פורטים, סיסמאות, קידודים אחרים עבור שרתים של IRC, מלא את " -"רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, \"password" -"\"}'. באופן משתמט שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה." +"רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, " +"\"password\"}'. באופן שגרתי שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה " +"ריקה." #: mod_irc.erl:696 msgid "" -"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." -"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." +"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, " +"{\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", " +"\"utf-8\"}]." msgstr "" -"דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." -"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." +"דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, " +"{\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", " +"\"utf-8\"}]." # פרמטרי חיבור #: mod_irc.erl:705 @@ -919,8 +906,6 @@ msgstr "פרמטרים של חיבור" msgid "Join IRC channel" msgstr "הצטרף לערוץ IRC" -# לא לשים סימן # ראשון -# לא לשים את סימן # הראשון #: mod_irc.erl:881 msgid "IRC channel (don't put the first #)" msgstr "ערוץ IRC (אל תשים סימן # ראשון)" @@ -978,19 +963,18 @@ msgstr "חדרי שיחה" # to register nickname #: mod_muc.erl:997 msgid "You need a client that supports x:data to register the nickname" -msgstr "עליך להשתמש בלקוח אשר תומך x:data בכדי לרשום את שם הכינוי" +msgstr "עליך להשתמש בלקוח אשר תומך x:data כדי לרשום את השם כינוי" #: mod_muc.erl:1007 msgid "Nickname Registration at " msgstr "רישום שם כינוי אצל " -# אותו ברצונך לרשום #: mod_muc.erl:1013 msgid "Enter nickname you want to register" -msgstr "הזן שם כינוי אשר ברצונך לרושמו" +msgstr "הזן שם כינוי אשר ברצונך לרשום" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "שם כינוי" @@ -1057,7 +1041,7 @@ msgstr " הגדיר/ה את הנושא אל: " #: mod_muc_log.erl:540 msgid "Chatroom is created" -msgstr "חדר שיחה הינו נוצר" +msgstr "חדר שיחה נוצר כעת" #: mod_muc_log.erl:542 msgid "Chatroom is destroyed" @@ -1065,7 +1049,7 @@ msgstr "חדר שיחה הינו הרוס" #: mod_muc_log.erl:544 msgid "Chatroom is started" -msgstr "חדר שיחה הינו מותחל" +msgstr "חדר שיחה מותחל כעת" #: mod_muc_log.erl:546 msgid "Chatroom is stopped" @@ -1196,19 +1180,19 @@ msgstr "תיאור חדר" #: mod_muc_room.erl:3363 msgid "Make room persistent" -msgstr "הפוך חדר אל קבוע" +msgstr "הפוך חדר לחדר קבוע" #: mod_muc_room.erl:3369 msgid "Make room public searchable" -msgstr "הפוך חדר אל בר חיפוש פומבי" +msgstr "הפוך חדר לחדר שנתון לחיפוש פומבי" #: mod_muc_room.erl:3372 msgid "Make participants list public" -msgstr "הפוך רשימת משתתפים אל פומבית" +msgstr "הפוך רשימת משתתפים לפומבית" #: mod_muc_room.erl:3374 msgid "Make room password protected" -msgstr "הפוך חדר אל מוגן במילת מעבר" +msgstr "הפוך חדר לחדר מוגן במילת מעבר" #: mod_muc_room.erl:3388 msgid "Maximum Number of Occupants" @@ -1218,10 +1202,9 @@ msgstr "מספר מרבי של נוכחים" msgid "No limit" msgstr "ללא הגבלה" -# הצג כתובות JID ממשיות ל #: mod_muc_room.erl:3430 msgid "Present real Jabber IDs to" -msgstr "הצג כתובות JID ממשיות" +msgstr "הצג כתובות Jabber ממשיות" #: mod_muc_room.erl:3444 mod_muc_room.erl:3507 msgid "moderators only" @@ -1233,18 +1216,16 @@ msgstr "לכל אחד" #: mod_muc_room.erl:3460 msgid "Make room members-only" -msgstr "הפוך חדר אל חברים-בלבד" +msgstr "הפוך חדר לחדר עבור חברים-בלבד" -# חדר מבוקר חדר תחת ביקורת #: mod_muc_room.erl:3463 msgid "Make room moderated" -msgstr "הפוך חדר אל מבוקר" +msgstr "הפוך חדר לחדר מבוקר" #: mod_muc_room.erl:3466 msgid "Default users as participants" -msgstr "משתמשים משתמטים כמשתתפים" +msgstr "משתמשים שגרתיים כמשתתפים" -# התרה #: mod_muc_room.erl:3469 msgid "Allow users to change the subject" msgstr "התר למשתמשים לשנות את הנושא" @@ -1271,7 +1252,7 @@ msgstr "התר למשתמשים לשלוח הזמנות" #: mod_muc_room.erl:3529 msgid "Allow visitors to send status text in presence updates" -msgstr "התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות" +msgstr "התר למבקרים לשלוח טקסט מצב בתוך עדכוני נוכחות" #: mod_muc_room.erl:3533 msgid "Allow visitors to change nickname" @@ -1287,16 +1268,15 @@ msgstr "תדירות מינימלית בין בקשות ביטוי (בשניות #: mod_muc_room.erl:3546 msgid "Make room CAPTCHA protected" -msgstr "הפוך חדר אל מוגן CAPTCHA" +msgstr "הפוך חדר לחדר מוגן CAPTCHA" #: mod_muc_room.erl:3553 msgid "Enable message archiving" msgstr "אפשר אחסון הודעות" -# זהויות #: mod_muc_room.erl:3559 msgid "Exclude Jabber IDs from CAPTCHA challenge" -msgstr "הוצא כתובות של Jabber מתוך אתגר CAPTCHA" +msgstr "הוצא כתובות Jabber מתוך אתגר CAPTCHA" #: mod_muc_room.erl:3568 msgid "Enable logging" @@ -1304,7 +1284,7 @@ msgstr "אפשר רישום פעילות" #: mod_muc_room.erl:3578 msgid "You need an x:data capable client to configure room" -msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר חדר" +msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר חדר" #: mod_muc_room.erl:4104 msgid "Number of occupants" @@ -1318,10 +1298,9 @@ msgstr "פרטי, " msgid "Voice request" msgstr "בקשת ביטוי" -# אשר או דחה #: mod_muc_room.erl:4243 msgid "Either approve or decline the voice request." -msgstr "או שתאשר או שתדחה את בקשת הביטוי." +msgstr "אשר או דחה בקשת ביטוי." #: mod_muc_room.erl:4263 msgid "User JID" @@ -1391,10 +1370,9 @@ msgstr "מודול Publish-Subscribe של ejabberd" msgid "PubSub subscriber request" msgstr "בקשת מנוי PubSub" -# ההרשמה #: mod_pubsub.erl:1544 msgid "Choose whether to approve this entity's subscription." -msgstr "בחר האם לאשר את המנוי של ישות זו." +msgstr "בחר האם לאשר את ההרשמה של ישות זו." #: mod_pubsub.erl:1560 msgid "Node ID" @@ -1406,15 +1384,15 @@ msgstr "כתובת מנוי" #: mod_pubsub.erl:1585 msgid "Allow this Jabber ID to subscribe to this pubsub node?" -msgstr "להתיר לכתובת JID זו להירשם לצומת PubSub זה?" +msgstr "להתיר למזהה Jabber זה להירשם לצומת PubSub זה?" #: mod_pubsub.erl:3702 msgid "Deliver payloads with event notifications" -msgstr "מסירת מטעני ייעוד (מטע״ד) יחד עם התראות אירוע" +msgstr "מסור מטעני ייעוד (מטע״ד) יחד עם התראות אירוע" #: mod_pubsub.erl:3704 msgid "Deliver event notifications" -msgstr "מסירת התראות אירוע" +msgstr "מסור התראות אירוע" # משתמשים רשומים #: mod_pubsub.erl:3706 @@ -1429,7 +1407,6 @@ msgstr "הודע מנויים כאשר הצומת נמחק" msgid "Notify subscribers when items are removed from the node" msgstr "הודע מנויים כאשר פריטים מוסרים מתוך הצומת" -# Typo: store #: mod_pubsub.erl:3712 msgid "Persist items to storage" msgstr "פריטים קבועים לאחסון" @@ -1445,31 +1422,27 @@ msgstr "מספר מרבי של פריטים לקיבוע" # בין אם #: mod_pubsub.erl:3718 msgid "Whether to allow subscriptions" -msgstr "האם להתיר מנויים" +msgstr "האם להתיר הרשמות" -# ציין מודל גישה #: mod_pubsub.erl:3720 msgid "Specify the access model" -msgstr "ציין את מודל הגישה" +msgstr "ציין מודל גישה" #: mod_pubsub.erl:3722 msgid "Roster groups allowed to subscribe" msgstr "קבוצות רשימה מורשות להירשם" -# ציין מודל פרסום #: mod_pubsub.erl:3724 msgid "Specify the publisher model" -msgstr "ציין את מודל הפרסום" +msgstr "ציין מודל פרסום" -# טהר #: mod_pubsub.erl:3726 msgid "Purge all items when the relevant publisher goes offline" -msgstr "טיהור כל הפריטים כאשר המפרסם הרלוונטי " +msgstr "טהר את כל הפריטים כאשר המפרסם הרלוונטי הופך לבלתי מקוון" -# ציין טיפוס הודעת אירוע #: mod_pubsub.erl:3728 msgid "Specify the event message type" -msgstr "ציין את טיפוס הודעת האירוע" +msgstr "ציין טיפוס הודעת אירוע" # בבתים בבייטים (bytes) #: mod_pubsub.erl:3730 @@ -1478,7 +1451,7 @@ msgstr "גודל מרבי של מטען ייעוד (payload) ביחידות מי #: mod_pubsub.erl:3732 msgid "When to send the last published item" -msgstr "מתי לשלוח פריט מפורסם אחרון" +msgstr "מתי לשלוח את הפריט המפורסם האחרון" #: mod_pubsub.erl:3734 msgid "Only deliver notifications to available users" @@ -1490,11 +1463,11 @@ msgstr "האוספים עמם צומת מסונף" #: mod_register.erl:250 msgid "You need a client that supports x:data and CAPTCHA to register" -msgstr "עליך להשתמש בלקוח אשר תומך x:data וגם CAPTCHA בכדי להירשם" +msgstr "עליך להשתמש בלקוח אשר תומך x:data וגם CAPTCHA כדי להירשם" #: mod_register.erl:256 mod_register.erl:317 msgid "Choose a username and password to register with this server" -msgstr "בחר שם משתמש וסיסמה להירשם עם שרת זה" +msgstr "בחר שם משתמש וסיסמה כדי להירשם בעזרת שרת זה" #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." @@ -1540,17 +1513,16 @@ msgid "" "carefully the instructions to fill correctly the fields." msgstr "" "עמוד זה מתיר ליצור חשבון Jabber בשרת Jabber זה. כתובת JID ‏(Jabber " -"IDentifier) תגובש באופן של: username@server. נא לקרוא בזהירות את ההוראות " -"למילוי השדות באופן נכון." +"IDentifier) תגובש באופן של: username@server. אנא קרא בזהירות את ההוראות " +"למילוי נכון של השדות." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 msgid "Username:" msgstr "שם משתמש:" -# כמו #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." -msgstr "חלק זה אינו ער לרישיות: macbeth הינה זהה כשם MacBeth וגם Macbeth." +msgstr "חלק זה אינו ער לרישיות: macbeth הינה זהה למחרוזת MacBeth וגם Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" @@ -1560,7 +1532,6 @@ msgstr "תווים לא מורשים:" msgid "Server:" msgstr "שרת:" -# אל נא לומר #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " @@ -1569,7 +1540,7 @@ msgstr "אל תגלה את הסיסמה שלך לאף אחד, אפילו לא ל #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." -msgstr "ביכולתך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber." +msgstr "באפשרותך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber." # בוטח # trust that your @@ -1610,7 +1581,7 @@ msgstr "סיסמה חדשה:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." -msgstr "עמוד זה מתיר לך לבטל רישום של חשבון Jabber בשרת Jabber זה." +msgstr "עמוד זה מתיר לך לבטל רישום של חשבון Jabber בתוך שרת Jabber זה." #: mod_register_web.erl:480 msgid "Unregister" @@ -1642,7 +1613,7 @@ msgstr "רשימה של " #: mod_roster.erl:1505 msgid "Add Jabber ID" -msgstr "הוסף JID" +msgstr "הוסף מזהה Jabber" #: mod_roster.erl:1623 msgid "Roster" @@ -1697,16 +1668,13 @@ msgstr "דוא״ל" msgid "Family Name" msgstr "שם משפחה" -# נא למלא -# שקול לתאום -# note: matching > wanted #: mod_vcard.erl:490 msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "" -"מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף " -"שדה כדי להתאים למחרוזת-משנה)" +"מלא את הטופס כדי לחפש אחר כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה " +"כדי להתאים למחרוזת-משנה)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" @@ -1731,7 +1699,7 @@ msgstr "חיפוש משתמשים אצל " #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" -msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי לחפש" +msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי לחפש" #: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" @@ -1862,7 +1830,7 @@ msgstr "מלא את שדות אלו כדי לחפש עבור כל משתמש Jab #~ msgstr "יותר מדי בקשות CAPTCHA" #~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "אין אפשרות לחולל CAPTCHA" +#~ msgstr "אין אפשרות להפיק CAPTCHA" #~ msgid "Incorrect password" #~ msgstr "מילת מעבר שגויה" From 51b9dd029bdcf8f5a59b472438c1a43d58c454e5 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 14 Dec 2015 14:08:44 +0100 Subject: [PATCH 413/695] Restore header in Hebrew translation file --- priv/msgs/he.po | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/priv/msgs/he.po b/priv/msgs/he.po index b2b78882691..b215aff2241 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -9,7 +9,9 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Language: he\n" +"X-Language: Hebrew\n" +"X-Poedit-Language: Hebrew (עברית)\n" +"X-Generator: Poedit 1.5.4\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Source-Language: en\n" From 3b69d263682aa40dfed35d1cd80ccaad0ad30250 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 15 Dec 2015 16:11:29 +0100 Subject: [PATCH 414/695] Fix pubsub headers --- src/gen_pubsub_node.erl | 45 +++++++++++++--------------- src/gen_pubsub_nodetree.erl | 45 +++++++++++++--------------- src/mod_pubsub.erl | 50 ++++++++++++------------------- src/node_buddy.erl | 39 ++++++++++++------------ src/node_club.erl | 39 ++++++++++++------------ src/node_dag.erl | 34 ++++++++++++--------- src/node_dispatch.erl | 51 ++++++++++++++++---------------- src/node_flat.erl | 39 ++++++++++++------------ src/node_flat_odbc.erl | 39 ++++++++++++------------ src/node_hometree.erl | 40 ++++++++++++------------- src/node_hometree_odbc.erl | 40 ++++++++++++------------- src/node_mb.erl | 40 ++++++++++++------------- src/node_pep.erl | 45 ++++++++++++++-------------- src/node_pep_odbc.erl | 45 ++++++++++++++-------------- src/node_private.erl | 39 ++++++++++++------------ src/node_public.erl | 39 ++++++++++++------------ src/nodetree_dag.erl | 38 ++++++++++++++---------- src/nodetree_tree.erl | 42 +++++++++++++------------- src/nodetree_tree_odbc.erl | 42 +++++++++++++------------- src/nodetree_virtual.erl | 42 +++++++++++++------------- src/pubsub_db_odbc.erl | 40 ++++++++++++++----------- src/pubsub_index.erl | 42 +++++++++++++------------- src/pubsub_subscription.erl | 39 +++++++++++++----------- src/pubsub_subscription_odbc.erl | 41 +++++++++++++------------ 24 files changed, 487 insertions(+), 508 deletions(-) diff --git a/src/gen_pubsub_node.erl b/src/gen_pubsub_node.erl index c608dad8124..c477466e130 100644 --- a/src/gen_pubsub_node.erl +++ b/src/gen_pubsub_node.erl @@ -1,32 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : gen_pubsub_node.erl +%%% Author : Christophe Romain +%%% Purpose : Define pubsub plugin behaviour +%%% Created : 1 Dec 2007 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - -%%% @private -%%% @doc

    The module {@module} defines the PubSub node -%%% plugin behaviour. This behaviour is used to check that a PubSub plugin -%%% respects the current ejabberd PubSub plugin API.

    +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(gen_pubsub_node). diff --git a/src/gen_pubsub_nodetree.erl b/src/gen_pubsub_nodetree.erl index ce6750dbac8..281234a6b5a 100644 --- a/src/gen_pubsub_nodetree.erl +++ b/src/gen_pubsub_nodetree.erl @@ -1,32 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : gen_pubsub_nodetree.erl +%%% Author : Christophe Romain +%%% Purpose : Define the pubsub node tree plugin behaviour +%%% Created : 1 Dec 2007 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - -%%% @private -%%% @doc

    The module {@module} defines the PubSub node -%%% tree plugin behaviour. This behaviour is used to check that a PubSub -%%% node tree plugin respects the current ejabberd PubSub plugin API.

    +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(gen_pubsub_nodetree). diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index a47a03942e6..c0b613d619f 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -1,40 +1,28 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%%---------------------------------------------------------------------- +%%% File : mod_pubsub.erl +%%% Author : Christophe Romain +%%% Purpose : Publish Subscribe service (XEP-0060) +%%% Created : 1 Dec 2007 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 ProcessOne %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - -%%% @doc The module {@module} is the core of the PubSub -%%% extension. It relies on PubSub plugins for a large part of its functions. +%%% 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. %%% -%%% @headerfile "pubsub.hrl" +%%% 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. %%% -%%% @reference See
    XEP-0060: Pubsub for -%%% the latest version of the PubSub specification. -%%% This module uses version 1.12 of the specification as a base. -%%% Most of the specification is implemented. -%%% Functions concerning configuration should be rewritten. +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% +%%%---------------------------------------------------------------------- + %%% Support for subscription-options and multi-subscribe features was %%% added by Brian Cully (bjc AT kublai.com). Subscriptions and options are %%% stored in the pubsub_subscription table, with a link to them provided diff --git a/src/node_buddy.erl b/src/node_buddy.erl index 410fd053408..412e58ed000 100644 --- a/src/node_buddy.erl +++ b/src/node_buddy.erl @@ -1,28 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_buddy.erl +%%% Author : Christophe Romain +%%% Purpose : +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_buddy). -behaviour(gen_pubsub_node). diff --git a/src/node_club.erl b/src/node_club.erl index cf433b695a1..25334cac9d7 100644 --- a/src/node_club.erl +++ b/src/node_club.erl @@ -1,28 +1,27 @@ -%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_club.erl +%%% Author : Christophe Romain +%%% Purpose : +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_club). -behaviour(gen_pubsub_node). diff --git a/src/node_dag.erl b/src/node_dag.erl index f0cbf17b8ba..23f0ca46b6d 100644 --- a/src/node_dag.erl +++ b/src/node_dag.erl @@ -1,21 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_dag.erl +%%% Author : Brian Cully +%%% Purpose : experimental support of XEP-248 +%%% Created : 15 Jun 2009 by Brian Cully %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @author Brian Cully -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_dag). -behaviour(gen_pubsub_node). diff --git a/src/node_dispatch.erl b/src/node_dispatch.erl index 258405cb056..a8ad2ba96ed 100644 --- a/src/node_dispatch.erl +++ b/src/node_dispatch.erl @@ -1,28 +1,33 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_dispatch.erl +%%% Author : Christophe Romain +%%% Purpose : Publish item to node and all child subnodes +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +%%% @doc

    The {@module} module is a PubSub plugin whose +%%% goal is to republished each published item to all its children.

    +%%%

    Users cannot subscribe to this node, but are supposed to subscribe to +%%% its children.

    +%%% This module can not work with virtual nodetree -module(node_dispatch). -behaviour(gen_pubsub_node). @@ -31,12 +36,6 @@ -include("pubsub.hrl"). -include("jlib.hrl"). -%%% @doc

    The {@module} module is a PubSub plugin whose -%%% goal is to republished each published item to all its children.

    -%%%

    Users cannot subscribe to this node, but are supposed to subscribe to -%%% its children.

    -%%% This module can not work with virtual nodetree - -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, create_node/2, delete_node/1, purge_node/2, subscribe_node/8, unsubscribe_node/4, diff --git a/src/node_flat.erl b/src/node_flat.erl index 80a4189f26e..8acfd48c5b8 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -1,28 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_flat.erl +%%% Author : Christophe Romain +%%% Purpose : Standard PubSub node plugin +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- %%% @doc The module {@module} is the default PubSub plugin. %%%

    It is used as a default for all unknown PubSub node type. It can serve diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index c922a901169..96779cb6d33 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -1,28 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_flat_odbc.erl +%%% Author : Christophe Romain +%%% Purpose : Standard PubSub node plugin with ODBC backend +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- %%% @doc The module {@module} is the default PubSub plugin. %%%

    It is used as a default for all unknown PubSub node type. It can serve diff --git a/src/node_hometree.erl b/src/node_hometree.erl index da29116aa1b..138773e80a3 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -1,29 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_hometree.erl +%%% Author : Christophe Romain +%%% Purpose : Standard tree ordered node plugin +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_hometree). -behaviour(gen_pubsub_node). diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index d5d29cf75cd..1d7ef88ab3b 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -1,29 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_hometree_odbc.erl +%%% Author : Christophe Romain +%%% Purpose : Standard tree ordered node plugin with ODBC backend +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== - +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_hometree_odbc). -behaviour(gen_pubsub_node). diff --git a/src/node_mb.erl b/src/node_mb.erl index 91e49505c92..99fc40dfe04 100644 --- a/src/node_mb.erl +++ b/src/node_mb.erl @@ -1,31 +1,31 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_mb.erl +%%% Author : Eric Cestari +%%% Purpose : PEP microglobing experimentation +%%% Created : 25 Sep 2008 by Eric Cestari %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Eric Cestari -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_mb). -behaviour(gen_pubsub_node). --author('eric@ohmforce.com'). +-author('ecestari@process-one.net'). -include("pubsub.hrl"). -include("jlib.hrl"). diff --git a/src/node_pep.erl b/src/node_pep.erl index 972a7386670..647a8cb0a1e 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -1,28 +1,30 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_pep.erl +%%% Author : Christophe Romain +%%% Purpose : Standard PubSub PEP plugin +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +%%% @doc The module {@module} is the pep PubSub plugin. +%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    -module(node_pep). -behaviour(gen_pubsub_node). @@ -32,9 +34,6 @@ -include("jlib.hrl"). -include("logger.hrl"). -%%% @doc The module {@module} is the pep PubSub plugin. -%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    - -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, create_node/2, delete_node/1, purge_node/2, subscribe_node/8, unsubscribe_node/4, diff --git a/src/node_pep_odbc.erl b/src/node_pep_odbc.erl index a15b548d537..21afb8c140a 100644 --- a/src/node_pep_odbc.erl +++ b/src/node_pep_odbc.erl @@ -1,28 +1,30 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_pep_odbc.erl +%%% Author : Christophe Romain +%%% Purpose : Standard PubSub PEP plugin with ODBC backend +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +%%% @doc The module {@module} is the pep PubSub plugin. +%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    -module(node_pep_odbc). -behaviour(gen_pubsub_node). @@ -32,9 +34,6 @@ -include("jlib.hrl"). -include("logger.hrl"). -%%% @doc The module {@module} is the pep PubSub plugin. -%%%

    PubSub plugin nodes are using the {@link gen_pubsub_node} behaviour.

    - -export([init/3, terminate/2, options/0, features/0, create_node_permission/6, create_node/2, delete_node/1, purge_node/2, subscribe_node/8, unsubscribe_node/4, diff --git a/src/node_private.erl b/src/node_private.erl index d27b5e29d2f..b5a4ff06810 100644 --- a/src/node_private.erl +++ b/src/node_private.erl @@ -1,28 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_private.erl +%%% Author : Christophe Romain +%%% Purpose : +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_private). -behaviour(gen_pubsub_node). diff --git a/src/node_public.erl b/src/node_public.erl index b3f2092510c..560cbfea8b0 100644 --- a/src/node_public.erl +++ b/src/node_public.erl @@ -1,28 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : node_public.erl +%%% Author : Christophe Romain +%%% Purpose : +%%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(node_public). -behaviour(gen_pubsub_node). diff --git a/src/nodetree_dag.erl b/src/nodetree_dag.erl index 6ca7802395f..4baf7e3b54d 100644 --- a/src/nodetree_dag.erl +++ b/src/nodetree_dag.erl @@ -1,21 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%%---------------------------------------------------------------------- +%%% File : nodetree_dag.erl +%%% Author : Brian Cully +%%% Purpose : experimental support of XEP-248 +%%% Created : 15 Jun 2009 by Brian Cully %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% %%% -%%% @author Brian Cully -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(nodetree_dag). -behaviour(gen_pubsub_nodetree). diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl index b45d82cca82..ec3c213ea70 100644 --- a/src/nodetree_tree.erl +++ b/src/nodetree_tree.erl @@ -1,29 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%%---------------------------------------------------------------------- +%%% File : nodetree_tree.erl +%%% Author : Christophe Romain +%%% Purpose : Standard node tree plugin +%%% Created : 1 Dec 2007 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- %%% @doc The module {@module} is the default PubSub node tree plugin. %%%

    It is used as a default for all unknown PubSub node type. It can serve diff --git a/src/nodetree_tree_odbc.erl b/src/nodetree_tree_odbc.erl index e28ea71ae35..881531dbb90 100644 --- a/src/nodetree_tree_odbc.erl +++ b/src/nodetree_tree_odbc.erl @@ -1,29 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%%---------------------------------------------------------------------- +%%% File : nodetree_tree_odbc.erl +%%% Author : Christophe Romain +%%% Purpose : Standard node tree plugin with ODBC backend +%%% Created : 1 Dec 2007 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- %%% @doc The module {@module} is the default PubSub node tree plugin. %%%

    It is used as a default for all unknown PubSub node type. It can serve diff --git a/src/nodetree_virtual.erl b/src/nodetree_virtual.erl index 9797ad8db64..f9c7d4eb487 100644 --- a/src/nodetree_virtual.erl +++ b/src/nodetree_virtual.erl @@ -1,29 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%%---------------------------------------------------------------------- +%%% File : nodetree_virtual.erl +%%% Author : Christophe Romain +%%% Purpose : Standard node tree plugin using no storage backend +%%% Created : 1 Dec 2007 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- %%% @doc The module {@module} is the PubSub node tree plugin that %%% allow virtual nodes handling. This prevent storage of nodes. diff --git a/src/pubsub_db_odbc.erl b/src/pubsub_db_odbc.erl index 56a500ebbfc..53df71d4676 100644 --- a/src/pubsub_db_odbc.erl +++ b/src/pubsub_db_odbc.erl @@ -1,24 +1,28 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : pubsub_db_odbc.erl +%%% Author : Pablo Polvorin +%%% Purpose : Provide helpers for PubSub ODBC backend +%%% Created : 7 Aug 2009 by Pablo Polvorin %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 ProcessOne %%% -%%% @author Pablo Polvorin -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + -module(pubsub_db_odbc). -author("pablo.polvorin@process-one.net"). diff --git a/src/pubsub_index.erl b/src/pubsub_index.erl index c9ec94a6252..acfdbcf1ae2 100644 --- a/src/pubsub_index.erl +++ b/src/pubsub_index.erl @@ -1,29 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. -%%% +%%%---------------------------------------------------------------------- +%%% File : pubsub_index.erl +%%% Author : Christophe Romain +%%% Purpose : Provide uniq integer index for pubsub node +%%% Created : 30 Apr 2009 by Christophe Romain %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. -%%% %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 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. %%% -%%% @copyright 2006-2015 ProcessOne -%%% @author Christophe Romain -%%% [http://www.process-one.net/] -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- %% important note: %% new/1 and free/2 MUST be called inside a transaction bloc diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index 67f8575a72f..d302f5f3b0f 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -1,24 +1,27 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : pubsub_subscription.erl +%%% Author : Brian Cully +%%% Purpose : Handle pubsub subscriptions options +%%% Created : 29 May 2009 by Brian Cully %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 ProcessOne %%% -%%% @author Brian Cully -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(pubsub_subscription). diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index 87296b620aa..b17d95b016f 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -1,25 +1,28 @@ -%%% ==================================================================== -%%% ``The contents of this file are subject to the Erlang Public License, -%%% Version 1.1, (the "License"); you may not use this file except in -%%% compliance with the License. You should have received a copy of the -%%% Erlang Public License along with this software. If not, it can be -%%% retrieved via the world wide web at http://www.erlang.org/. +%%%---------------------------------------------------------------------- +%%% File : pubsub_subscription_odbc.erl +%%% Author : Pablo Polvorin +%%% Purpose : Handle pubsub subscriptions options with ODBC backend +%%% based on pubsub_subscription.erl by Brian Cully +%%% Created : 7 Aug 2009 by Pablo Polvorin %%% -%%% Software distributed under the License is distributed on an "AS IS" -%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%%% the License for the specific language governing rights and limitations -%%% under the License. %%% -%%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne -%%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% ejabberd, Copyright (C) 2002-2015 ProcessOne %%% -%%% @author Pablo Polvorin -%%% @author based on pubsub_subscription.erl by Brian Cully -%%% @version {@vsn}, {@date} {@time} -%%% @end -%%% ==================================================================== +%%% 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- -module(pubsub_subscription_odbc). -author("pablo.polvorin@process-one.net"). From 6efdf78ce3705d18436b45cea03fa31a25f51b4e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 15 Dec 2015 16:19:54 +0100 Subject: [PATCH 415/695] PubSub plugin for online users only --- src/node_online.erl | 173 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/node_online.erl diff --git a/src/node_online.erl b/src/node_online.erl new file mode 100644 index 00000000000..0249aab11aa --- /dev/null +++ b/src/node_online.erl @@ -0,0 +1,173 @@ +%%%---------------------------------------------------------------------- +%%% File : node_online.erl +%%% Author : Christophe Romain +%%% Purpose : Handle only online users, remove offline subscriptions and nodes +%%% Created : 15 Dec 2015 by Christophe Romain +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-module(node_online). +-behaviour(gen_pubsub_node). +-author('christophe.romain@process-one.net'). + +-include("pubsub.hrl"). +-include("jlib.hrl"). + +-export([init/3, terminate/2, options/0, features/0, + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). + +-export([user_offline/3]). + +init(Host, ServerHost, Opts) -> + node_flat:init(Host, ServerHost, Opts), + ejabberd_hooks:add(sm_remove_connection_hook, ServerHost, + ?MODULE, user_offline, 75), + ok. + +terminate(Host, ServerHost) -> + node_flat:terminate(Host, ServerHost), + ejabberd_hooks:delete(sm_remove_connection_hook, ServerHost, + ?MODULE, user_offline, 75), + ok. + +user_offline(_SID, #jid{luser=LUser,lserver=LServer}, _Info) -> + mod_pubsub:remove_user(LUser, LServer). + +options() -> + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, false}, + {purge_offline, true}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, open}, + {roster_groups_allowed, []}, + {publish_model, publishers}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, on_sub_and_presence}, + {deliver_notifications, true}, + {presence_based_delivery, true}]. + +features() -> + node_flat:features(). + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_flat:create_node(Nidx, Owner). + +delete_node(Removed) -> + node_flat:delete_node(Removed). + +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). + +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). + +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). + +purge_node(Nidx, Owner) -> + node_flat:purge_node(Nidx, Owner). + +get_entity_affiliations(Host, Owner) -> + node_flat:get_entity_affiliations(Host, Owner). + +get_node_affiliations(Nidx) -> + node_flat:get_node_affiliations(Nidx). + +get_affiliation(Nidx, Owner) -> + node_flat:get_affiliation(Nidx, Owner). + +set_affiliation(Nidx, Owner, Affiliation) -> + node_flat:set_affiliation(Nidx, Owner, Affiliation). + +get_entity_subscriptions(Host, Owner) -> + node_flat:get_entity_subscriptions(Host, Owner). + +get_node_subscriptions(Nidx) -> + node_flat:get_node_subscriptions(Nidx). + +get_subscriptions(Nidx, Owner) -> + node_flat:get_subscriptions(Nidx, Owner). + +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). + +get_pending_nodes(Host, Owner) -> + node_flat:get_pending_nodes(Host, Owner). + +get_states(Nidx) -> + node_flat:get_states(Nidx). + +get_state(Nidx, JID) -> + node_flat:get_state(Nidx, JID). + +set_state(State) -> + node_flat:set_state(State). + +get_items(Nidx, From, RSM) -> + node_flat:get_items(Nidx, From, RSM). + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_flat:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). + +get_item(Nidx, ItemId) -> + node_flat:get_item(Nidx, ItemId). + +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). + +set_item(Item) -> + node_flat:set_item(Item). + +get_item_name(Host, Node, Id) -> + node_flat:get_item_name(Host, Node, Id). + +node_to_path(Node) -> + node_flat:node_to_path(Node). + +path_to_node(Path) -> + node_flat:path_to_node(Path). From 5bb70e844d8d326082178f542ede7102d4df65f9 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 15 Dec 2015 21:02:12 +0100 Subject: [PATCH 416/695] Fix mod_carboncopy configuration for test suite The mod_carboncopy module doesn't have the "db_type" option. --- test/ejabberd_SUITE_data/ejabberd.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 111d72f7975..c0d3aa8c17c 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -204,8 +204,7 @@ Welcome to this XMPP server." db_type: internal mod_vcard_xupdate: db_type: internal - mod_carboncopy: - db_type: internal + mod_carboncopy: [] mod_client_state: drop_chat_states: true queue_presence: true From 0e330da2a631aad97ab634014c7a272a5c0a0b71 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 15 Dec 2015 21:05:04 +0100 Subject: [PATCH 417/695] mod_mam: Keep 'to' attribute for MUC MAM messages --- src/mod_mam.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 7e2051057b6..3d81b0d6667 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -781,8 +781,7 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, [] end, Pkt1 = Pkt#xmlel{children = Items ++ Els}, - Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1), - jlib:remove_attr(<<"to">>, Pkt2). + Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1). is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> PrioRes = ejabberd_sm:get_user_present_resources(U, S), From 11ad96fced3d99deeeaf5e8d8406b7f8893c3b8a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 15 Dec 2015 21:37:41 +0100 Subject: [PATCH 418/695] Use MUC domain for 'by' attribute of Let mod_mam specify only the domain part of the room JID in the 'by' attribute of tags. --- src/mod_mam.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 3d81b0d6667..54572fb0901 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -200,12 +200,12 @@ user_send_packet(Pkt, C2SState, JID, Peer) -> muc_filter_message(Pkt, #state{config = Config} = MUCState, RoomJID, From, FromNick) -> if Config#config.mam -> - By = jid:to_string(RoomJID), - NewPkt = strip_my_archived_tag(Pkt, By), + LServer = RoomJID#jid.lserver, + NewPkt = strip_my_archived_tag(Pkt, LServer), case store_muc(MUCState, NewPkt, RoomJID, From, FromNick) of {ok, ID} -> StanzaID = #xmlel{name = <<"stanza-id">>, - attrs = [{<<"by">>, By}, + attrs = [{<<"by">>, LServer}, {<<"xmlns">>, ?NS_SID_0}, {<<"id">>, ID}]}, NewEls = [StanzaID|NewPkt#xmlel.children], From 5fd1aa0d046aedc4d3b61a150899085ad863ca0f Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 16 Dec 2015 00:08:23 +0100 Subject: [PATCH 419/695] Advertise MAM in disco info for account/room JID As per XEP-0313 version 0.2 and newer, advertise the MAM feature in the service discovery information for the bare account (or MUC room) JID. Some clients check the server's discovery information instead, so we'll continue to advertise the feature there as well. --- src/mod_mam.erl | 17 +++++++++++++++-- src/mod_muc_room.erl | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 54572fb0901..dba8b1cbfcb 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -34,8 +34,8 @@ -export([start/2, stop/1]). -export([user_send_packet/4, user_receive_packet/5, - process_iq_v0_2/3, process_iq_v0_3/3, remove_user/2, - remove_user/3, mod_opt_type/1, muc_process_iq/4, + process_iq_v0_2/3, process_iq_v0_3/3, disco_sm_features/5, + remove_user/2, remove_user/3, mod_opt_type/1, muc_process_iq/4, muc_filter_message/5]). -include_lib("stdlib/include/ms_transform.hrl"). @@ -88,6 +88,8 @@ start(Host, Opts) -> muc_filter_message, 50), ejabberd_hooks:add(muc_process_iq, Host, ?MODULE, muc_process_iq, 50), + ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, + disco_sm_features, 50), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, @@ -130,6 +132,8 @@ stop(Host) -> gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_0), gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_MAM_1), gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MAM_1), + ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, + disco_sm_features, 50), ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, @@ -276,6 +280,15 @@ get_xdata_fields(SubEl) -> [] end. +disco_sm_features(empty, From, To, Node, Lang) -> + disco_sm_features({result, []}, From, To, Node, Lang); +disco_sm_features({result, OtherFeatures}, + #jid{luser = U, lserver = S}, + #jid{luser = U, lserver = S}, <<>>, _Lang) -> + {result, [?NS_MAM_TMP, ?NS_MAM_0, ?NS_MAM_1 | OtherFeatures]}; +disco_sm_features(Acc, _From, _To, _Node, _Lang) -> + Acc. + %%%=================================================================== %%% Internal functions %%%=================================================================== diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index dd7f78163ff..1606b593a1d 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -4144,6 +4144,13 @@ process_iq_disco_info(_From, get, Lang, StateData) -> <<"muc_moderated">>, <<"muc_unmoderated">>), ?CONFIG_OPT_TO_FEATURE((Config#config.password_protected), <<"muc_passwordprotected">>, <<"muc_unsecured">>)] + ++ case {gen_mod:is_loaded(StateData#state.server_host, mod_mam), + Config#config.mam} of + {true, true} -> + [?FEATURE(?NS_MAM_0)]; + _ -> + [] + end ++ iq_disco_info_extras(Lang, StateData), StateData}. From bae333788b168ef06609c50f16254b183fde7f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 16 Dec 2015 12:22:15 +0100 Subject: [PATCH 420/695] Add plugin for passing extra erl_opts flags to deps, and use it for hipe This fixes #425 in github issue tracker --- plugins/deps_erl_opts.erl | 12 ++++++++++++ rebar.config.script | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 plugins/deps_erl_opts.erl diff --git a/plugins/deps_erl_opts.erl b/plugins/deps_erl_opts.erl new file mode 100644 index 00000000000..72580266441 --- /dev/null +++ b/plugins/deps_erl_opts.erl @@ -0,0 +1,12 @@ +-module(deps_erl_opts). +-export([preprocess/2]). + +preprocess(Config, Dirs) -> + ExtraOpts = rebar_config:get(Config, deps_erl_opts, []), + Opts = rebar_config:get(Config, erl_opts, []), + NewOpts = lists:foldl(fun(Opt, Acc) when is_tuple(Opt) -> + lists:keystore(element(1, Opt), 1, Acc, Opt); + (Opt, Acc) -> + [Opt | lists:delete(Opt, Acc)] + end, Opts, ExtraOpts), + {ok, rebar_config:set(Config, erl_opts, NewOpts), []}. diff --git a/rebar.config.script b/rebar.config.script index e47890036d1..0204e7b70c8 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -157,10 +157,10 @@ CfgXrefs = lists:flatmap( ElixirConfig = case lists:keysearch(elixir, 1, Cfg) of {value, {elixir, true}} -> - [{plugins, [rebar_elixir_compiler, rebar_exunit] }, + [{plugins, [deps_erl_opts, rebar_elixir_compiler, rebar_exunit] }, {lib_dirs, ["deps/elixir/lib"]}]; _ -> - [] + [{plugins, [deps_erl_opts]}] end, {ok, Cwd} = file:get_cwd(), @@ -181,6 +181,7 @@ AllDeps = case lists:keytake(lager, 1, AllDeps0) of Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++ [{src_dirs, [asn1, src | SrcDirs]}]}, + {deps_erl_opts, HiPE}, {sub_dirs, ["rel"]}, {keep_build_info, true}, {ct_extra_params, "-ct_hooks cth_surefire " From b5cc4a3a7d59136022bcfeca4dda7fd11344d4ca Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 12 Jul 2015 20:58:22 +0200 Subject: [PATCH 421/695] Remove "--enable-nif" flag Specifying "--enable-nif" or "--disable-nif" when running ejabberd's configure script has no effect anymore: NIF support is enabled by default and can only be disabled by building the p1_xml dependency with "--disable-nif". --- configure.ac | 15 +++------------ rebar.config.script | 6 +----- vars.config.in | 1 - 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index 57b9aa7473d..13b1fe13bc3 100644 --- a/configure.ac +++ b/configure.ac @@ -100,10 +100,10 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-nif --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) nif=true odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; - no) nif=false odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; + yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; + no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -115,14 +115,6 @@ AC_ARG_ENABLE(tools, *) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;; esac],[if test "x$tools" = "x"; then tools=false; fi]) -AC_ARG_ENABLE(nif, -[AC_HELP_STRING([--enable-nif], [replace some functions with C equivalents. Requires Erlang R13B04 or higher (default: no)])], -[case "${enableval}" in - yes) nif=true ;; - no) nif=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-nif) ;; -esac],[if test "x$nif" = "x"; then nif=false; fi]) - AC_ARG_ENABLE(odbc, [AC_HELP_STRING([--enable-odbc], [enable pure ODBC support (default: no)])], [case "${enableval}" in @@ -249,7 +241,6 @@ fi AC_SUBST(hipe) AC_SUBST(roster_gateway_workaround) AC_SUBST(full_xml) -AC_SUBST(nif) AC_SUBST(db_type) AC_SUBST(odbc) AC_SUBST(mysql) diff --git a/rebar.config.script b/rebar.config.script index 0204e7b70c8..2642fc68217 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -19,8 +19,6 @@ Cfg = case file:consult("vars.config") of Macros = lists:flatmap( fun({roster_gateway_workaround, true}) -> [{d, 'ROSTER_GATEWAY_WORKAROUND'}]; - ({nif, true}) -> - [{d, 'NIF'}]; ({db_type, mssql}) -> [{d, 'mssql'}]; ({lager, true}) -> @@ -76,9 +74,7 @@ ConfigureCmd = fun(Pkg, Flags) -> end, XMLFlags = lists:foldl( - fun({nif, true}, Acc) -> - Acc ++ " --enable-nif"; - ({full_xml, true}, Acc) -> + fun({full_xml, true}, Acc) -> Acc ++ " --enable-full-xml"; (_, Acc) -> Acc diff --git a/vars.config.in b/vars.config.in index 5c37fb976f5..313e40b8d5b 100644 --- a/vars.config.in +++ b/vars.config.in @@ -9,7 +9,6 @@ %% Macros {roster_gateway_workaround, @roster_gateway_workaround@}. {full_xml, @full_xml@}. -{nif, @nif@}. {db_type, @db_type@}. {debug, @debug@}. {hipe, @hipe@}. From 08b0530164bd0907536f3c0a00467908451cea20 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 16 Dec 2015 12:56:06 +0100 Subject: [PATCH 422/695] Don't read pubsub options when plugin does not use them This also revert commit 6052f7b --- src/mod_pubsub.erl | 11 +++++++++-- src/node_flat.erl | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index c0b613d619f..a3494067ec3 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3424,12 +3424,19 @@ get_node_subs_by_depth(Host, Node, From) -> [{Depth, [{N, get_node_subs(Host, N)} || N <- Nodes]} || {Depth, Nodes} <- ParentTree]. get_node_subs(Host, #pubsub_node{type = Type, id = Nidx}) -> + WithOptions = lists:member(<<"subscription-options">>, plugin_features(Host, Type)), case node_call(Host, Type, get_node_subscriptions, [Nidx]) of - {result, Subs} -> get_options_for_subs(Host, Nidx, Subs); + {result, Subs} -> get_options_for_subs(Host, Nidx, Subs, WithOptions); Other -> Other end. -get_options_for_subs(Host, Nidx, Subs) -> +get_options_for_subs(_Host, _Nidx, Subs, false) -> + lists:foldl(fun({JID, subscribed, SubID}, Acc) -> + [{JID, SubID, []} | Acc]; + (_, Acc) -> + Acc + end, [], Subs); +get_options_for_subs(Host, Nidx, Subs, true) -> SubModule = subscription_plugin(Host), lists:foldl(fun({JID, subscribed, SubID}, Acc) -> case SubModule:get_subscription(JID, Nidx, SubID) of diff --git a/src/node_flat.erl b/src/node_flat.erl index 8acfd48c5b8..e35dd6e9b27 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -50,7 +50,7 @@ path_to_node/1, can_fetch_item/2, is_subscribed/1]). init(_Host, _ServerHost, _Opts) -> - pubsub_subscription:init(), + %pubsub_subscription:init(), mnesia:create_table(pubsub_state, [{disc_copies, [node()]}, {type, ordered_set}, From c6798fc515523aab1daf726528309ae9741b3767 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Wed, 16 Dec 2015 17:26:44 +0300 Subject: [PATCH 423/695] Add accept_interval option in ejabberd_listener --- src/ejabberd_listener.erl | 63 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index bebb15c4846..ac981fcff22 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -292,6 +292,40 @@ get_ip_tuple(IPOpt, _IPVOpt) -> IPOpt. accept(ListenSocket, Module, Opts) -> + IntervalOpt = + case proplists:get_value(accept_interval, Opts) of + [{linear, [I1_, T1_, T2_, I2_]}] -> + {linear, I1_, T1_, T2_, I2_}; + I_ -> I_ + end, + Interval = + case IntervalOpt of + undefined -> + 0; + I when is_integer(I), I >= 0 -> + I; + {linear, I1, T1, T2, I2} + when is_integer(I1), + is_integer(T1), + is_integer(T2), + is_integer(I2), + I1 >= 0, + I2 >= 0, + T2 > 0 -> + {MSec, Sec, _USec} = os:timestamp(), + TS = MSec * 1000000 + Sec, + {linear, I1, TS + T1, T2, I2}; + I -> + ?WARNING_MSG("There is a problem in the configuration: " + "~p is a wrong accept_interval value. " + "Using 0 as fallback", + [I]), + 0 + end, + accept(ListenSocket, Module, Opts, Interval). + +accept(ListenSocket, Module, Opts, Interval) -> + NewInterval = check_rate_limit(Interval), case gen_tcp:accept(ListenSocket) of {ok, Socket} -> case {inet:sockname(Socket), inet:peername(Socket)} of @@ -307,11 +341,11 @@ accept(ListenSocket, Module, Opts) -> false -> ejabberd_socket end, CallMod:start(strip_frontend(Module), gen_tcp, Socket, Opts), - accept(ListenSocket, Module, Opts); + accept(ListenSocket, Module, Opts, NewInterval); {error, Reason} -> ?ERROR_MSG("(~w) Failed TCP accept: ~w", [ListenSocket, Reason]), - accept(ListenSocket, Module, Opts) + accept(ListenSocket, Module, Opts, NewInterval) end. udp_recv(Socket, Module, Opts) -> @@ -555,6 +589,31 @@ format_error(Reason) -> ReasonStr end. +check_rate_limit(Interval) -> + NewInterval = receive + {rate_limit, AcceptInterval} -> + AcceptInterval + after 0 -> + Interval + end, + case NewInterval of + 0 -> ok; + Ms when is_integer(Ms) -> + timer:sleep(Ms); + {linear, I1, T1, T2, I2} -> + {MSec, Sec, _USec} = os:timestamp(), + TS = MSec * 1000000 + Sec, + I = + if + TS =< T1 -> I1; + TS >= T1 + T2 -> I2; + true -> + round((I2 - I1) * (TS - T1) / T2 + I1) + end, + timer:sleep(I) + end, + NewInterval. + -define(IS_CHAR(C), (is_integer(C) and (C >= 0) and (C =< 255))). -define(IS_UINT(U), (is_integer(U) and (U >= 0) and (U =< 65535))). -define(IS_PORT(P), (is_integer(P) and (P > 0) and (P =< 65535))). From c8986ffa5e1177b70c68bede404bb763c9a3d8de Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 16 Dec 2015 16:19:35 +0100 Subject: [PATCH 424/695] Use correct notification_type for last items (#827) --- src/mod_pubsub.erl | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index a3494067ec3..690422c3eb9 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -2520,18 +2520,18 @@ send_items(Host, Node, Nidx, Type, Options, LJID, last) -> undefined -> ok; LastItem -> - Stanza = items_event_stanza(Node, [LastItem]), - dispatch_items(Host, LJID, Node, Options, Stanza) + Stanza = items_event_stanza(Node, Options, [LastItem]), + dispatch_items(Host, LJID, Node, Stanza) end; send_items(Host, Node, Nidx, Type, Options, LJID, Number) when Number > 0 -> - Stanza = items_event_stanza(Node, get_last_items(Host, Type, Nidx, Number, LJID)), - dispatch_items(Host, LJID, Node, Options, Stanza); + Stanza = items_event_stanza(Node, Options, get_last_items(Host, Type, Nidx, Number, LJID)), + dispatch_items(Host, LJID, Node, Stanza); send_items(Host, Node, _Nidx, _Type, Options, LJID, _) -> - Stanza = items_event_stanza(Node, []), - dispatch_items(Host, LJID, Node, Options, Stanza). + Stanza = items_event_stanza(Node, Options, []), + dispatch_items(Host, LJID, Node, Stanza). -dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To, Node, - Options, Stanza) -> +dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To, + Node, Stanza) -> C2SPid = case ejabberd_sm:get_session_pid(ToU, ToS, ToR) of ToPid when is_pid(ToPid) -> ToPid; _ -> @@ -2543,17 +2543,13 @@ dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To, Node, end, if C2SPid == undefined -> ok; true -> - NotificationType = get_option(Options, notification_type, headline), - Message = add_message_type(Stanza, NotificationType), ejabberd_c2s:send_filtered(C2SPid, {pep_message, <>}, service_jid(From), jid:make(To), - Message) + Stanza) end; -dispatch_items(From, To, _Node, Options, Stanza) -> - NotificationType = get_option(Options, notification_type, headline), - Message = add_message_type(Stanza, NotificationType), - ejabberd_router:route(service_jid(From), jid:make(To), Message). +dispatch_items(From, To, _Node, Stanza) -> + ejabberd_router:route(service_jid(From), jid:make(To), Stanza). %% @doc

    Return the list of affiliations as an XMPP response.

    -spec(get_affiliations/4 :: @@ -3257,7 +3253,8 @@ payload_xmlelements([#xmlel{} | Tail], Count) -> payload_xmlelements([_ | Tail], Count) -> payload_xmlelements(Tail, Count). -items_event_stanza(Node, Items) -> +items_event_stanza(Node, Options, Items) -> + NotificationType = get_option(Options, notification_type, headline), MoreEls = case Items of [LastItem] -> {ModifNow, ModifUSR} = LastItem#pubsub_item.modification, @@ -3271,7 +3268,11 @@ items_event_stanza(Node, Items) -> [] end, event_stanza_with_els([#xmlel{name = <<"items">>, - attrs = [{<<"type">>, <<"headline">>} | nodeAttr(Node)], + attrs = case NotificationType of + normal -> nodeAttr(Node); + _ -> [{<<"type">>, jlib:atom_to_binary(NotificationType)} + | nodeAttr(Node)] + end, children = itemsEls(Items)}], MoreEls). From 6957e892dde33511101e8f6012b774e4ffee7ae0 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 16 Dec 2015 17:04:45 +0100 Subject: [PATCH 425/695] Fix last item message type as message attribute --- src/mod_pubsub.erl | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 690422c3eb9..9c334ebc0c6 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3254,7 +3254,6 @@ payload_xmlelements([_ | Tail], Count) -> payload_xmlelements(Tail, Count). items_event_stanza(Node, Options, Items) -> - NotificationType = get_option(Options, notification_type, headline), MoreEls = case Items of [LastItem] -> {ModifNow, ModifUSR} = LastItem#pubsub_item.modification, @@ -3267,14 +3266,12 @@ items_event_stanza(Node, Options, Items) -> _ -> [] end, - event_stanza_with_els([#xmlel{name = <<"items">>, - attrs = case NotificationType of - normal -> nodeAttr(Node); - _ -> [{<<"type">>, jlib:atom_to_binary(NotificationType)} - | nodeAttr(Node)] - end, + BaseStanza = event_stanza_with_els([#xmlel{name = <<"items">>, + attrs = nodeAttr(Node), children = itemsEls(Items)}], - MoreEls). + MoreEls), + NotificationType = get_option(Options, notification_type, headline), + add_message_type(BaseStanza, NotificationType). event_stanza(Els) -> event_stanza_with_els(Els, []). From bb5a8a42c31048bc1004b54528699dae51f5a418 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 17 Dec 2015 10:16:17 +0100 Subject: [PATCH 426/695] Fix pubsub virtual nodetree plugin --- src/nodetree_virtual.erl | 43 ++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/nodetree_virtual.erl b/src/nodetree_virtual.erl index f9c7d4eb487..9fc9b53c501 100644 --- a/src/nodetree_virtual.erl +++ b/src/nodetree_virtual.erl @@ -59,15 +59,12 @@ get_node(Host, Node, _From) -> get_node(Host, Node). get_node(Host, Node) -> - get_node(nodeidx(Host, Node)). + Nidx = nodeidx(Host, Node), + node_record(Host, Node, Nidx). get_node(Nidx) -> {Host, Node} = nodeid(Nidx), - [Type|_] = mod_pubsub:plugins(Host), - Module = mod_pubsub:plugin(Host, Type), - #pubsub_node{nodeid = Node, id = Nidx, type = Type, - owners = [{<<"">>, Host, <<"">>}], - options = Module:options()}. + node_record(Host, Node, Nidx). get_nodes(Host, _From) -> get_nodes(Host). @@ -79,10 +76,7 @@ get_parentnodes(_Host, _Node, _From) -> []. get_parentnodes_tree(Host, Node, From) -> - case get_node(Host, Node, From) of - Node when is_record(Node, pubsub_node) -> [{0, [Node]}]; - _Error -> [] - end. + [{0, [get_node(Host, Node, From)]}]. get_subnodes(Host, Node, _From) -> get_subnodes(Host, Node). @@ -97,12 +91,35 @@ get_subnodes_tree(_Host, _Node) -> []. create_node(Host, Node, _Type, _Owner, _Options, _Parents) -> - {error, {virtual, {Host, Node}}}. + {error, {virtual, nodeidx(Host, Node)}}. delete_node(Host, Node) -> [get_node(Host, Node)]. %% internal helper -nodeidx(Host, Node) -> term_to_binary({Host, Node}). -nodeid(Nidx) -> binary_to_term(Nidx). +node_record({U,S,R}, Node, Nidx) -> + Host = mod_pubsub:host(S), + Type = <<"pep">>, + Module = mod_pubsub:plugin(Host, Type), + #pubsub_node{nodeid = {{U,S,R},Node}, id = Nidx, type = Type, + owners = [{U,S,R}], + options = Module:options()}; +node_record(Host, Node, Nidx) -> + [Type|_] = mod_pubsub:plugins(Host), + Module = mod_pubsub:plugin(Host, Type), + #pubsub_node{nodeid = {Host, Node}, id = Nidx, type = Type, + owners = [{<<"">>, Host, <<"">>}], + options = Module:options()}. + +nodeidx({U,S,R}, Node) -> + JID = jid:to_string(jid:make(U,S,R)), + <>; +nodeidx(Host, Node) -> + <>. +nodeid(Nidx) -> + [Head, Node] = binary:split(Nidx, <<":">>), + case jid:from_string(Head) of + {jid,<<>>,Host,<<>>,_,_,_} -> {Host, Node}; + {jid,U,S,R,_,_,_} -> {{U,S,R}, Node} + end. From 99fdba0745241ea9f2c2de211993eb2a3ab2aef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 18 Dec 2015 17:17:13 +0100 Subject: [PATCH 427/695] Convert rebar.config.script to more declarative format --- rebar.config | 89 +++++++++++++++++ rebar.config.script | 230 ++++++++++++++------------------------------ 2 files changed, 163 insertions(+), 156 deletions(-) create mode 100644 rebar.config diff --git a/rebar.config b/rebar.config new file mode 100644 index 00000000000..039d0bf2fac --- /dev/null +++ b/rebar.config @@ -0,0 +1,89 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeniy Khramtsov +%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 1 May 2013 by Evgeniy Khramtsov +%%%------------------------------------------------------------------- + +{deps, [{if_var_true, lager, {lager, ".*", {git, "git://github.com/basho/lager"}}}, + {if_var_false, lager, {p1_logger, ".*", {git, "git://github.com/processone/p1_logger"}}}, + {cache_tab, ".*", {git, "git://github.com/processone/cache_tab", {tag, "1.0.1"}}}, + {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, + {p1_stringprep, ".*", {git, "git://github.com/processone/stringprep"}}, + {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, + {esip, ".*", {git, "git://github.com/processone/p1_sip"}}, + {p1_stun, ".*", {git, "git://github.com/processone/stun"}}, + {p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}}, + {p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}, + {jiffy, ".*", {git, "git://github.com/davisp/jiffy"}}, + {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, + {xmlrpc, ".*", {git, "git://github.com/rds13/xmlrpc"}}, + {if_var_true, mysql, {p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}}, + {if_var_true, pgsql, {p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}}, + {if_var_true, sqlite, {sqlite3, ".*", {git, "git://github.com/alexeyr/erlang-sqlite3"}}}, + {if_var_true, pam, {p1_pam, ".*", {git, "git://github.com/processone/epam"}}}, + {if_var_true, zlib, {p1_zlib, ".*", {git, "git://github.com/processone/zlib"}}}, + {if_var_true, riak, {riakc, ".*", {git, "git://github.com/basho/riak-erlang-client"}}}, + {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "git@github.com:processone/rebar_elixir_plugin.git"}}}, + {if_var_true, elixir, {elixir, ".*", {git, "git://github.com/elixir-lang/elixir", {branch, "v1.0"}}}}, + {if_var_true, iconv, {p1_iconv, ".*", {git, "git://github.com/processone/eiconv"}}}, + {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, + {if_var_true, redis, {eredis, ".*", {git, "git://github.com/wooga/eredis"}}}]}. + +{erl_opts, [nowarn_deprecated_function, + {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, + {if_var_match, db_type, mssql, {d, 'mssql'}}, + {if_var_true, lager, {d, 'LAGER'}}, + {if_var_true, erlang_deprecated_types, {d, 'ERL_DEPRECATED_TYPES'}}, + {if_var_true, hipe, native}, + {src_dirs, [asn1, src, + {if_var_true, tools, tools}, + {if_var_true, elixir, include}]}]}. + +{deps_erl_opts, [{if_var_true, hipe, native}]}. + +{plugins, [deps_erl_opts, + {if_var_true, elixir, rebar_elixir_compiler}, + {if_var_true, elixir, rebar_exunit}]}. + +{lib_dirs, [{if_var_true, elixir, "deps/elixir/lib"}]}. + +{sub_dirs, ["rel"]}. + +{keep_build_info, true}. + +{xref_warnings, false}. + +{xref_checks, [deprecated_function_calls]}. + +{xref_exclusions, [ + "(\"gen_transport\":_/_)", + "(\"eprof\":_/_)", + {if_var_false, mysql, "(\".*mysql.*\":_/_)"}, + {if_var_false, pgsql, "(\".*pgsql.*\":_/_)"}, + {if_var_false, pam, "(\"epam\":_/_)"}, + {if_var_false, riak, "(\"riak.*\":_/_)"}, + {if_var_true, riak, "(\"riak_object\":_/_)"}, + {if_var_false, zlib, "(\"ezlib\":_/_)"}, + {if_var_false, http, "(\"lhttpc\":_/_)"}, + {if_var_false, iconv, "(\"iconv\":_/_)"}, + {if_var_false, odbc, "(\"odbc\":_/_)"}, + {if_var_false, sqlite, "(\"sqlite3\":_/_)"}, + {if_var_false, redis, "(\"eredis\":_/_)"}]}. + +{eunit_compile_opts, [{i, "tools"}]}. + +{post_hook_configure, [{"p1_tls", []}, + {"p1_stringprep", []}, + {"p1_yaml", []}, + {"esip", []}, + {"p1_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, + {if_var_true, pam, {"p1_pam", []}}, + {if_var_true, zlib, {"p1_zlib", []}}, + {if_var_true, iconv, {"p1_iconv", []}}]}. + +{port_env, [{"CFLAGS", "-g -O2 -Wall"}]}. + +{port_specs, [{"priv/lib/jid.so", ["c_src/jid.c"]}]}. diff --git a/rebar.config.script b/rebar.config.script index 2642fc68217..fdba3a91a4e 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -7,8 +7,6 @@ %%% Created : 1 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -{require_min_otp_vsn, "16"}. - Cfg = case file:consult("vars.config") of {ok, Terms} -> Terms; @@ -16,51 +14,34 @@ Cfg = case file:consult("vars.config") of [] end, -Macros = lists:flatmap( - fun({roster_gateway_workaround, true}) -> - [{d, 'ROSTER_GATEWAY_WORKAROUND'}]; - ({db_type, mssql}) -> - [{d, 'mssql'}]; - ({lager, true}) -> - [{d, 'LAGER'}]; - ({erlang_deprecated_types, true}) -> - [{d, 'ERL_DEPRECATED_TYPES'}]; - (_) -> - [] - end, Cfg), - -DebugInfo = case lists:keysearch(debug, 1, Cfg) of - {value, {debug, true}} -> - []; - _ -> - [no_debug_info] - end, - -HiPE = case lists:keysearch(hipe, 1, Cfg) of - {value, {hipe, true}} -> - [native]; - _ -> - [] - end, - -SrcDirs = lists:foldl( - fun({tools, true}, Acc) -> - [tools|Acc]; - (_, Acc) -> - Acc - end, [], Cfg), - -Deps = [{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.1"}}}, - {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, - {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep"}}, - {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, - {esip, ".*", {git, "https://github.com/processone/p1_sip"}}, - {p1_stun, ".*", {git, "https://github.com/processone/stun"}}, - {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml"}}, - {p1_utils, ".*", {git, "https://github.com/processone/p1_utils"}}, - {jiffy, ".*", {git, "https://github.com/davisp/jiffy"}}, - {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, - {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc.git"}}], +ProcessVars = fun(_F, [], Acc) -> + lists:reverse(Acc); + (F, [{Type, Var, Value} | Tail], Acc) when + Type == if_var_true orelse + Type == if_var_false -> + Flag = Type == if_var_true, + case proplists:get_bool(Var, Cfg) of + V when V == Flag -> + F(F, Tail, [Value | Acc]); + _ -> + F(F, Tail, Acc) + end; + (F, [{Type, Var, Match, Value} | Tail], Acc) when + Type == if_var_match orelse + Type == if_var_no_match -> + case proplists:get_value(Var, Cfg) of + V when V == Match -> + F(F, Tail, [Value | Acc]); + _ -> + F(F, Tail, Acc) + end; + (F, [Other1 | Tail1], Acc) -> + F(F, Tail1, [F(F, Other1, []) | Acc]); + (F, Val, Acc) when is_tuple(Val) -> + list_to_tuple(F(F, tuple_to_list(Val), Acc)); + (_F, Other2, _Acc) -> + Other2 + end, CFLags = proplists:get_value(cflags, Cfg, ""), CPPFLags = proplists:get_value(cppflags, Cfg, ""), @@ -70,97 +51,19 @@ ConfigureCmd = fun(Pkg, Flags) -> {'get-deps', "sh -c 'cd deps/" ++ Pkg ++ " && CFLAGS=\""++ CFLags ++"\" CPPFLAGS=\""++ CPPFLags ++"\" LDFLAGS=\""++ LDFLags ++"\"" ++ - " ./configure" ++ Flags ++ "'"} + " ./configure " ++ Flags ++ "'"} end, -XMLFlags = lists:foldl( - fun({full_xml, true}, Acc) -> - Acc ++ " --enable-full-xml"; - (_, Acc) -> - Acc - end, "", Cfg), - -PostHooks = [ConfigureCmd("p1_tls", ""), - ConfigureCmd("p1_stringprep", ""), - ConfigureCmd("p1_yaml", ""), - ConfigureCmd("esip", ""), - ConfigureCmd("p1_xml", XMLFlags)], +Conf = ProcessVars(ProcessVars, CONFIG, []), -CfgDeps = lists:flatmap( - fun({mysql, true}) -> - [{p1_mysql, ".*", {git, "https://github.com/processone/mysql"}}]; - ({pgsql, true}) -> - [{p1_pgsql, ".*", {git, "https://github.com/processone/pgsql"}}]; - ({sqlite, true}) -> - [{sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3"}}]; - ({pam, true}) -> - [{p1_pam, ".*", {git, "https://github.com/processone/epam"}}]; - ({zlib, true}) -> - [{p1_zlib, ".*", {git, "https://github.com/processone/zlib"}}]; - ({riak, true}) -> - [{riakc, ".*", {git, "https://github.com/basho/riak-erlang-client"}}]; - ({elixir, true}) -> - [{rebar_elixir_plugin, ".*", {git, "https://github.com/yrashk/rebar_elixir_plugin"}}, - {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {branch, "v1.0"}}}]; - ({iconv, true}) -> - [{p1_iconv, ".*", {git, "https://github.com/processone/eiconv"}}]; - ({lager, true}) -> - [{lager, ".*", {git, "https://github.com/basho/lager"}}]; - ({lager, false}) -> - [{p1_logger, ".*", {git, "https://github.com/processone/p1_logger"}}]; - ({tools, true}) -> - [{meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}]; - ({redis, true}) -> - [{eredis, ".*", {git, "https://github.com/wooga/eredis"}}]; - (_) -> - [] - end, Cfg), - -CfgPostHooks = lists:flatmap( - fun({pam, true}) -> - [ConfigureCmd("p1_pam", "")]; - ({zlib, true}) -> - [ConfigureCmd("p1_zlib", "")]; - ({iconv, true}) -> - [ConfigureCmd("p1_iconv", "")]; - (_) -> - [] - end, Cfg), - -CfgXrefs = lists:flatmap( - fun({mysql, false}) -> - ["(\".*mysql.*\":_/_)"]; - ({pgsql, false}) -> - ["(\".*pgsql.*\":_/_)"]; - ({pam, false}) -> - ["(\"epam\":_/_)"]; - ({riak, false}) -> - ["(\"riak.*\":_/_)"]; - ({riak, true}) -> - % used in map-reduce function called from riak vm - ["(\"riak_object\":_/_)"]; - ({zlib, false}) -> - ["(\"ezlib\":_/_)"]; - ({http, false}) -> - ["(\"lhttpc\":_/_)"]; - ({iconv, false}) -> - ["(\"iconv\":_/_)"]; - ({odbc, false}) -> - ["(\"odbc\":_/_)"]; - (_) -> - [] - end, Cfg), - -ElixirConfig = case lists:keysearch(elixir, 1, Cfg) of - {value, {elixir, true}} -> - [{plugins, [deps_erl_opts, rebar_elixir_compiler, rebar_exunit] }, - {lib_dirs, ["deps/elixir/lib"]}]; - _ -> - [{plugins, [deps_erl_opts]}] - end, +Conf1 = case lists:keytake(post_hook_configure, 1, Conf) of + {value, {_, Items}, Rest} -> + [{post_hooks, [ConfigureCmd(Mod, string:join(Opts, " ")) || {Mod, Opts} <- Items]} | Rest]; + _ -> + Conf + end, {ok, Cwd} = file:get_cwd(), - TestConfigFile = filename:join([Cwd, "test", "config.ctc"]), TestConfig = case file:read_file_info(TestConfigFile) of {ok, _} -> @@ -169,29 +72,44 @@ TestConfig = case file:read_file_info(TestConfigFile) of "" end, -AllDeps0 = Deps ++ CfgDeps, -AllDeps = case lists:keytake(lager, 1, AllDeps0) of - {value, Tuple, Rest} -> [Tuple|Rest]; - false -> AllDeps0 - end, - -Config = [{erl_opts, Macros ++ HiPE ++ DebugInfo ++ - [{src_dirs, [asn1, src | SrcDirs]}]}, - {deps_erl_opts, HiPE}, - {sub_dirs, ["rel"]}, - {keep_build_info, true}, - {ct_extra_params, "-ct_hooks cth_surefire " - ++ TestConfig - ++ "-include " ++ filename:join([Cwd, "tools"])}, - {xref_warnings, false}, - {xref_checks, [deprecated_function_calls]}, - {xref_queries, - [{"(XC - UC) || (XU - X - B - " - ++ string:join(CfgXrefs, " - ") ++ ")", []}]}, - {post_hooks, PostHooks ++ CfgPostHooks}, - {deps, AllDeps}] ++ ElixirConfig, -%%io:format("ejabberd configuration:~n ~p~n", [Config]), -Config. +Conf2 = [{ct_extra_params, "-ct_hooks cth_surefire " + ++ TestConfig + ++ "-include " + ++ filename:join([Cwd, "tools"])} | Conf1], + +Conf3 = case lists:keytake(xref_exclusions, 1, Conf2) of + {value, {_, Items2}, Rest2} -> + [{xref_queries, [{lists:flatten(["(XC - UC) || (XU - X - B ", + [[" - ", V] || V <- Items2], ")"]), []}]} | Rest2]; + _ -> + Conf2 + end, + +Conf5 = case lists:keytake(floating_deps, 1, Conf3) of + {value, {_, FloatingDeps}, Rest4} -> + case lists:keytake(deps, 1, Rest4) of + {value, {_, Deps}, Rest41} -> + ND = lists:map(fun({DepName, Ver, {git, Repo, _Commit}}=Dep) -> + case lists:member(DepName, FloatingDeps) of + true -> + {DepName, ".*", {git, Repo}}; + _ -> + Dep + end; + (Dep2) -> + Dep2 + end, Deps), + [{deps, ND} | Rest41]; + _ -> + Rest4 + end; + _ -> + Conf3 + end, + +%io:format("ejabberd configuration:~n ~p~n", [Conf5]), + +Conf5. %% Local Variables: %% mode: erlang From 48909bdbee89958c4a90c521b873c9dbd79d48a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 18 Dec 2015 17:20:18 +0100 Subject: [PATCH 428/695] Add --enable-latest-deps to configure This option make 'rebar get-deps' command to always fetch latest versions of deps that are developed together with ejabberd instead of using frozen commit/branch/tag. --- configure.ac | 9 +++++++++ rebar.config | 16 ++++++++++++++++ vars.config.in | 2 ++ 3 files changed, 27 insertions(+) diff --git a/configure.ac b/configure.ac index 13b1fe13bc3..f8a41508828 100644 --- a/configure.ac +++ b/configure.ac @@ -211,6 +211,14 @@ AC_ARG_ENABLE(lager, *) AC_MSG_ERROR(bad value ${enableval} for --enable-lager) ;; esac],[if test "x$lager" = "x"; then lager=true; fi]) +AC_ARG_ENABLE(latest_deps, +[AC_HELP_STRING([--enable-latest-deps], [makes rebar use latest commits for dependences instead of tagged versions (default: no)])], +[case "${enableval}" in + yes) latest_deps=true ;; + no) latest_deps=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-latest-deps) ;; +esac],[if test "x$latest_deps" = "x"; then latest_deps=false; fi]) + AC_CONFIG_FILES([Makefile vars.config src/ejabberd.app.src]) @@ -255,6 +263,7 @@ AC_SUBST(iconv) AC_SUBST(debug) AC_SUBST(lager) AC_SUBST(tools) +AC_SUBST(latest_deps) AC_SUBST(CFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(LDFLAGS) diff --git a/rebar.config b/rebar.config index 039d0bf2fac..62b44d13ab1 100644 --- a/rebar.config +++ b/rebar.config @@ -32,6 +32,22 @@ {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, {if_var_true, redis, {eredis, ".*", {git, "git://github.com/wooga/eredis"}}}]}. +{if_var_true, latest_deps, + {floating_deps, [p1_logger, + cache_tab, + p1_tls, + p1_stringprep, + p1_xml, + esip, + p1_stun, + p1_yaml, + p1_utils, + p1_mysql, + p1_pgsql, + p1_pam, + p1_zlib, + p1_iconv]}}. + {erl_opts, [nowarn_deprecated_function, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, {if_var_match, db_type, mssql, {d, 'mssql'}}, diff --git a/vars.config.in b/vars.config.in index 313e40b8d5b..fceff7d673a 100644 --- a/vars.config.in +++ b/vars.config.in @@ -45,6 +45,8 @@ {libdir, "{{release_dir}}/lib"}. {docdir, "{{release_dir}}/doc"}. +{latest_deps, @latest_deps@}. + {ldflags, "@LDFLAGS@"}. {cflags, "@CFLAGS@"}. {cppflags, "@CPPFLAGS@"}. From d039b9b72b29e0c0b1c58e3f833cf9511b415725 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 20 Dec 2015 23:26:57 +0100 Subject: [PATCH 429/695] ejabberd_http: Log debug message on receive errors --- src/ejabberd_http.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 7225e74cfda..6d54a7edaac 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -518,7 +518,9 @@ recv_data(State, Len, Acc) -> of {ok, Data} -> recv_data(State, Len - byte_size(Data), <>); - _ -> <<"">> + Err -> + ?DEBUG("Cannot receive HTTP data: ~p", [Err]), + <<"">> end; _ -> Trail = (State#state.trail), From 2d22507636ea9deff5909d548d376e4cb626de13 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 20 Dec 2015 23:30:11 +0100 Subject: [PATCH 430/695] ejabberd_http: Cope with large POST/PUT requests gen_tcp returns 'enomem' if we try to receive more than 64 MiB. --- src/ejabberd_http.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 6d54a7edaac..920361017c1 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -513,8 +513,8 @@ recv_data(#state{trail = Trail} = State, Len, <<>>) when byte_size(Trail) > Len recv_data(State, Len, Acc) -> case State#state.trail of <<>> -> - case (State#state.sockmod):recv(State#state.socket, Len, - 300000) + case (State#state.sockmod):recv(State#state.socket, + min(Len, 16#4000000), 300000) of {ok, Data} -> recv_data(State, Len - byte_size(Data), <>); From d88d5d68070417964df9011ea02d6d55a09dbf50 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 21 Dec 2015 02:23:50 +0300 Subject: [PATCH 431/695] Support presence_broadcast in default_room_options mod_muc option --- src/mod_muc.erl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 385bf54b0bc..b03dde3c668 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -364,6 +364,14 @@ init([Host, Opts]) -> end; max_users -> fun(I) when is_integer(I), I > 0 -> I end; + presence_broadcast -> + fun(L) -> + lists:map( + fun(moderator) -> moderator; + (participant) -> participant; + (visitor) -> visitor + end, L) + end; _ -> ?ERROR_MSG("unknown option ~p with value ~p", [Opt, Val]), From 88c9991f908314ecd9fbbacea42f994dfc0bf5b8 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Dec 2015 16:19:24 +0100 Subject: [PATCH 432/695] 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 c3664af0fa7..c6162d94987 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 5c8597f2eab..eed7006c957 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]), From cfe0aea219a858c310fdffe0ad19f2f9af7e3105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 22 Dec 2015 11:48:25 +0100 Subject: [PATCH 433/695] Use built-in nif for integer_to_binary/binary_to_integer --- src/jlib.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index 321781216a4..2196ba57e00 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -872,16 +872,16 @@ binary_to_atom(Bin) -> erlang:binary_to_atom(Bin, utf8). binary_to_integer(Bin) -> - list_to_integer(binary_to_list(Bin)). + erlang:binary_to_integer(Bin). binary_to_integer(Bin, Base) -> - list_to_integer(binary_to_list(Bin), Base). + erlang:binary_to_integer(Bin, Base). integer_to_binary(I) -> - list_to_binary(integer_to_list(I)). + erlang:integer_to_binary(I). integer_to_binary(I, Base) -> - list_to_binary(erlang:integer_to_list(I, Base)). + erlang:integer_to_binary(I, Base). tuple_to_binary(T) -> iolist_to_binary(tuple_to_list(T)). From 8cf0d31ee916d3c5358dd2079e4d41670ef00df3 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 22 Dec 2015 13:20:23 +0100 Subject: [PATCH 434/695] Revert "mod_mam: Keep 'to' attribute for MUC MAM messages" This reverts commit 0e330da2a631aad97ab634014c7a272a5c0a0b71. XEP-0313 says: "When sending out the archives to a requesting client, the 'to' of the forwarded stanza MUST be empty". --- src/mod_mam.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index dba8b1cbfcb..e989fba9926 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -794,7 +794,8 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, [] end, Pkt1 = Pkt#xmlel{children = Items ++ Els}, - Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1). + Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1), + jlib:remove_attr(<<"to">>, Pkt2). is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> PrioRes = ejabberd_sm:get_user_present_resources(U, S), From 1f4916041ed87139f7e5ff193496283f9d759ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 23 Dec 2015 14:11:49 +0100 Subject: [PATCH 435/695] Update set-dep-versions script to work with new rebar.config --- tools/set-dep-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/set-dep-versions b/tools/set-dep-versions index 65b250516cf..3681def2277 100755 --- a/tools/set-dep-versions +++ b/tools/set-dep-versions @@ -6,7 +6,7 @@ set -u export PATH="/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:$PATH" deps_dir='deps' -rebar_script='rebar.config.script' +rebar_script='rebar.config' temp_file=$(mktemp "$rebar_script.XXXXXX") trap 'rm -f $temp_file' EXIT INT TERM From c42e026f9cf1af344043e1bb411f0a88139335b6 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 23 Dec 2015 19:34:23 +0100 Subject: [PATCH 436/695] Degenderise room error message (#747) --- src/mod_muc_room.erl | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 1606b593a1d..df7b7d3e307 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -225,8 +225,9 @@ normal_state({route, From, <<"">>, <<"error">> -> case is_user_online(From, StateData) of true -> - ErrorText = <<"This participant is kicked from the " - "room because he sent an error message">>, + ErrorText = <<"It is not allowed to send error messages to the" + " room. This participant (~s) sent an error " + "message (~s) and gets kicked from the room">>, NewState = expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)), @@ -512,9 +513,9 @@ normal_state({route, From, ToNick, of {expulse_sender, Reason} -> ?DEBUG(Reason, []), - ErrorText = <<"This participant is kicked from the " - "room because he sent an error message " - "to another participant">>, + ErrorText = <<"It is not allowed to send error messages to the" + " room. This participant (~s) sent an error " + "message (~s) and gets kicked from the room">>, NewState = expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)), {next_state, normal_state, NewState}; @@ -1053,9 +1054,9 @@ process_presence(From, Nick, end, remove_online_user(From, NewState, Reason); <<"error">> -> - ErrorText = - <<"This participant is kicked from the " - "room because he sent an error presence">>, + ErrorText = <<"It is not allowed to send error messages to the" + " room. This participant (~s) sent an error " + "message (~s) and gets kicked from the room">>, expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)); @@ -1310,11 +1311,13 @@ get_error_condition2(Packet) -> <- EEls], {condition, Condition}. +make_reason(Packet, From, StateData, Reason1) -> + {ok, #user{nick = FromNick}} = (?DICT):find(jlib:jid_tolower(From), StateData#state.users), + Condition = get_error_condition(Packet), + iolist_to_binary(io_lib:format(Reason1, [FromNick, Condition])). + expulse_participant(Packet, From, StateData, Reason1) -> - ErrorCondition = get_error_condition(Packet), - Reason2 = iolist_to_binary( - io_lib:format(binary_to_list(Reason1) ++ ": " ++ "~s", - [ErrorCondition])), + Reason2 = make_reason(Packet, From, StateData, Reason1), NewState = add_user_presence_un(From, #xmlel{name = <<"presence">>, attrs = From f3cb5e0d7714ca3f1784017b0000cd1baa9da04b Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 23 Dec 2015 20:54:40 +0100 Subject: [PATCH 437/695] Support binary strings in extract_translations --- contrib/extract_translations/extract_translations.erl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contrib/extract_translations/extract_translations.erl b/contrib/extract_translations/extract_translations.erl index 97bef684c88..46710023674 100644 --- a/contrib/extract_translations/extract_translations.erl +++ b/contrib/extract_translations/extract_translations.erl @@ -115,6 +115,12 @@ parse_form(Dir, File, Form, Used) -> {string, Line, Value} } -> ets:insert(vars, {Name, Value, Line}); + {match, + _, + {var, _, Name}, + {bin,Line,[{bin_element,_,{string,_,Value},_,_}]} + } -> + ets:insert(vars, {Name, Value, Line}); L when is_list(L) -> lists:foreach( fun(F) -> From babb484cfc7c1d89e84f5b821a2e3e873f74177e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 24 Dec 2015 15:01:33 +0300 Subject: [PATCH 438/695] Restrict access to MAM archives for members-only rooms --- src/mod_mam.erl | 22 +++++++++++++++++++--- src/mod_muc_room.erl | 2 ++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index e989fba9926..7124e2c6d13 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -251,7 +251,7 @@ process_iq_v0_3(#jid{lserver = LServer} = From, process_iq_v0_3(From, To, IQ) -> process_iq(From, To, IQ). -muc_process_iq(#iq{type = set, +muc_process_iq(#iq{type = set, lang = Lang, sub_el = #xmlel{name = <<"query">>, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> @@ -259,8 +259,24 @@ muc_process_iq(#iq{type = set, ?NS_MAM_0 -> LServer = MUCState#state.server_host, Role = mod_muc_room:get_role(From, MUCState), - process_iq(LServer, From, To, IQ, SubEl, - get_xdata_fields(SubEl), {groupchat, Role, MUCState}); + Config = MUCState#state.config, + if Config#config.members_only -> + case mod_muc_room:is_occupant_or_admin(From, MUCState) of + true -> + process_iq(LServer, From, To, IQ, SubEl, + get_xdata_fields(SubEl), + {groupchat, Role, MUCState}); + false -> + Text = <<"Only members are allowed to query " + "archives of this room">>, + Error = ?ERRT_FORBIDDEN(Lang, Text), + IQ#iq{type = error, sub_el = [SubEl, Error]} + end; + true -> + process_iq(LServer, From, To, IQ, SubEl, + get_xdata_fields(SubEl), + {groupchat, Role, MUCState}) + end; _ -> IQ end; diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index df7b7d3e307..760bd729281 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -35,6 +35,8 @@ start/9, start/7, get_role/2, + get_affiliation/2, + is_occupant_or_admin/2, route/4]). %% gen_fsm callbacks From a18a3dfbb17deac4484155cd32490e62a63d33f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 28 Dec 2015 12:19:49 +0100 Subject: [PATCH 439/695] Add commands for generating html or markdown documentation for commands --- include/ejabberd_commands.hrl | 7 +- src/ejabberd_commands.erl | 31 +- src/ejabberd_commands_doc.erl | 542 ++++++++++++++++++++++++++++++++++ src/mod_admin_extra.erl | 2 +- 4 files changed, 578 insertions(+), 4 deletions(-) create mode 100644 src/ejabberd_commands_doc.erl diff --git a/include/ejabberd_commands.hrl b/include/ejabberd_commands.hrl index 82ee891c3a6..44f170e841b 100644 --- a/include/ejabberd_commands.hrl +++ b/include/ejabberd_commands.hrl @@ -35,7 +35,11 @@ function :: atom(), args = [] :: [aterm()] | '_' | '$1' | '$2', policy = restricted :: open | restricted | admin | user, - result = {res, rescode} :: rterm() | '_' | '$2'}). + result = {res, rescode} :: rterm() | '_' | '$2', + args_desc = none :: none | [string()] | '_', + result_desc = none :: none | string() | '_', + args_example = none :: none | [any()] | '_', + result_example = none :: any()}). -type ejabberd_commands() :: #ejabberd_commands{name :: atom(), tags :: [atom()], @@ -72,4 +76,3 @@ %% @type rterm() = {Name::atom(), Type::rtype()}. %% A result term is a tuple with the term name and the term type. - diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index be798c6f0ab..b82c962b40b 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -230,7 +230,36 @@ init() -> ets:new(ejabberd_commands, [named_table, set, public, - {keypos, #ejabberd_commands.name}]). + {keypos, #ejabberd_commands.name}]), + register_commands([ + #ejabberd_commands{name = gen_html_doc_for_commands, tags = [documentation], + desc = "Generates html documentation for ejabberd_commands", + module = ejabberd_commands_doc, function = generate_html_output, + args = [{file, binary}, {regexp, binary}, {examples, binary}], + result = {res, rescode}, + args_desc = ["Path to file where generated " + "documentation should be stored", + "Regexp matching names of commands or modules " + "that will be included inside generated document", + "Comma separated list of languages (choosen from java, perl, xmlrpc, json)" + "that will have example invocation include in markdown document"], + result_desc = "0 if command failed, 1 when succedded", + args_example = ["/home/me/docs/api.html", "mod_admin", "java,json"], + result_example = ok}, + #ejabberd_commands{name = gen_markdown_doc_for_commands, tags = [documentation], + desc = "Generates markdown documentation for ejabberd_commands", + module = ejabberd_commands_doc, function = generate_md_output, + args = [{file, binary}, {regexp, binary}, {examples, binary}], + result = {res, rescode}, + args_desc = ["Path to file where generated " + "documentation should be stored", + "Regexp matching names of commands or modules " + "that will be included inside generated document", + "Comma separated list of languages (choosen from java, perl, xmlrpc, json)" + "that will have example invocation include in markdown document"], + result_desc = "0 if command failed, 1 when succedded", + args_example = ["/home/me/docs/api.html", "mod_admin", "java,json"], + result_example = ok}]). -spec register_commands([ejabberd_commands()]) -> ok. diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl new file mode 100644 index 00000000000..8d25897efd7 --- /dev/null +++ b/src/ejabberd_commands_doc.erl @@ -0,0 +1,542 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_commands_doc.erl +%%% Author : Badlop +%%% Purpose : Management of ejabberd commands +%%% Created : 20 May 2008 by Badlop +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-module(ejabberd_commands_doc). +-author('pawel@process-one.net'). + +-export([generate_html_output/3]). +-export([generate_md_output/3]). + +-include("ejabberd_commands.hrl"). +-include("ejabberd.hrl"). + +-define(RAW(V), if HTMLOutput -> xml:crypt(iolist_to_binary(V)); true -> iolist_to_binary(V) end). +-define(TAG(N), if HTMLOutput -> [<<"<", ??N, "/>">>]; true -> md_tag(N, <<"">>) end). +-define(TAG(N, V), if HTMLOutput -> [<<"<", ??N, ">">>, V, <<"">>]; true -> md_tag(N, V) end). +-define(TAG(N, C, V), if HTMLOutput -> [<<"<", ??N, " class='", C, "'>">>, V, <<"">>]; true -> md_tag(N, V) end). +-define(TAG_R(N, V), ?TAG(N, ?RAW(V))). +-define(TAG_R(N, C, V), ?TAG(N, C, ?RAW(V))). +-define(SPAN(N, V), ?TAG_R(span, ??N, V)). + +-define(STR(A), ?SPAN(str,[<<"\"">>, A, <<"\"">>])). +-define(NUM(A), ?SPAN(num,jlib:integer_to_binary(A))). +-define(FIELD(A), ?SPAN(field,A)). +-define(ID(A), ?SPAN(id,A)). +-define(OP(A), ?SPAN(op,A)). +-define(ARG(A), ?FIELD(atom_to_list(A))). +-define(KW(A), ?SPAN(kw,A)). +-define(BR, <<"\n">>). + +-define(ARG_S(A), ?STR(atom_to_list(A))). + +-define(RAW_L(A), ?RAW(<>)). +-define(STR_L(A), ?STR(<>)). +-define(FIELD_L(A), ?FIELD(<>)). +-define(ID_L(A), ?ID(<>)). +-define(OP_L(A), ?OP(<>)). +-define(KW_L(A), ?KW(<>)). + +-define(STR_A(A), ?STR(atom_to_list(A))). +-define(ID_A(A), ?ID(atom_to_list(A))). + +list_join_with([], _M) -> + []; +list_join_with([El|Tail], M) -> + lists:reverse(lists:foldl(fun(E, Acc) -> + [E, M | Acc] + end, [El], Tail)). + +md_tag(dt, V) -> + [<<"\n">>, V, <<"\n">>]; +md_tag(dd, V) -> + [<<"\n: ">>, V, <<"\n">>]; +md_tag(li, V) -> + [<<"- ">>, V, <<"\n">>]; +md_tag(pre, V) -> + [<<"\n">>, V, <<"\n">>]; +md_tag(p, V) -> + [<<"\n\n">>, V, <<"\n">>]; +md_tag(h1, V) -> + [<<"\n## ">>, V, <<"\n">>]; +md_tag(h2, V) -> + [<<"\n### ">>, V, <<"\n">>]; +md_tag(strong, V) -> + [<<"*">>, V, <<"*">>]; +md_tag(_, V) -> + V. + + +%% rescode_to_int(ok) -> +%% 0; +%% rescode_to_int(true) -> +%% 0; +%% rescode_to_int(_) -> +%% 1. + +perl_gen({Name, integer}, Int, _Indent, HTMLOutput) -> + [?ARG(Name), ?OP_L(" => "), ?NUM(Int)]; +perl_gen({Name, string}, Str, _Indent, HTMLOutput) -> + [?ARG(Name), ?OP_L(" => "), ?STR(Str)]; +perl_gen({Name, binary}, Str, _Indent, HTMLOutput) -> + [?ARG(Name), ?OP_L(" => "), ?STR(Str)]; +perl_gen({Name, atom}, Atom, _Indent, HTMLOutput) -> + [?ARG(Name), ?OP_L(" => "), ?STR_A(Atom)]; +perl_gen({Name, {tuple, Fields}}, Tuple, Indent, HTMLOutput) -> + Res = lists:map(fun({A,B})->perl_gen(A, B, Indent, HTMLOutput) end, lists:zip(Fields, tuple_to_list(Tuple))), + [?ARG(Name), ?OP_L(" => {"), list_join_with(Res, [?OP_L(", ")]), ?OP_L("}")]; +perl_gen({Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> + Res = lists:map(fun(E) -> [?OP_L("{"), perl_gen(ElDesc, E, Indent, HTMLOutput), ?OP_L("}")] end, List), + [?ARG(Name), ?OP_L(" => ["), list_join_with(Res, [?OP_L(", ")]), ?OP_L("]")]. + +perl_call(Name, ArgsDesc, Values, HTMLOutput) -> + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!perl\n">>} end, + [Preamble, + Indent, ?ID_L("XMLRPC::Lite"), ?OP_L("->"), ?ID_L("proxy"), ?OP_L("("), ?ID_L("$url"), ?OP_L(")->"), + ?ID_L("call"), ?OP_L("("), ?STR_A(Name), ?OP_L(", {"), ?BR, Indent, <<" ">>, + list_join_with(lists:map(fun({A,B})->perl_gen(A, B, <>, HTMLOutput) end, lists:zip(ArgsDesc, Values)), [?OP_L(","), ?BR, Indent, <<" ">>]), + ?BR, Indent, ?OP_L("})->"), ?ID_L("results"), ?OP_L("()")]. + +java_gen_map(Vals, Indent, HTMLOutput) -> + {Split, NL} = case Indent of + none -> {<<" ">>, <<" ">>}; + _ -> {[?BR, <<" ", Indent/binary>>], [?BR, Indent]} + end, + [?KW_L("new "), ?ID_L("HashMap"), ?OP_L("<"), ?ID_L("String"), ?OP_L(", "), ?ID_L("Object"), + ?OP_L(">() {{"), Split, list_join_with(Vals, Split), NL, ?OP_L("}}")]. + +java_gen({Name, integer}, Int, _Indent, HTMLOutput) -> + [?ID_L("put"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), ?KW_L("new "), ?ID_L("Integer"), ?OP_L("("), ?NUM(Int), ?OP_L("));")]; +java_gen({Name, string}, Str, _Indent, HTMLOutput) -> + [?ID_L("put"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), ?STR(Str), ?OP_L(");")]; +java_gen({Name, binary}, Str, _Indent, HTMLOutput) -> + [?ID_L("put"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), ?STR(Str), ?OP_L(");")]; +java_gen({Name, atom}, Atom, _Indent, HTMLOutput) -> + [?ID_L("put"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), ?STR_A(Atom), ?OP_L(");")]; +java_gen({Name, {tuple, Fields}}, Tuple, Indent, HTMLOutput) -> + NewIndent = <<" ", Indent/binary>>, + Res = lists:map(fun({A, B}) -> [java_gen(A, B, NewIndent, HTMLOutput)] end, lists:zip(Fields, tuple_to_list(Tuple))), + [?ID_L("put"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), java_gen_map(Res, Indent, HTMLOutput), ?OP_L(")")]; +java_gen({Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> + {NI, NI2, I} = case List of + [_] -> {" ", " ", Indent}; + _ -> {[?BR, <<" ", Indent/binary>>], + [?BR, <<" ", Indent/binary>>], + <<" ", Indent/binary>>} + end, + Res = lists:map(fun(E) -> java_gen_map([java_gen(ElDesc, E, I, HTMLOutput)], none, HTMLOutput) end, List), + [?ID_L("put"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), ?KW_L("new "), ?ID_L("Object"), ?OP_L("[] {"), NI, + list_join_with(Res, [?OP_L(","), NI]), NI2, ?OP_L("});")]. + +java_call(Name, ArgsDesc, Values, HTMLOutput) -> + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!java\n">>} end, + [Preamble, + Indent, ?ID_L("XmlRpcClientConfigImpl config"), ?OP_L(" = "), ?KW_L("new "), ?ID_L("XmlRpcClientConfigImpl"), ?OP_L("();"), ?BR, + Indent, ?ID_L("config"), ?OP_L("."), ?ID_L("setServerURL"), ?OP_L("("), ?ID_L("url"), ?OP_L(");"), ?BR, Indent, ?BR, + Indent, ?ID_L("XmlRpcClient client"), ?OP_L(" = "), ?KW_L("new "), ?ID_L("XmlRpcClient"), ?OP_L("();"), ?BR, + Indent, ?ID_L("client"), ?OP_L("."), ?ID_L("setConfig"), ?OP_L("("), ?ID_L("config"), ?OP_L(");"), ?BR, Indent, ?BR, + Indent, ?ID_L("client"), ?OP_L("."), ?ID_L("execute"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), + java_gen_map(lists:map(fun({A,B})->java_gen(A, B, Indent, HTMLOutput) end, lists:zip(ArgsDesc, Values)), Indent, HTMLOutput), + ?OP_L(");"), ?BR]. + +-define(XML_S(N, V), ?OP_L("<"), ?FIELD_L(??N), ?OP_L(">"), V). +-define(XML_E(N), ?OP_L("")). +-define(XML(N, Indent, V), ?BR, Indent, ?XML_S(N, V), ?BR, Indent, ?XML_E(N)). +-define(XML(N, Indent, D, V), ?XML(N, [Indent, lists:duplicate(D, <<" ">>)], V)). +-define(XML_L(N, Indent, V), ?BR, Indent, ?XML_S(N, V), ?XML_E(N)). +-define(XML_L(N, Indent, D, V), ?XML_L(N, [Indent, lists:duplicate(D, <<" ">>)], V)). + +xml_gen({Name, integer}, Int, Indent, HTMLOutput) -> + [?XML(member, Indent, + [?XML_L(name, Indent, 1, ?ID_A(Name)), + ?XML(value, Indent, 1, + [?XML_L(integer, Indent, 2, ?ID(jlib:integer_to_binary(Int)))])])]; +xml_gen({Name, string}, Str, Indent, HTMLOutput) -> + [?XML(member, Indent, + [?XML_L(name, Indent, 1, ?ID_A(Name)), + ?XML(value, Indent, 1, + [?XML_L(string, Indent, 2, ?ID(Str))])])]; +xml_gen({Name, binary}, Str, Indent, HTMLOutput) -> + [?XML(member, Indent, + [?XML_L(name, Indent, 1, ?ID_A(Name)), + ?XML(value, Indent, 1, + [?XML_L(string, Indent, 2, ?ID(Str))])])]; +xml_gen({Name, atom}, Atom, Indent, HTMLOutput) -> + [?XML(member, Indent, + [?XML_L(name, Indent, 1, ?ID_A(Name)), + ?XML(value, Indent, 1, + [?XML_L(string, Indent, 2, ?ID(atom_to_list(Atom)))])])]; +xml_gen({Name, {tuple, Fields}}, Tuple, Indent, HTMLOutput) -> + NewIndent = <<" ", Indent/binary>>, + Res = lists:map(fun({A, B}) -> xml_gen(A, B, NewIndent, HTMLOutput) end, lists:zip(Fields, tuple_to_list(Tuple))), + [?XML(member, Indent, + [?XML_L(name, Indent, 1, ?ID_A(Name)), + ?XML(value, Indent, 1, [?XML(struct, NewIndent, Res)])])]; +xml_gen({Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> + Ind1 = <<" ", Indent/binary>>, + Ind2 = <<" ", Ind1/binary>>, + Res = lists:map(fun(E) -> [?XML(value, Ind1, [?XML(struct, Ind1, 1, xml_gen(ElDesc, E, Ind2, HTMLOutput))])] end, List), + [?XML(member, Indent, + [?XML_L(name, Indent, 1, ?ID_A(Name)), + ?XML(value, Indent, 1, [?XML(array, Indent, 2, [?XML(data, Indent, 3, Res)])])])]. + +xml_call(Name, ArgsDesc, Values, HTMLOutput) -> + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!xml">>} end, + Res = lists:map(fun({A, B}) -> xml_gen(A, B, <>, HTMLOutput) end, lists:zip(ArgsDesc, Values)), + [Preamble, + ?XML(methodCall, Indent, + [?XML_L(methodName, Indent, 1, ?ID_A(Name)), + ?XML(params, Indent, 1, + [?XML(param, Indent, 2, + [?XML(value, Indent, 3, + [?XML(struct, Indent, 4, Res)])])])])]. + +% [?ARG_S(Name), ?OP_L(": "), ?STR(Str)]; +json_gen({_Name, integer}, Int, _Indent, HTMLOutput) -> + [?NUM(Int)]; +json_gen({_Name, string}, Str, _Indent, HTMLOutput) -> + [?STR(Str)]; +json_gen({_Name, binary}, Str, _Indent, HTMLOutput) -> + [?STR(Str)]; +json_gen({_Name, atom}, Atom, _Indent, HTMLOutput) -> + [?STR_A(Atom)]; +json_gen({_Name, rescode}, Val, _Indent, HTMLOutput) -> + [?ID_A(Val == ok orelse Val == true)]; +json_gen({_Name, restuple}, {Val, Str}, _Indent, HTMLOutput) -> + [?OP_L("{"), ?STR_L("res"), ?OP_L(": "), ?ID_A(Val == ok orelse Val == true), ?OP_L(", "), + ?STR_L("text"), ?OP_L(": "), ?STR(Str), ?OP_L("}")]; +json_gen({_Name, {list, {_, {tuple, [{_, atom}, ValFmt]}}}}, List, Indent, HTMLOutput) -> + Indent2 = <<" ", Indent/binary>>, + Res = lists:map(fun({N, V})->[?STR_A(N), ?OP_L(": "), json_gen(ValFmt, V, Indent2, HTMLOutput)] end, List), + [?OP_L("{"), ?BR, Indent2, list_join_with(Res, [?OP_L(","), ?BR, Indent2]), ?BR, Indent, ?OP_L("}")]; +json_gen({_Name, {tuple, Fields}}, Tuple, Indent, HTMLOutput) -> + Indent2 = <<" ", Indent/binary>>, + Res = lists:map(fun({{N, _} = A, B})->[?STR_A(N), ?OP_L(": "), json_gen(A, B, Indent2, HTMLOutput)] end, + lists:zip(Fields, tuple_to_list(Tuple))), + [?OP_L("{"), ?BR, Indent2, list_join_with(Res, [?OP_L(","), ?BR, Indent2]), ?BR, Indent, ?OP_L("}")]; +json_gen({_Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> + Indent2 = <<" ", Indent/binary>>, + Res = lists:map(fun(E) -> json_gen(ElDesc, E, Indent2, HTMLOutput) end, List), + [?OP_L("["), ?BR, Indent2, list_join_with(Res, [?OP_L(","), ?BR, Indent2]), ?BR, Indent, ?OP_L("]")]. + +json_call(Name, ArgsDesc, Values, ResultDesc, Result, HTMLOutput) -> + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!json\n">>} end, + {Code, ResultStr} = case {ResultDesc, Result} of + {{_, rescode}, V} when V == true; V == ok -> + {200, [?STR_L("")]}; + {{_, rescode}, _} -> + {500, [?STR_L("")]}; + {{_, restuple}, {V1, Text1}} when V1 == true; V1 == ok -> + {200, [?STR(Text1)]}; + {{_, restuple}, {_, Text2}} -> + {500, [?STR(Text2)]}; + {{_, {list, _}}, _} -> + {200, json_gen(ResultDesc, Result, Indent, HTMLOutput)}; + {{_, {tuple, _}}, _} -> + {200, json_gen(ResultDesc, Result, Indent, HTMLOutput)}; + {{Name0, _}, _} -> + {200, [Indent, ?OP_L("{"), ?STR_A(Name0), ?OP_L(": "), + json_gen(ResultDesc, Result, Indent, HTMLOutput), Indent, ?OP_L("}")]} + end, + CodeStr = case Code of + 200 -> <<" 200 OK">>; + 500 -> <<" 500 Internal Server Error">> + end, + [Preamble, + Indent, ?ID_L("POST /api/"), ?ID_A(Name), ?BR, + Indent, ?OP_L("{"), ?BR, Indent, <<" ">>, + list_join_with(lists:map(fun({{N,_}=A,B})->[?STR_A(N), ?OP_L(": "), json_gen(A, B, <>, HTMLOutput)] end, + lists:zip(ArgsDesc, Values)), [?OP_L(","), ?BR, Indent, <<" ">>]), + ?BR, Indent, ?OP_L("}"), ?BR, Indent, ?BR, Indent, + ?ID_L("HTTP/1.1"), ?ID(CodeStr), ?BR, Indent, + ResultStr + ]. + +generate_example_input({_Name, integer}, {LastStr, LastNum}) -> + {LastNum+1, {LastStr, LastNum+1}}; +generate_example_input({_Name, string}, {LastStr, LastNum}) -> + {string:chars(LastStr+1, 5), {LastStr+1, LastNum}}; +generate_example_input({_Name, binary}, {LastStr, LastNum}) -> + {iolist_to_binary(string:chars(LastStr+1, 5)), {LastStr+1, LastNum}}; +generate_example_input({_Name, atom}, {LastStr, LastNum}) -> + {list_to_atom(string:chars(LastStr+1, 5)), {LastStr+1, LastNum}}; +generate_example_input({_Name, rescode}, {LastStr, LastNum}) -> + {ok, {LastStr, LastNum}}; +generate_example_input({_Name, restuple}, {LastStr, LastNum}) -> + {{ok, <<"Success">>}, {LastStr, LastNum}}; +generate_example_input({_Name, {tuple, Fields}}, Data) -> + {R, D} = lists:foldl(fun(Field, {Res2, Data2}) -> + {Res3, Data3} = generate_example_input(Field, Data2), + {[Res3 | Res2], Data3} + end, {[], Data}, Fields), + {list_to_tuple(lists:reverse(R)), D}; +generate_example_input({_Name, {list, Desc}}, Data) -> + {R1, D1} = generate_example_input(Desc, Data), + {R2, D2} = generate_example_input(Desc, D1), + {[R1, R2], D2}. + +gen_calls(#ejabberd_commands{args_example=none, args=ArgsDesc} = C, HTMLOutput, Langs) -> + {R, _} = lists:foldl(fun(Arg, {Res, Data}) -> + {Res3, Data3} = generate_example_input(Arg, Data), + {[Res3 | Res], Data3} + end, {[], {$a-1, 0}}, ArgsDesc), + gen_calls(C#ejabberd_commands{args_example=lists:reverse(R)}, HTMLOutput, Langs); +gen_calls(#ejabberd_commands{result_example=none, result=ResultDesc} = C, HTMLOutput, Langs) -> + {R, _} = generate_example_input(ResultDesc, {$a-1, 0}), + gen_calls(C#ejabberd_commands{result_example=R}, HTMLOutput, Langs); +gen_calls(#ejabberd_commands{args_example=Values, args=ArgsDesc, + result_example=Result, result=ResultDesc, + name=Name}, HTMLOutput, Langs) -> + Perl = perl_call(Name, ArgsDesc, Values, HTMLOutput), + Java = java_call(Name, ArgsDesc, Values, HTMLOutput), + XML = xml_call(Name, ArgsDesc, Values, HTMLOutput), + JSON = json_call(Name, ArgsDesc, Values, ResultDesc, Result, HTMLOutput), + if HTMLOutput -> + [?TAG(ul, "code-samples-names", + [case lists:member(<<"java">>, Langs) of true -> ?TAG(li, <<"Java">>); _ -> [] end, + case lists:member(<<"perl">>, Langs) of true -> ?TAG(li, <<"Perl">>); _ -> [] end, + case lists:member(<<"xmlrpc">>, Langs) of true -> ?TAG(li, <<"XML">>); _ -> [] end, + case lists:member(<<"json">>, Langs) of true -> ?TAG(li, <<"JSON">>); _ -> [] end]), + ?TAG(ul, "code-samples", + [case lists:member(<<"java">>, Langs) of true -> ?TAG(li, ?TAG(pre, Java)); _ -> [] end, + case lists:member(<<"perl">>, Langs) of true -> ?TAG(li, ?TAG(pre, Perl)); _ -> [] end, + case lists:member(<<"xmlrpc">>, Langs) of true -> ?TAG(li, ?TAG(pre, XML)); _ -> [] end, + case lists:member(<<"json">>, Langs) of true -> ?TAG(li, ?TAG(pre, JSON)); _ -> [] end])]; + true -> + [case lists:member(<<"java">>, Langs) of true -> [<<"Java example\n\n">>, ?TAG(pre, Java)]; _ -> [] end, + case lists:member(<<"perl">>, Langs) of true -> [<<"Perl example\n\n">>, ?TAG(pre, Perl)]; _ -> [] end, + case lists:member(<<"xmlrpc">>, Langs) of true -> [<<"XmlRPC example\n\n">>, ?TAG(pre, XML)]; _ -> [] end, + case lists:member(<<"json">>, Langs) of true -> [<<"JSON example\n\n">>, ?TAG(pre, JSON)]; _ -> [] end] + end. + +gen_doc(#ejabberd_commands{name=Name, tags=_Tags, desc=Desc, longdesc=LongDesc, + args=Args, args_desc=ArgsDesc, + result=Result, result_desc=ResultDesc}=Cmd, HTMLOutput, Langs) -> + LDesc = case LongDesc of + "" -> Desc; + _ -> LongDesc + end, + ArgsText = case ArgsDesc of + none -> + [?TAG(ul, "args-list", lists:map(fun({AName, Type}) -> + [?TAG(li, [?TAG_R(strong, atom_to_list(AName)), <<" :: ">>, + ?RAW(io_lib:format("~p", [Type]))])] + end, Args))]; + _ -> + [?TAG(dl, "args-list", lists:map(fun({{AName, Type}, ADesc}) -> + [?TAG(dt, [?TAG_R(strong, atom_to_list(AName)), <<" :: ">>, + ?RAW(io_lib:format("~p", [Type]))]), + ?TAG(dd, ?RAW(ADesc))] + end, lists:zip(Args, ArgsDesc)))] + end, + ResultText = case ResultDesc of + none -> + [?RAW(io_lib:format("~p", [Result]))]; + _ -> + [?RAW(io_lib:format("~p", [Result])), + ?TAG_R(p, ResultDesc)] + end, + + [?TAG(h1, [?TAG(strong, atom_to_list(Name)), <<" - ">>, ?RAW(Desc)]), + ?TAG(p, ?RAW(LDesc)), + ?TAG(h2, <<"Arguments:">>), + ArgsText, + ?TAG(h2, <<"Result:">>), + ResultText, + ?TAG(h2, <<"Examples:">>), + gen_calls(Cmd, HTMLOutput, Langs)]. + +generate_html_output(File, RegExp, Languages) -> + Cmds = lists:map(fun({N, _, _}) -> + ejabberd_commands:get_command_definition(N) + end, ejabberd_commands:list_commands()), + {ok, RE} = re:compile(RegExp), + Cmds2 = lists:filter(fun(#ejabberd_commands{name=Name, module=Module}) -> + re:run(atom_to_list(Name), RE, [{capture, none}]) == match orelse + re:run(atom_to_list(Module), RE, [{capture, none}]) == match + end, Cmds), + Cmds3 = lists:sort(fun(#ejabberd_commands{name=N1}, #ejabberd_commands{name=N2}) -> + N1 =< N2 + end, Cmds2), + Langs = binary:split(Languages, <<",">>, [global]), + Out = lists:map(fun(C) -> gen_doc(C, true, Langs) end, Cmds3), + {ok, Fh} = file:open(File, [write]), + io:format(Fh, "~s", [[html_pre(), Out, html_post()]]), + file:close(Fh), + ok. + +generate_md_output(File, RegExp, Languages) -> + Cmds = lists:map(fun({N, _, _}) -> + ejabberd_commands:get_command_definition(N) + end, ejabberd_commands:list_commands()), + {ok, RE} = re:compile(RegExp), + Cmds2 = lists:filter(fun(#ejabberd_commands{name=Name, module=Module}) -> + re:run(atom_to_list(Name), RE, [{capture, none}]) == match orelse + re:run(atom_to_list(Module), RE, [{capture, none}]) == match + end, Cmds), + Cmds3 = lists:sort(fun(#ejabberd_commands{name=N1}, #ejabberd_commands{name=N2}) -> + N1 =< N2 + end, Cmds2), + Langs = binary:split(Languages, <<",">>, [global]), + Out = lists:map(fun(C) -> gen_doc(C, false, Langs) end, Cmds3), + {ok, Fh} = file:open(File, [write]), + io:format(Fh, "~s", [[Out]]), + file:close(Fh), + ok. + +html_pre() -> + " + + + + + + + ". + +html_post() -> +" + +". diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index ee0e9d0921e..01478782580 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -303,7 +303,7 @@ commands() -> desc = "Set multiple contents in a vCard subfield", longdesc = Vcard2FieldsString ++ "\n\n" ++ Vcard1FieldsString ++ "\n" ++ VcardXEP, module = ?MODULE, function = set_vcard, - args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {contents, {list, binary}}], + args = [{user, binary}, {host, binary}, {name, binary}, {subname, binary}, {contents, {list, {value, binary}}}], result = {res, rescode}}, #ejabberd_commands{name = add_rosteritem, tags = [roster], From 0df6d7ae396eb085e4068b25d4f50162b80a49c1 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 28 Dec 2015 15:08:59 +0100 Subject: [PATCH 440/695] Improve explanation in registration page (#876) --- src/mod_register_web.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index 7f7cf36b632..dd069593d71 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -250,8 +250,8 @@ form_new_get(Host, Lang, IP) -> "a Jabber client.">>), ?XCT(<<"li">>, <<"Some Jabber clients can store your password " - "in your computer. Use that feature only " - "if you trust your computer is safe.">>), + "in the computer, but you should do this only " + "in your personal computer for safety reasons.">>), ?XCT(<<"li">>, <<"Memorize your password, or write it " "in a paper placed in a safe place. In " From 48deb47021409a6be955add2c445e4ab34a94f53 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 28 Dec 2015 15:09:49 +0100 Subject: [PATCH 441/695] Update translations --- priv/msgs/ca.msg | 39 +- priv/msgs/ca.po | 924 +++++++++++++++++++++------------------ priv/msgs/cs.msg | 39 +- priv/msgs/cs.po | 914 +++++++++++++++++++++------------------ priv/msgs/de.msg | 39 +- priv/msgs/de.po | 929 +++++++++++++++++++++------------------ priv/msgs/ejabberd.pot | 795 +++++++++++++++++++++------------- priv/msgs/el.msg | 39 +- priv/msgs/el.po | 934 ++++++++++++++++++++++------------------ priv/msgs/eo.msg | 39 +- priv/msgs/eo.po | 917 +++++++++++++++++++++------------------ priv/msgs/es.msg | 39 +- priv/msgs/es.po | 919 +++++++++++++++++++++------------------ priv/msgs/fr.msg | 34 +- priv/msgs/fr.po | 923 +++++++++++++++++++++------------------ priv/msgs/gl.msg | 28 +- priv/msgs/gl.po | 908 ++++++++++++++++++++++----------------- priv/msgs/he.msg | 129 ++++-- priv/msgs/he.po | 955 ++++++++++++++++++++++------------------- priv/msgs/id.msg | 34 +- priv/msgs/id.po | 912 +++++++++++++++++++++------------------ priv/msgs/it.msg | 39 +- priv/msgs/it.po | 931 +++++++++++++++++++++------------------ priv/msgs/ja.msg | 39 +- priv/msgs/ja.po | 918 +++++++++++++++++++++------------------ priv/msgs/nl.msg | 39 +- priv/msgs/nl.po | 928 +++++++++++++++++++++------------------ priv/msgs/no.msg | 39 +- priv/msgs/no.po | 913 +++++++++++++++++++++------------------ priv/msgs/pl.msg | 39 +- priv/msgs/pl.po | 914 +++++++++++++++++++++------------------ priv/msgs/pt-br.msg | 39 +- priv/msgs/pt-br.po | 914 +++++++++++++++++++++------------------ priv/msgs/pt.msg | 16 + priv/msgs/pt.po | 903 +++++++++++++++++++++----------------- priv/msgs/ru.msg | 39 +- priv/msgs/ru.po | 917 +++++++++++++++++++++------------------ priv/msgs/sk.msg | 39 +- priv/msgs/sk.po | 916 +++++++++++++++++++++------------------ priv/msgs/sv.msg | 26 +- priv/msgs/sv.po | 906 +++++++++++++++++++++----------------- priv/msgs/th.msg | 21 +- priv/msgs/th.po | 904 +++++++++++++++++++++----------------- priv/msgs/tr.msg | 39 +- priv/msgs/tr.po | 918 +++++++++++++++++++++------------------ priv/msgs/uk.msg | 35 +- priv/msgs/uk.po | 905 ++++++++++++++++++++------------------ priv/msgs/vi.msg | 21 +- priv/msgs/vi.po | 912 ++++++++++++++++++++++----------------- priv/msgs/wa.msg | 23 +- priv/msgs/wa.po | 912 ++++++++++++++++++++++----------------- priv/msgs/zh.msg | 39 +- priv/msgs/zh.po | 911 +++++++++++++++++++++------------------ 53 files changed, 14423 insertions(+), 11220 deletions(-) diff --git a/priv/msgs/ca.msg b/priv/msgs/ca.msg index a9765c2ae1f..85907332fda 100644 --- a/priv/msgs/ca.msg +++ b/priv/msgs/ca.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Configuració de la Llista de Control d'Accés"}. {"Access Control Lists","Llista de Control d'Accés"}. {"Access control lists","Llistes de Control de Accés"}. +{"Access denied by service policy","Accés denegat per la política del servei"}. {"Access rules","Regles d'accés"}. {"Access Rules","Regles d'Accés"}. {"Action on user","Acció en l'usuari"}. @@ -11,6 +12,7 @@ {"Add User","Afegir usuari"}. {"Administration","Administració"}. {"Administration of ","Administració de "}. +{"Administrator privileges required","Es necessita tenir privilegis d'administrador"}. {"A friendly name for the node","Un nom per al node"}. {"All activity","Tota l'activitat"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Permetre que aquesta Jabber ID es puga subscriure a aquest node pubsub"}. @@ -25,6 +27,7 @@ {"All Users","Tots els usuaris"}. {"Announcements","Anuncis"}. {"anyone","qualsevol"}. +{"A password is required to enter this room","Es necessita contrasenya per a entrar en aquesta sala"}. {"April","Abril"}. {"August","Agost"}. {"Backup","Guardar còpia de seguretat"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Tria si aprova aquesta entitat de subscripció"}. {"City","Ciutat"}. {"Commands","Comandaments"}. +{"Conference room does not exist","La sala de conferències no existeix"}. {"Configuration","Configuració"}. {"Configuration of room ~s","Configuració de la sala ~s"}. {"Connected Resources:","Recursos connectats:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Exporta totes les taules a un fitxer SQL:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportar dades de tots els usuaris del servidor a arxius PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportar dades d'usuaris d'un host a arxius PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","No s'ha pogut extraure el JID de la teva aprovació de petició de veu"}. {"Family Name","Cognom"}. {"February","Febrer"}. {"Fill in fields to search for any matching Jabber User","Emplena camps per a buscar usuaris Jabber que concorden"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importar dades d'usuaris del directori de spool de jabberd14:"}. {"Import Users from Dir at ","Importar usuaris des del directori en "}. {"Import Users From jabberd14 Spool Files","Importar usuaris de jabberd14"}. +{"Improper message type","Tipus de missatge incorrecte"}. +{"Incorrect password","Contrasenya incorrecta"}. {"Invalid affiliation: ~s","Afiliació invàlida: ~s"}. {"Invalid role: ~s","Rol invàlid: ~s"}. {"IP addresses","Adreça IP"}. @@ -147,6 +154,9 @@ {"IRC username","Nom d'usuari al IRC"}. {"IRC Username","Nom d'usuari al IRC"}. {"is now known as","ara es conegut com"}. +{"It is not allowed to send private messages","No està permés enviar missatges privats"}. +{"It is not allowed to send private messages of type \"groupchat\"","No està permés enviar missatges del tipus \"groupchat\""}. +{"It is not allowed to send private messages to the conference","No està permès l'enviament de missatges privats a la sala"}. {"Jabber Account Registration","Registre de compte Jabber"}. {"Jabber ID","ID Jabber"}. {"Jabber ID ~s is invalid","El Jabber ID ~s no és vàlid"}. @@ -179,12 +189,14 @@ {"Max # of items to persist","Màxim # d'elements que persistixen"}. {"Max payload size in bytes","Màxim tamany del payload en bytes"}. {"May","Maig"}. +{"Membership is required to enter this room","Necessites ser membre d'aquesta sala per a poder entrar"}. {"Members:","Membre:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memoritza la teva contrasenya, o escriu-la en un paper guardat a un lloc segur.A Jabber no hi ha una forma automatitzada de recuperar la teva contrasenya si la oblides."}. {"Memory","Memòria"}. {"Message body","Missatge"}. {"Middle Name","Segon nom"}. {"Minimum interval between voice requests (in seconds)","Interval mínim entre peticions de veu (en segons)"}. +{"Moderator privileges required","Es necessita tenir privilegis de moderador"}. {"moderators only","només moderadors"}. {"Modified modules","Mòduls modificats"}. {"Module","Mòdul"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Sols enviar notificacions als usuaris disponibles"}. {"Only moderators and participants are allowed to change the subject in this room","Només els moderadors i participants poden canviar l'assumpte d'aquesta sala"}. {"Only moderators are allowed to change the subject in this room","Només els moderadors poden canviar l'assumpte d'aquesta sala"}. +{"Only moderators can approve voice requests","Només els moderadors poden aprovar les peticions de veu"}. +{"Only occupants are allowed to send messages to the conference","Sols els ocupants poden enviar missatges a la sala"}. +{"Only occupants are allowed to send queries to the conference","Sols els ocupants poden enviar sol·licituds a la sala"}. +{"Only service administrators are allowed to send service messages","Sols els administradors del servei tenen permís per a enviar missatges de servei"}. {"Options","Opcions"}. {"Organization Name","Nom de la organizació"}. {"Organization Unit","Unitat de la organizació"}. {"Outgoing s2s Connections:","Connexions d'eixida s2s"}. {"Outgoing s2s Connections","Connexions s2s d'eixida"}. -{"Outgoing s2s Servers:","Servidors d'eixida de s2s"}. +{"Owner privileges required","Es requerixen privilegis de propietari de la sala"}. {"Packet","Paquet"}. {"Password ~b","Contrasenya ~b"}. {"Password:","Contrasenya:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Persistir elements al guardar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Recorda que aquestes opcions només fan còpia de seguretat de la base de dades Mnesia. Si estàs utilitzant el mòdul d'ODBC també deus de fer una còpia de seguretat de la base de dades de SQL a part."}. +{"Please, wait for a while before sending new voice request","Si us plau, espera una mica abans d'enviar una nova petició de veu"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Publicar-subscriure't"}. {"PubSub subscriber request","Petició de subscriptor PubSub"}. {"Purge all items when the relevant publisher goes offline","Eliminar tots els elements quan el publicant relevant es desconnecti"}. +{"Queries to the conference members are not allowed in this room"," En aquesta sala no es permeten sol·licituds als membres de la conferència"}. {"RAM and disc copy","Còpia en RAM i disc"}. {"RAM copy","Còpia en RAM"}. {"Raw","en format text"}. {"Really delete message of the day?","Segur que vols eliminar el missatge del dia?"}. +{"Recipient is not in the conference room","El receptor no està en la sala de conferència"}. {"Register a Jabber account","Registrar un compte Jabber"}. {"Registered nicknames","Sobrenoms registrats"}. {"Registered Users:","Usuaris registrats:"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Restaurar una còpia de seguretat en format de text pla ara mateix:"}. {"Restore","Restaurar"}. {"Room Configuration","Configuració de la sala"}. +{"Room creation is denied by service policy","Se t'ha denegat el crear la sala per política del servei"}. {"Room description","Descripció de la sala:"}. {"Room Occupants","Nombre d'ocupants"}. {"Room title","Títol de la sala"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Mostrar Taula Ordinaria"}. {"Shut Down Service","Apager el Servei"}. {"~s invites you to the room ~s","~s et convida a la sala ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Alguns clients Jabber poden emmagatzemar la teva contrasenya al teu ordinador. Fes servir aquesta característica només si saps que el teu ordinador és segur."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clients Jabber poden emmagatzemar la teva contrasenya al teu ordinador. Fes servir aquesta característica només si saps que el teu ordinador és segur."}. {"Specify the access model","Especificar el model d'accés"}. {"Specify the event message type","Especifica el tipus de missatge d'event"}. {"Specify the publisher model","Especificar el model del publicant"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Adreça del Subscriptor"}. {"Subscription","Subscripció"}. {"Sunday","Diumenge"}. +{"That nickname is already in use by another occupant","El Nickname està siguent utilitzat per una altra persona"}. +{"That nickname is registered by another person","El nickname ja està registrat per una altra persona"}. {"The CAPTCHA is valid.","El CAPTCHA es vàlid."}. +{"The CAPTCHA verification has failed","La verificació CAPTCHA ha fallat"}. {"The collections with which a node is affiliated","Les col.leccions amb les que un node està afiliat"}. {"the password is","la contrasenya és"}. +{"The password is too weak","La contrasenya és massa simple"}. {"The password of your Jabber account was successfully changed.","La contrasenya del teu compte Jabber s'ha canviat correctament."}. {"There was an error changing the password: ","Hi ha hagut un error canviant la contrasenya: "}. {"There was an error creating the account: ","Hi ha hagut un error creant el compte: "}. @@ -347,16 +371,19 @@ {"Thursday","Dijous"}. {"Time","Data"}. {"Time delay","Temps de retard"}. +{"Too many CAPTCHA requests","Massa peticions de CAPTCHA"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Massa autenticacions (~p) han fallat des d'aquesta adreça IP (~s). L'adreça serà desbloquejada en ~s UTC"}. {"Too many unacked stanzas","Massa missatges sense haver reconegut la seva recepció"}. {"To","Per a"}. {"To ~s","A ~s"}. {"Total rooms","Nombre total de sales"}. +{"Traffic rate limit is exceeded","El llímit de tràfic ha sigut sobrepassat"}. {"Transactions Aborted:","Transaccions Avortades"}. {"Transactions Committed:","Transaccions Realitzades:"}. {"Transactions Logged:","Transaccions registrades"}. {"Transactions Restarted:","Transaccions reiniciades"}. {"Tuesday","Dimarts"}. +{"Unable to generate a CAPTCHA","No s'ha pogut generar un CAPTCHA"}. {"Unauthorized","No autoritzat"}. {"Unregister a Jabber account","Anul·lar el registre d'un compte Jabber"}. {"Unregister","Anul·lar el registre"}. @@ -371,6 +398,7 @@ {"User JID","JID del usuari "}. {"User Management","Gestió d'Usuaris"}. {"Username:","Nom d'usuari:"}. +{"Users are not allowed to register accounts so quickly","Els usuaris no tenen permís per a crear comptes tan depresa"}. {"Users Last Activity","Última activitat d'usuari"}. {"User ~s","Usuari ~s"}. {"Users","Usuaris"}. @@ -378,16 +406,23 @@ {"Validate","Validar"}. {"vCard User Search","Recerca de vCard d'usuari"}. {"Virtual Hosts","Hosts virtuals"}. +{"Visitors are not allowed to change their nicknames in this room","Els visitants no tenen permés canviar el seus Nicknames en esta sala"}. +{"Visitors are not allowed to send messages to all occupants","Els visitants no poden enviar missatges a tots els ocupants"}. {"Voice request","Petició de veu"}. +{"Voice requests are disabled in this conference","Les peticions de veu es troben desactivades en aquesta conferència"}. {"Wednesday","Dimecres"}. {"When to send the last published item","Quan s'ha enviat l'última publicació"}. {"Whether to allow subscriptions","Permetre subscripcions"}. {"You can later change your password using a Jabber client.","Podràs canviar la teva contrasenya més endavant utilitzant un client Jabber."}. +{"You have been banned from this room","Has sigut bloquejat en aquesta sala"}. +{"You must fill in field \"Nickname\" in the form","Deus d'omplir el camp \"Nickname\" al formulari"}. {"You need a client that supports x:data and CAPTCHA to register","Necessites un client amb suport x:data i de CAPTCHA para poder registrar-te"}. {"You need a client that supports x:data to register the nickname","Necessites un client amb suport x:data per a poder registrar el sobrenom"}. {"You need an x:data capable client to configure mod_irc settings","Necessites un client amb suport x:data per a configurar les opcions de mod_irc"}. {"You need an x:data capable client to configure room","Necessites un client amb suport x:data per a configurar la sala"}. {"You need an x:data capable client to search","Necessites un client amb suport x:data per a poder buscar"}. +{"Your active privacy list has denied the routing of this stanza.","La teva llista de privacitat activa ha denegat l'encaminament d'aquesta stanza."}. +{"Your contact offline message queue is full. The message has been discarded.","La cua de missatges offline és plena. El missatge ha sigut descartat"}. {"Your Jabber account was successfully created.","El teu compte Jabber ha sigut creat correctament."}. {"Your Jabber account was successfully deleted.","El teu compte Jabber ha sigut esborrat correctament."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Els teus missatges per ~s s'estan bloquejant. Per desbloquejar-los, visita ~s"}. diff --git a/priv/msgs/ca.po b/priv/msgs/ca.po index ba23d682cd9..519d7a09a92 100644 --- a/priv/msgs/ca.po +++ b/priv/msgs/ca.po @@ -15,50 +15,56 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Poedit 1.6.10\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "És obligatori utilitzar STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Recurs no disponible" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Reemplaçat per una nova connexió" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "Has sigut expulsat" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" +"La teva llista de privacitat activa ha denegat l'encaminament d'aquesta " +"stanza." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Massa missatges sense haver reconegut la seva recepció" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Introdueix el text que veus" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Els teus missatges per ~s s'estan bloquejant. Per desbloquejar-los, visita ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Si no veus la imatge CAPTCHA açí, visita la pàgina web." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Pàgina web del CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es vàlid." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Usuari" @@ -67,9 +73,9 @@ msgstr "Usuari" msgid "Server" msgstr "Servidor:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Contrasenya" @@ -86,275 +92,276 @@ msgstr "No autoritzat" msgid "ejabberd Web Admin" msgstr "Web d'administració del ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administració" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Llista de Control d'Accés" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Enviat" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Format erroni" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "en format text" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Eliminar els seleccionats" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Regles d'Accés" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configuració de les Regles d'Accés ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Hosts virtuals" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuaris" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuaris conectats" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Última activitat d'usuari" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Període: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Últim mes" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Últim any" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tota l'activitat" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Taula Ordinaria" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Taula Integral" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estadístiques" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "No Trobat" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Node no trobat" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Afegir nou" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuaris registrats" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Afegir usuari" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Missatges offline" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última activitat" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Mai" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Connectat" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuaris registrats:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Usuaris en línia:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Connexions d'eixida s2s" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Servidors d'eixida de s2s" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Connexions d'eixida s2s" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Cap" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Canviar Contrasenya" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Usuari ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos connectats:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contrasenya:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar usuari" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "No hi ha dades" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodes" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodes funcionant" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodes parats" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Node ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de dades" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar còpia de seguretat" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Ports a l'escolta" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualitzar" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Detindre" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Mòduls" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Error de cridada RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Taules de la base de dades en ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nom" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipus d'emmagatzematge" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elements" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memòria" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Error" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Còpia de seguretat de ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -364,144 +371,144 @@ msgstr "" "dades Mnesia. Si estàs utilitzant el mòdul d'ODBC també deus de fer una " "còpia de seguretat de la base de dades de SQL a part." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Guardar una còpia de seguretat binària:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Acceptar" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar una còpia de seguretat binària ara mateix." -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar una còpia de seguretat binària després de reiniciar el ejabberd " "(requereix menys memòria:" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Guardar una còpia de seguretat en format de text pla:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaurar una còpia de seguretat en format de text pla ara mateix:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar dades d'usuaris des d'un arxiu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar dades de tots els usuaris del servidor a arxius PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Exportar dades d'usuaris d'un host a arxius PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Exporta totes les taules a un fitxer SQL:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importar dades d'usuaris de l'arxiu de spool de jabberd14" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar dades d'usuaris del directori de spool de jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Ports a la escolta en " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Mòduls en ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estadístiques de ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Temps en marxa" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Temps de CPU" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaccions Realitzades:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaccions Avortades" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaccions reiniciades" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaccions registrades" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Actualitzar ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Pla d'actualització" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Mòduls modificats" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script d'actualització" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script d'actualització de baix nivell" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Comprovar script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Mòdul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opcions" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" @@ -788,8 +795,8 @@ msgstr "Regles d'accés" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" @@ -806,31 +813,31 @@ msgstr "Número d'Usuaris Registrats" msgid "Number of online users" msgstr "Número d'usuaris connectats" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Últim login" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamany de la llista" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adreça IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administració de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Acció en l'usuari" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propietats" @@ -842,29 +849,41 @@ msgstr "" "Massa autenticacions (~p) han fallat des d'aquesta adreça IP (~s). L'adreça " "serà desbloquejada en ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Esta adreça IP està a la llista negra en ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Accés denegat per la política del servei" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transport a IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "mòdul ejabberd IRC" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Necessites un client amb suport x:data per a configurar les opcions de " "mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registre en mod_irc per a" -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -872,11 +891,11 @@ msgstr "" "Introdueix el nom d'usuari, les codificacions de caràcters, els ports i " "contrasenyes per a utilitzar al connectar als servidors de IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nom d'usuari al IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -888,7 +907,7 @@ msgstr "" "\"codificació\", port, \"contrasenya\"}'. Aquest servei utilitza per " "defecte la codificació \"~s\", port ~p, no contrasenya." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -896,35 +915,35 @@ msgstr "" "Exemple: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Paràmetres de connexió" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entra a canal d'IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal d'IRC (no posis la primera #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor d'IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Entra al canal d'IRC aquí." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Entra al canal d'IRC en aquesta Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Configuració d'IRC." -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -934,49 +953,80 @@ msgstr "" "als servidors de IRC. Apreta \"Seguent\" per veure més caps per omplir. " "Apreta \"Completar\" per guardar la configuració. " -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nom d'usuari al IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Contrasenya ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificació pel servidor ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Només els moderadors poden canviar l'assumpte d'aquesta sala" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Sols els administradors del servei tenen permís per a enviar missatges de " +"servei" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Se t'ha denegat el crear la sala per política del servei" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "La sala de conferències no existeix" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Sales de xat" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necessites un client amb suport x:data per a poder registrar el sobrenom" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registre del sobrenom en " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Introdueix el sobrenom que vols registrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Sobrenom" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "El nickname ja està registrat per una altra persona" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Deus d'omplir el camp \"Nickname\" al formulari" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "mòdul ejabberd MUC" @@ -1001,356 +1051,485 @@ msgstr "Sobrenoms registrats" msgid "List of rooms" msgstr "Llista de sales" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configuració de la sala de xat modificada" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "Entrar a la sala" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "Deixar la sala" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "Has sigut banejat" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "Has sigut expulsat a causa d'un canvi d'afiliació" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "Has sigut expulsat perquè la sala ha canviat a sols membres" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "Has sigut expulsat perquè el sistema s'ha apagat" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "ara es conegut com" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ha posat l'assumpte: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "La sala s'ha creat" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "La sala s'ha destruït" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "La sala s'ha iniciat" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "La sala s'ha aturat" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Dilluns" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Dimarts" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Dimecres" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Dijous" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Divendres" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Dissabte" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Diumenge" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Gener" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Febrer" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Març" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Maig" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Juny" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Juliol" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Agost" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Setembre" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Octubre" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Novembre" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Decembre" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuració de la sala" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Nombre d'ocupants" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "El llímit de tràfic ha sigut sobrepassat" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "No està permès l'enviament de missatges privats a la sala" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Si us plau, espera una mica abans d'enviar una nova petició de veu" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Les peticions de veu es troben desactivades en aquesta conferència" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "No s'ha pogut extraure el JID de la teva aprovació de petició de veu" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Només els moderadors poden aprovar les peticions de veu" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Tipus de missatge incorrecte" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "No està permés enviar missatges del tipus \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "El receptor no està en la sala de conferència" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "No està permés enviar missatges privats" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Sols els ocupants poden enviar missatges a la sala" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Sols els ocupants poden enviar sol·licituds a la sala" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +" En aquesta sala no es permeten sol·licituds als membres de la conferència" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Només els moderadors i participants poden canviar l'assumpte d'aquesta sala" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Només els moderadors poden canviar l'assumpte d'aquesta sala" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Els visitants no poden enviar missatges a tots els ocupants" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Els visitants no tenen permés canviar el seus Nicknames en esta sala" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "El Nickname està siguent utilitzat per una altra persona" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Has sigut bloquejat en aquesta sala" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Necessites ser membre d'aquesta sala per a poder entrar" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Es necessita contrasenya per a entrar en aquesta sala" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Massa peticions de CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "No s'ha pogut generar un CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Contrasenya incorrecta" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Es necessita tenir privilegis d'administrador" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Es necessita tenir privilegis de moderador" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no és vàlid" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "El sobrenom ~s no existeix a la sala" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliació invàlida: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Rol invàlid: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Es requerixen privilegis de propietari de la sala" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Configuració de la sala ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Títol de la sala" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descripció de la sala:" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Crear una sala persistent" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Crear una sala pública" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Crear una llista de participants pública" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Crear una sala amb contrasenya" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número màxim d'ocupants" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sense Llímit" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Presentar Jabber ID's reals a" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "només moderadors" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "qualsevol" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "només moderadors" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Crear una sala de \"només membres\"" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Crear una sala moderada" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Els usuaris són participants per defecte" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permetre que els usuaris canviin el tema" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permetre que els usuaris envien missatges privats" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Permetre als visitants enviar missatges privats a" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "ningú" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permetre que els usuaris fagen peticions a altres usuaris" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permetre que els usuaris envien invitacions" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permetre als visitants enviar text d'estat en les actualitzacions de " "presència" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Permetre als visitants canviar el sobrenom" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permetre als visitants enviar peticions de veu" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Interval mínim entre peticions de veu (en segons)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Crear una sala protegida per CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Activar l'emmagatzematge de missatges" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excloure Jabber IDs de la comprovació CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Habilitar el registre de la conversa" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Necessites un client amb suport x:data per a configurar la sala" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Número d'ocupants" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privat" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Petició de veu" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Aprova o denega la petició de veu" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID del usuari " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Concedir veu a aquesta persona?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s et convida a la sala ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "la contrasenya és" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Servei de Multicast d'ejabberd" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "La cua de missatges offline és plena. El missatge ha sigut descartat" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s's cua de missatges offline" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Data" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Per a" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paquet" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Missatges fora de línia:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Eliminar tots els missatges offline" @@ -1358,115 +1537,127 @@ msgstr "Eliminar tots els missatges offline" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "mòdul ejabberd SOCKS5 Bytestreams" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publicar-subscriure't" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Mòdul ejabberd Publicar-Subscriure" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Petició de subscriptor PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Tria si aprova aquesta entitat de subscripció" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID del Node" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adreça del Subscriptor" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Permetre que aquesta Jabber ID es puga subscriure a aquest node pubsub" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads junt a les notificacions d'events" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entrega de notificacions d'events" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptors quan canvia la configuració del node" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptors quan el node és eliminat" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscriptors quan els elements són eliminats del node" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Persistir elements al guardar" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nom per al node" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Màxim # d'elements que persistixen" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permetre subscripcions" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especificar el model d'accés" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Llista de grups que tenen permés subscriures" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar el model del publicant" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Eliminar tots els elements quan el publicant relevant es desconnecti" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Especifica el tipus de missatge d'event" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Màxim tamany del payload en bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Quan s'ha enviat l'última publicació" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Sols enviar notificacions als usuaris disponibles" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Les col.leccions amb les que un node està afiliat" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "La verificació CAPTCHA ha fallat" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Necessites un client amb suport x:data i de CAPTCHA para poder registrar-te" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Tria nom d'usuari i contrasenya per a registrar-te en aquest servidor" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "La contrasenya és massa simple" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Els usuaris no tenen permís per a crear comptes tan depresa" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "El teu compte Jabber ha sigut creat correctament." @@ -1547,8 +1738,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Alguns clients Jabber poden emmagatzemar la teva contrasenya al teu " "ordinador. Fes servir aquesta característica només si saps que el teu " @@ -1590,60 +1781,60 @@ msgstr "" msgid "Unregister" msgstr "Anul·lar el registre" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscripció" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Pendent" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grups" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Borrar" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Llista de contactes de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Afegir Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Llista de contactes" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Grups de contactes compartits" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nom:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descripció:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membre:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Mostrar grups:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grup " @@ -1719,65 +1910,21 @@ msgstr "Resultat de la búsqueda" msgid "Fill in fields to search for any matching Jabber User" msgstr "Emplena camps per a buscar usuaris Jabber que concorden" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Servidors d'eixida de s2s" + #~ msgid "Delete" #~ msgstr "Eliminar" #~ msgid "This room is not anonymous" #~ msgstr "Aquesta sala no és anònima" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "La teva llista de privacitat activa ha denegat l'encaminament d'aquesta " -#~ "stanza." - -#~ msgid "Access denied by service policy" -#~ msgstr "Accés denegat per la política del servei" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Sols els administradors del servei tenen permís per a enviar missatges de " -#~ "servei" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Se t'ha denegat el crear la sala per política del servei" - -#~ msgid "Conference room does not exist" -#~ msgstr "La sala de conferències no existeix" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "El nickname ja està registrat per una altra persona" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Deus d'omplir el camp \"Nickname\" al formulari" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "El llímit de tràfic ha sigut sobrepassat" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Aquest participant ha sigut expulsat de la sala perque ha enviat un " #~ "missatge d'error" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "No està permès l'enviament de missatges privats a la sala" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Si us plau, espera una mica abans d'enviar una nova petició de veu" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Les peticions de veu es troben desactivades en aquesta conferència" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "" -#~ "No s'ha pogut extraure el JID de la teva aprovació de petició de veu" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Només els moderadors poden aprovar les peticions de veu" - -#~ msgid "Improper message type" -#~ msgstr "Tipus de missatge incorrecte" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1785,83 +1932,12 @@ msgstr "Emplena camps per a buscar usuaris Jabber que concorden" #~ "Aquest participant ha sigut expulsat de la sala perque ha enviat un " #~ "missatge erroni a un altre participant" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "No està permés enviar missatges del tipus \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "El receptor no està en la sala de conferència" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "No està permés enviar missatges privats" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Sols els ocupants poden enviar missatges a la sala" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Sols els ocupants poden enviar sol·licituds a la sala" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ " En aquesta sala no es permeten sol·licituds als membres de la conferència" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Els visitants no poden enviar missatges a tots els ocupants" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Aquest participant ha sigut expulsat de la sala perque ha enviat un error " #~ "de presencia" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Els visitants no tenen permés canviar el seus Nicknames en esta sala" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "El Nickname està siguent utilitzat per una altra persona" - -#~ msgid "You have been banned from this room" -#~ msgstr "Has sigut bloquejat en aquesta sala" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Necessites ser membre d'aquesta sala per a poder entrar" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Es necessita contrasenya per a entrar en aquesta sala" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Massa peticions de CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "No s'ha pogut generar un CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Contrasenya incorrecta" - -#~ msgid "Administrator privileges required" -#~ msgstr "Es necessita tenir privilegis d'administrador" - -#~ msgid "Moderator privileges required" -#~ msgstr "Es necessita tenir privilegis de moderador" - -#~ msgid "Owner privileges required" -#~ msgstr "Es requerixen privilegis de propietari de la sala" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "La cua de missatges offline és plena. El missatge ha sigut descartat" - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "La verificació CAPTCHA ha fallat" - -#~ msgid "The password is too weak" -#~ msgstr "La contrasenya és massa simple" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Els usuaris no tenen permís per a crear comptes tan depresa" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "El CAPTCHA es vàlid." diff --git a/priv/msgs/cs.msg b/priv/msgs/cs.msg index 63597b9b2ae..a370d02a695 100644 --- a/priv/msgs/cs.msg +++ b/priv/msgs/cs.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfigurace seznamu přístupových práv (ACL)"}. {"Access control lists","Seznamy přístupových práv (ACL)"}. {"Access Control Lists","Seznamy přístupových práv (ACL)"}. +{"Access denied by service policy","Přístup byl zamítnut nastavením služby"}. {"Access rules","Pravidla přístupů"}. {"Access Rules","Pravidla přístupů"}. {"Action on user","Akce aplikovaná na uživatele"}. @@ -11,6 +12,7 @@ {"Add User","Přidat uživatele"}. {"Administration","Administrace"}. {"Administration of ","Administrace "}. +{"Administrator privileges required","Potřebujete práva administrátora"}. {"A friendly name for the node","Přívětivé jméno pro uzel"}. {"All activity","Všechny aktivity"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Povolit tomuto Jabber ID odebírat tento pubsub uzel?"}. @@ -25,6 +27,7 @@ {"All Users","Všichni uživatelé"}. {"Announcements","Oznámení"}. {"anyone","každému"}. +{"A password is required to enter this room","Pro vstup do místnosti musíte zadat heslo"}. {"April",". dubna"}. {"August",". srpna"}. {"Backup Management","Správa zálohování"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","Zvolte, zda chcete schválit odebírání touto entitou"}. {"City","Město"}. {"Commands","Příkazy"}. +{"Conference room does not exist","Konferenční místnost neexistuje"}. {"Configuration","Konfigurace"}. {"Configuration of room ~s","Konfigurace místnosti ~s"}. {"Connected Resources:","Připojené zdroje:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","Vyloučit Jabber ID z procesu CAPTCHA ověřování"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportovat všechny uživatele do souboru ve formátu PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportovat uživatele na hostiteli do souboru ve formátu PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Došlo k chybě při získávání Jabber ID z vaší žádosti o voice práva"}. {"Family Name","Příjmení"}. {"February",". února"}. {"Fill in fields to search for any matching Jabber User","Vyplňte políčka pro vyhledání uživatele Jabberu"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","Importovat uživatele z jabberd14 spool souborů:"}. {"Import Users from Dir at ","Importovat uživatele z adresáře na "}. {"Import Users From jabberd14 Spool Files","Importovat uživatele z jabberd14 spool souborů"}. +{"Improper message type","Nesprávný typ zprávy"}. +{"Incorrect password","Nesprávné heslo"}. {"Invalid affiliation: ~s","Neplatné přiřazení: ~s"}. {"Invalid role: ~s","Neplatná role: ~s"}. {"IP addresses","IP adresy"}. @@ -142,6 +149,9 @@ {"IRC username","IRC přezdívka"}. {"IRC Username","IRC přezdívka"}. {"is now known as","se přejmenoval(a) na"}. +{"It is not allowed to send private messages","Je zakázáno posílat soukromé zprávy"}. +{"It is not allowed to send private messages of type \"groupchat\"","Není dovoleno odeslání soukromé zprávy typu \"skupinová zpráva\" "}. +{"It is not allowed to send private messages to the conference","Není povoleno odesílat soukromé zprávy do konference"}. {"Jabber Account Registration","Registrace účtu Jabberu"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s je neplatné"}. @@ -174,11 +184,13 @@ {"Max payload size in bytes","Maximální náklad v bajtech"}. {"May",". května"}. {"Members:","Členové:"}. +{"Membership is required to enter this room","Pro vstup do místnosti musíte být členem"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Svoje heslo si zapamatujte, nebo si jej poznamenejte na papírek a ten uschovejte v bezpečí. Jabber nemá žádný automatizovaný způsob obnovy hesla."}. {"Memory","Paměť"}. {"Message body","Tělo zprávy"}. {"Middle Name","Druhé jméno"}. {"Minimum interval between voice requests (in seconds)","Minimální interval mezi žádostmi o voice práva (v sekundách)"}. +{"Moderator privileges required","Potřebujete práva moderátora"}. {"moderators only","moderátorům"}. {"Modified modules","Aktualizované moduly"}. {"Module","Modul"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","Doručovat upozornění jen právě přihlášeným uživatelům"}. {"Only moderators and participants are allowed to change the subject in this room","Jen moderátoři a účastníci mají povoleno měnit téma této místnosti"}. {"Only moderators are allowed to change the subject in this room","Jen moderátoři mají povoleno měnit téma místnosti"}. +{"Only moderators can approve voice requests","Pouze moderátoři mohou schválit žádosti o voice práva"}. +{"Only occupants are allowed to send messages to the conference","Jen členové mají povolené zasílat zprávy do konference"}. +{"Only occupants are allowed to send queries to the conference","Jen členové mohou odesílat požadavky (query) do konference"}. +{"Only service administrators are allowed to send service messages","Pouze správci služby smí odesílat servisní zprávy"}. {"Options","Nastavení"}. {"Organization Name","Název firmy"}. {"Organization Unit","Oddělení"}. {"Outgoing s2s Connections:","Odchozí s2s spojení:"}. {"Outgoing s2s Connections","Odchozí s2s spojení"}. -{"Outgoing s2s Servers:","Odchozí s2s servery:"}. +{"Owner privileges required","Jsou vyžadována práva vlastníka"}. {"Packet","Paket"}. {"Password ~b","Heslo ~b"}. {"Password:","Heslo:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","Uložit položky natrvalo do úložiště"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Podotýkáme, že tato nastavení budou zálohována do zabudované databáze Mnesia. Pokud používáte ODBC modul, musíte zálohovat svoji SQL databázi samostatně."}. +{"Please, wait for a while before sending new voice request","Prosím, počkejte chvíli před posláním nové žádosti o voice práva"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","Publish-Subscribe"}. {"PubSub subscriber request","Žádost odběratele PubSub"}. {"Purge all items when the relevant publisher goes offline","Smazat všechny položky, pokud se příslušný poskytovatel odpojí"}. +{"Queries to the conference members are not allowed in this room","Požadavky (queries) na členy konference nejsou v této místnosti povolené"}. {"RAM and disc copy","Kopie RAM a disku"}. {"RAM copy","Kopie RAM"}. {"Raw","Zdroj"}. {"Really delete message of the day?","Skutečně smazat zprávu dne?"}. +{"Recipient is not in the conference room","Příjemce se nenachází v konferenční místnosti"}. {"Register a Jabber account","Zaregistrujte si účet Jabberu"}. {"Registered Users","Registrovaní uživatelé"}. {"Registered Users:","Registrovaní živatelé:"}. @@ -270,6 +289,7 @@ {"Restore","Obnovit"}. {"Restore plain text backup immediately:","Okamžitě obnovit zálohu z textového souboru:"}. {"Room Configuration","Nastavení místnosti"}. +{"Room creation is denied by service policy","Pravidla služby nepovolují vytvořit místnost"}. {"Room description","Popis místnosti"}. {"Room Occupants","Počet účastníků"}. {"Room title","Název místnosti"}. @@ -298,7 +318,7 @@ {"Show Ordinary Table","Zobrazit běžnou tabulku"}. {"Shut Down Service","Vypnout službu"}. {"~s invites you to the room ~s","~s vás zve do místnosti ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Někteří klienti umí uložit vaše heslo na disk počítače. Tuto funkci používejte, pouze pokud věříte zabezpečení svého počítače."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Někteří klienti umí uložit vaše heslo na disk počítače. Tuto funkci používejte, pouze pokud věříte zabezpečení svého počítače."}. {"Specify the access model","Uveďte přístupový model"}. {"Specify the event message type","Zvolte typ zpráv pro události"}. {"Specify the publisher model","Specifikovat model pro publikování"}. @@ -321,9 +341,13 @@ {"Subscriber Address","Adresa odběratele"}. {"Subscription","Přihlášení"}. {"Sunday","Neděle"}. +{"That nickname is already in use by another occupant","Přezdívka je již používána jiným členem"}. +{"That nickname is registered by another person","Přezdívka je zaregistrována jinou osobou"}. {"The CAPTCHA is valid.","CAPTCHA souhlasí."}. +{"The CAPTCHA verification has failed","Ověření CAPTCHA se nezdařilo"}. {"The collections with which a node is affiliated","Kolekce, se kterými je uzel spřízněn"}. {"the password is","heslo je"}. +{"The password is too weak","Heslo je příliš slabé"}. {"The password of your Jabber account was successfully changed.","Heslo vašeho účtu Jabberu bylo úspěšně změněno."}. {"There was an error changing the password: ","Při změně hesla došlo k chybě: "}. {"There was an error creating the account: ","Při vytváření účtu došlo k chybě."}. @@ -334,13 +358,16 @@ {"Thursday","Čtvrtek"}. {"Time","Čas"}. {"Time delay","Časový posun"}. +{"Too many CAPTCHA requests","Přiliš mnoho CAPTCHA žádostí"}. {"To","Pro"}. {"To ~s","Pro ~s"}. +{"Traffic rate limit is exceeded","Byl překročen limit"}. {"Transactions Aborted:","Transakce zrušena"}. {"Transactions Committed:","Transakce potvrzena"}. {"Transactions Logged:","Transakce zaznamenána"}. {"Transactions Restarted:","Transakce restartována"}. {"Tuesday","Úterý"}. +{"Unable to generate a CAPTCHA","Nebylo možné vygenerovat CAPTCHA"}. {"Unauthorized","Nemáte oprávnění"}. {"Unregister a Jabber account","Zrušte registraci účtu Jabberu"}. {"Unregister","Zrušit registraci"}. @@ -354,22 +381,30 @@ {"User JID","Jabber ID uživatele"}. {"User Management","Správa uživatelů"}. {"Username:","Uživatelské jméno:"}. +{"Users are not allowed to register accounts so quickly","Je zakázáno registrovat účty v tak rychlém sledu"}. {"Users Last Activity","Poslední aktivita uživatele"}. {"Users","Uživatelé"}. {"User","Uživatel"}. {"Validate","Ověřit"}. {"vCard User Search","Hledání uživatelů podle vizitek"}. {"Virtual Hosts","Virtuální hostitelé"}. +{"Visitors are not allowed to change their nicknames in this room","Návštěvníkům této místnosti je zakázáno měnit přezdívku"}. +{"Visitors are not allowed to send messages to all occupants","Návštevníci nemají povoleno zasílat zprávy všem účastníkům konference"}. +{"Voice requests are disabled in this conference","Voice žádosti jsou v této konferenci zakázány"}. {"Voice request","Žádost o voice práva"}. {"Wednesday","Středa"}. {"When to send the last published item","Kdy odeslat poslední publikovanou položku"}. {"Whether to allow subscriptions","Povolit odebírání"}. {"You can later change your password using a Jabber client.","Později můžete své heslo změnit pomocí klienta Jabberu."}. +{"You have been banned from this room","Byl jste vyloučen z této místnosti"}. +{"You must fill in field \"Nickname\" in the form","Musíte vyplnit políčko \"Přezdívka\" ve formuláři"}. {"You need a client that supports x:data and CAPTCHA to register","Pro registraci potřebujete klienta s podporou x:data a CAPTCHA"}. {"You need a client that supports x:data to register the nickname","Pro registraci přezdívky potřebujete klienta s podporou x:data"}. {"You need an x:data capable client to configure mod_irc settings","Pro konfiguraci mod_irc potřebujete klienta s podporou x:data"}. {"You need an x:data capable client to configure room","Ke konfiguraci místnosti potřebujete klienta podporujícího x:data"}. {"You need an x:data capable client to search","K vyhledávání potřebujete klienta podporujícího x:data"}. +{"Your active privacy list has denied the routing of this stanza.","Vaše nastavení soukromí znemožnilo směrování této stance."}. +{"Your contact offline message queue is full. The message has been discarded.","Fronta offline zpráv pro váš kontakt je plná. Zpráva byla zahozena."}. {"Your Jabber account was successfully created.","Váš účet Jabberu byl úspěšně vytvořen."}. {"Your Jabber account was successfully deleted.","Váš účet Jabberu byl úspěšně smazán."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Nesmíte posílat zprávy na ~s. Pro povolení navštivte ~s"}. diff --git a/priv/msgs/cs.po b/priv/msgs/cs.po index 6e651729f00..3055b4fb3b3 100644 --- a/priv/msgs/cs.po +++ b/priv/msgs/cs.po @@ -8,49 +8,53 @@ msgstr "" "X-Language: Czech (čeština)\n" "X-Additional-Translator: Milos Svasek [DuxforD] from openheads.net\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Je vyžadováno STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nebyl poskytnut žádný zdroj" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Nahrazeno novým spojením" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "byl(a) vyhozen(a) z místnosti" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Vaše nastavení soukromí znemožnilo směrování této stance." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Zadejte text, který vidíte" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Nesmíte posílat zprávy na ~s. Pro povolení navštivte ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Pokud zde nevidíte obrázek CAPTCHA, přejděte na webovou stránku." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Webová stránka CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "CAPTCHA souhlasí." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Uživatel" @@ -59,9 +63,9 @@ msgstr "Uživatel" msgid "Server" msgstr "Server:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Heslo" @@ -78,279 +82,280 @@ msgstr "Nemáte oprávnění" msgid "ejabberd Web Admin" msgstr "Webová administrace ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrace" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Seznamy přístupových práv (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Odeslané" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Nesprávný formát" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Odeslat" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Zdroj" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Smazat vybrané" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Pravidla přístupů" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s konfigurace pravidla přístupu" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuální hostitelé" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Uživatelé" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Online uživatelé" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Poslední aktivita uživatele" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Čas: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Poslední měsíc" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Poslední rok" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Všechny aktivity" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Zobrazit běžnou tabulku" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Zobrazit kompletní tabulku" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiky" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nenalezeno" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Uzel nenalezen" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Přidat nový" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Hostitel" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrovaní uživatelé" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Přidat uživatele" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Offline zprávy" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Poslední aktivita" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nikdy" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrovaní živatelé:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Online uživatelé:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Odchozí s2s spojení:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Odchozí s2s servery:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Odchozí s2s spojení:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nic" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Změnit heslo" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Uživatel " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Připojené zdroje:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Heslo:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Odstranit uživatele" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Žádná data" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Uzly" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Běžící uzly" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zastavené uzly" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Uzel " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databáze" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Zálohovat" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Otevřené porty" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualizovat" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Restart" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stop" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduly" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Chyba RPC volání" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Databázové tabulky na " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Jméno" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Typ úložiště" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Položek" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Paměť" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Chyba" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Záloha na " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -360,146 +365,146 @@ msgstr "" "Mnesia. Pokud používáte ODBC modul, musíte zálohovat svoji SQL databázi " "samostatně." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Uložit binární zálohu:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Okamžitě obnovit binární zálohu:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Obnovit binární zálohu při následujícím restartu ejabberd (vyžaduje méně " "paměti)" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Uložit zálohu do textového souboru:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Okamžitě obnovit zálohu z textového souboru:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importovat uživatele ze souboru ve formátu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "Exportovat všechny uživatele do souboru ve formátu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportovat uživatele na hostiteli do souboru ve formátu PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importovat uživatele z jabberd14 spool souborů:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importovat uživatele z jabberd14 spool souborů:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Otevřené porty na " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduly na " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiky ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Čas běhu:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Čas procesoru" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakce potvrzena" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakce zrušena" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakce restartována" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakce zaznamenána" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Aktualizovat " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Aktualizovat plán" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Aktualizované moduly" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Aktualizované skripty" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Nízkoúrovňový aktualizační skript" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Kontrola skriptu" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Nastavení" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Start" @@ -784,8 +789,8 @@ msgstr "Pravidla přístupů" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -802,31 +807,31 @@ msgstr "Počet registrovaných uživatelů" msgid "Number of online users" msgstr "Počet online uživatelů" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Poslední přihlášení" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Velikost seznamu kontaktů" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresy" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Zdroje" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrace " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Akce aplikovaná na uživatele" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Upravit vlastnosti" @@ -836,27 +841,39 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Přístup byl zamítnut nastavením služby" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Pro konfiguraci mod_irc potřebujete klienta s podporou x:data" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registrace do mod_irc na " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -864,11 +881,11 @@ msgstr "" "Zadejte přezdívku, kódování, porty a hesla, které chcete používat pro " "připojení k serverům IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC přezdívka" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -879,7 +896,7 @@ msgstr "" "ve formátu '{\"irc server\",\"encoding\", port, \"password\"}'. Výchozí " "kódování pro tuto službu je \"~s\", port ~p, empty password." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -887,35 +904,35 @@ msgstr "" "Příklad: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].2\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parametry spojení" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Vstoupit do IRC kanálu" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanál (bez počátečního #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC přezdívka" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Vstoupit do tohoto IRC kanálu." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Vstupte do IRC kanálu s tímto Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Nastavení IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -925,48 +942,77 @@ msgstr "" "IRC. Stiskněte 'Další' pro více políček k vyplnění. Stiskněte 'Dokončit' pro " "uložení nastavení." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC přezdívka" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Heslo ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kódování pro server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Jen moderátoři mají povoleno měnit téma místnosti" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Pouze správci služby smí odesílat servisní zprávy" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Pravidla služby nepovolují vytvořit místnost" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Konferenční místnost neexistuje" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Konference" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Pro registraci přezdívky potřebujete klienta s podporou x:data" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registrace přezdívky na " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Zadejte přezdívku, kterou chcete zaregistrovat" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Přezdívka" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Přezdívka je zaregistrována jinou osobou" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Musíte vyplnit políčko \"Přezdívka\" ve formuláři" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -994,353 +1040,482 @@ msgstr "Registrovaní uživatelé" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Nastavení diskuzní místnosti bylo změněno" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "vstoupil(a) do místnosti" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "opustil(a) místnost" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "byl(a) zablokován(a)" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "byl(a) vyhozen(a) kvůli změně přiřazení" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "byl(a) vyhozen(a), protože mísnost je nyní pouze pro členy" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "byl(a) vyhozen(a), protože dojde k vypnutí systému" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "se přejmenoval(a) na" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " změnil(a) téma na: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Konference vytvořena" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Konference zrušena" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Konference spuštěna" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Konference zastavena" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Pondělí" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Úterý" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Středa" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Čtvrtek" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Pátek" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sobota" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Neděle" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr ". ledna" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr ". února" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr ". března" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr ". dubna" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr ". května" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr ". června" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr ". července" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr ". srpna" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr ". září" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr ". října" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr ". listopadu" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr ". prosince" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Nastavení místnosti" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Byl překročen limit" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Není povoleno odesílat soukromé zprávy do konference" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Prosím, počkejte chvíli před posláním nové žádosti o voice práva" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Voice žádosti jsou v této konferenci zakázány" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Došlo k chybě při získávání Jabber ID z vaší žádosti o voice práva" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Pouze moderátoři mohou schválit žádosti o voice práva" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Nesprávný typ zprávy" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Není dovoleno odeslání soukromé zprávy typu \"skupinová zpráva\" " + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Příjemce se nenachází v konferenční místnosti" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Je zakázáno posílat soukromé zprávy" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Jen členové mají povolené zasílat zprávy do konference" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Jen členové mohou odesílat požadavky (query) do konference" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Požadavky (queries) na členy konference nejsou v této místnosti povolené" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Jen moderátoři a účastníci mají povoleno měnit téma této místnosti" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Jen moderátoři mají povoleno měnit téma místnosti" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Návštevníci nemají povoleno zasílat zprávy všem účastníkům konference" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Návštěvníkům této místnosti je zakázáno měnit přezdívku" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Přezdívka je již používána jiným členem" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Byl jste vyloučen z této místnosti" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Pro vstup do místnosti musíte být členem" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Pro vstup do místnosti musíte zadat heslo" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Přiliš mnoho CAPTCHA žádostí" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Nebylo možné vygenerovat CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Nesprávné heslo" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Potřebujete práva administrátora" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Potřebujete práva moderátora" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s je neplatné" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Přezdívka ~s v místnosti neexistuje" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Neplatné přiřazení: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Neplatná role: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Jsou vyžadována práva vlastníka" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Konfigurace místnosti ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Název místnosti" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Popis místnosti" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Nastavit místnost jako stálou" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Nastavit místnost jako veřejnou" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Nastavit seznam účastníků jako veřejný" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Chránit místnost heslem" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Odhalovat skutečná Jabber ID" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderátorům" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "každému" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "moderátorům" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Zpřístupnit místnost jen členům" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Nastavit místnost jako moderovanou" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Uživatelé jsou implicitně členy" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Povolit uživatelům měnit téma místnosti" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Povolit uživatelům odesílat soukromé zprávy" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Povolit návštěvníkům odesílat soukromé zprávy" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "nikdo" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Povolit uživatelům odesílat požadavky (query) ostatním uživatelům" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Povolit uživatelům posílání pozvánek" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Povolit návštěvníkům posílat stavové zprávy ve statusu" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Povolit návštěvníkům měnit přezdívku" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Povolit uživatelům posílat žádosti o voice práva" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimální interval mezi žádostmi o voice práva (v sekundách)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Chránit místnost pomocí CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Vyloučit Jabber ID z procesu CAPTCHA ověřování" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Zaznamenávat konverzace" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Ke konfiguraci místnosti potřebujete klienta podporujícího x:data" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "soukromá, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Žádost o voice práva" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Povolit nebo odmítnout voice žádost." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Jabber ID uživatele" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Udělit voice práva této osobě?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s vás zve do místnosti ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "heslo je" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "Fronta offline zpráv pro váš kontakt je plná. Zpráva byla zahozena." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Fronta offline zpráv uživatele ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Čas" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Od" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Pro" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline zprávy:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Odstranit všechny offline zprávy" @@ -1348,114 +1523,126 @@ msgstr "Odstranit všechny offline zprávy" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Žádost odběratele PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Zvolte, zda chcete schválit odebírání touto entitou" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID uzlu" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresa odběratele" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Povolit tomuto Jabber ID odebírat tento pubsub uzel?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Doručovat náklad s upozorněním na událost" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Doručovat upozornění na události" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Upozornit odběratele na změnu nastavení uzlu" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Upozornit odběratele na smazání uzlu" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Upozornit odběratele na odstranění položek z uzlu" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Uložit položky natrvalo do úložiště" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Přívětivé jméno pro uzel" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maximální počet položek, které je možné natrvalo uložit" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Povolit odebírání" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Uveďte přístupový model" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Skupiny kontaktů, které mohou odebírat" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Specifikovat model pro publikování" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Smazat všechny položky, pokud se příslušný poskytovatel odpojí" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Zvolte typ zpráv pro události" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximální náklad v bajtech" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kdy odeslat poslední publikovanou položku" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Doručovat upozornění jen právě přihlášeným uživatelům" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Kolekce, se kterými je uzel spřízněn" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Ověření CAPTCHA se nezdařilo" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Pro registraci potřebujete klienta s podporou x:data a CAPTCHA" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Zadejte jméno uživatele a heslo pro registraci na tomto serveru" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Heslo je příliš slabé" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Je zakázáno registrovat účty v tak rychlém sledu" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Váš účet Jabberu byl úspěšně vytvořen." @@ -1532,8 +1719,8 @@ msgstr "Později můžete své heslo změnit pomocí klienta Jabberu." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Někteří klienti umí uložit vaše heslo na disk počítače. Tuto funkci " "používejte, pouze pokud věříte zabezpečení svého počítače." @@ -1571,60 +1758,60 @@ msgstr "Zde můžete zrušit registraci účtu na tomto serveru Jabberu." msgid "Unregister" msgstr "Zrušit registraci" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Přihlášení" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Čekající" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Skupiny" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Ověřit" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Odstranit" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Seznam kontaktů " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Přidat Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Seznam kontaktů" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Skupiny pro sdílený seznam kontaktů" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Jméno:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Popis:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Členové:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Zobrazené skupiny:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Skupina " @@ -1700,58 +1887,19 @@ msgstr "Výsledky hledání pro " msgid "Fill in fields to search for any matching Jabber User" msgstr "Vyplňte políčka pro vyhledání uživatele Jabberu" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Odchozí s2s servery:" + #~ msgid "Delete" #~ msgstr "Smazat" #~ msgid "This room is not anonymous" #~ msgstr "Tato místnost není anonymní" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Vaše nastavení soukromí znemožnilo směrování této stance." - -#~ msgid "Access denied by service policy" -#~ msgstr "Přístup byl zamítnut nastavením služby" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Pouze správci služby smí odesílat servisní zprávy" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Pravidla služby nepovolují vytvořit místnost" - -#~ msgid "Conference room does not exist" -#~ msgstr "Konferenční místnost neexistuje" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Přezdívka je zaregistrována jinou osobou" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Musíte vyplnit políčko \"Přezdívka\" ve formuláři" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Byl překročen limit" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "Tento účastník byl vyhozen, protože odeslal chybovou zprávu" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Není povoleno odesílat soukromé zprávy do konference" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Prosím, počkejte chvíli před posláním nové žádosti o voice práva" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Voice žádosti jsou v této konferenci zakázány" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Došlo k chybě při získávání Jabber ID z vaší žádosti o voice práva" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Pouze moderátoři mohou schválit žádosti o voice práva" - -#~ msgid "Improper message type" -#~ msgstr "Nesprávný typ zprávy" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1759,80 +1907,10 @@ msgstr "Vyplňte políčka pro vyhledání uživatele Jabberu" #~ "Tento účastník byl vyhozen, protože odeslal chybovou zprávu jinému " #~ "účastníkovi" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Není dovoleno odeslání soukromé zprávy typu \"skupinová zpráva\" " - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Příjemce se nenachází v konferenční místnosti" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Je zakázáno posílat soukromé zprávy" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Jen členové mají povolené zasílat zprávy do konference" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Jen členové mohou odesílat požadavky (query) do konference" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Požadavky (queries) na členy konference nejsou v této místnosti povolené" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "" -#~ "Návštevníci nemají povoleno zasílat zprávy všem účastníkům konference" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "Tento účastník byl vyhozen, protože odeslal chybový status" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Návštěvníkům této místnosti je zakázáno měnit přezdívku" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Přezdívka je již používána jiným členem" - -#~ msgid "You have been banned from this room" -#~ msgstr "Byl jste vyloučen z této místnosti" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Pro vstup do místnosti musíte být členem" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Pro vstup do místnosti musíte zadat heslo" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Přiliš mnoho CAPTCHA žádostí" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Nebylo možné vygenerovat CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Nesprávné heslo" - -#~ msgid "Administrator privileges required" -#~ msgstr "Potřebujete práva administrátora" - -#~ msgid "Moderator privileges required" -#~ msgstr "Potřebujete práva moderátora" - -#~ msgid "Owner privileges required" -#~ msgstr "Jsou vyžadována práva vlastníka" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "Fronta offline zpráv pro váš kontakt je plná. Zpráva byla zahozena." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Ověření CAPTCHA se nezdařilo" - -#~ msgid "The password is too weak" -#~ msgstr "Heslo je příliš slabé" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Je zakázáno registrovat účty v tak rychlém sledu" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Zkouška CAPTCHA neprošla." diff --git a/priv/msgs/de.msg b/priv/msgs/de.msg index e3ca5906afe..1d313b2a842 100644 --- a/priv/msgs/de.msg +++ b/priv/msgs/de.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfiguration der Zugangskontrolllisten"}. {"Access control lists","Zugangskontroll-Listen (ACL)"}. {"Access Control Lists","Zugangskontroll-Listen (ACL)"}. +{"Access denied by service policy","Zugang aufgrund der Dienstrichtlinien verweigert"}. {"Access rules","Zugangsregeln"}. {"Access Rules","Zugangsregeln"}. {"Action on user","Aktion auf Benutzer"}. @@ -11,6 +12,7 @@ {"Add User","Benutzer hinzufügen"}. {"Administration of ","Administration von "}. {"Administration","Verwaltung"}. +{"Administrator privileges required","Administratorenrechte benötigt"}. {"A friendly name for the node","Ein merkbarer Name für den Knoten"}. {"All activity","Alle Aktivitäten"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Dieser Jabber-ID das Abonnement dieses pubsub-Knotens erlauben?"}. @@ -25,6 +27,7 @@ {"All Users","Alle Benutzer"}. {"Announcements","Ankündigungen"}. {"anyone","jeden"}. +{"A password is required to enter this room","Sie brauchen ein Passwort um diesen Raum zu betreten"}. {"April","April"}. {"August","August"}. {"Backup","Datensicherung"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Wählen sie, ob dieses Abonnement akzeptiert werden soll."}. {"City","Stadt"}. {"Commands","Befehle"}. +{"Conference room does not exist","Konferenzraum existiert nicht"}. {"Configuration","Konfiguration"}. {"Configuration of room ~s","Konfiguration für Raum ~s"}. {"Connected Resources:","Verbundene Ressourcen:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Alle Tabellen als SQL Abfragen in eine Datei exportieren:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Alle Benutzerdaten des Servers in PIEFXIS Dateien (XEP-0227) exportieren:"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Alle Benutzerdaten des Hosts in PIEFXIS Dateien (XEP-0227) exportieren:"}. +{"Failed to extract JID from your voice request approval","Fehler beim Auslesen der JID aus der Anfragenbestätigung für Sprachrechte"}. {"Family Name","Nachname"}. {"February","Februar"}. {"Fill in fields to search for any matching Jabber User","Füllen sie die Felder aus, um nach bestimmten Jabber-Benutzern zu suchen"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importiere Benutzer von jabberd14 Spool Verzeichnis:"}. {"Import Users from Dir at ","Benutzer importieren aus dem Verzeichnis "}. {"Import Users From jabberd14 Spool Files","Importiere Benutzer aus jabberd14-Spool-Dateien"}. +{"Improper message type","Unzulässiger Nachrichtentyp"}. +{"Incorrect password","Falsches Passwort"}. {"Invalid affiliation: ~s","Ungültige Mitgliedschaft: ~s"}. {"Invalid role: ~s","Ungültige Rolle: ~s"}. {"IP addresses","IP Adressen"}. @@ -147,6 +154,9 @@ {"IRC username","IRC Benutzername"}. {"IRC Username","IRC-Benutzername"}. {"is now known as","ist nun bekannt als"}. +{"It is not allowed to send private messages","Es ist nicht erlaubt private Nachrichten zu senden"}. +{"It is not allowed to send private messages of type \"groupchat\"","Es ist nicht erlaubt private Nachrichten des Typs \"Gruppenchat\" zu senden"}. +{"It is not allowed to send private messages to the conference","Es ist nicht erlaubt private Nachrichten an den Raum zu schicken"}. {"Jabber Account Registration","Jabber Konto Anmeldung"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Die Jabber-ID ~s ist ungültig"}. @@ -179,12 +189,14 @@ {"Max # of items to persist","Maximale Anzahl dauerhaft zu speichernder Einträge"}. {"Max payload size in bytes","Maximale Nutzlastgrösse in Bytes"}. {"May","Mai"}. +{"Membership is required to enter this room","Um diesen Raum zu betreten müssen sie Mitglied sein"}. {"Members:","Mitglieder:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Merken sie sich ihr Passwort, oder schreiben sie es auf einen Zettel den sie sicher verwahren. Bei Jabber gibt es keine automatische Möglichkeit, das Passwort wiederherzustellen."}. {"Memory","Speicher"}. {"Message body","Nachrichtentext"}. {"Middle Name","Zweiter Vorname"}. {"Minimum interval between voice requests (in seconds)","Mindestdauer zwischen Anfragen für Sprachrechte (in Sekunden)"}. +{"Moderator privileges required","Moderatorrechte benötigt"}. {"moderators only","ausschliesslich Moderatoren"}. {"Modified modules","Geänderte Module"}. {"Module","Modul"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Benachrichtigungen nur an verfügbare Benutzer schicken"}. {"Only moderators and participants are allowed to change the subject in this room","Nur Moderatoren und Mitglieder dürfen das Thema in diesem Raum ändern"}. {"Only moderators are allowed to change the subject in this room","Nur Moderatoren dürfen das Thema in diesem Raum ändern"}. +{"Only moderators can approve voice requests","Nur Moderatoren können Anfragen für Sprachrechte bestätigen"}. +{"Only occupants are allowed to send messages to the conference","Nur Teilnehmer dürfen Nachrichten an den Raum schicken"}. +{"Only occupants are allowed to send queries to the conference","Nur Teilnehmer sind berechtigt Anfragen an die Konferenz zu senden"}. +{"Only service administrators are allowed to send service messages","Nur Service-Administratoren sind berechtigt, Servicenachrichten zu versenden"}. {"Options","Optionen"}. {"Organization Name","Name der Organisation"}. {"Organization Unit","Abteilung"}. {"Outgoing s2s Connections:","Ausgehende s2s-Verbindungen:"}. {"Outgoing s2s Connections","Ausgehende s2s-Verbindungen"}. -{"Outgoing s2s Servers:","Ausgehende s2s-Server:"}. +{"Owner privileges required","Besitzerrechte benötigt"}. {"Packet","Paket"}. {"Password ~b","Passwort ~b"}. {"Password:","Passwort:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Einträge dauerhaft speichern"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Beachten sie, das diese Optionen nur die eingebaute Mnesia-Datenbank sichern. Wenn sie das ODBC-Modul verwenden, müssen sie die SQL-Datenbank manuell sichern."}. +{"Please, wait for a while before sending new voice request","Bitte warten sie ein wenig, bevor sie eine weitere Anfrage für Sprachrechte senden"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Publish-Subscribe"}. {"PubSub subscriber request","PubSub-Abonnenten-Anfrage"}. {"Purge all items when the relevant publisher goes offline","Alle Einträge entfernen, wenn der relevante Veröffentlicher offline geht"}. +{"Queries to the conference members are not allowed in this room","Anfragen an die Teilnehmer sind in diesem Raum nicht erlaubt"}. {"RAM and disc copy","RAM und Festplatte"}. {"RAM copy","Nur RAM"}. {"Raw","Unformatiert"}. {"Really delete message of the day?","Die Nachricht des Tages wirklich löschen?"}. +{"Recipient is not in the conference room","Der Empfänger ist nicht im Raum"}. {"Register a Jabber account","Jabber Konto registrieren"}. {"Register","Anmelden"}. {"Registered nicknames","Registrierte Benutzernamen"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Stelle Klartext-Sicherung sofort wieder her:"}. {"Restore","Wiederherstellung"}. {"Room Configuration","Raum-Konfiguration"}. +{"Room creation is denied by service policy","Anlegen des Raumes aufgrund der Dienstrichtlinien verweigert"}. {"Room description","Raum Beschreibung"}. {"Room Occupants","Teilnehmer in diesem Raum"}. {"Room title","Raumname"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Gewöhnliche Tabelle anzeigen"}. {"Shut Down Service","Dienst herunterfahren"}. {"~s invites you to the room ~s","~s lädt sie in den Raum ~s ein"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Einige Jabber Client Programme speichern ihr Passwort auf ihrem Computer. Verwenden sie diese Möglichkeit nur auf Computern, die sie als sicher einstufen."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Einige Jabber Client Programme speichern ihr Passwort auf ihrem Computer. Verwenden sie diese Möglichkeit nur auf Computern, die sie als sicher einstufen."}. {"Specify the access model","Geben sie das Zugangsmodell an"}. {"Specify the event message type","Geben sie den Ereignis-Nachrichtentyp an"}. {"Specify the publisher model","Geben sie das Publikationsmodell an"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Abonnenten-Adresse"}. {"Subscription","Abonnement"}. {"Sunday","Sonntag"}. +{"That nickname is already in use by another occupant","Dieser Benutzername wird bereits von einem Teilnehmer genutzt"}. +{"That nickname is registered by another person","Dieser Benutzername wurde bereits von jemand anderem registriert"}. {"The CAPTCHA is valid.","Die Verifizierung ist gültig."}. +{"The CAPTCHA verification has failed","Die CAPTCHA Verifizierung schlug fehl"}. {"The collections with which a node is affiliated","Sammlungen, mit denen ein Knoten verknüpft ist"}. {"the password is","das Passwort lautet"}. +{"The password is too weak","Das Passwort ist zu einfach"}. {"The password of your Jabber account was successfully changed.","Das Passwort von ihrem Jabber Konto wurde geändert."}. {"There was an error changing the password: ","Es trat ein Fehler beim Ändern des Passworts auf: "}. {"There was an error creating the account: ","Es trat ein Fehler beim Erstellen des Kontos auf: "}. @@ -348,15 +372,18 @@ {"Time delay","Zeitverzögerung"}. {"Time","Zeit"}. {"To","An"}. +{"Too many CAPTCHA requests","Zu viele CAPTCHA Anfragen"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Zu viele (~p) fehlgeschlagene Anmeldeversuche von dieser IP Adresse (~s). Die Adresse wird bis ~s UTC blockiert."}. {"Too many unacked stanzas","Zu viele unbestätigte Stanzas"}. {"To ~s","An ~s"}. {"Total rooms","Alle Chaträume"}. +{"Traffic rate limit is exceeded","Datenratenlimit wurde überschritten"}. {"Transactions Aborted:","Abgebrochene Transaktionen:"}. {"Transactions Committed:","Durchgeführte Transaktionen:"}. {"Transactions Logged:","Protokollierte Transaktionen:"}. {"Transactions Restarted:","Neu gestartete Transaktionen:"}. {"Tuesday","Dienstag"}. +{"Unable to generate a CAPTCHA","Konnte CAPTCHA nicht erstellen"}. {"Unauthorized","Nicht berechtigt"}. {"Unregister","Abmelden"}. {"Unregister a Jabber account","Jabber Konto entfernen"}. @@ -372,22 +399,30 @@ {"User JID","Benutzer JID"}. {"User Management","Benutzerverwaltung"}. {"Username:","Benutzername:"}. +{"Users are not allowed to register accounts so quickly","Benutzer dürfen Konten nicht so schnell registrieren"}. {"Users","Benutzer"}. {"User ~s","Benutzer ~s"}. {"Users Last Activity","Letzte Benutzeraktivität"}. {"Validate","Validieren"}. {"vCard User Search","vCard-Benutzer-Suche"}. {"Virtual Hosts","Virtuelle Hosts"}. +{"Visitors are not allowed to change their nicknames in this room","Besucher dürfen in diesem Raum ihren Benutzernamen nicht ändern"}. +{"Visitors are not allowed to send messages to all occupants","Besucher dürfen nicht an alle Teilnehmer Nachrichten verschicken"}. {"Voice request","Anfrage für Sprachrechte"}. +{"Voice requests are disabled in this conference","Anfragen für Sprachrechte sind in diesem Raum deaktiviert"}. {"Wednesday","Mittwoch"}. {"When to send the last published item","Wann das letzte veröffentlichte Objekt gesendet werden soll"}. {"Whether to allow subscriptions","Ob Abonnements erlaubt sind"}. {"You can later change your password using a Jabber client.","Sie können das Passwort später mit einem Jabber Client Programm ändern."}. +{"You have been banned from this room","Sie wurden aus diesem Raum verbannt"}. +{"You must fill in field \"Nickname\" in the form","Sie müssen das Feld \"Benutzername\" ausfüllen"}. {"You need a client that supports x:data and CAPTCHA to register","Sie benötigen einen Client, der x:data und CAPTCHA unterstützt, um Ihren Benutzernamen zu registrieren"}. {"You need a client that supports x:data to register the nickname","Sie benötigen einen Client, der x:data unterstützt, um Ihren Benutzernamen zu registrieren"}. {"You need an x:data capable client to configure mod_irc settings","Sie benötigen einen Client, der x:data unterstützt, um die mod_irc-Einstellungen zu konfigurieren"}. {"You need an x:data capable client to configure room","Sie benötigen einen Client, der x:data unterstützt, um den Raum zu konfigurieren"}. {"You need an x:data capable client to search","Sie benötigen einen Client, der x:data unterstützt, um die Suche verwenden zu können"}. +{"Your active privacy list has denied the routing of this stanza.","Ihre aktive Privacy Liste hat die Weiterleitung des Stanzas unterbunden."}. +{"Your contact offline message queue is full. The message has been discarded.","Ihre Offline-Nachrichten-Warteschlange ist voll. Die Nachricht wurde verworfen."}. {"Your Jabber account was successfully created.","Ihr Jabber Konto wurde erfolgreich erstellt."}. {"Your Jabber account was successfully deleted.","Ihr Jabber Konto wurde erfolgreich gelöscht."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ihre Nachrichten an ~s werden blockiert. Um dies zu ändern, besuchen sie ~s"}. diff --git a/priv/msgs/de.po b/priv/msgs/de.po index ec5565dabb7..d8ad2b59b96 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -18,51 +18,56 @@ msgstr "" "X-Additional-Translator: Marina Hahn\n" "X-Generator: Poedit 1.8.4\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Verwendung von STARTTLS erforderlich" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Keine Ressource angegeben" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Durch neue Verbindung ersetzt" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "wurde entfernt" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" +"Ihre aktive Privacy Liste hat die Weiterleitung des Stanzas unterbunden." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Zu viele unbestätigte Stanzas" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Geben sie den Text den sie sehen ein" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Ihre Nachrichten an ~s werden blockiert. Um dies zu ändern, besuchen sie ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "Wenn sie das CAPTCHA Bild nicht sehen, besuchen sie bitte die Webseite." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA Webseite" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Die Verifizierung ist gültig." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Benutzer" @@ -71,9 +76,9 @@ msgstr "Benutzer" msgid "Server" msgstr "Server:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Passwort" @@ -90,275 +95,276 @@ msgstr "Nicht berechtigt" msgid "ejabberd Web Admin" msgstr "ejabberd Web-Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Verwaltung" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Zugangskontroll-Listen (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Gesendet" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Ungültiges Format" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Senden" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Unformatiert" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Markierte löschen" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Zugangsregeln" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s Zugangsregel-Konfiguration" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuelle Hosts" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Benutzer" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Angemeldete Benutzer" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Letzte Benutzeraktivität" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Zeitraum: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Letzter Monat" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Letztes Jahr" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Alle Aktivitäten" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Gewöhnliche Tabelle anzeigen" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Integrale Tabelle anzeigen" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiken" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nicht gefunden" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Knoten nicht gefunden" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Neue(n) hinzufügen" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrierte Benutzer" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Benutzer hinzufügen" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Offline-Nachrichten" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Letzte Aktivität" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nie" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Angemeldet" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrierte Benutzer:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Angemeldete Benutzer:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Ausgehende s2s-Verbindungen:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Ausgehende s2s-Server:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Ausgehende s2s-Verbindungen:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Keine" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Passwort ändern" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Benutzer ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Verbundene Ressourcen:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Passwort:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Benutzer löschen" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Keine Daten" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Knoten" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Aktive Knoten" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Angehaltene Knoten" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Knoten ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Datenbank" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Datensicherung" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Aktive Ports" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualisieren" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Neustart" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppen" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Module" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Fehler bei RPC-Aufruf" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Datenbanktabellen auf ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Vorname" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Speichertyp" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elemente" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Speicher" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Fehler" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Sicherung von ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -368,145 +374,145 @@ msgstr "" "sichern. Wenn sie das ODBC-Modul verwenden, müssen sie die SQL-Datenbank " "manuell sichern." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Speichere binäre Sicherung:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Stelle binäre Sicherung sofort wieder her:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Stelle binäre Sicherung beim nächsten ejabberd-Neustart wieder her (benötigt " "weniger Speicher):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Speichere Klartext-Sicherung:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Stelle Klartext-Sicherung sofort wieder her:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Benutzerdaten von einer PIEFXIS Datei (XEP-0227) importieren:" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Alle Benutzerdaten des Servers in PIEFXIS Dateien (XEP-0227) exportieren:" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Alle Benutzerdaten des Hosts in PIEFXIS Dateien (XEP-0227) exportieren:" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Alle Tabellen als SQL Abfragen in eine Datei exportieren:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importiere Benutzer von jabberd14 Spool Datei:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importiere Benutzer von jabberd14 Spool Verzeichnis:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Aktive Ports bei" -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Module bei ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiken von ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Betriebszeit:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU-Zeit:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Durchgeführte Transaktionen:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Abgebrochene Transaktionen:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Neu gestartete Transaktionen:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Protokollierte Transaktionen:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Aktualisierung ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Aktualisierungsplan" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Geänderte Module" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Aktualisierungsscript" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Low level Aktualisierungsscript" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Script-Überprüfung" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokoll" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Optionen" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Starten" @@ -793,8 +799,8 @@ msgstr "Zugangsregeln" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -811,31 +817,31 @@ msgstr "Anzahl der registrierten Benutzer" msgid "Number of online users" msgstr "Anzahl der angemeldeten Benutzer" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Letzte Anmeldung" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Kontaktlistengröße" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP Adressen" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Ressourcen" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administration von " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Aktion auf Benutzer" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Einstellungen ändern" @@ -847,29 +853,41 @@ msgstr "" "Zu viele (~p) fehlgeschlagene Anmeldeversuche von dieser IP Adresse (~s). " "Die Adresse wird bis ~s UTC blockiert." +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Diese IP Adresse ist blockiert in ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Zugang aufgrund der Dienstrichtlinien verweigert" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC-Modul" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um die mod_irc-" "Einstellungen zu konfigurieren" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registrierung in mod_irc für " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -877,11 +895,11 @@ msgstr "" "Geben sie den Benutzernamen, Zeichenkodierung, Ports und Passwörter, die sie " "für die Verbindung zum IRC-Server verwenden wollen, an" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC-Benutzername" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -893,7 +911,7 @@ msgstr "" "\", \"Kodierung\", Port, \"Passwort\"}'. Standardmäßig benutzt dieser " "Dienst die \"~s\" Kodierung, den Port ~p und kein Passwort." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -901,35 +919,35 @@ msgstr "" "Beispiel: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Verbindungsparameter" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "IRC Channel beitreten" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC Channel (ohne dem ersten #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC Server" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Hier den IRC Channel beitreten." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Den IRC Channel mit dieser Jabber ID beitreten: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC Einstellungen" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -939,50 +957,80 @@ msgstr "" "Drücken sie 'Mehr' um leere Felder hinzuzufügen. Drücken sie 'Beenden' um " "die Einstellungen zu speichern." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC Benutzername" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Passwort ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kodierung für Server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Nur Moderatoren dürfen das Thema in diesem Raum ändern" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Nur Service-Administratoren sind berechtigt, Servicenachrichten zu versenden" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Anlegen des Raumes aufgrund der Dienstrichtlinien verweigert" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Konferenzraum existiert nicht" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Chaträume" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um Ihren Benutzernamen " "zu registrieren" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registrieren des Benutzernames auf" -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Geben sie den zu registrierenden Benutzernamen ein" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Benutzername" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Dieser Benutzername wurde bereits von jemand anderem registriert" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Sie müssen das Feld \"Benutzername\" ausfüllen" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC-Modul" @@ -1007,355 +1055,489 @@ msgstr "Registrierte Benutzernamen" msgid "List of rooms" msgstr "Liste von Chaträumen" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Chatraum-Konfiguration geändert" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "betretet den Raum" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "verlässt den Raum" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "wurde gebannt" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "wurde wegen Änderung des Mitgliederstatus entfernt" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "wurde entfernt weil der Raum auf Nur-Mitglieder umgestellt wurde" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "wurde wegen einer Systemabschaltung entfernt" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "ist nun bekannt als" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " hat das Thema geändert auf: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Chatraum wurde erstellt" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Chatraum wurde entfernt" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Chatraum wurde gestartet" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Chatraum wurde beendet" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Montag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Dienstag" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mittwoch" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Donnerstag" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Freitag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Samstag" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Sonntag" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Januar" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Februar" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "März" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "April" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Mai" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "August" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "September" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "November" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Dezember" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Raum-Konfiguration" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Teilnehmer in diesem Raum" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Datenratenlimit wurde überschritten" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Es ist nicht erlaubt private Nachrichten an den Raum zu schicken" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" +"Bitte warten sie ein wenig, bevor sie eine weitere Anfrage für Sprachrechte " +"senden" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Anfragen für Sprachrechte sind in diesem Raum deaktiviert" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" +"Fehler beim Auslesen der JID aus der Anfragenbestätigung für Sprachrechte" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Nur Moderatoren können Anfragen für Sprachrechte bestätigen" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Unzulässiger Nachrichtentyp" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"Es ist nicht erlaubt private Nachrichten des Typs \"Gruppenchat\" zu senden" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Der Empfänger ist nicht im Raum" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Es ist nicht erlaubt private Nachrichten zu senden" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Nur Teilnehmer dürfen Nachrichten an den Raum schicken" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Nur Teilnehmer sind berechtigt Anfragen an die Konferenz zu senden" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Anfragen an die Teilnehmer sind in diesem Raum nicht erlaubt" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Nur Moderatoren und Mitglieder dürfen das Thema in diesem Raum ändern" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Nur Moderatoren dürfen das Thema in diesem Raum ändern" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Besucher dürfen nicht an alle Teilnehmer Nachrichten verschicken" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Besucher dürfen in diesem Raum ihren Benutzernamen nicht ändern" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Dieser Benutzername wird bereits von einem Teilnehmer genutzt" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Sie wurden aus diesem Raum verbannt" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Um diesen Raum zu betreten müssen sie Mitglied sein" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Sie brauchen ein Passwort um diesen Raum zu betreten" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Zu viele CAPTCHA Anfragen" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Konnte CAPTCHA nicht erstellen" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Falsches Passwort" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Administratorenrechte benötigt" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Moderatorrechte benötigt" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Die Jabber-ID ~s ist ungültig" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Der Benutzername ~s existiert im Raum nicht" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ungültige Mitgliedschaft: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ungültige Rolle: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Besitzerrechte benötigt" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Konfiguration für Raum ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Raumname" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Raum Beschreibung" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Raum persistent machen" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Raum öffentlich suchbar machen" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Teilnehmerliste öffentlich machen" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Raum mit Passwort schützen" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maximale Anzahl von Teilnehmern" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Keine Begrenzung" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Echte Jabber-IDs anzeigen für" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "ausschliesslich Moderatoren" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "jeden" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "ausschliesslich Moderatoren" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Raum nur für Mitglieder zugänglich machen" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Raum moderiert machen" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Benutzer werden standardmäßig vollwertige Teilnehmer" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Erlaube Benutzern das Thema zu ändern" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Erlaube Benutzern private Nachrichten zu senden" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Erlaube Besuchern das Senden von privaten Nachrichten an" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "niemanden" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Erlaube Benutzern Informationen über andere Benutzer abzufragen" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Erlaube Benutzern Einladungen zu senden" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Erlaube Besuchern einen Text bei Statusänderung zu senden" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Erlaube Besuchern ihren Benutzernamen zu ändern" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Anfragen von Sprachrechten für Benutzer erlauben" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Mindestdauer zwischen Anfragen für Sprachrechte (in Sekunden)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Raum mit Verifizierung (Captcha) versehen" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Nachrichtenarchivierung aktivieren" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Von CAPTCHA Überprüfung ausgeschlossene Jabber IDs" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Protokollierung aktivieren" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um den Raum zu " "konfigurieren" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Anzahl der Teilnehmer" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Anfrage für Sprachrechte" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Diese Anfrage für Sprachrechte bestätigen oder ablehnen." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Benutzer JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Sprachrechte dieser Person erteilen?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s lädt sie in den Raum ~s ein" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "das Passwort lautet" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast Dienst" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Ihre Offline-Nachrichten-Warteschlange ist voll. Die Nachricht wurde " +"verworfen." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s's Offline-Nachrichten-Warteschlange" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Zeit" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Von" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "An" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline-Nachrichten:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Alle Offline Nachrichten löschen" @@ -1363,117 +1545,129 @@ msgstr "Alle Offline Nachrichten löschen" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5-Bytestreams-Modul" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe-Modul" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub-Abonnenten-Anfrage" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Wählen sie, ob dieses Abonnement akzeptiert werden soll." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Knoten-ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonnenten-Adresse" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Dieser Jabber-ID das Abonnement dieses pubsub-Knotens erlauben?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Nachrichten mit Ereignis-Benachrichtigungen zustellen" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Ereignisbenachrichtigung zustellen" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Abonnenten benachrichtigen, wenn sich die Knotenkonfiguration ändert" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Abonnenten benachrichtigen, wenn der Knoten gelöscht wird" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Abonnenten benachrichtigen, wenn Einträge vom Knoten entfernt werden" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Einträge dauerhaft speichern" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Ein merkbarer Name für den Knoten" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maximale Anzahl dauerhaft zu speichernder Einträge" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Ob Abonnements erlaubt sind" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Geben sie das Zugangsmodell an" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kontaktlisten-Gruppen die abonnieren dürfen" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Geben sie das Publikationsmodell an" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Alle Einträge entfernen, wenn der relevante Veröffentlicher offline geht" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Geben sie den Ereignis-Nachrichtentyp an" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximale Nutzlastgrösse in Bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Wann das letzte veröffentlichte Objekt gesendet werden soll" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Benachrichtigungen nur an verfügbare Benutzer schicken" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Sammlungen, mit denen ein Knoten verknüpft ist" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Die CAPTCHA Verifizierung schlug fehl" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Sie benötigen einen Client, der x:data und CAPTCHA unterstützt, um Ihren " "Benutzernamen zu registrieren" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Wählen sie zum Registrieren einen Benutzernamen und ein Passwort" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Das Passwort ist zu einfach" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Benutzer dürfen Konten nicht so schnell registrieren" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Ihr Jabber Konto wurde erfolgreich erstellt." @@ -1554,8 +1748,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Einige Jabber Client Programme speichern ihr Passwort auf ihrem Computer. " "Verwenden sie diese Möglichkeit nur auf Computern, die sie als sicher " @@ -1596,60 +1790,60 @@ msgstr "" msgid "Unregister" msgstr "Abmelden" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Abonnement" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Schwebend" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Gruppen" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validieren" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Entfernen" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktliste von " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber-ID hinzufügen" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktliste" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Gruppen der gemeinsamen Kontaktliste" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Name:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beschreibung:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Mitglieder:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Angezeigte Gruppen:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Gruppe " @@ -1728,66 +1922,21 @@ msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Füllen sie die Felder aus, um nach bestimmten Jabber-Benutzern zu suchen" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Ausgehende s2s-Server:" + #~ msgid "Delete" #~ msgstr "Löschen" #~ msgid "This room is not anonymous" #~ msgstr "Dieser Raum ist nicht anonym" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "Ihre aktive Privacy Liste hat die Weiterleitung des Stanzas unterbunden." - -#~ msgid "Access denied by service policy" -#~ msgstr "Zugang aufgrund der Dienstrichtlinien verweigert" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Nur Service-Administratoren sind berechtigt, Servicenachrichten zu " -#~ "versenden" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Anlegen des Raumes aufgrund der Dienstrichtlinien verweigert" - -#~ msgid "Conference room does not exist" -#~ msgstr "Konferenzraum existiert nicht" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Dieser Benutzername wurde bereits von jemand anderem registriert" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Sie müssen das Feld \"Benutzername\" ausfüllen" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Datenratenlimit wurde überschritten" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Dieser Teilnehmer wurde aus dem Raum geworfen, da er eine fehlerhafte " #~ "Nachricht gesendet hat" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Es ist nicht erlaubt private Nachrichten an den Raum zu schicken" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "" -#~ "Bitte warten sie ein wenig, bevor sie eine weitere Anfrage für " -#~ "Sprachrechte senden" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Anfragen für Sprachrechte sind in diesem Raum deaktiviert" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "" -#~ "Fehler beim Auslesen der JID aus der Anfragenbestätigung für Sprachrechte" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Nur Moderatoren können Anfragen für Sprachrechte bestätigen" - -#~ msgid "Improper message type" -#~ msgstr "Unzulässiger Nachrichtentyp" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1795,84 +1944,12 @@ msgstr "" #~ "Dieser Teilnehmer wurde aus dem Raum geworfen, da er eine fehlerhafte " #~ "Nachricht an einen anderen Teilnehmer gesendet hat" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Es ist nicht erlaubt private Nachrichten des Typs \"Gruppenchat\" zu " -#~ "senden" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Der Empfänger ist nicht im Raum" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Es ist nicht erlaubt private Nachrichten zu senden" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Nur Teilnehmer dürfen Nachrichten an den Raum schicken" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Nur Teilnehmer sind berechtigt Anfragen an die Konferenz zu senden" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Anfragen an die Teilnehmer sind in diesem Raum nicht erlaubt" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Besucher dürfen nicht an alle Teilnehmer Nachrichten verschicken" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Dieser Teilnehmer wurde aus dem Raum gekickt, da er einen fehlerhaften " #~ "Status gesendet hat" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Besucher dürfen in diesem Raum ihren Benutzernamen nicht ändern" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Dieser Benutzername wird bereits von einem Teilnehmer genutzt" - -#~ msgid "You have been banned from this room" -#~ msgstr "Sie wurden aus diesem Raum verbannt" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Um diesen Raum zu betreten müssen sie Mitglied sein" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Sie brauchen ein Passwort um diesen Raum zu betreten" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Zu viele CAPTCHA Anfragen" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Konnte CAPTCHA nicht erstellen" - -#~ msgid "Incorrect password" -#~ msgstr "Falsches Passwort" - -#~ msgid "Administrator privileges required" -#~ msgstr "Administratorenrechte benötigt" - -#~ msgid "Moderator privileges required" -#~ msgstr "Moderatorrechte benötigt" - -#~ msgid "Owner privileges required" -#~ msgstr "Besitzerrechte benötigt" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Ihre Offline-Nachrichten-Warteschlange ist voll. Die Nachricht wurde " -#~ "verworfen." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Die CAPTCHA Verifizierung schlug fehl" - -#~ msgid "The password is too weak" -#~ msgstr "Das Passwort ist zu einfach" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Benutzer dürfen Konten nicht so schnell registrieren" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Die Verifizierung ist gültig." diff --git a/priv/msgs/ejabberd.pot b/priv/msgs/ejabberd.pot index c1862d97ae6..7f903ffd94b 100644 --- a/priv/msgs/ejabberd.pot +++ b/priv/msgs/ejabberd.pot @@ -1,55 +1,59 @@ msgid "" msgstr "" -"Project-Id-Version: 15.07\n" +"Project-Id-Version: 15.11.117\n" "X-Language: Language Name\n" "Last-Translator: Translator name and contact method\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "" @@ -57,9 +61,9 @@ msgstr "" msgid "Server" msgstr "" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "" @@ -76,416 +80,416 @@ msgstr "" msgid "ejabberd Web Admin" msgstr "" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" +#: ejabberd_web_admin.erl:1559 +msgid "Incoming s2s Connections:" msgstr "" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " "separately." msgstr "" -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "" -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "" @@ -770,8 +774,8 @@ msgstr "" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "" @@ -788,31 +792,31 @@ msgstr "" msgid "Number of online users" msgstr "" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "" -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "" @@ -822,37 +826,49 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "" -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -860,89 +876,117 @@ msgid "" "~p, empty password." msgstr "" -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " "settings." msgstr "" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +msgid "Only members are allowed to query archives of this room" +msgstr "" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "" -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "" @@ -967,353 +1011,480 @@ msgstr "" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr "" -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +msgid "Moderator" +msgstr "" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "" @@ -1321,114 +1492,126 @@ msgstr "" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1500,8 +1683,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1535,60 +1718,60 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "" -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "" diff --git a/priv/msgs/el.msg b/priv/msgs/el.msg index 9a53ca7eb83..ce1632dc7f1 100644 --- a/priv/msgs/el.msg +++ b/priv/msgs/el.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Διαχείριση στις Λίστες Ελέγχου Πρόσβασης"}. {"Access control lists","Λίστες Ελέγχου Πρόσβασης"}. {"Access Control Lists","Λίστες Ελέγχου Πρόσβασης"}. +{"Access denied by service policy","Άρνηση πρόσβασης, λόγω τακτικής παροχής υπηρεσιών"}. {"Access rules","Κανόνες Πρόσβασης"}. {"Access Rules","Κανόνες Πρόσβασης"}. {"Action on user","Eνέργεια για το χρήστη"}. @@ -11,6 +12,7 @@ {"Add User","Προσθήκη Χρήστη"}. {"Administration of ","Διαχείριση του"}. {"Administration","Διαχείριση"}. +{"Administrator privileges required","Aπαιτούνται προνόμια διαχειριστή"}. {"A friendly name for the node","Ένα φιλικό όνομα για τον κόμβο"}. {"All activity","Όλες οι δραστηριότητες"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Επιτρέπετε σε αυτή την Jabber Ταυτότητα να εγγραφεί σε αυτό τον κόμβο Δημοσίευσης-Εγγραφής;"}. @@ -25,6 +27,7 @@ {"All Users","Όλοι οι χρήστες"}. {"Announcements","Ανακοινώσεις"}. {"anyone","οποιοσδήποτε"}. +{"A password is required to enter this room","Απαιτείται κωδικός πρόσβασης για είσοδο σε αυτή την αίθουσα"}. {"April","Απρίλιος"}. {"August","Αύγουστος"}. {"Backup Management","Διαχείριση Αντιγράφου Ασφαλείας"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","Επιλέξτε αν θα εγκρίθεί η εγγραφή αυτής της οντότητας."}. {"City","Πόλη"}. {"Commands","Εντολές"}. +{"Conference room does not exist","Αίθουσα σύνεδριασης δεν υπάρχει"}. {"Configuration of room ~s","Διαμόρφωση Αίθουσας σύνεδριασης ~s"}. {"Configuration","Διαμόρφωση"}. {"Connected Resources:","Συνδεδεμένοι Πόροι:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","Εξαίρεση από τις ταυτότητες Jabber, ή CAPTCHA πρόκληση"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Εξαγωγή δεδομένων όλων των χρηστών του διακομιστή σε PIEFXIS αρχεία (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Εξαγωγή δεδομένων των χρηστών κεντρικού υπολογιστή σε PIEFXIS αρχεία (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Απέτυχε η εξαγωγή JID από την έγκριση του αιτήματος φωνής σας"}. {"Family Name","Επώνυμο"}. {"February","Φεβρουάριος"}. {"Fill in fields to search for any matching Jabber User","Συμπληρώστε τα πεδία για να αναζητήσετε οποιαδήποτε ταιριάζοντα Jabber χρήστη"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","Εισαγωγή δεδομένων χρηστών από κατάλογο αρχείων σειράς jabberd14:"}. {"Import Users from Dir at ","Εισαγωγή χρηστών από κατάλογο αρχείων στο "}. {"Import Users From jabberd14 Spool Files","Εισαγωγή Χρηστών από αρχεία σειράς jabberd14"}. +{"Improper message type","Ακατάλληλο είδος μηνύματος"}. +{"Incorrect password","Εσφαλμένος κωδικός πρόσβασης"}. {"Invalid affiliation: ~s","Άκυρη υπαγωγή: ~s"}. {"Invalid role: ~s","Άκυρος ρόλο: ~s"}. {"IP addresses","Διευθύνσεις IP"}. @@ -142,6 +149,9 @@ {"IRC username","IRC όνομα χρήστη"}. {"IRC Username","IRC Όνομα χρήστη"}. {"is now known as","είναι τώρα γνωστή ως"}. +{"It is not allowed to send private messages of type \"groupchat\"","Δεν επιτρέπεται να στείλει προσωπικά μηνύματα του τύπου \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Δεν επιτρέπεται να στείλει προσωπικά μηνύματα για τη διάσκεψη"}. +{"It is not allowed to send private messages","Δεν επιτρέπεται η αποστολή προσωπικών μηνυμάτων"}. {"Jabber Account Registration","Εγγραφή λογαριασμού Jabber"}. {"Jabber ID ~s is invalid","Η Jabber Ταυτότητα ~s είναι άκυρη"}. {"Jabber ID","Ταυτότητα Jabber"}. @@ -173,12 +183,14 @@ {"Max # of items to persist","Μέγιστος αριθμός μόνιμων στοιχείων"}. {"Max payload size in bytes","Μέγιστο μέγεθος φορτίου σε bytes"}. {"May","Μάιος"}. +{"Membership is required to enter this room","Απαιτείται αίτηση συμετοχής για είσοδο σε αυτή την αίθουσα"}. {"Members:","Μέλη:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Απομνημονεύστε τον κωδικό πρόσβασής σας, ή γράψετε τον σε ένα χαρτί που είχε τοποθετηθεί σε ασφαλές μέρος. Στο Jabber δεν υπάρχει αυτοματοποιημένος τρόπος για να ανακτήσετε τον κωδικό σας αν τον ξεχάσετε."}. {"Memory","Μνήμη"}. {"Message body","Περιεχόμενο μηνυμάτως"}. {"Middle Name","Πατρώνυμο"}. {"Minimum interval between voice requests (in seconds)","Ελάχιστο χρονικό διάστημα μεταξύ αιτημάτων φωνής (σε δευτερόλεπτα)"}. +{"Moderator privileges required","Aπαιτούνται προνόμια συντονιστή"}. {"moderators only","συντονιστές μόνο"}. {"Modified modules","Τροποποιημένα modules"}. {"Module","Module"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","Παράδωση κοινοποιήσεων μόνο σε διαθέσιμους χρήστες"}. {"Only moderators and participants are allowed to change the subject in this room","Μόνο οι συντονιστές και οι συμμετέχοντες μπορούν να αλλάξουν το θέμα αυτής της αίθουσας"}. {"Only moderators are allowed to change the subject in this room","Μόνο οι συντονιστές μπορούν να αλλάξουν το θέμα αυτής της αίθουσας"}. +{"Only moderators can approve voice requests","Μόνο οι συντονιστές μπορούν να εγκρίνουν τις αιτήσεις φωνής"}. +{"Only occupants are allowed to send messages to the conference","Μόνο οι συμμετέχωντες μπορούν να στέλνουν μηνύματα στο συνέδριο"}. +{"Only occupants are allowed to send queries to the conference","Μόνο οι συμετεχόντες μπορούν να στείλουν ερωτήματα στη διάσκεψη"}. +{"Only service administrators are allowed to send service messages","Μόνο οι διαχειριστές των υπηρεσιών επιτρέπεται να στείλουν υπηρεσιακά μηνύματα"}. {"Options","Επιλογές"}. {"Organization Name","Όνομα Οργανισμού"}. {"Organization Unit","Μονάδα Οργανισμού"}. {"Outgoing s2s Connections:","Εξερχόμενες S2S Συνδέσεις:"}. {"Outgoing s2s Connections","Εξερχόμενες S2S Συνδέσεις"}. -{"Outgoing s2s Servers:","Εξερχόμενοι S2S διακομιστές:"}. +{"Owner privileges required","Aπαιτούνται προνόμια ιδιοκτήτη"}. {"Packet","Πακέτο"}. {"Password ~b","Κωδικός πρόσβασης ~b"}. {"Password Verification:","Επαλήθευση κωδικού πρόσβασης:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","Μονιμη αποθήκευση στοιχείων"}. {"Ping","Πινγκ"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Παρακαλώ σημειώστε ότι οι επιλογές αυτές θα αποθήκευσουν Αντιγράφο Ασφαλείας μόνο της ενσωματωμένης βάσης δεδομένων Mnesia. Εάν χρησιμοποιείτε το module ODBC, θα πρέπει επίσης να κάνετε χωριστά Αντιγράφο Ασφαλείας της SQL βάση δεδομένων σας ."}. +{"Please, wait for a while before sending new voice request","Παρακαλώ, περιμένετε για λίγο πριν την αποστολή νέου αιτήματος φωνής"}. {"Pong","Πονγκ"}. {"Port ~b","Θύρα ~b"}. {"Port","Θύρα"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","Δημοσίευση-Εγγραφή"}. {"PubSub subscriber request","Αίτηση συνδρομητή Δημοσίευσης-Εγγραφής"}. {"Purge all items when the relevant publisher goes offline","Διαγραφή όλων των στοιχείων όταν ο σχετικός εκδότης αποσυνδέεται"}. +{"Queries to the conference members are not allowed in this room","Ερωτήματα πρώς τα μέλη της διασκέψεως δεν επιτρέπονται σε αυτήν την αίθουσα"}. {"RAM and disc copy","Αντίγραφο μόνο σε RAM καί δίσκο"}. {"RAM copy","Αντίγραφο σε RAM"}. {"Raw","Ακατέργαστο"}. {"Really delete message of the day?","Πραγματικά να διαγράψετε το μήνυμα της ημέρας;"}. +{"Recipient is not in the conference room","Παραλήπτης δεν είναι στην αίθουσα συνεδριάσεων"}. {"Register a Jabber account","Καταχωρήστε έναν λογαριασμό Jabber"}. {"Registered Users:","Εγγεγραμμένοι Χρήστες:"}. {"Registered Users","Εγγεγραμμένοι Χρήστες"}. @@ -270,6 +289,7 @@ {"Restore plain text backup immediately:","Επαναφορά αντιγράφου ασφαλείας από αρχείο κειμένου αμέσως:"}. {"Restore","Επαναφορά Αντιγράφου Ασφαλείας"}. {"Room Configuration","Διαμόρφωση Αίθουσας σύνεδριασης"}. +{"Room creation is denied by service policy","Άρνηση δημιουργίας αίθουσας , λόγω τακτικής παροχής υπηρεσιών"}. {"Room description","Περιγραφή Αίθουσας"}. {"Room Occupants","Συμετεχόντες Αίθουσας σύνεδριασης"}. {"Room title","Τίτλος Αίθουσας "}. @@ -298,7 +318,7 @@ {"Show Ordinary Table","Δείτε Κοινό Πίνακα"}. {"Shut Down Service","Κλείσιμο Υπηρεσίας"}. {"~s invites you to the room ~s","~s σας προσκαλεί στην αίθουσα ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Μερικοί πελάτες Jabber μπορεί να αποθηκεύσουν τον κωδικό πρόσβασής σας στον υπολογιστή σας. Χρησιμοποιήστε αυτό το χαρακτηριστικό μόνο εάν εμπιστεύεστε την ασφάλεια του υπολογιστή σας."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Μερικοί πελάτες Jabber μπορεί να αποθηκεύσουν τον κωδικό πρόσβασής σας στον υπολογιστή σας. Χρησιμοποιήστε αυτό το χαρακτηριστικό μόνο εάν εμπιστεύεστε την ασφάλεια του υπολογιστή σας."}. {"Specify the access model","Καθορίστε το μοντέλο πρόσβασης"}. {"Specify the event message type","Καθορίστε τον τύπο μηνύματος συμβάντος"}. {"Specify the publisher model","Καθορίστε το μοντέλο εκδότη"}. @@ -321,8 +341,12 @@ {"Subscriber Address","Διεύθυνση Συνδρομητή"}. {"Subscription","Συνδρομή"}. {"Sunday","Κυριακή"}. +{"That nickname is already in use by another occupant","Αυτό το ψευδώνυμο είναι ήδη σε χρήση από άλλον συμμετέχων"}. +{"That nickname is registered by another person","Αυτό το ψευδώνυμο είναι καταχωρημένο από άλλο πρόσωπο"}. {"The CAPTCHA is valid.","Το CAPTCHA είναι έγκυρο."}. +{"The CAPTCHA verification has failed","Η επαλήθευση της εικόνας CAPTCHA απέτυχε"}. {"The collections with which a node is affiliated","Οι συλλογές με την οποία είναι ένας κόμβος συνδέεται"}. +{"The password is too weak","Ο κωδικός πρόσβασης είναι πολύ ασθενές"}. {"the password is","ο κωδικός πρόσβασης είναι"}. {"The password of your Jabber account was successfully changed.","Ο κωδικός πρόσβασης του Jabber λογαριασμού σας έχει αλλάξει επιτυχώς."}. {"There was an error changing the password: ","Υπήρξε ένα σφάλμα κατά την αλλαγή του κωδικού πρόσβασης:"}. @@ -334,13 +358,16 @@ {"Thursday","Πέμπτη"}. {"Time delay","Χρόνος καθυστέρησης"}. {"Time","Χρόνος"}. +{"Too many CAPTCHA requests","Πάρα πολλά αιτήματα CAPTCHA"}. {"To ~s","Πρώς ~s"}. {"To","Πρώς"}. +{"Traffic rate limit is exceeded","Υπέρφορτωση"}. {"Transactions Aborted:","Αποτυχημένες συναλλαγές:"}. {"Transactions Committed:","Παραδοθείς συναλλαγές:"}. {"Transactions Logged:","Καταγραμμένες συναλλαγές:"}. {"Transactions Restarted:","Επανειλημμένες συναλλαγές:"}. {"Tuesday","Τρίτη"}. +{"Unable to generate a CAPTCHA","Αδήνατο να δημιουργηθεί CAPTCHA"}. {"Unauthorized","Χορίς Εξουσιοδότηση"}. {"Unregister a Jabber account","Καταργήστε την εγγραφή ενός λογαριασμού Jabber"}. {"Unregister","Καταργήση εγγραφής"}. @@ -354,22 +381,30 @@ {"User JID","JID Χρήστη"}. {"User Management","Διαχείριση χρηστών"}. {"Username:","Όνομα χρήστη"}. +{"Users are not allowed to register accounts so quickly","Οι χρήστες δεν επιτρέπεται να εγγραφούν λογαριασμούς τόσο γρήγορα"}. {"Users Last Activity","Τελευταία Δραστηριότητα Χρήστη"}. {"Users","Χρήστες"}. {"User","Χρήστης"}. {"Validate","Επαληθεύστε"}. {"vCard User Search","vCard Αναζήτηση χρηστών"}. {"Virtual Hosts","εικονικοί κεντρικοί υπολογιστές"}. +{"Visitors are not allowed to change their nicknames in this room","Οι επισκέπτες δεν επιτρέπεται να αλλάξουν τα ψευδώνυμα τους σε αυτή την αίθουσα"}. +{"Visitors are not allowed to send messages to all occupants","Οι επισκέπτες δεν επιτρέπεται να στείλουν μηνύματα σε όλους τους συμμετέχωντες"}. +{"Voice requests are disabled in this conference","Τα αιτήματα φωνής είναι απενεργοποιημένα, σε αυτό το συνέδριο"}. {"Voice request","Αίτημα φωνής"}. {"Wednesday","Τετάρτη"}. {"When to send the last published item","Πότε να αποσταλθεί το τελευταίο στοιχείο που δημοσιεύθηκε"}. {"Whether to allow subscriptions","Εάν επιτρέποντε συνδρομές"}. {"You can later change your password using a Jabber client.","Μπορείτε αργότερα να αλλάξετε τον κωδικό πρόσβασής σας χρησιμοποιώντας έναν πελάτη Jabber."}. +{"You have been banned from this room","Σας έχει απαγορευθεί η είσοδος σε αυτή την αίθουσα"}. +{"You must fill in field \"Nickname\" in the form","Θα πρέπει να συμπληρώσετε το πεδίο \"Ψευδώνυμο\" στη φόρμα"}. {"You need a client that supports x:data and CAPTCHA to register","Χρειάζεστε ένα x:data και CAPTCHA ικανό πελάτη για εγγραφή"}. {"You need a client that supports x:data to register the nickname","Χρειάζεστε ένα x:data ικανό πελάτη για εγγραφή με ψευδώνυμο"}. {"You need an x:data capable client to configure mod_irc settings","Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε το mod_irc"}. {"You need an x:data capable client to configure room","Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε την αίθουσα "}. {"You need an x:data capable client to search","Χρειάζεστε ένα x:data ικανό πελάτη για αναζήτηση"}. +{"Your active privacy list has denied the routing of this stanza.","Ο ενεργός κατάλογος απορρήτου, έχει αρνηθεί τη δρομολόγηση αυτής της στροφής (stanza)."}. +{"Your contact offline message queue is full. The message has been discarded.","Η μνήμη χωρίς σύνδεση μήνυματών είναι πλήρης. Το μήνυμα έχει απορριφθεί."}. {"Your Jabber account was successfully created.","Ο Jabber λογαριασμός σας δημιουργήθηκε με επιτυχία."}. {"Your Jabber account was successfully deleted.","Ο Jabber λογαριασμός σας διαγράφηκε με επιτυχία."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Τα μηνύματά σας πρως ~s είναι αποκλεισμένα. Για αποδεσμεύση, επισκεφθείτε ~s"}. diff --git a/priv/msgs/el.po b/priv/msgs/el.po index 60b47dffcff..28db8614aa3 100644 --- a/priv/msgs/el.po +++ b/priv/msgs/el.po @@ -11,50 +11,56 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Greek (ελληνικά)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Απαιτείται χρήση STARTTLS " -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Δεν προμηθεύτικε πόρος" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Αντικαταστάθικε από νέα σύνδεση" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "αποβλήθηκε " -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" +"Ο ενεργός κατάλογος απορρήτου, έχει αρνηθεί τη δρομολόγηση αυτής της στροφής " +"(stanza)." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Πληκτρολογήστε το κείμενο που βλέπετε" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Τα μηνύματά σας πρως ~s είναι αποκλεισμένα. Για αποδεσμεύση, επισκεφθείτε ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Εάν δεν βλέπετε την εικόνα CAPTCHA εδώ, επισκεφθείτε την ιστοσελίδα." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Ιστοσελίδα CAPTCHA " -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Το CAPTCHA είναι έγκυρο." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Χρήστης" @@ -63,9 +69,9 @@ msgstr "Χρήστης" msgid "Server" msgstr "Διακομιστής:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Κωδικός Πρόσβασης" @@ -82,279 +88,280 @@ msgstr "Χορίς Εξουσιοδότηση" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Διαχείριση" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Λίστες Ελέγχου Πρόσβασης" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Υποβλήθηκε" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Ακατάλληλη μορφή" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Υποβοβολή" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ακατέργαστο" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Διαγραφή επιλεγμένων" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Κανόνες Πρόσβασης" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s διαμόρφωση κανόνα πρόσβασης" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "εικονικοί κεντρικοί υπολογιστές" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Χρήστες" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Συνδεμένοι χρήστες" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Τελευταία Δραστηριότητα Χρήστη" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Περίοδος: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Περασμένο μήνα" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Πέρυσι" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Όλες οι δραστηριότητες" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Δείτε Κοινό Πίνακα" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Δείτε Ολοκληρωτικό Πίνακα" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Στατιστικές" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Δεν Βρέθηκε" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Κόμβος δεν βρέθηκε" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Προσθήκη νέου" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Κεντρικός Υπολογιστής" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Εγγεγραμμένοι Χρήστες" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Προσθήκη Χρήστη" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Χωρίς Σύνδεση Μηνύματα" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Τελευταία Δραστηριότητα" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Ποτέ" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Συνδεδεμένο" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Εγγεγραμμένοι Χρήστες:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Online Χρήστες:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Εξερχόμενες S2S Συνδέσεις:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Εξερχόμενοι S2S διακομιστές:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Εξερχόμενες S2S Συνδέσεις:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Κανένα" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Αλλαγή κωδικού" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Χρήστης" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Συνδεδεμένοι Πόροι:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Κωδικός πρόσβασης:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Αφαίρεση χρήστη" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Κανένα στοιχείο" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Κόμβοι" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Ενεργοί Κόμβοι" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Σταματημένοι Κόμβοι" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Κόμβος" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Βάση δεδομένων" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Αποθήκευση Αντιγράφου Ασφαλείας" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Παρακολουθούμενες Θύρες" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Ενημέρωση" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Επανεκκίνηση" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Σταμάτημα" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Σφάλμα RPC Κλήσης" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Πίνακες βάσης δεδομένων στο " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Όνομα" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Τύπος Αποθήκευσης" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Στοιχεία" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Μνήμη" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Σφάλμα" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Αντιγράφο Ασφαλείας του " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -365,149 +372,149 @@ msgstr "" "ODBC, θα πρέπει επίσης να κάνετε χωριστά Αντιγράφο Ασφαλείας της SQL βάση " "δεδομένων σας ." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Αποθηκεύση δυαδικού αντιγράφου ασφαλείας:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Όλλα Καλά" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Επαναφορά δυαδικού αντιγράφου ασφαλείας αμέσως:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Επαναφορά δυαδικού αντιγράφου ασφαλείας μετά την επόμενη επανεκκίνηση του " "ejabberd (απαιτεί λιγότερη μνήμη):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Αποθηκεύση αντιγράφου ασφαλείας σε αρχείο κειμένου:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Επαναφορά αντιγράφου ασφαλείας από αρχείο κειμένου αμέσως:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Εισαγωγή δεδομένων χρηστών από ένα αρχείο PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Εξαγωγή δεδομένων όλων των χρηστών του διακομιστή σε PIEFXIS αρχεία " "(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Εξαγωγή δεδομένων των χρηστών κεντρικού υπολογιστή σε PIEFXIS αρχεία " "(XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Εισαγωγή δεδομένων χρήστη από το αρχείο σειράς jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Εισαγωγή δεδομένων χρηστών από κατάλογο αρχείων σειράς jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Παρακολουθούμενες Θύρες στο " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Modules στο " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Στατιστικές του ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Ώρα CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Παραδοθείς συναλλαγές:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Αποτυχημένες συναλλαγές:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Επανειλημμένες συναλλαγές:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Καταγραμμένες συναλλαγές:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Ενημέρωση" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Σχέδιο ενημέρωσης" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Τροποποιημένα modules" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Προγράμα ενημέρωσης" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Προγράμα ενημέρωσης χαμηλού επίπεδου " -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Script ελέγχου" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Θύρα" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Πρωτόκολλο" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Επιλογές" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Εκκίνηση" @@ -800,8 +807,8 @@ msgstr "Κανόνες Πρόσβασης" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Ταυτότητα Jabber" @@ -818,31 +825,31 @@ msgstr "Αριθμός εγγεγραμμένων χρηστών" msgid "Number of online users" msgstr "Αριθμός συνδεδεμένων χρηστών" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Τελευταία σύνδεση" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Μέγεθος Καταλόγου Επαφών" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Διευθύνσεις IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Πόροι" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Διαχείριση του" -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Eνέργεια για το χρήστη" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Επεξεργασία ιδιοτήτων" @@ -852,27 +859,39 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Άρνηση πρόσβασης, λόγω τακτικής παροχής υπηρεσιών" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Διαβιβάσεις" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC module" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε το mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Εγγραφή στο mod_irc για " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -880,11 +899,11 @@ msgstr "" "Εισάγετε το όνομα χρήστη, κωδικοποιήσεις, τις θύρες και τους κωδικούς " "πρόσβασης που θέλετε να χρησιμοποιήσετε για σύνδεση με IRC διακομιστή" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC Όνομα χρήστη" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -897,7 +916,7 @@ msgstr "" "Προεπιλεγμενα αυτή η υπηρεσία χρησιμοποιεί \"~s\" κωδικοποιήση, θύρα ~p, " "κενό κωδικό πρόσβασης." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -905,35 +924,35 @@ msgstr "" "Παράδειγμα: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Παράμετροι Συνδέσης" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Είσοδος στο IRC κανάλι" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC κανάλι (μην τεθεί το πρώτο #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Διακομιστής IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Είσοδος στο κανάλι IRC εδώ." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Είσοδος στο κανάλι IRC αυτής της Jabber Ταυτότητας: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC Ρυθμίσεις" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -944,48 +963,79 @@ msgstr "" "πάρετε περισσότερα πεδία να συμπληρώσετε. Πατήστε 'Complete' για να " "αποθηκεύσετε ρυθμίσεις." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC όνομα χρήστη" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Κωδικός πρόσβασης ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Θύρα ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Κωδικοποίηση για διακομιστή ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Διακομιστής ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Μόνο οι συντονιστές μπορούν να αλλάξουν το θέμα αυτής της αίθουσας" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Μόνο οι διαχειριστές των υπηρεσιών επιτρέπεται να στείλουν υπηρεσιακά " +"μηνύματα" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Άρνηση δημιουργίας αίθουσας , λόγω τακτικής παροχής υπηρεσιών" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Αίθουσα σύνεδριασης δεν υπάρχει" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Αίθουσες σύνεδριασης" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για εγγραφή με ψευδώνυμο" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Εγγραφή με Ψευδώνυμο στο " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Πληκτρολογήστε το ψευδώνυμο που θέλετε να εγγραφείτε" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Ψευδώνυμο" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Αυτό το ψευδώνυμο είναι καταχωρημένο από άλλο πρόσωπο" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Θα πρέπει να συμπληρώσετε το πεδίο \"Ψευδώνυμο\" στη φόρμα" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC module" @@ -1013,143 +1063,202 @@ msgstr "Εγγεγραμμένοι Χρήστες" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Διαμόρφωση Αίθουσaς σύνεδριασης τροποποιηθηκε" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "συνδέετε στην αίθουσα" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "εγκαταλείπει την αίθουσα" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "έχει απαγορευθεί" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "Έχει αποβληθεί λόγω αλλαγής υπαγωγής" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "αποβλήθηκε επειδή η αίθουσα αλλάξε γιά μέλη μόνο" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "αποβλήθηκε λόγω τερματισμού συστήματος" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "είναι τώρα γνωστή ως" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " έχει θέσει το θέμα σε: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Η αίθουσα σύνεδριασης δημιουργήθηκε" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Η αίθουσα σύνεδριασης διαγράφηκε" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Η αίθουσα σύνεδριασης έχει ξεκινήσει" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Η αίθουσα σύνεδριασης έχει σταματήσει" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Δευτέρα" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Τρίτη" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Τετάρτη" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Πέμπτη" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Παρασκευή" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Σάββατο" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Κυριακή" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Ιανουάριος" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Φεβρουάριος" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Μάρτιος" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Απρίλιος" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Μάιος" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Ιούνιος" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Ιούλιος" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Αύγουστος" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Σεπτέμβριος" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Οκτώβριος" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Νοέμβριος" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Δεκέμβριος" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Διαμόρφωση Αίθουσας σύνεδριασης" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Συμετεχόντες Αίθουσας σύνεδριασης" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Υπέρφορτωση" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Δεν επιτρέπεται να στείλει προσωπικά μηνύματα για τη διάσκεψη" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Παρακαλώ, περιμένετε για λίγο πριν την αποστολή νέου αιτήματος φωνής" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Τα αιτήματα φωνής είναι απενεργοποιημένα, σε αυτό το συνέδριο" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Απέτυχε η εξαγωγή JID από την έγκριση του αιτήματος φωνής σας" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Μόνο οι συντονιστές μπορούν να εγκρίνουν τις αιτήσεις φωνής" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Ακατάλληλο είδος μηνύματος" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Δεν επιτρέπεται να στείλει προσωπικά μηνύματα του τύπου \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Παραλήπτης δεν είναι στην αίθουσα συνεδριάσεων" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Δεν επιτρέπεται η αποστολή προσωπικών μηνυμάτων" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Μόνο οι συμμετέχωντες μπορούν να στέλνουν μηνύματα στο συνέδριο" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Μόνο οι συμετεχόντες μπορούν να στείλουν ερωτήματα στη διάσκεψη" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Ερωτήματα πρώς τα μέλη της διασκέψεως δεν επιτρέπονται σε αυτήν την αίθουσα" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1157,213 +1266,288 @@ msgstr "" "Μόνο οι συντονιστές και οι συμμετέχοντες μπορούν να αλλάξουν το θέμα αυτής " "της αίθουσας" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Μόνο οι συντονιστές μπορούν να αλλάξουν το θέμα αυτής της αίθουσας" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "" +"Οι επισκέπτες δεν επιτρέπεται να στείλουν μηνύματα σε όλους τους " +"συμμετέχωντες" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "" +"Οι επισκέπτες δεν επιτρέπεται να αλλάξουν τα ψευδώνυμα τους σε αυτή την " +"αίθουσα" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Αυτό το ψευδώνυμο είναι ήδη σε χρήση από άλλον συμμετέχων" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Σας έχει απαγορευθεί η είσοδος σε αυτή την αίθουσα" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Απαιτείται αίτηση συμετοχής για είσοδο σε αυτή την αίθουσα" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Απαιτείται κωδικός πρόσβασης για είσοδο σε αυτή την αίθουσα" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Πάρα πολλά αιτήματα CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Αδήνατο να δημιουργηθεί CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Εσφαλμένος κωδικός πρόσβασης" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Aπαιτούνται προνόμια διαχειριστή" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Aπαιτούνται προνόμια συντονιστή" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Η Jabber Ταυτότητα ~s είναι άκυρη" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Ψευδώνυμο ~s δεν υπάρχει σε αυτή την αίθουσα" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Άκυρη υπαγωγή: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Άκυρος ρόλο: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Aπαιτούνται προνόμια ιδιοκτήτη" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Διαμόρφωση Αίθουσας σύνεδριασης ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Τίτλος Αίθουσας " -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Περιγραφή Αίθουσας" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Κάντε αίθουσα μόνιμη" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Κάντε την δημόσια αναζήτηση δυνατή για αυτή την αίθουσα" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Κάντε κοινό τον κατάλογο συμμετεχόντων" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Κάντε την αίθουσα προστατεύομενη με κωδικό πρόσβασης" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Μέγιστος αριθμός συμετεχόντων" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Χωρίς όριο" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Παρούσιαση πραγματικών ταυτοτήτων Jabber σε" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "συντονιστές μόνο" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "οποιοσδήποτε" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "συντονιστές μόνο" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Κάντε την αίθουσα μόνο για μέλη" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Κάντε την αίθουσα εποπτεύονομενη" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Προεπιλογη χρήστων ως συμμετέχοντες" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Επιτρέψετε στους χρήστες να αλλάζουν το θέμα" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν ιδιωτικά μηνύματα" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν ιδιωτικά μηνύματα σε" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "κανείς" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Επιτρέπστε στους χρήστες να ερωτούν άλλους χρήστες" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Επιτρέψετε στους χρήστες να αποστέλλουν προσκλήσεις" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Επιτρέψτε στους επισκέπτες να αποστέλλουν κατάσταση στις ενημερώσεις " "παρουσίας" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Επιτρέψετε στους επισκέπτες να αλλάζου ψευδώνυμο" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Επιτρέψτε στους επισκέπτες να στέλνουν αιτήματα φωνής" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ελάχιστο χρονικό διάστημα μεταξύ αιτημάτων φωνής (σε δευτερόλεπτα)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Κάντε την αίθουσα CAPTCHA προστατεύονομενη" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Εξαίρεση από τις ταυτότητες Jabber, ή CAPTCHA πρόκληση" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Ενεργοποίηση καταγραφής" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε την αίθουσα " -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Αριθμός συμετεχόντων" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "ιδιωτικό," -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Αίτημα φωνής" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Είτε εγκρίνετε ή απορρίψτε το αίτημα φωνής." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID Χρήστη" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Παραχώρηση φωνής σε αυτό το άτομο;" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s σας προσκαλεί στην αίθουσα ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "ο κωδικός πρόσβασης είναι" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Η μνήμη χωρίς σύνδεση μήνυματών είναι πλήρης. Το μήνυμα έχει απορριφθεί." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Η Σειρά Χωρίς Σύνδεση Μηνύματων τού ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Χρόνος" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Από" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Πρώς" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Πακέτο" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Χωρίς Σύνδεση Μηνύματα:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Αφαίρεση Όλων των Χωρίς Σύνδεση Μηνύματων" @@ -1371,118 +1555,130 @@ msgstr "Αφαίρεση Όλων των Χωρίς Σύνδεση Μηνύμα msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Δημοσίευση-Εγγραφή" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd module Δημοσίευσης-Εγγραφής" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Αίτηση συνδρομητή Δημοσίευσης-Εγγραφής" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Επιλέξτε αν θα εγκρίθεί η εγγραφή αυτής της οντότητας." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Ταυτότητα Κόμβου" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Διεύθυνση Συνδρομητή" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" "Επιτρέπετε σε αυτή την Jabber Ταυτότητα να εγγραφεί σε αυτό τον κόμβο " "Δημοσίευσης-Εγγραφής;" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Κοινοποιήσεις με την παράδοση φορτίων" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Κοινοποιήσεις παράδοσης" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Ειδοποιηση στους συνδρομητές όταν αλλάζει η διαμόρφωση κόμβου" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Ειδοποιηση στους συνδρομητές όταν ο κόμβος διαγράφεται" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Ειδοποιηση στους συνδρομητές όταν αφαίρούντε στοιχεία από τον κόμβο" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Μονιμη αποθήκευση στοιχείων" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Ένα φιλικό όνομα για τον κόμβο" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Μέγιστος αριθμός μόνιμων στοιχείων" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Εάν επιτρέποντε συνδρομές" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Καθορίστε το μοντέλο πρόσβασης" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Ομάδες Καταλόγου Επαφών μπορούν να εγγραφούν" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Καθορίστε το μοντέλο εκδότη" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Διαγραφή όλων των στοιχείων όταν ο σχετικός εκδότης αποσυνδέεται" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Καθορίστε τον τύπο μηνύματος συμβάντος" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Μέγιστο μέγεθος φορτίου σε bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Πότε να αποσταλθεί το τελευταίο στοιχείο που δημοσιεύθηκε" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Παράδωση κοινοποιήσεων μόνο σε διαθέσιμους χρήστες" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Οι συλλογές με την οποία είναι ένας κόμβος συνδέεται" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Η επαλήθευση της εικόνας CAPTCHA απέτυχε" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Χρειάζεστε ένα x:data και CAPTCHA ικανό πελάτη για εγγραφή" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Επιλέξτε ένα όνομα χρήστη και κωδικό πρόσβασης για να εγγραφείτε σε αυτό τον " "διακομιστή" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Ο κωδικός πρόσβασης είναι πολύ ασθενές" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Οι χρήστες δεν επιτρέπεται να εγγραφούν λογαριασμούς τόσο γρήγορα" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Ο Jabber λογαριασμός σας δημιουργήθηκε με επιτυχία." @@ -1564,8 +1760,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Μερικοί πελάτες Jabber μπορεί να αποθηκεύσουν τον κωδικό πρόσβασής σας στον " "υπολογιστή σας. Χρησιμοποιήστε αυτό το χαρακτηριστικό μόνο εάν εμπιστεύεστε " @@ -1607,60 +1803,60 @@ msgstr "" msgid "Unregister" msgstr "Καταργήση εγγραφής" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Συνδρομή" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Εκκρεμεί" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Ομάδες" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Επαληθεύστε" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Αφαίρεστε" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Καταλόγος Επαφών τού" -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Προσθήκη Jabber Ταυτότητας" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Καταλόγος Επαφών" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Κοινές Ομάδες Καταλόγων Επαφών" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Όνομα:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Περιγραφή:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Μέλη:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Εμφανίσμενες Ομάδες:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Ομάδα" @@ -1738,65 +1934,21 @@ msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Συμπληρώστε τα πεδία για να αναζητήσετε οποιαδήποτε ταιριάζοντα Jabber χρήστη" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Εξερχόμενοι S2S διακομιστές:" + #~ msgid "Delete" #~ msgstr "Διαγραφή" #~ msgid "This room is not anonymous" #~ msgstr "Η αίθουσα αυτή δεν είναι ανώνυμη" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "Ο ενεργός κατάλογος απορρήτου, έχει αρνηθεί τη δρομολόγηση αυτής της " -#~ "στροφής (stanza)." - -#~ msgid "Access denied by service policy" -#~ msgstr "Άρνηση πρόσβασης, λόγω τακτικής παροχής υπηρεσιών" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Μόνο οι διαχειριστές των υπηρεσιών επιτρέπεται να στείλουν υπηρεσιακά " -#~ "μηνύματα" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Άρνηση δημιουργίας αίθουσας , λόγω τακτικής παροχής υπηρεσιών" - -#~ msgid "Conference room does not exist" -#~ msgstr "Αίθουσα σύνεδριασης δεν υπάρχει" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Αυτό το ψευδώνυμο είναι καταχωρημένο από άλλο πρόσωπο" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Θα πρέπει να συμπληρώσετε το πεδίο \"Ψευδώνυμο\" στη φόρμα" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Υπέρφορτωση" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Αυτός ο συμμετέχων αποβλήθηκε από την αίθουσα, επειδή έστειλε ένα μήνυμα " #~ "σφάλματος" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Δεν επιτρέπεται να στείλει προσωπικά μηνύματα για τη διάσκεψη" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "" -#~ "Παρακαλώ, περιμένετε για λίγο πριν την αποστολή νέου αιτήματος φωνής" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Τα αιτήματα φωνής είναι απενεργοποιημένα, σε αυτό το συνέδριο" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Απέτυχε η εξαγωγή JID από την έγκριση του αιτήματος φωνής σας" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Μόνο οι συντονιστές μπορούν να εγκρίνουν τις αιτήσεις φωνής" - -#~ msgid "Improper message type" -#~ msgstr "Ακατάλληλο είδος μηνύματος" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1804,88 +1956,12 @@ msgstr "" #~ "Αυτός ο συμμετέχων αποβλήθηκε από την αίθουσα, επειδή έστειλε ένα μήνυμα " #~ "σφάλματος σε άλλον συμμετέχων" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Δεν επιτρέπεται να στείλει προσωπικά μηνύματα του τύπου \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Παραλήπτης δεν είναι στην αίθουσα συνεδριάσεων" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Δεν επιτρέπεται η αποστολή προσωπικών μηνυμάτων" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Μόνο οι συμμετέχωντες μπορούν να στέλνουν μηνύματα στο συνέδριο" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Μόνο οι συμετεχόντες μπορούν να στείλουν ερωτήματα στη διάσκεψη" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Ερωτήματα πρώς τα μέλη της διασκέψεως δεν επιτρέπονται σε αυτήν την " -#~ "αίθουσα" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "" -#~ "Οι επισκέπτες δεν επιτρέπεται να στείλουν μηνύματα σε όλους τους " -#~ "συμμετέχωντες" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Αυτός ο συμμετέχων αποβλήθηκε από την αίθουσα, επειδή έστειλε σφάλμα " #~ "παρουσίας " -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Οι επισκέπτες δεν επιτρέπεται να αλλάξουν τα ψευδώνυμα τους σε αυτή την " -#~ "αίθουσα" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Αυτό το ψευδώνυμο είναι ήδη σε χρήση από άλλον συμμετέχων" - -#~ msgid "You have been banned from this room" -#~ msgstr "Σας έχει απαγορευθεί η είσοδος σε αυτή την αίθουσα" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Απαιτείται αίτηση συμετοχής για είσοδο σε αυτή την αίθουσα" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Απαιτείται κωδικός πρόσβασης για είσοδο σε αυτή την αίθουσα" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Πάρα πολλά αιτήματα CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Αδήνατο να δημιουργηθεί CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Εσφαλμένος κωδικός πρόσβασης" - -#~ msgid "Administrator privileges required" -#~ msgstr "Aπαιτούνται προνόμια διαχειριστή" - -#~ msgid "Moderator privileges required" -#~ msgstr "Aπαιτούνται προνόμια συντονιστή" - -#~ msgid "Owner privileges required" -#~ msgstr "Aπαιτούνται προνόμια ιδιοκτήτη" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Η μνήμη χωρίς σύνδεση μήνυματών είναι πλήρης. Το μήνυμα έχει απορριφθεί." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Η επαλήθευση της εικόνας CAPTCHA απέτυχε" - -#~ msgid "The password is too weak" -#~ msgstr "Ο κωδικός πρόσβασης είναι πολύ ασθενές" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Οι χρήστες δεν επιτρέπεται να εγγραφούν λογαριασμούς τόσο γρήγορα" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Το CAPTCHA είναι έγκυρο." diff --git a/priv/msgs/eo.msg b/priv/msgs/eo.msg index 32509b9bb60..52a2f53a47f 100644 --- a/priv/msgs/eo.msg +++ b/priv/msgs/eo.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Agordo de atingokontrolo"}. {"Access control lists","Atingokontrol-listoj"}. {"Access Control Lists","Atingokontrol-listoj"}. +{"Access denied by service policy","Atingo rifuzita de serv-politiko"}. {"Access rules","Atingo-reguloj"}. {"Access Rules","Atingo-reguloj"}. {"Action on user","Ago je uzanto"}. @@ -11,6 +12,7 @@ {"Add User","Aldonu Uzanton"}. {"Administration","Administro"}. {"Administration of ","Mastrumado de "}. +{"Administrator privileges required","Administrantaj rajtoj bezonata"}. {"A friendly name for the node","Kromnomo por ĉi tiu nodo"}. {"All activity","Ĉiu aktiveco"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Ĉu permesi ĉi tiun Jabber ID aboni al la jena PubAbo-nodo"}. @@ -25,6 +27,7 @@ {"All Users","Ĉiuj Uzantoj"}. {"Announcements","Anoncoj"}. {"anyone","iu ajn"}. +{"A password is required to enter this room","Pasvorto estas bezonata por eniri ĉi tiun babilejon"}. {"April","Aprilo"}. {"August","Aŭgusto"}. {"Backup","Faru Sekurkopion"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Elektu ĉu permesi la abonon de ĉi tiu ento"}. {"City","Urbo"}. {"Commands","Ordonoj"}. +{"Conference room does not exist","Babilejo ne ekzistas"}. {"Configuration","Agordo"}. {"Configuration of room ~s","Agordo de babilejo ~s"}. {"Connected Resources:","Konektataj risurcoj:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Eksportu ĉiuj tabeloj kiel SQL-informmendo al dosierujo:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Eksportu datumojn de ĉiuj uzantoj en servilo al PIEFXIS dosieroj (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Eksportu datumoj de uzantoj en gastigo al PIEFXIS dosieroj (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Malsukcesis ekstrakti JID-on de via voĉ-pet-aprobo"}. {"Family Name","Lasta Nomo"}. {"February","Februaro"}. {"Fill in fields to search for any matching Jabber User","Kompletigu la formon por serĉi rekonata Jabber-uzanto"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importu uzantojn de jabberd14-uzantdosieroj"}. {"Import Users from Dir at ","Importu uzantojn de dosierujo ĉe "}. {"Import Users From jabberd14 Spool Files","Importu uzantojn de jabberd14-uzantdosieroj"}. +{"Improper message type","Malĝusta mesaĝo-tipo"}. +{"Incorrect password","Nekorekta pasvorto"}. {"Invalid affiliation: ~s","Nevalida aparteneco: ~s"}. {"Invalid role: ~s","Nevalida rolo: ~s"}. {"IP addresses","IP-adresoj"}. @@ -147,6 +154,9 @@ {"IRC Username","IRC-kaŝnomo"}. {"IRC username","IRC-uzantnomo"}. {"is now known as","nun nomiĝas"}. +{"It is not allowed to send private messages","Ne estas permesata sendi privatajn mesaĝojn"}. +{"It is not allowed to send private messages of type \"groupchat\"","Malpermesas sendi mesaĝojn de tipo \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Nur partoprenantoj rajtas sendi privatajn mesaĝojn al la babilejo"}. {"Jabber Account Registration","Ĵabber-konto registrado"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s estas nevalida"}. @@ -179,12 +189,14 @@ {"Max # of items to persist","Maksimuma kiomo de eroj en konservado"}. {"Max payload size in bytes","Maksimuma aĵo-grando je bajtoj"}. {"May","Majo"}. +{"Membership is required to enter this room","Membreco estas bezonata por eniri ĉi tiun babilejon"}. {"Members:","Membroj:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memoru vian pasvorton, aŭ skribu ĝin sur papero formetata je sekura loko. Je Ĵabber ne ekzistas aŭtomata metodo por reakiri vian pasvorton se vi forgesas ĝin."}. {"Memory","Memoro"}. {"Message body","Teksto de mesaĝo"}. {"Middle Name","Meza Nomo"}. {"Minimum interval between voice requests (in seconds)","Minimuma intervalo inter voĉ-petoj (je sekundoj)"}. +{"Moderator privileges required","Moderantaj rajtoj bezonata"}. {"moderators only","moderantoj sole"}. {"Modified modules","Ĝisdatigitaj moduloj"}. {"Module","Modulo"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Nur liveru sciigojn al konektataj uzantoj"}. {"Only moderators and participants are allowed to change the subject in this room","Nur moderigantoj kaj partoprenantoj rajtas ŝanĝi la temon en ĉi tiu babilejo"}. {"Only moderators are allowed to change the subject in this room","Nur moderigantoj rajtas ŝanĝi la temon en ĉi tiu babilejo"}. +{"Only moderators can approve voice requests","Nur moderigantoj povas aprobi voĉ-petojn"}. +{"Only occupants are allowed to send messages to the conference","Nur partoprenantoj rajtas sendi mesaĝojn al la babilejo"}. +{"Only occupants are allowed to send queries to the conference","Nur partoprenantoj rajtas sendi informmendojn al la babilejoj"}. +{"Only service administrators are allowed to send service messages","Nur servo-administrantoj rajtas sendi serv-mesaĝojn"}. {"Options","Elektebloj"}. {"Organization Name","Organiz-nomo"}. {"Organization Unit","Organiz-parto"}. {"Outgoing s2s Connections:","Elirantaj s-al-s-konektoj:"}. {"Outgoing s2s Connections","Elirantaj s-al-s-konektoj"}. -{"Outgoing s2s Servers:","Elirantaj s-al-s-serviloj"}. +{"Owner privileges required","Mastraj rajtoj bezonata"}. {"Packet","Pakaĵo"}. {"Password ~b","Pasvorto ~b"}. {"Password:","Pasvorto:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Savu erojn en konservado"}. {"Ping","Sondaĵo"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Rimarku ke ĉi tiuj elektebloj nur sekurkopias la propran Mnesia-datumbazon. Se vi uzas la ODBC-modulon, vi ankaŭ devas sekurkopii tiujn SQL-datumbazoj aparte."}. +{"Please, wait for a while before sending new voice request","Bonvolu atendi iomete antaŭ ol sendi plian voĉ-peton"}. {"Pong","Resondaĵo"}. {"Port ~b","Pordo ~b"}. {"Port","Pordo"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Public-Abonado"}. {"PubSub subscriber request","PubAbo abonpeto"}. {"Purge all items when the relevant publisher goes offline","Forigu ĉiujn erojn kiam la rilata publikanto malkonektiĝas"}. +{"Queries to the conference members are not allowed in this room","Malpermesas informmendoj al partoprenantoj en ĉi tiu babilejo"}. {"RAM and disc copy","RAM- kaj disk-kopio"}. {"RAM copy","RAM-kopio"}. {"Raw","Kruda"}. {"Really delete message of the day?","Ĉu vere forigi mesaĝon de la tago?"}. +{"Recipient is not in the conference room","Ricevanto ne ĉeestas en la babilejo "}. {"Register a Jabber account","Registru Ĵabber-konton"}. {"Registered nicknames","Registritaj uzantnomoj"}. {"Registered Users:","Registritaj uzantoj:"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Restaŭrigu sekurkopion el plata tekstdosiero tuj"}. {"Restore","Restaŭru"}. {"Room Configuration","Babilejo-agordo"}. +{"Room creation is denied by service policy","Ĉi tiu serv-politiko ne permesas babilejo-kreadon"}. {"Room description","Babilejo-priskribo"}. {"Room Occupants","Nombro de ĉeestantoj"}. {"Room title","Babilejo-nomo"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Montru ordinaran tabelon"}. {"Shut Down Service","Haltigu Servon"}. {"~s invites you to the room ~s","~s invitas vin al la babilejo ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Kelkaj Ĵabber-klientoj povas memori vian pasvorton je via komputilo. Nur uzu tiun eblon se vi fidas ke via komputilo estas sekura."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Kelkaj Ĵabber-klientoj povas memori vian pasvorton je via komputilo. Nur uzu tiun eblon se vi fidas ke via komputilo estas sekura."}. {"Specify the access model","Specifu atingo-modelon"}. {"Specify the event message type","Specifu tipo de event-mesaĝo"}. {"Specify the publisher model","Enmetu publikadan modelon"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Abonanta adreso"}. {"Subscription","Abono"}. {"Sunday","Dimanĉo"}. +{"That nickname is already in use by another occupant","Tiu kaŝnomo jam estas uzata de alia partoprenanto"}. +{"That nickname is registered by another person","Kaŝnomo estas registrita de alia persono"}. {"The CAPTCHA is valid.","La CAPTCHA ĝustas"}. +{"The CAPTCHA verification has failed","La CAPTCHA-kontrolado malsukcesis"}. {"The collections with which a node is affiliated","Aro kun kiu nodo estas filigita"}. {"the password is","la pasvorto estas"}. +{"The password is too weak","La pasvorto estas ne sufiĉe forta"}. {"The password of your Jabber account was successfully changed.","La pasvorto de via Ĵabber-konto estas sukcese ŝanĝata."}. {"There was an error changing the password: ","Estis eraro dum ŝanĝi de la pasvortro:"}. {"There was an error creating the account: ","Estis eraro dum kreado de la konto:"}. @@ -348,15 +372,18 @@ {"Time delay","Prokrasto"}. {"Time","Tempo"}. {"To","Ĝis"}. +{"Too many CAPTCHA requests","Tro multaj CAPTCHA-petoj"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Tro da malsukcesaj aŭtentprovoj (~p) de ĉi tiu IP-adreso (~s). La adreso estos malbarata je ~s UTC."}. {"Too many unacked stanzas","Tro da neagnoskitaj stancoj"}. {"To ~s","Al ~s"}. {"Total rooms","Babilejoj"}. +{"Traffic rate limit is exceeded","Trafikrapida limigo superita"}. {"Transactions Aborted:","Transakcioj nuligitaj"}. {"Transactions Committed:","Transakcioj enmetitaj"}. {"Transactions Logged:","Transakcioj protokolitaj"}. {"Transactions Restarted:","Transakcioj restartitaj"}. {"Tuesday","Mardo"}. +{"Unable to generate a CAPTCHA","Ne eblis krei CAPTCHA"}. {"Unauthorized","Nepermesita"}. {"Unregister a Jabber account","Malregistru Ĵabber-konton"}. {"Unregister","Malregistru"}. @@ -371,6 +398,7 @@ {"User JID","Uzant-JID"}. {"User Management","Uzanto-administrado"}. {"Username:","Uzantnomo"}. +{"Users are not allowed to register accounts so quickly","Ne estas permesata al uzantoj registri tiel rapide"}. {"Users Last Activity","Lasta aktiveco de uzanto"}. {"Users","Uzantoj"}. {"User ~s","Uzanto ~s"}. @@ -378,16 +406,23 @@ {"Validate","Validigu"}. {"vCard User Search","Serĉado de vizitkartoj"}. {"Virtual Hosts","Virtual-gastigoj"}. +{"Visitors are not allowed to change their nicknames in this room","Ne estas permesata al vizitantoj ŝanĝi siajn kaŝnomojn en ĉi tiu ĉambro"}. +{"Visitors are not allowed to send messages to all occupants","Vizitantoj ne rajtas sendi mesaĝojn al ĉiuj partoprenantoj"}. +{"Voice requests are disabled in this conference","Voĉ-petoj estas malebligita en jena babilejo"}. {"Voice request","Voĉ-peto"}. {"Wednesday","Merkredo"}. {"When to send the last published item","Kiam sendi la laste publicitan eron"}. {"Whether to allow subscriptions","Ĉu permesi aboni"}. {"You can later change your password using a Jabber client.","Poste vi povas ŝanĝi vian pasvorton per Ĵabber-kliento."}. +{"You have been banned from this room","Vi estas malpermesata en ĉi tiu babilejo"}. +{"You must fill in field \"Nickname\" in the form","Vi devas kompletigi la \"Kaŝnomo\" kampon"}. {"You need a client that supports x:data and CAPTCHA to register","Vi bezonas klienton subtenante x:data-funkcio kaj CAPTCHA por registri kaŝnomon"}. {"You need a client that supports x:data to register the nickname","Vi bezonas klienton subtenante x:data-funkcio por registri kaŝnomon"}. {"You need an x:data capable client to configure mod_irc settings","Vi bezonas klienton kun x:data-funkcio por agordi mod_irc"}. {"You need an x:data capable client to configure room","Vi bezonas klienton kun x:data-funkcio por agordi la babilejon"}. {"You need an x:data capable client to search","Vi bezonas klienton kun x:data-funkcio por serĉado"}. +{"Your active privacy list has denied the routing of this stanza.","Via aktiva privatec-listo malpermesas enkursigi ĉi-tiun pakaĵon"}. +{"Your contact offline message queue is full. The message has been discarded.","Mesaĝo-atendovico de la senkonekta kontakto estas plena. La mesaĝo estas forĵetita"}. {"Your Jabber account was successfully created.","Via Ĵabber-konto estis sukcese kreata."}. {"Your Jabber account was successfully deleted.","Via Ĵabber-konto estas sukcese forigita."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Viaj mesaĝoj al ~s estas blokata. Por malbloki ilin, iru al ~s"}. diff --git a/priv/msgs/eo.po b/priv/msgs/eo.po index ba0b8d91a12..fd5e5fb68ce 100644 --- a/priv/msgs/eo.po +++ b/priv/msgs/eo.po @@ -12,49 +12,53 @@ msgstr "" "X-Language: Esperanto\n" "X-Generator: Poedit 1.6.10\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Uzo de STARTTLS bezonata" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Neniu risurco donita" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Anstataŭigita je nova konekto" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "estas forpelita" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Via aktiva privatec-listo malpermesas enkursigi ĉi-tiun pakaĵon" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Tro da neagnoskitaj stancoj" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Enmetu montrita teksto" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Viaj mesaĝoj al ~s estas blokata. Por malbloki ilin, iru al ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Se vi ne vidas la CAPTCHA-imagon jene, vizitu la teksaĵ-paĝon." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA teksaĵ-paĝo" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "La CAPTCHA ĝustas" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Uzanto" @@ -63,9 +67,9 @@ msgstr "Uzanto" msgid "Server" msgstr "Servilo:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Pasvorto" @@ -82,275 +86,276 @@ msgstr "Nepermesita" msgid "ejabberd Web Admin" msgstr "ejabberd Teksaĵa Administro" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administro" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Atingokontrol-listoj" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Sendita" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Malĝusta formo" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Sendu" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Kruda" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Forigu elektata(j)n" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Atingo-reguloj" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Agordo de atingo-reguloj de ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtual-gastigoj" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Uzantoj" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Konektataj Uzantoj" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Lasta aktiveco de uzanto" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Lasta monato" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Lasta jaro" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Ĉiu aktiveco" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Montru ordinaran tabelon" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Montru integran tabelon" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistikoj" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Ne trovita" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo ne trovita" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Aldonu novan" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Gastigo" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registritaj uzantoj" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Aldonu Uzanton" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Liverontaj mesaĝoj" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Lasta aktiveco" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Neniam" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Konektata" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registritaj uzantoj:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Konektataj uzantoj:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Elirantaj s-al-s-konektoj:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Elirantaj s-al-s-serviloj" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Elirantaj s-al-s-konektoj:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nenio" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Ŝanĝu pasvorton" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Uzanto ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Konektataj risurcoj:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Pasvorto:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Forigu uzanton" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Neniu datumo" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodoj" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Funkciantaj Nodoj" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Neaktivaj Nodoj" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Nodo ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Datumbazo" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Faru Sekurkopion" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Atentataj pordoj" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Ĝisdatigu" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Restartu" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Haltigu" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduloj" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Eraro de RPC-alvoko" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Datumbaz-tabeloj je ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nomo" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Konserv-tipo" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Eroj" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoro" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Eraro" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Sekurkopio de ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -360,142 +365,142 @@ msgstr "" "Se vi uzas la ODBC-modulon, vi ankaŭ devas sekurkopii tiujn SQL-datumbazoj " "aparte." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Konservu duuman sekurkopion:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Bone" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Restaŭrigu duuman sekurkopion tuj:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "Restaŭrigu duuman sekurkopion post sekvonta ejabberd-restarto" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Skribu sekurkopion en plata tekstdosiero" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaŭrigu sekurkopion el plata tekstdosiero tuj" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importu uzanto-datumojn de PIEFXIS dosiero (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Eksportu datumojn de ĉiuj uzantoj en servilo al PIEFXIS dosieroj (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Eksportu datumoj de uzantoj en gastigo al PIEFXIS dosieroj (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Eksportu ĉiuj tabeloj kiel SQL-informmendo al dosierujo:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importu uzantojn de jabberd14-uzantdosieroj" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Atentataj pordoj je " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Moduloj je ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistikoj de ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Daŭro de funkciado" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU-tempo" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakcioj enmetitaj" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakcioj nuligitaj" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakcioj restartitaj" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakcioj protokolitaj" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Ĝisdatigu ~p-n" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Ĝisdatigo-plano" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Ĝisdatigitaj moduloj" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Ĝisdatigo-skripto" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Bazanivela ĝisdatigo-skripto" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Skript-kontrolo" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Pordo" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokolo" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modulo" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Elektebloj" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Startu" @@ -781,8 +786,8 @@ msgstr "Atingo-reguloj" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -799,31 +804,31 @@ msgstr "Nombro de registritaj uzantoj" msgid "Number of online users" msgstr "Nombro de konektataj uzantoj" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Lasta ensaluto" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Kontaktlist-grando" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP-adresoj" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Risurcoj" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Mastrumado de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Ago je uzanto" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Redaktu atributojn" @@ -835,27 +840,39 @@ msgstr "" "Tro da malsukcesaj aŭtentprovoj (~p) de ĉi tiu IP-adreso (~s). La adreso " "estos malbarata je ~s UTC." +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Ĉi tiu IP-adreso estas barata in ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Atingo rifuzita de serv-politiko" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC-transportilo" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC-modulo" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Vi bezonas klienton kun x:data-funkcio por agordi mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registraĵo en mod_irc de " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -863,11 +880,11 @@ msgstr "" "Enmetu uzantnomon,j enkodigojn, pordojn kaj pasvortojn kiujn vi volas uzi " "por konektoj al IRC-serviloj" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC-kaŝnomo" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -879,7 +896,7 @@ msgstr "" "\"enkodigo\", porto, \"pasvorto\"}'. Se ne specifita, ĉi tiu servilo uzas la " "enkodigo \"~s\", porto ~p, malplena pasvorto." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -887,35 +904,35 @@ msgstr "" "Ekzemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"sekreto\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.iutestservilo.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Konekto-parametroj" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Eniras IRC-babilejon" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC-babilejo (ne aldonu #-prefikson)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-servilo" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Eniru IRC-babilejon jen" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Eniru IRC-babilejon en ĉi Jabber-ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC agordoj" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -925,48 +942,77 @@ msgstr "" "serviloj. Elektu 'Sekvonto' por ekhavi pliajn kampojn. Elektu 'Kompletigu' " "por savi agordojn." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC-uzantnomo" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Pasvorto ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Pordo ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Enkodigo por servilo ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servilo ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Nur moderigantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Nur servo-administrantoj rajtas sendi serv-mesaĝojn" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Ĉi tiu serv-politiko ne permesas babilejo-kreadon" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Babilejo ne ekzistas" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Babilejoj" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Vi bezonas klienton subtenante x:data-funkcio por registri kaŝnomon" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Kaŝnomo-registrado je " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Enmetu kaŝnomon kiun vi volas registri" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Kaŝnomo" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Kaŝnomo estas registrita de alia persono" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Vi devas kompletigi la \"Kaŝnomo\" kampon" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC-modulo" @@ -991,354 +1037,485 @@ msgstr "Registritaj uzantnomoj" msgid "List of rooms" msgstr "Listo de babilejoj" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Agordo de babilejo ŝanĝita" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "eniras la babilejo" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "eliras la babilejo" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "estas forbarita" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "estas forpelita pro aparteneca ŝanĝo" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "estas forpelita ĉar la babilejo fariĝis sole por membroj" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "estas forpelita pro sistem-haltigo" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "nun nomiĝas" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ŝanĝis la temon al: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Babilejo kreita" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Babilejo neniigita" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Babilejo lanĉita" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Babilejo haltita" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Lundo" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Mardo" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Merkredo" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Ĵaŭdo" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Vendredo" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sabato" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Dimanĉo" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Januaro" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Februaro" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Marĉo" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Aprilo" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Majo" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Junio" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Julio" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Aŭgusto" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Septembro" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Oktobro" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Decembro" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Babilejo-agordo" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Trafikrapida limigo superita" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Nur partoprenantoj rajtas sendi privatajn mesaĝojn al la babilejo" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Bonvolu atendi iomete antaŭ ol sendi plian voĉ-peton" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Voĉ-petoj estas malebligita en jena babilejo" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Malsukcesis ekstrakti JID-on de via voĉ-pet-aprobo" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Nur moderigantoj povas aprobi voĉ-petojn" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Malĝusta mesaĝo-tipo" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Malpermesas sendi mesaĝojn de tipo \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Ricevanto ne ĉeestas en la babilejo " + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Ne estas permesata sendi privatajn mesaĝojn" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Nur partoprenantoj rajtas sendi mesaĝojn al la babilejo" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Nur partoprenantoj rajtas sendi informmendojn al la babilejoj" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Malpermesas informmendoj al partoprenantoj en ĉi tiu babilejo" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Nur moderigantoj kaj partoprenantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Nur moderigantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Vizitantoj ne rajtas sendi mesaĝojn al ĉiuj partoprenantoj" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "" +"Ne estas permesata al vizitantoj ŝanĝi siajn kaŝnomojn en ĉi tiu ĉambro" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Tiu kaŝnomo jam estas uzata de alia partoprenanto" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Vi estas malpermesata en ĉi tiu babilejo" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Membreco estas bezonata por eniri ĉi tiun babilejon" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Pasvorto estas bezonata por eniri ĉi tiun babilejon" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Tro multaj CAPTCHA-petoj" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Ne eblis krei CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Nekorekta pasvorto" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Administrantaj rajtoj bezonata" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Moderantaj rajtoj bezonata" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s estas nevalida" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Kaŝnomo ~s ne ekzistas en la babilejo" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Nevalida aparteneco: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Nevalida rolo: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Mastraj rajtoj bezonata" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Agordo de babilejo ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Babilejo-nomo" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Babilejo-priskribo" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Farigu babilejon daŭra" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Farigu babilejon publike trovebla" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Farigu partoprento-liston publika" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Farigu babilejon protektata per pasvorto" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Limigo de nombro de partoprenantoj" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Neniu limigo" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Montru verajn Jabber ID-ojn al" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderantoj sole" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "iu ajn" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "moderantoj sole" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Farigu babilejon sole por membroj" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Farigu babilejon moderigata" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Kutime farigu uzantojn kiel partpoprenantoj" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permesu uzantojn ŝanĝi la temon" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permesu uzantojn sendi privatajn mesaĝojn" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Permesu uzantojn sendi privatajn mesaĝojn al" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "neniu" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permesu uzantojn informpeti aliajn uzantojn" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permesu uzantojn sendi invitojn" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Permesu al vizitantoj sendi statmesaĝon en ĉeest-sciigoj" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Permesu al vizitantoj ŝanĝi siajn kaŝnomojn" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permesu uzantojn sendi voĉ-petojn" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimuma intervalo inter voĉ-petoj (je sekundoj)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Farigu babilejon protektata per CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Ŝaltu mesaĝo-arkivo" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Esceptu Ĵabber-identigilojn je CAPTCHA-defio" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Ŝaltu protokoladon" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Vi bezonas klienton kun x:data-funkcio por agordi la babilejon" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privata, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Voĉ-peto" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Ĉu aprobu, aŭ malaprobu la voĉ-peton." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Uzant-JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Koncedu voĉon al ĉi-persono?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s invitas vin al la babilejo ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "la pasvorto estas" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast-servo" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Mesaĝo-atendovico de la senkonekta kontakto estas plena. La mesaĝo estas " +"forĵetita" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Mesaĝo-atendovico de ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Tempo" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Ĝis" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pakaĵo" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Liverontaj mesaĝoj" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Forigu ĉiujn liverontajn mesaĝojn" @@ -1346,116 +1523,128 @@ msgstr "Forigu ĉiujn liverontajn mesaĝojn" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bajtfluo modulo" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Public-Abonado" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Public-Abonada modulo" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubAbo abonpeto" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Elektu ĉu permesi la abonon de ĉi tiu ento" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Nodo ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonanta adreso" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Ĉu permesi ĉi tiun Jabber ID aboni al la jena PubAbo-nodo" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Liveru aĵojn de event-sciigoj" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Liveru event-sciigojn" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Sciigu abonantoj kiam la agordo de la nodo ŝanĝas" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Sciigu abonantoj kiam la nodo estas forigita" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Sciigu abonantoj kiam eroj estas forigita de la nodo" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Savu erojn en konservado" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Kromnomo por ĉi tiu nodo" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maksimuma kiomo de eroj en konservado" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Ĉu permesi aboni" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Specifu atingo-modelon" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kontaktlist-grupoj kiuj rajtas aboni" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Enmetu publikadan modelon" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Forigu ĉiujn erojn kiam la rilata publikanto malkonektiĝas" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Specifu tipo de event-mesaĝo" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maksimuma aĵo-grando je bajtoj" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kiam sendi la laste publicitan eron" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Nur liveru sciigojn al konektataj uzantoj" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Aro kun kiu nodo estas filigita" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "La CAPTCHA-kontrolado malsukcesis" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Vi bezonas klienton subtenante x:data-funkcio kaj CAPTCHA por registri " "kaŝnomon" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Elektu uzantnomon kaj pasvorton por registri je ĉi tiu servilo" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "La pasvorto estas ne sufiĉe forta" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Ne estas permesata al uzantoj registri tiel rapide" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Via Ĵabber-konto estis sukcese kreata." @@ -1532,8 +1721,8 @@ msgstr "Poste vi povas ŝanĝi vian pasvorton per Ĵabber-kliento." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Kelkaj Ĵabber-klientoj povas memori vian pasvorton je via komputilo. Nur uzu " "tiun eblon se vi fidas ke via komputilo estas sekura." @@ -1572,60 +1761,60 @@ msgstr "Jena pagxo ebligas malregistri Jxabber-konton je ĉi-servilo." msgid "Unregister" msgstr "Malregistru" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Abono" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Atendanta" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupoj" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validigu" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Forigu" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktlisto de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Aldonu Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktlisto" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Komuna Kontaktlist-grupo" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nomo:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Priskribo:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membroj:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Montrataj grupoj:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " @@ -1701,60 +1890,21 @@ msgstr "Serĉ-rezultoj de " msgid "Fill in fields to search for any matching Jabber User" msgstr "Kompletigu la formon por serĉi rekonata Jabber-uzanto" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Elirantaj s-al-s-serviloj" + #~ msgid "Delete" #~ msgstr "Forigu" #~ msgid "This room is not anonymous" #~ msgstr "Ĉi tiu babilejo ne estas anonima" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Via aktiva privatec-listo malpermesas enkursigi ĉi-tiun pakaĵon" - -#~ msgid "Access denied by service policy" -#~ msgstr "Atingo rifuzita de serv-politiko" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Nur servo-administrantoj rajtas sendi serv-mesaĝojn" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Ĉi tiu serv-politiko ne permesas babilejo-kreadon" - -#~ msgid "Conference room does not exist" -#~ msgstr "Babilejo ne ekzistas" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Kaŝnomo estas registrita de alia persono" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Vi devas kompletigi la \"Kaŝnomo\" kampon" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Trafikrapida limigo superita" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Ĉi tiu partoprenanta estas forpelata de la babilejo pro sendado de erar-" #~ "mesaĝo" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Nur partoprenantoj rajtas sendi privatajn mesaĝojn al la babilejo" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Bonvolu atendi iomete antaŭ ol sendi plian voĉ-peton" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Voĉ-petoj estas malebligita en jena babilejo" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Malsukcesis ekstrakti JID-on de via voĉ-pet-aprobo" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Nur moderigantoj povas aprobi voĉ-petojn" - -#~ msgid "Improper message type" -#~ msgstr "Malĝusta mesaĝo-tipo" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1762,83 +1912,12 @@ msgstr "Kompletigu la formon por serĉi rekonata Jabber-uzanto" #~ "Ĉi tiu partoprenanto estas forpelata de la babilejo pro sendo de erar-" #~ "mesaĝo al alia partoprenanto" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Malpermesas sendi mesaĝojn de tipo \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Ricevanto ne ĉeestas en la babilejo " - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Ne estas permesata sendi privatajn mesaĝojn" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Nur partoprenantoj rajtas sendi mesaĝojn al la babilejo" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Nur partoprenantoj rajtas sendi informmendojn al la babilejoj" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Malpermesas informmendoj al partoprenantoj en ĉi tiu babilejo" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Vizitantoj ne rajtas sendi mesaĝojn al ĉiuj partoprenantoj" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Ĉi tiu partoprenanto estas forpelata de la babilejo pro sendo de erar-" #~ "ĉeesto" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Ne estas permesata al vizitantoj ŝanĝi siajn kaŝnomojn en ĉi tiu ĉambro" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Tiu kaŝnomo jam estas uzata de alia partoprenanto" - -#~ msgid "You have been banned from this room" -#~ msgstr "Vi estas malpermesata en ĉi tiu babilejo" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Membreco estas bezonata por eniri ĉi tiun babilejon" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Pasvorto estas bezonata por eniri ĉi tiun babilejon" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Tro multaj CAPTCHA-petoj" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Ne eblis krei CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Nekorekta pasvorto" - -#~ msgid "Administrator privileges required" -#~ msgstr "Administrantaj rajtoj bezonata" - -#~ msgid "Moderator privileges required" -#~ msgstr "Moderantaj rajtoj bezonata" - -#~ msgid "Owner privileges required" -#~ msgstr "Mastraj rajtoj bezonata" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Mesaĝo-atendovico de la senkonekta kontakto estas plena. La mesaĝo estas " -#~ "forĵetita" - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "La CAPTCHA-kontrolado malsukcesis" - -#~ msgid "The password is too weak" -#~ msgstr "La pasvorto estas ne sufiĉe forta" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Ne estas permesata al uzantoj registri tiel rapide" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "La aŭtomata Turingtesto estas ĝusta" diff --git a/priv/msgs/es.msg b/priv/msgs/es.msg index 8173df0e359..29bba768826 100644 --- a/priv/msgs/es.msg +++ b/priv/msgs/es.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Configuración de la Lista de Control de Acceso"}. {"Access control lists","Listas de Control de Acceso"}. {"Access Control Lists","Listas de Control de Acceso"}. +{"Access denied by service policy","Acceso denegado por la política del servicio"}. {"Access rules","Reglas de acceso"}. {"Access Rules","Reglas de Acceso"}. {"Action on user","Acción en el usuario"}. @@ -11,6 +12,7 @@ {"Add User","Añadir usuario"}. {"Administration","Administración"}. {"Administration of ","Administración de "}. +{"Administrator privileges required","Se necesita privilegios de administrador"}. {"A friendly name for the node","Un nombre sencillo para el nodo"}. {"All activity","Toda la actividad"}. {"Allow this Jabber ID to subscribe to this pubsub node?","¿Deseas permitir a este Jabber ID que se subscriba a este nodo PubSub?"}. @@ -25,6 +27,7 @@ {"All Users","Todos los usuarios"}. {"Announcements","Anuncios"}. {"anyone","cualquiera"}. +{"A password is required to enter this room","Se necesita contraseña para entrar en esta sala"}. {"April","abril"}. {"August","agosto"}. {"Backup","Guardar copia de seguridad"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Decidir si aprobar la subscripción de esta entidad."}. {"City","Ciudad"}. {"Commands","Comandos"}. +{"Conference room does not exist","La sala de conferencias no existe"}. {"Configuration","Configuración"}. {"Configuration of room ~s","Configuración para la sala ~s"}. {"Connected Resources:","Recursos conectados:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Exportar todas las tablas a un fichero SQL:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportar datos de todos los usuarios del servidor a ficheros PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportar datos de los usuarios de un dominio a ficheros PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Fallo al extraer el Jabber ID de tu aprobación de petición de voz"}. {"Family Name","Apellido"}. {"February","febrero"}. {"Fill in fields to search for any matching Jabber User","Rellena campos para buscar usuarios Jabber que concuerden"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importar usuarios del directorio spool de jabberd14:"}. {"Import Users from Dir at ","Importar usuarios desde el directorio en "}. {"Import Users From jabberd14 Spool Files","Importar usuarios de ficheros spool de jabberd-1.4"}. +{"Improper message type","Tipo de mensaje incorrecto"}. +{"Incorrect password","Contraseña incorrecta"}. {"Invalid affiliation: ~s","Afiliación no válida: ~s"}. {"Invalid role: ~s","Rol no válido: ~s"}. {"IP addresses","Direcciones IP"}. @@ -147,6 +154,9 @@ {"IRC username","Nombre de usuario en IRC"}. {"IRC Username","Nombre de usuario en IRC"}. {"is now known as","se cambia el nombre a"}. +{"It is not allowed to send private messages","No está permitido enviar mensajes privados"}. +{"It is not allowed to send private messages of type \"groupchat\"","No está permitido enviar mensajes privados del tipo \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Impedir el envio de mensajes privados a la sala"}. {"Jabber Account Registration","Registro de Cuenta Jabber"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","El Jabber ID ~s no es válido"}. @@ -179,12 +189,14 @@ {"Max # of items to persist","Máximo # de elementos que persisten"}. {"Max payload size in bytes","Máximo tamaño del contenido en bytes"}. {"May","mayo"}. +{"Membership is required to enter this room","Necesitas ser miembro de esta sala para poder entrar"}. {"Members:","Miembros:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memoriza tu contraseña, o apúntala en un papel en un lugar seguro. En Jabber no hay un método automatizado para recuperar la contraseña si la olvidas."}. {"Memory","Memoria"}. {"Message body","Cuerpo del mensaje"}. {"Middle Name","Segundo nombre"}. {"Minimum interval between voice requests (in seconds)","Intervalo mínimo entre peticiones de voz (en segundos)"}. +{"Moderator privileges required","Se necesita privilegios de moderador"}. {"moderators only","solo moderadores"}. {"Modified modules","Módulos modificados"}. {"Module","Módulo"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Solo enviar notificaciones a los usuarios disponibles"}. {"Only moderators and participants are allowed to change the subject in this room","Solo los moderadores y participantes pueden cambiar el asunto de esta sala"}. {"Only moderators are allowed to change the subject in this room","Solo los moderadores pueden cambiar el asunto de esta sala"}. +{"Only moderators can approve voice requests","Solo los moderadores pueden aprobar peticiones de voz"}. +{"Only occupants are allowed to send messages to the conference","Solo los ocupantes pueden enviar mensajes a la sala"}. +{"Only occupants are allowed to send queries to the conference","Solo los ocupantes pueden enviar solicitudes a la sala"}. +{"Only service administrators are allowed to send service messages","Solo los administradores del servicio tienen permiso para enviar mensajes de servicio"}. {"Options","Opciones"}. {"Organization Name","Nombre de la organización"}. {"Organization Unit","Unidad de la organización"}. {"Outgoing s2s Connections:","Conexiones S2S salientes:"}. {"Outgoing s2s Connections","Conexiones S2S salientes"}. -{"Outgoing s2s Servers:","Servidores S2S salientes:"}. +{"Owner privileges required","Se requieren privilegios de propietario de la sala"}. {"Packet","Paquete"}. {"Password ~b","Contraseña ~b"}. {"Password:","Contraseña:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Persistir elementos al almacenar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Ten en cuenta que estas opciones solo harán copia de seguridad de la base de datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia de seguridad de tu base de datos SQL."}. +{"Please, wait for a while before sending new voice request","Por favor, espera un poco antes de enviar otra petición de voz"}. {"Pong","Pong"}. {"Port ~b","Puerto ~b"}. {"Port","Puerto"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Servicio de Publicar-Subscribir"}. {"PubSub subscriber request","Petición de subscriptor de PubSub"}. {"Purge all items when the relevant publisher goes offline","Borra todos los elementos cuando el publicador relevante se desconecta"}. +{"Queries to the conference members are not allowed in this room","En esta sala no se permiten solicitudes a los miembros de la sala"}. {"RAM and disc copy","Copia en RAM y disco"}. {"RAM copy","Copia en RAM"}. {"Raw","Crudo"}. {"Really delete message of the day?","¿Está seguro de quere borrar el mensaje del dia?"}. +{"Recipient is not in the conference room","El receptor no está en la sala de conferencia"}. {"Register a Jabber account","Registrar una cuenta Jabber"}. {"Registered nicknames","Apodos registrados"}. {"Registered Users:","Usuarios registrados:"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Restaurar copias de seguridad de texto plano inmediatamente:"}. {"Restore","Restaurar"}. {"Room Configuration","Configuración de la sala"}. +{"Room creation is denied by service policy","Se te ha denegado crear la sala por política del servicio"}. {"Room description","Descripción de la sala"}. {"Room Occupants","Ocupantes de la sala"}. {"Room title","Título de la sala"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Mostrar Tabla Ordinaria"}. {"Shut Down Service","Detener el servicio"}. {"~s invites you to the room ~s","~s te invita a la sala ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Algunos clientes Jabber pueden recordar tu contraseña en la máquina. Usa esa opción solo si confías en que la máquina que usas es segura."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Algunos clientes Jabber pueden recordar tu contraseña en la máquina. Usa esa opción solo si confías en que la máquina que usas es segura."}. {"Specify the access model","Especifica el modelo de acceso"}. {"Specify the event message type","Especifica el tipo del mensaje de evento"}. {"Specify the publisher model","Especificar el modelo del publicante"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Dirección del subscriptor"}. {"Subscription","Subscripción"}. {"Sunday","domingo"}. +{"That nickname is already in use by another occupant","Ese apodo ya está siendo usado por otro ocupante"}. +{"That nickname is registered by another person","El apodo ya está registrado por otra persona"}. {"The CAPTCHA is valid.","El CAPTCHA es válido."}. +{"The CAPTCHA verification has failed","La verificación de CAPTCHA ha fallado"}. {"The collections with which a node is affiliated","Las colecciones a las que un nodo está afiliado"}. {"the password is","la contraseña es"}. +{"The password is too weak","La contraseña es demasiado débil"}. {"The password of your Jabber account was successfully changed.","La contraseña de tu cuenta Jabber se ha cambiado correctamente."}. {"There was an error changing the password: ","Hubo un error cambiando la contraseña."}. {"There was an error creating the account: ","Hubo uno error al crear la cuenta:"}. @@ -347,16 +371,19 @@ {"Thursday","jueves"}. {"Time delay","Retraso temporal"}. {"Time","Fecha"}. +{"Too many CAPTCHA requests","Demasiadas peticiones de CAPTCHA"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Demasiadas (~p) autenticaciones fallidas de esta dirección IP (~s). La dirección será desbloqueada en ~s UTC"}. {"Too many unacked stanzas","Demasiados mensajes sin haber reconocido recibirlos"}. {"To","Para"}. {"To ~s","A ~s"}. {"Total rooms","Salas totales"}. +{"Traffic rate limit is exceeded","Se ha exedido el límite de tráfico"}. {"Transactions Aborted:","Transacciones abortadas:"}. {"Transactions Committed:","Transacciones finalizadas:"}. {"Transactions Logged:","Transacciones registradas:"}. {"Transactions Restarted:","Transacciones reiniciadas:"}. {"Tuesday","martes"}. +{"Unable to generate a CAPTCHA","No se pudo generar un CAPTCHA"}. {"Unauthorized","No autorizado"}. {"Unregister a Jabber account","Borrar una cuenta Jabber"}. {"Unregister","Borrar"}. @@ -371,6 +398,7 @@ {"User JID","Jabber ID del usuario"}. {"User Management","Administración de usuarios"}. {"Username:","Nombre de usuario:"}. +{"Users are not allowed to register accounts so quickly","Los usuarios no tienen permitido crear cuentas con tanta rapidez"}. {"Users Last Activity","Última actividad de los usuarios"}. {"User ~s","Usuario ~s"}. {"Users","Usuarios"}. @@ -378,16 +406,23 @@ {"Validate","Validar"}. {"vCard User Search","Buscar vCard de usuario"}. {"Virtual Hosts","Dominios Virtuales"}. +{"Visitors are not allowed to change their nicknames in this room","Los visitantes no tienen permitido cambiar sus apodos en esta sala"}. +{"Visitors are not allowed to send messages to all occupants","Los visitantes no pueden enviar mensajes a todos los ocupantes"}. {"Voice request","Petición de voz"}. +{"Voice requests are disabled in this conference","Las peticiones de voz están desactivadas en esta sala"}. {"Wednesday","miércoles"}. {"When to send the last published item","Cuando enviar el último elemento publicado"}. {"Whether to allow subscriptions","Permitir subscripciones"}. {"You can later change your password using a Jabber client.","Puedes cambiar tu contraseña después, usando un cliente Jabber."}. +{"You have been banned from this room","Has sido bloqueado en esta sala"}. +{"You must fill in field \"Nickname\" in the form","Debes rellenar el campo \"Apodo\" en el formulario"}. {"You need a client that supports x:data and CAPTCHA to register","Necesitas un cliente con soporte de x:data y CAPTCHA para registrarte"}. {"You need a client that supports x:data to register the nickname","Necesitas un cliente con soporte de x:data para poder registrar el apodo"}. {"You need an x:data capable client to configure mod_irc settings","Necesitas un cliente con soporte de x:data para configurar las opciones de mod_irc"}. {"You need an x:data capable client to configure room","Necesitas un cliente con soporte de x:data para configurar la sala"}. {"You need an x:data capable client to search","Necesitas un cliente con soporte de x:data para poder buscar"}. +{"Your active privacy list has denied the routing of this stanza.","Tu lista de privacidad activa ha denegado el encío de este paquete."}. +{"Your contact offline message queue is full. The message has been discarded.","Tu cola de mensajes diferidos de contactos está llena. El mensaje se ha descartado."}. {"Your Jabber account was successfully created.","Tu cuenta Jabber se ha creado correctamente."}. {"Your Jabber account was successfully deleted.","Tu cuenta Jabber se ha borrado correctamente."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Tus mensajes a ~s están siendo bloqueados. Para desbloquearlos, visita ~s"}. diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 24eda50d4f0..43c9454bc26 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -14,50 +14,54 @@ msgstr "" "X-Language: Spanish (castellano)\n" "X-Generator: Poedit 1.6.10\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Es obligatorio usar STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "No se ha proporcionado recurso" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Reemplazado por una nueva conexión" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "ha sido expulsado" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Tu lista de privacidad activa ha denegado el encío de este paquete." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Demasiados mensajes sin haber reconocido recibirlos" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Teclea el texto que ves" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Tus mensajes a ~s están siendo bloqueados. Para desbloquearlos, visita ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Si no ves la imagen CAPTCHA aquí, visita la página web." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Página web de CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "El CAPTCHA es válido." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Usuario" @@ -66,9 +70,9 @@ msgstr "Usuario" msgid "Server" msgstr "Servidor:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Contraseña" @@ -85,275 +89,276 @@ msgstr "No autorizado" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administración" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Control de Acceso" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Enviado" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Mal formato" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Crudo" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Eliminar los seleccionados" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Reglas de Acceso" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configuración de las Regla de Acceso ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Dominios Virtuales" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuarios" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Última actividad de los usuarios" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Último mes" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Último año" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Toda la actividad" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Tabla Ordinaria" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Tabla Integral" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estadísticas" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "No encontrado" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo no encontrado" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Añadir nuevo" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Dominio" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuarios registrados" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Añadir usuario" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Mensajes diferidos" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última actividad" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuarios registrados:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Usuarios conectados:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Conexiones S2S salientes:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Servidores S2S salientes:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Conexiones S2S salientes:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Ninguno" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Cambiar contraseña" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Usuario ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contraseña:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar usuario" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Sin datos" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detenidos" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Nodo ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar copia de seguridad" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Puertos de escucha" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Detener" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Error en la llamada RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tablas de la base de datos en ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nombre" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de almacenamiento" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Error" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Copia de seguridad de ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -363,146 +368,146 @@ msgstr "" "datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia " "de seguridad de tu base de datos SQL." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Guardar copia de seguridad binaria:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Aceptar" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridad binaria:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar copia de seguridad binaria en el siguiente reinicio de ejabberd " "(requiere menos memoria que si instantánea):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Guardar copia de seguridad en texto plano:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaurar copias de seguridad de texto plano inmediatamente:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuarios desde un fichero PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos los usuarios del servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de los usuarios de un dominio a ficheros PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Exportar todas las tablas a un fichero SQL:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importar usuario de fichero spool de jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar usuarios del directorio spool de jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Puertos de escucha en " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Módulos en ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estadísticas de ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tiempo desde el inicio:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tiempo consumido de CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transacciones finalizadas:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transacciones abortadas:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transacciones reiniciadas:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transacciones registradas:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Actualizar ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan de actualización" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Módulos modificados" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de actualización" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de actualización a bajo nivel" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Comprobación de script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Puerto" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocolo" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opciones" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" @@ -789,8 +794,8 @@ msgstr "Reglas de acceso" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -807,31 +812,31 @@ msgstr "Número de usuarios registrados" msgid "Number of online users" msgstr "Número de usuarios conectados" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Última conexión" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamaño de la lista de contactos" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Direcciones IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administración de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Acción en el usuario" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propiedades" @@ -843,29 +848,41 @@ msgstr "" "Demasiadas (~p) autenticaciones fallidas de esta dirección IP (~s). La " "dirección será desbloqueada en ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Esta dirección IP está en la lista negra en ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Acceso denegado por la política del servicio" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transporte de IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Módulo de IRC para ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Necesitas un cliente con soporte de x:data para configurar las opciones de " "mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registro en mod_irc para" -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -873,11 +890,11 @@ msgstr "" "Introduce el nombre de usuario, codificaciones de carácteres, puertos y " "contraseñas que quieras usar al conectar en los servidores de IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nombre de usuario en IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -889,7 +906,7 @@ msgstr "" "'{\"servidor irc\", \"codificación\", \"puerto\", \"contrasela\"}'. Este " "servicio usa por defecto la codificación \"~s\", puerto ~p, sin contraseña." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -897,35 +914,35 @@ msgstr "" "Ejemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parámetros de conexiones" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entrar en canal IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal IRC (no pongas el # del principio)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Entrar en el canal de IRC aquí" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Entra en el canal de IRC en esta dirección Jabber: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Opciones de IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -935,49 +952,80 @@ msgstr "" "usar al conectar en los servidores de IRC. Pulsa Siguiente para conseguir " "más campos en el formulario. Pulsa Completar para guardar las opciones." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nombre de usuario en IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Contraseña ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Puerto ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificación del servidor ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Solo los administradores del servicio tienen permiso para enviar mensajes de " +"servicio" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Se te ha denegado crear la sala por política del servicio" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "La sala de conferencias no existe" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder registrar el apodo" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registro del apodo en " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Introduce el apodo que quieras registrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Apodo" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "El apodo ya está registrado por otra persona" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Debes rellenar el campo \"Apodo\" en el formulario" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" @@ -1002,356 +1050,486 @@ msgstr "Apodos registrados" msgid "List of rooms" msgstr "Lista de salas" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configuración de la sala modificada" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "entra en la sala" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "sale de la sala" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "ha sido bloqueado" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "ha sido expulsado por un cambio de su afiliación" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "ha sido expulsado porque la sala es ahora solo para miembros" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "ha sido expulsado porque el sistema se va a detener" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "se cambia el nombre a" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ha puesto el asunto: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Se ha creado la sala" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Se ha destruido la sala" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Se ha iniciado la sala" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Se ha detenido la sala" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "lunes" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "martes" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "miércoles" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "jueves" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "viernes" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "sábado" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "domingo" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "enero" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "febrero" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "marzo" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "abril" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "mayo" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "junio" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "julio" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "agosto" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "septiembre" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "octubre" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "noviembre" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "diciembre" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuración de la sala" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Ocupantes de la sala" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Se ha exedido el límite de tráfico" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Impedir el envio de mensajes privados a la sala" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Por favor, espera un poco antes de enviar otra petición de voz" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Las peticiones de voz están desactivadas en esta sala" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Fallo al extraer el Jabber ID de tu aprobación de petición de voz" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Solo los moderadores pueden aprobar peticiones de voz" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Tipo de mensaje incorrecto" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "No está permitido enviar mensajes privados del tipo \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "El receptor no está en la sala de conferencia" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "No está permitido enviar mensajes privados" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Solo los ocupantes pueden enviar mensajes a la sala" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Solo los ocupantes pueden enviar solicitudes a la sala" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "En esta sala no se permiten solicitudes a los miembros de la sala" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "" "Solo los moderadores y participantes pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Los visitantes no pueden enviar mensajes a todos los ocupantes" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Los visitantes no tienen permitido cambiar sus apodos en esta sala" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Ese apodo ya está siendo usado por otro ocupante" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Has sido bloqueado en esta sala" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Necesitas ser miembro de esta sala para poder entrar" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Se necesita contraseña para entrar en esta sala" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Demasiadas peticiones de CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "No se pudo generar un CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Contraseña incorrecta" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Se necesita privilegios de administrador" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Se necesita privilegios de moderador" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "El Jabber ID ~s no es válido" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "El apodo ~s no existe en la sala" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliación no válida: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Rol no válido: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Se requieren privilegios de propietario de la sala" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Configuración para la sala ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Título de la sala" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descripción de la sala" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Sala públicamente visible" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "La lista de participantes es pública" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Proteger la sala con contraseña" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sin límite" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Los Jabber ID reales pueden verlos" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "solo moderadores" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "cualquiera" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "solo moderadores" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Sala sólo para miembros" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Sala moderada" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Los usuarios son participantes por defecto" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permitir a los usuarios cambiar el asunto" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permitir a los usuarios enviar mensajes privados" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Permitir a los visitantes enviar mensajes privados a" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "nadie" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permitir a los usuarios consultar a otros usuarios" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permitir a los usuarios enviar invitaciones" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir a los visitantes enviar texto de estado en las actualizaciones de " "presencia" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Permitir a los visitantes cambiarse el apodo" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permitir a los visitantes enviar peticiones de voz" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalo mínimo entre peticiones de voz (en segundos)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Proteger la sala con CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Activar el almacenamiento de mensajes" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir Jabber IDs de las pruebas de CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Guardar históricos" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar la sala" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Petición de voz" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Aprueba o rechaza la petición de voz." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Jabber ID del usuario" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "¿Conceder voz a esta persona?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s te invita a la sala ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "la contraseña es" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Servicio Multicast de ejabberd" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Tu cola de mensajes diferidos de contactos está llena. El mensaje se ha " +"descartado." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Cola de mensajes diferidos de ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Fecha" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Para" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paquete" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Mensajes diferidos:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Borrar todos los mensajes diferidos" @@ -1359,115 +1537,127 @@ msgstr "Borrar todos los mensajes diferidos" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Módulo SOCKS5 Bytestreams para ejabberd" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Servicio de Publicar-Subscribir" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo de Publicar-Subscribir de ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Petición de subscriptor de PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Decidir si aprobar la subscripción de esta entidad." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Nodo ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Dirección del subscriptor" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "¿Deseas permitir a este Jabber ID que se subscriba a este nodo PubSub?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar contenidos junto con las notificaciones de eventos" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entregar notificaciones de eventos" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptores cuando cambia la configuración del nodo" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptores cuando el nodo se borra" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscriptores cuando los elementos se borran del nodo" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Persistir elementos al almacenar" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nombre sencillo para el nodo" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persisten" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permitir subscripciones" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especifica el modelo de acceso" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Grupos de contactos que pueden suscribirse" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar el modelo del publicante" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Borra todos los elementos cuando el publicador relevante se desconecta" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Especifica el tipo del mensaje de evento" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Máximo tamaño del contenido en bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Cuando enviar el último elemento publicado" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Solo enviar notificaciones a los usuarios disponibles" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Las colecciones a las que un nodo está afiliado" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "La verificación de CAPTCHA ha fallado" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Necesitas un cliente con soporte de x:data y CAPTCHA para registrarte" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Escoge un nombre de usuario y contraseña para registrarte en este servidor" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "La contraseña es demasiado débil" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Los usuarios no tienen permitido crear cuentas con tanta rapidez" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Tu cuenta Jabber se ha creado correctamente." @@ -1545,8 +1735,8 @@ msgstr "Puedes cambiar tu contraseña después, usando un cliente Jabber." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Algunos clientes Jabber pueden recordar tu contraseña en la máquina. Usa esa " "opción solo si confías en que la máquina que usas es segura." @@ -1585,60 +1775,60 @@ msgstr "" msgid "Unregister" msgstr "Borrar" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscripción" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Pendiente" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Borrar" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contactos de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Añadir Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contactos" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Grupos Compartidos" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nombre:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descripción:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Miembros:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Mostrar grupos:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " @@ -1714,62 +1904,21 @@ msgstr "Buscar resultados por " msgid "Fill in fields to search for any matching Jabber User" msgstr "Rellena campos para buscar usuarios Jabber que concuerden" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Servidores S2S salientes:" + #~ msgid "Delete" #~ msgstr "Eliminar" #~ msgid "This room is not anonymous" #~ msgstr "Sala no anónima" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Tu lista de privacidad activa ha denegado el encío de este paquete." - -#~ msgid "Access denied by service policy" -#~ msgstr "Acceso denegado por la política del servicio" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Solo los administradores del servicio tienen permiso para enviar mensajes " -#~ "de servicio" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Se te ha denegado crear la sala por política del servicio" - -#~ msgid "Conference room does not exist" -#~ msgstr "La sala de conferencias no existe" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "El apodo ya está registrado por otra persona" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Debes rellenar el campo \"Apodo\" en el formulario" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Se ha exedido el límite de tráfico" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Este participante ha sido expulsado de la sala porque envió un mensaje de " #~ "error" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Impedir el envio de mensajes privados a la sala" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Por favor, espera un poco antes de enviar otra petición de voz" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Las peticiones de voz están desactivadas en esta sala" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Fallo al extraer el Jabber ID de tu aprobación de petición de voz" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Solo los moderadores pueden aprobar peticiones de voz" - -#~ msgid "Improper message type" -#~ msgstr "Tipo de mensaje incorrecto" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1777,78 +1926,8 @@ msgstr "Rellena campos para buscar usuarios Jabber que concuerden" #~ "Este participante ha sido expulsado de la sala porque envió un mensaje de " #~ "error a otro participante" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "No está permitido enviar mensajes privados del tipo \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "El receptor no está en la sala de conferencia" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "No está permitido enviar mensajes privados" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Solo los ocupantes pueden enviar mensajes a la sala" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Solo los ocupantes pueden enviar solicitudes a la sala" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "En esta sala no se permiten solicitudes a los miembros de la sala" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Los visitantes no pueden enviar mensajes a todos los ocupantes" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Este participante ha sido expulsado de la sala porque envió una presencia " #~ "de error" - -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Los visitantes no tienen permitido cambiar sus apodos en esta sala" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Ese apodo ya está siendo usado por otro ocupante" - -#~ msgid "You have been banned from this room" -#~ msgstr "Has sido bloqueado en esta sala" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Necesitas ser miembro de esta sala para poder entrar" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Se necesita contraseña para entrar en esta sala" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Demasiadas peticiones de CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "No se pudo generar un CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Contraseña incorrecta" - -#~ msgid "Administrator privileges required" -#~ msgstr "Se necesita privilegios de administrador" - -#~ msgid "Moderator privileges required" -#~ msgstr "Se necesita privilegios de moderador" - -#~ msgid "Owner privileges required" -#~ msgstr "Se requieren privilegios de propietario de la sala" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Tu cola de mensajes diferidos de contactos está llena. El mensaje se ha " -#~ "descartado." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "La verificación de CAPTCHA ha fallado" - -#~ msgid "The password is too weak" -#~ msgstr "La contraseña es demasiado débil" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Los usuarios no tienen permitido crear cuentas con tanta rapidez" diff --git a/priv/msgs/fr.msg b/priv/msgs/fr.msg index 738abd648e3..697faf95585 100644 --- a/priv/msgs/fr.msg +++ b/priv/msgs/fr.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Configuration des droits (ACL)"}. {"Access control lists","Droits (ACL)"}. {"Access Control Lists","Droits (ACL)"}. +{"Access denied by service policy","L'accès au service est refusé"}. {"Access rules","Règles d'accès"}. {"Access Rules","Règles d'accès"}. {"Action on user","Action sur l'utilisateur"}. @@ -11,6 +12,7 @@ {"Add User","Ajouter un utilisateur"}. {"Administration","Administration"}. {"Administration of ","Administration de "}. +{"Administrator privileges required","Les droits d'administrateur sont nécessaires"}. {"A friendly name for the node","Un nom convivial pour le noeud"}. {"All activity","Toute activité"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Autoriser ce Jabber ID à s'abonner à ce nœud PubSub"}. @@ -25,6 +27,7 @@ {"All Users","Tous les utilisateurs"}. {"Announcements","Annonces"}. {"anyone","tout le monde"}. +{"A password is required to enter this room","Un mot de passe est nécessaire pour accèder à ce salon"}. {"April","Avril"}. {"August","Août"}. {"Backup Management","Gestion des sauvegardes"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Accepter cet abonnement ?"}. {"City","Ville"}. {"Commands","Commandes"}. +{"Conference room does not exist","La salle de conférence n'existe pas"}. {"Configuration","Configuration"}. {"Configuration of room ~s","Configuration pour le salon ~s"}. {"Connected Resources:","Ressources connectées:"}. @@ -136,6 +140,8 @@ {"Import users data from jabberd14 spool directory:","Importer des utilisateurs depuis un fichier spool Jabberd 1.4:"}. {"Import Users from Dir at ","Importer des utilisateurs depuis le répertoire sur "}. {"Import Users From jabberd14 Spool Files","Importer des utilisateurs depuis un fichier spool Jabberd 1.4"}. +{"Improper message type","Mauvais type de message"}. +{"Incorrect password","Mot de passe incorrect"}. {"Invalid affiliation: ~s","Affiliation invalide : ~s"}. {"Invalid role: ~s","Role invalide : ~s"}. {"IP addresses","Adresses IP"}. @@ -147,6 +153,9 @@ {"IRC username","Nom d'utilisateur IRC"}. {"IRC Username","Nom d'utilisateur IRC"}. {"is now known as","est maintenant connu comme"}. +{"It is not allowed to send private messages","L'envoi de messages privés n'est pas autorisé"}. +{"It is not allowed to send private messages of type \"groupchat\"","Il n'est pas permis d'envoyer des messages privés de type \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Il n'est pas permis d'envoyer des messages \"normaux\" à la conférence"}. {"Jabber Account Registration","Enregistrement du Compte Jabber"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Le Jabber ID ~s n'est pas valide"}. @@ -179,12 +188,14 @@ {"Max # of items to persist","Nombre maximum d'éléments à stocker"}. {"Max payload size in bytes","Taille maximum pour le contenu du message en octet"}. {"May","Mai"}. +{"Membership is required to enter this room","Vous devez être membre pour accèder à ce salon"}. {"Members:","Membres :"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Mémorisez votre mot de passe, ou écrivez-le sur un papier conservé dans un endroit secret. Dans Jabber il n'y a pas de mécanisme pour retrouver votre mot de passe si vous l'avez oublié."}. {"Memory","Mémoire"}. {"Message body","Corps du message"}. {"Middle Name","Autre nom"}. {"Minimum interval between voice requests (in seconds)","Intervalle minimum entre les demandes de 'voice' (en secondes)"}. +{"Moderator privileges required","Les droits de modérateur sont nécessaires"}. {"moderators only","modérateurs seulement"}. {"Modified modules","Modules mis à jour"}. {"Module","Module"}. @@ -229,12 +240,15 @@ {"Only deliver notifications to available users","Envoyer les notifications uniquement aux utilisateurs disponibles"}. {"Only moderators and participants are allowed to change the subject in this room","Seuls les modérateurs et les participants peuvent changer le sujet dans ce salon"}. {"Only moderators are allowed to change the subject in this room","Seuls les modérateurs peuvent changer le sujet dans ce salon"}. +{"Only occupants are allowed to send messages to the conference","Seuls les occupants peuvent envoyer des messages à la conférence"}. +{"Only occupants are allowed to send queries to the conference","Seuls les occupants sont autorisés à envoyer des requêtes à la conférence"}. +{"Only service administrators are allowed to send service messages","Seuls les administrateurs du service sont autoriser à envoyer des messages de service"}. {"Options","Options"}. {"Organization Name","Nom de l'organisation"}. {"Organization Unit","Unité de l'organisation"}. {"Outgoing s2s Connections:","Connexions s2s sortantes:"}. {"Outgoing s2s Connections","Connexions s2s sortantes"}. -{"Outgoing s2s Servers:","Serveurs s2s sortants"}. +{"Owner privileges required","Les droits de propriétaire sont nécessaires"}. {"Packet","Paquet"}. {"Password ~b","Mot de passe ~b"}. {"Password:","Mot de passe:"}. @@ -258,10 +272,12 @@ {"Publish-Subscribe","Publication-Abonnement"}. {"PubSub subscriber request","Demande d'abonnement PubSub"}. {"Purge all items when the relevant publisher goes offline","Purger tous les items lorsque publieur est hors-ligne"}. +{"Queries to the conference members are not allowed in this room","Les requêtes sur les membres de la conférence ne sont pas autorisé dans ce salon"}. {"RAM and disc copy","Copie en mémoire vive (RAM) et sur disque"}. {"RAM copy","Copie en mémoire vive (RAM)"}. {"Raw","Brut"}. {"Really delete message of the day?","Confirmer la suppression du message du jour ?"}. +{"Recipient is not in the conference room","Le destinataire n'est pas dans la conférence"}. {"Register a Jabber account","Enregistrer un compte Jabber"}. {"Registered nicknames","Pseudos enregistrés"}. {"Registered Users:","Utilisateurs enregistrés:"}. @@ -282,6 +298,7 @@ {"Restore plain text backup immediately:","Restauration immédiate d'une sauvegarde texte:"}. {"Restore","Restauration"}. {"Room Configuration","Configuration du salon"}. +{"Room creation is denied by service policy","La création de salons est interdite par le service"}. {"Room description","Description :"}. {"Room Occupants","Occupants du salon"}. {"Room title","Titre du salon"}. @@ -310,7 +327,7 @@ {"Show Ordinary Table","Montrer la table ordinaire"}. {"Shut Down Service","Arrêter le service"}. {"~s invites you to the room ~s","~s vous a invité dans la salle de discussion ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Certains clients Jabber peuvent stocker votre mot de passe sur votre ordinateur. N'utilisez cette fonctionnalité que si vous avez confiance en la sécurité de votre ordinateur."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Certains clients Jabber peuvent stocker votre mot de passe sur votre ordinateur. N'utilisez cette fonctionnalité que si vous avez confiance en la sécurité de votre ordinateur."}. {"Specify the access model","Définir le modèle d'accès"}. {"Specify the event message type","Définir le type de message d'événement"}. {"Specify the publisher model","Définir le modèle de publication"}. @@ -333,9 +350,13 @@ {"Subscriber Address","Adresse de l'abonné"}. {"Subscription","Abonnement"}. {"Sunday","Dimanche"}. +{"That nickname is already in use by another occupant","Le pseudo est déjà utilisé par un autre occupant"}. +{"That nickname is registered by another person","Le pseudo est enregistré par une autre personne"}. {"The CAPTCHA is valid.","Le CAPTCHA est valide"}. +{"The CAPTCHA verification has failed","La vérification du CAPTCHA a échoué"}. {"The collections with which a node is affiliated","Les collections avec lesquelle un nœud est affilié"}. {"the password is","le mot de passe est"}. +{"The password is too weak","Le mot de passe est trop faible"}. {"The password of your Jabber account was successfully changed.","Le mot de passe de votre compte Jabber a été changé avec succès."}. {"There was an error changing the password: ","Il y a eu une erreur en changeant le mot de passe :"}. {"There was an error creating the account: ","Il y a eu une erreur en créant le compte :"}. @@ -352,11 +373,13 @@ {"Too many unacked stanzas","Trop de stanzas sans accusé de réception (ack)"}. {"To ~s","A ~s"}. {"Total rooms","Nombre de salons"}. +{"Traffic rate limit is exceeded","La limite de trafic a été dépassée"}. {"Transactions Aborted:","Transactions annulées :"}. {"Transactions Committed:","Transactions commitées :"}. {"Transactions Logged:","Transactions journalisées :"}. {"Transactions Restarted:","Transactions redémarrées :"}. {"Tuesday","Mardi"}. +{"Unable to generate a CAPTCHA","Impossible de générer le CAPTCHA"}. {"Unauthorized","Non autorisé"}. {"Unregister a Jabber account","Effacer un compte Jabber"}. {"Unregister","Effacer"}. @@ -371,6 +394,7 @@ {"User JID","JID de l'utilisateur "}. {"User Management","Gestion des utilisateurs"}. {"Username:","Nom d'utilisateur :"}. +{"Users are not allowed to register accounts so quickly","Les utilisateurs ne sont pas autorisés à enregistrer des comptes si rapidement"}. {"Users Last Activity","Dernière activité des utilisateurs"}. {"User ~s","Utilisateur ~s"}. {"Users","Utilisateurs"}. @@ -378,16 +402,22 @@ {"Validate","Valider"}. {"vCard User Search","Recherche dans l'annnuaire"}. {"Virtual Hosts","Serveurs virtuels"}. +{"Visitors are not allowed to change their nicknames in this room","Les visiteurs ne sont pas autorisés à changer de pseudo dans ce salon"}. +{"Visitors are not allowed to send messages to all occupants","Les visiteurs ne sont pas autorisés à envoyer des messages à tout les occupants"}. {"Voice request","Demande de 'voice'"}. {"Wednesday","Mercredi"}. {"When to send the last published item","A quel moment envoyer le dernier élément publié"}. {"Whether to allow subscriptions","Autoriser l'abonnement ?"}. {"You can later change your password using a Jabber client.","Vous pouvez changer votre mot de passe plus tard en utilisant un client Jabber."}. +{"You have been banned from this room","Vous avez été exclus de ce salon"}. +{"You must fill in field \"Nickname\" in the form","Vous devez préciser le champ \"pseudo\" dans le formulaire"}. {"You need a client that supports x:data and CAPTCHA to register","Vous avez besoin d'un client prenant en charge x:data et CAPTCHA pour enregistrer un pseudo"}. {"You need a client that supports x:data to register the nickname","Vous avez besoin d'un client prenant en charge x:data pour enregistrer un pseudo"}. {"You need an x:data capable client to configure mod_irc settings","Vous avez besoin d'un client supportant x:data pour configurer le module IRC"}. {"You need an x:data capable client to configure room","Vous avez besoin d'un client supportant x:data pour configurer le salon"}. {"You need an x:data capable client to search","Vous avez besoin d'un client supportant x:data pour faire une recherche"}. +{"Your active privacy list has denied the routing of this stanza.","Votre règle de flitrage active a empêché le routage de ce stanza."}. +{"Your contact offline message queue is full. The message has been discarded.","La file d'attente de message de votre contact est pleine. Votre message a été détruit."}. {"Your Jabber account was successfully created.","Votre compte Jabber a été créé avec succès."}. {"Your Jabber account was successfully deleted.","Votre compte Jabber a été effacé avec succès."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Vos messages pour ~s sont bloqués. Pour les débloquer, veuillez visiter ~s"}. diff --git a/priv/msgs/fr.po b/priv/msgs/fr.po index 4d03a7845ba..f3a58099db9 100644 --- a/priv/msgs/fr.po +++ b/priv/msgs/fr.po @@ -15,50 +15,54 @@ msgstr "" "X-Additional-Translator: Vincent Ricard\n" "X-Generator: Poedit 1.8.4\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "L'utilisation de STARTTLS est impérative" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Aucune ressource fournie" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Remplacé par une nouvelle connexion" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "a été expulsé" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Votre règle de flitrage active a empêché le routage de ce stanza." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Trop de stanzas sans accusé de réception (ack)" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Tapez le texte que vous voyez" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Vos messages pour ~s sont bloqués. Pour les débloquer, veuillez visiter ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "SI vous ne voyez pas l'image CAPTCHA ici, visitez la page web." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Page web de CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Le CAPTCHA est valide" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Utilisateur" @@ -67,9 +71,9 @@ msgstr "Utilisateur" msgid "Server" msgstr "Serveur :" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Mot de passe" @@ -86,275 +90,276 @@ msgstr "Non autorisé" msgid "ejabberd Web Admin" msgstr "Console Web d'administration de ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administration" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Droits (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Soumis" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Mauvais format" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Soumettre" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Brut" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Suppression des éléments sélectionnés" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Règles d'accès" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configuration des règles d'accès ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Serveurs virtuels" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Utilisateurs" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Utilisateurs en ligne" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Dernière activité des utilisateurs" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Période :" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Dernier mois" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Dernière année" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Toute activité" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Montrer la table ordinaire" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Montrer la table intégralement" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiques" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nœud non trouvé" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Noeud non trouvé" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Ajouter" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Serveur" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Utilisateurs enregistrés" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Ajouter un utilisateur" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Messages en attente" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Dernière Activité" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Jamais" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "En ligne" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Utilisateurs enregistrés:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Utilisateurs connectés:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Connexions s2s sortantes:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Serveurs s2s sortants" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Connexions s2s sortantes:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Aucun" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Modifier le mot de passe" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Utilisateur ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Ressources connectées:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Mot de passe:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Supprimer l'utilisateur" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Aucune information disponible" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Noeuds" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Noeuds actifs" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Noeuds arrêtés" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Noeud ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de données" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sauvegarde" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Ports ouverts" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Mettre à jour" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Redémarrer" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Arrêter" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Erreur d'appel RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tables de base de données sur ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nom" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Type de stockage" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Éléments" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Mémoire" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Erreur" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Sauvegarde de ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -363,148 +368,148 @@ msgstr "" "Ces options sauvegardent uniquement la base de données interne Mnesia. Si " "vous utilisez le module ODBC vous devez sauvegarde votre base SQL séparément." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Sauvegarde binaire:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Restauration immédiate d'une sauvegarde binaire:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restauration de la sauvegarde binaire après redémarrage (nécessite moins de " "mémoire):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Sauvegarde texte:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restauration immédiate d'une sauvegarde texte:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" "Importer les données utilisateurs à partir d'un fichier PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exporter les données de tous les utilisateurs du serveur vers un fichier " "PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exporter les données utilisateurs d'un hôte vers un fichier PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Exporter toutes les tables en tant que requêtes SQL vers un fichier:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importer des utilisateurs depuis un fichier spool Jabberd 1.4:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importer des utilisateurs depuis un fichier spool Jabberd 1.4:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Ports ouverts sur " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Modules sur ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiques de ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Temps depuis le démarrage :" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Temps CPU :" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transactions commitées :" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transactions annulées :" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transactions redémarrées :" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transactions journalisées :" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Mise à jour de ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan de mise à jour" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Modules mis à jour" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de mise à jour" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de mise à jour de bas-niveau" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Validation du script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocole" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Options" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Démarrer" @@ -793,8 +798,8 @@ msgstr "Règles d'accès" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -811,31 +816,31 @@ msgstr "Nombre d'utilisateurs enregistrés" msgid "Number of online users" msgstr "Nombre d'utilisateurs en ligne" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Dernière connexion" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Taille de la liste de contacts" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adresses IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Ressources" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administration de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Action sur l'utilisateur" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Modifier les propriétés" @@ -847,28 +852,40 @@ msgstr "" "Trop (~p) d'authentification ont échoué pour cette adresse IP (~s). " "L'adresse sera débloquée à ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Cette adresse IP est blacklistée dans ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "L'accès au service est refusé" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Passerelle IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Module IRC ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Vous avez besoin d'un client supportant x:data pour configurer le module IRC" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Enregistrement du mod_irc pour " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -876,11 +893,11 @@ msgstr "" "Entrez le nom d'utilisateur, les encodages, les ports et mots de passe que " "vous souhaitez utiliser pour vous connecter aux serveurs IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nom d'utilisateur IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -892,7 +909,7 @@ msgstr "" "'{\"serveur irc\", \"encodage\", port, \"mot de passe\"}'. Par défaut ce " "service utilise l'encodage \"~s\", port ~p, mot de passe vide." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -900,35 +917,35 @@ msgstr "" "Exemple: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Paramètres de connexion" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Rejoindre un canal IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal IRC (ne pas insérer le premier caractère #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Serveur IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Rejoindre un canal IRC ici" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Rejoindre un canal IRC avec ce Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Configuration IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -938,50 +955,81 @@ msgstr "" "pour vous connecter aux serveurs IRC. Appuyez sur 'Suivant' pour pour avoir " "d'autres champs à remplir. Appuyez sur 'Terminer' pour sauver les paramètres." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nom d'utilisateur IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Mot de passe ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codage pour le serveur ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Serveur ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Seuls les modérateurs peuvent changer le sujet dans ce salon" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Seuls les administrateurs du service sont autoriser à envoyer des messages " +"de service" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "La création de salons est interdite par le service" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "La salle de conférence n'existe pas" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salons de discussion" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Vous avez besoin d'un client prenant en charge x:data pour enregistrer un " "pseudo" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Enregistrement d'un pseudo sur " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Entrez le pseudo que vous souhaitez enregistrer" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Pseudo" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Le pseudo est enregistré par une autre personne" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Vous devez préciser le champ \"pseudo\" dans le formulaire" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Module MUC ejabberd" @@ -1006,143 +1054,206 @@ msgstr "Pseudos enregistrés" msgid "List of rooms" msgstr "Liste des salons" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configuration du salon modifiée" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "rejoint le salon" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "quitte le salon" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "a été banni" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "a été éjecté à cause d'un changement d'autorisation" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "a été éjecté car la salle est désormais réservée aux membres" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "a été éjecté en raison de l'arrêt du système" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "est maintenant connu comme" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " a changé le sujet pour: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Le salon de discussion est créé" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Le salon de discussion est détruit" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Le salon de discussion a démarré" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Le salon de discussion est stoppé" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Lundi" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Mardi" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mercredi" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Jeudi" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Vendredi" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Samedi" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Dimanche" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Janvier" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Février" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Mars" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Avril" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Mai" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Juin" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Juillet" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Août" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Septembre" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Octobre" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Novembre" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Décembre" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuration du salon" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Occupants du salon" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "La limite de trafic a été dépassée" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Il n'est pas permis d'envoyer des messages \"normaux\" à la conférence" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Permettre aux visiteurs d'envoyer des demandes de 'voice'" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Mauvais type de message" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"Il n'est pas permis d'envoyer des messages privés de type \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Le destinataire n'est pas dans la conférence" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "L'envoi de messages privés n'est pas autorisé" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Seuls les occupants peuvent envoyer des messages à la conférence" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "" +"Seuls les occupants sont autorisés à envoyer des requêtes à la conférence" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Les requêtes sur les membres de la conférence ne sont pas autorisé dans ce " +"salon" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1150,213 +1261,287 @@ msgstr "" "Seuls les modérateurs et les participants peuvent changer le sujet dans ce " "salon" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Seuls les modérateurs peuvent changer le sujet dans ce salon" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "" +"Les visiteurs ne sont pas autorisés à envoyer des messages à tout les " +"occupants" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Les visiteurs ne sont pas autorisés à changer de pseudo dans ce salon" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Le pseudo est déjà utilisé par un autre occupant" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Vous avez été exclus de ce salon" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Vous devez être membre pour accèder à ce salon" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Un mot de passe est nécessaire pour accèder à ce salon" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Impossible de générer le CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Mot de passe incorrect" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Les droits d'administrateur sont nécessaires" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Les droits de modérateur sont nécessaires" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Le Jabber ID ~s n'est pas valide" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Le pseudo ~s n'existe pas dans ce salon" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Affiliation invalide : ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Role invalide : ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Les droits de propriétaire sont nécessaires" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Configuration pour le salon ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Titre du salon" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Description :" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Rendre le salon persistant" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Rendre le salon public" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Rendre la liste des participants publique" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Protéger le salon par mot de passe" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Nombre maximum d'occupants" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Pas de limite" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Rendre le Jabber ID réel visible pour" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "modérateurs seulement" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "tout le monde" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "modérateurs seulement" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Réserver le salon aux membres uniquement" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Rendre le salon modéré" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Les utilisateurs sont par défaut participant" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Autoriser les utilisateurs à changer le sujet" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Autoriser les utilisateurs à envoyer des messages privés" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Autoriser les visiteurs à envoyer des messages privés" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "personne" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "" "Permettre aux utilisateurs d'envoyer des requêtes aux autres utilisateurs" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permettre aux utilisateurs d'envoyer des invitations" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Autoriser les visiteurs à envoyer un message d'état avec leur présence" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Autoriser les visiteurs à changer de pseudo" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permettre aux visiteurs d'envoyer des demandes de 'voice'" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervalle minimum entre les demandes de 'voice' (en secondes)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Protéger le salon par un CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Activer l'archivage de messages" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Exempter des Jabberd IDs du test CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Activer l'archivage" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Vous avez besoin d'un client supportant x:data pour configurer le salon" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Nombre d'occupants" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privé" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Demande de 'voice'" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Approuver ou refuser la demande de 'voice'" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID de l'utilisateur " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Accorder 'voice' à cet utilisateur" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s vous a invité dans la salle de discussion ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "le mot de passe est" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multidiffusion" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Service de Multidiffusion d'ejabberd" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"La file d'attente de message de votre contact est pleine. Votre message a " +"été détruit." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s messages en file d'attente" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Heure" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "A" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paquet" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Messages en attente :" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Effacer tous les messages hors ligne" @@ -1364,118 +1549,132 @@ msgstr "Effacer tous les messages hors ligne" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publication-Abonnement" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Module Publish-Subscribe d'ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Demande d'abonnement PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Accepter cet abonnement ?" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Identifiant du nœud" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresse de l'abonné" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Autoriser ce Jabber ID à s'abonner à ce nœud PubSub" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Inclure le contenu du message avec la notification" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Envoyer les notifications d'événement" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Avertir les abonnés lorsque la configuration du nœud change" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Avertir les abonnés lorsque le nœud est supprimé" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Avertir les abonnés lorsque des éléments sont supprimés sur le nœud" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Stockage persistant des éléments" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nom convivial pour le noeud" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Nombre maximum d'éléments à stocker" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Autoriser l'abonnement ?" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Définir le modèle d'accès" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Groupes de liste de contact autorisés à s'abonner" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Définir le modèle de publication" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Purger tous les items lorsque publieur est hors-ligne" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Définir le type de message d'événement" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Taille maximum pour le contenu du message en octet" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "A quel moment envoyer le dernier élément publié" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Envoyer les notifications uniquement aux utilisateurs disponibles" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Les collections avec lesquelle un nœud est affilié" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "La vérification du CAPTCHA a échoué" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Vous avez besoin d'un client prenant en charge x:data et CAPTCHA pour " "enregistrer un pseudo" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Choisissez un nom d'utilisateur et un mot de passe pour s'enregistrer sur ce " "serveur" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Le mot de passe est trop faible" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "" +"Les utilisateurs ne sont pas autorisés à enregistrer des comptes si " +"rapidement" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Votre compte Jabber a été créé avec succès." @@ -1556,8 +1755,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Certains clients Jabber peuvent stocker votre mot de passe sur votre " "ordinateur. N'utilisez cette fonctionnalité que si vous avez confiance en la " @@ -1597,60 +1796,60 @@ msgstr "Cette page permet d'effacer un compte Jabber sur ce serveur Jabber." msgid "Unregister" msgstr "Effacer" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Abonnement" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "En suspens" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Groupes" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Valider" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Enlever" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Liste de contact de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Ajouter un Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Liste de contacts" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Groupes de liste de contacts partagée" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nom :" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Description :" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membres :" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Groupes affichés :" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Groupe " @@ -1727,50 +1926,20 @@ msgstr "Résultats de recherche pour " msgid "Fill in fields to search for any matching Jabber User" msgstr "Remplissez les champs pour rechercher un utilisateur Jabber" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Serveurs s2s sortants" + #~ msgid "Delete" #~ msgstr "Supprimer" #~ msgid "This room is not anonymous" #~ msgstr "Ce salon n'est pas anonyme" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Votre règle de flitrage active a empêché le routage de ce stanza." - -#~ msgid "Access denied by service policy" -#~ msgstr "L'accès au service est refusé" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Seuls les administrateurs du service sont autoriser à envoyer des " -#~ "messages de service" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "La création de salons est interdite par le service" - -#~ msgid "Conference room does not exist" -#~ msgstr "La salle de conférence n'existe pas" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Le pseudo est enregistré par une autre personne" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Vous devez préciser le champ \"pseudo\" dans le formulaire" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "La limite de trafic a été dépassée" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Ce participant est expulsé du salon pour avoir envoyé un message erronée" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "" -#~ "Il n'est pas permis d'envoyer des messages \"normaux\" à la conférence" - -#~ msgid "Improper message type" -#~ msgstr "Mauvais type de message" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1778,87 +1947,11 @@ msgstr "Remplissez les champs pour rechercher un utilisateur Jabber" #~ "Ce participant est expulsé du salon pour avoir envoyé un message erronée " #~ "à un autre participant" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Il n'est pas permis d'envoyer des messages privés de type \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Le destinataire n'est pas dans la conférence" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "L'envoi de messages privés n'est pas autorisé" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Seuls les occupants peuvent envoyer des messages à la conférence" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "" -#~ "Seuls les occupants sont autorisés à envoyer des requêtes à la conférence" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Les requêtes sur les membres de la conférence ne sont pas autorisé dans " -#~ "ce salon" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "" -#~ "Les visiteurs ne sont pas autorisés à envoyer des messages à tout les " -#~ "occupants" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Ce participant est expulsé du salon pour avoir envoyé une présence erronée" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Les visiteurs ne sont pas autorisés à changer de pseudo dans ce salon" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Le pseudo est déjà utilisé par un autre occupant" - -#~ msgid "You have been banned from this room" -#~ msgstr "Vous avez été exclus de ce salon" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Vous devez être membre pour accèder à ce salon" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Un mot de passe est nécessaire pour accèder à ce salon" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Impossible de générer le CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Mot de passe incorrect" - -#~ msgid "Administrator privileges required" -#~ msgstr "Les droits d'administrateur sont nécessaires" - -#~ msgid "Moderator privileges required" -#~ msgstr "Les droits de modérateur sont nécessaires" - -#~ msgid "Owner privileges required" -#~ msgstr "Les droits de propriétaire sont nécessaires" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "La file d'attente de message de votre contact est pleine. Votre message a " -#~ "été détruit." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "La vérification du CAPTCHA a échoué" - -#~ msgid "The password is too weak" -#~ msgstr "Le mot de passe est trop faible" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "" -#~ "Les utilisateurs ne sont pas autorisés à enregistrer des comptes si " -#~ "rapidement" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Le CAPTCHA est valide" diff --git a/priv/msgs/gl.msg b/priv/msgs/gl.msg index ae5ece73012..b3e364d5d1e 100644 --- a/priv/msgs/gl.msg +++ b/priv/msgs/gl.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Configuración da Lista de Control de Acceso"}. {"Access control lists","Listas de Control de Acceso"}. {"Access Control Lists","Listas de Control de Acceso"}. +{"Access denied by service policy","Acceso denegado pola política do servizo"}. {"Access rules","Regras de acceso"}. {"Access Rules","Regras de Acceso"}. {"Action on user","Acción no usuario"}. @@ -11,6 +12,7 @@ {"Add User","Engadir usuario"}. {"Administration","Administración"}. {"Administration of ","Administración de "}. +{"Administrator privileges required","Necesítase privilexios de administrador"}. {"A friendly name for the node","Un nome para o nodo"}. {"All activity","Toda a actividade"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Desexas permitir a este JabberID que se subscriba a este nodo PubSub?"}. @@ -23,6 +25,7 @@ {"All Users","Todos os usuarios"}. {"Announcements","Anuncios"}. {"anyone","calquera"}. +{"A password is required to enter this room","Necesítase contrasinal para entrar nesta sala"}. {"April","Abril"}. {"August","Agosto"}. {"Backup","Gardar copia de seguridade"}. @@ -40,6 +43,7 @@ {"Choose whether to approve this entity's subscription.","Decidir se aprobar a subscripción desta entidade."}. {"City","Cidade"}. {"Commands","Comandos"}. +{"Conference room does not exist","A sala de conferencias non existe"}. {"Configuration","Configuración"}. {"Configuration of room ~s","Configuración para a sala ~s"}. {"Connected Resources:","Recursos conectados:"}. @@ -118,6 +122,8 @@ {"Import users data from jabberd14 spool directory:","Importar usuarios do directorio spool de jabberd14:"}. {"Import Users from Dir at ","Importar usuarios desde o directorio en "}. {"Import Users From jabberd14 Spool Files","Importar usuarios de ficheiros spool de jabberd-1.4"}. +{"Improper message type","Tipo de mensaxe incorrecta"}. +{"Incorrect password","Contrasinal incorrecta"}. {"Invalid affiliation: ~s","Afiliación non válida: ~s"}. {"Invalid role: ~s","Rol non válido: ~s"}. {"IP addresses","Direccións IP"}. @@ -129,6 +135,9 @@ {"IRC username","Nome de usuario en IRC"}. {"IRC Username","Nome de usuario en IRC"}. {"is now known as","cámbiase o nome a"}. +{"It is not allowed to send private messages","Non está permitido enviar mensaxes privadas"}. +{"It is not allowed to send private messages of type \"groupchat\"","Non está permitido enviar mensaxes privadas do tipo \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Impedir o envio de mensaxes privadas á sala"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","O Jabber ID ~s non é válido"}. {"January","Xaneiro"}. @@ -159,10 +168,12 @@ {"Max # of items to persist","Máximo # de elementos que persisten"}. {"Max payload size in bytes","Máximo tamaño do payload en bytes"}. {"May","Maio"}. +{"Membership is required to enter this room","Necesitas ser membro desta sala para poder entrar"}. {"Members:","Membros:"}. {"Memory","Memoria"}. {"Message body","Corpo da mensaxe"}. {"Middle Name","Segundo nome"}. +{"Moderator privileges required","Necesítase privilexios de moderador"}. {"moderators only","só moderadores"}. {"Modified modules","Módulos Modificados"}. {"Module","Módulo"}. @@ -200,12 +211,15 @@ {"Only deliver notifications to available users","Só enviar notificacións aos usuarios dispoñibles"}. {"Only moderators and participants are allowed to change the subject in this room","Só os moderadores e os participantes se lles permite cambiar o tema nesta sala"}. {"Only moderators are allowed to change the subject in this room","Só os moderadores están autorizados a cambiar o tema nesta sala"}. +{"Only occupants are allowed to send messages to the conference","Só os ocupantes poden enviar mensaxes á sala"}. +{"Only occupants are allowed to send queries to the conference","Só os ocupantes poden enviar solicitudes á sala"}. +{"Only service administrators are allowed to send service messages","Só os administradores do servizo teñen permiso para enviar mensaxes de servizo"}. {"Options","Opcións"}. {"Organization Name","Nome da organización"}. {"Organization Unit","Unidade da organización"}. {"Outgoing s2s Connections:","Conexións S2S saíntes:"}. {"Outgoing s2s Connections","Conexións S2S saíntes"}. -{"Outgoing s2s Servers:","Servidores S2S saíntes:"}. +{"Owner privileges required","Requírense privilexios de propietario da sala"}. {"Packet","Paquete"}. {"Password ~b","Contrasinal ~b"}. {"Password:","Contrasinal:"}. @@ -226,10 +240,12 @@ {"Protocol","Protocolo"}. {"Publish-Subscribe","Publicar-Subscribir"}. {"PubSub subscriber request","Petición de subscriptor de PubSub"}. +{"Queries to the conference members are not allowed in this room","Nesta sala non se permiten solicitudes aos membros da sala"}. {"RAM and disc copy","Copia en RAM e disco"}. {"RAM copy","Copia en RAM"}. {"Raw","Cru"}. {"Really delete message of the day?","Está seguro de quere borrar a mensaxe do dia?"}. +{"Recipient is not in the conference room","O receptor non está na sala de conferencia"}. {"Registered Users:","Usuarios rexistrados:"}. {"Registered Users","Usuarios rexistrados"}. {"Registration in mod_irc for ","Rexistro en mod_irc para"}. @@ -247,6 +263,7 @@ {"Restore plain text backup immediately:","Restaurar copias de seguridade de texto plano inmediatamente:"}. {"Restore","Restaurar"}. {"Room Configuration","Configuración da Sala"}. +{"Room creation is denied by service policy","Denegar crear a sala por política do servizo"}. {"Room description","Descrición da sala"}. {"Room Occupants","Ocupantes da sala"}. {"Room title","Título da sala"}. @@ -295,6 +312,8 @@ {"Subscriber Address","Dirección do subscriptor"}. {"Subscription","Subscripción"}. {"Sunday","Domingo"}. +{"That nickname is already in use by another occupant","Ese alcume que xa está en uso por outro ocupante"}. +{"That nickname is registered by another person","O alcume xa está rexistrado por outra persoa"}. {"The CAPTCHA is valid.","O CAPTCHA é válido."}. {"The collections with which a node is affiliated","As coleccións coas que un nodo está afiliado"}. {"the password is","a contrasinal é"}. @@ -303,6 +322,7 @@ {"Time delay","Atraso temporal"}. {"To","Para"}. {"To ~s","A ~s"}. +{"Traffic rate limit is exceeded","Hase exedido o límite de tráfico"}. {"Transactions Aborted:","Transaccións abortadas:"}. {"Transactions Committed:","Transaccións finalizadas:"}. {"Transactions Logged:","Transaccións rexistradas:"}. @@ -317,16 +337,22 @@ {"Uptime:","Tempo desde o inicio:"}. {"Use of STARTTLS required","É obrigatorio usar STARTTLS"}. {"User Management","Administración de usuarios"}. +{"Users are not allowed to register accounts so quickly","Os usuarios non están autorizados a rexistrar contas con tanta rapidez"}. {"Users Last Activity","Última actividade dos usuarios"}. {"Users","Usuarios"}. {"User","Usuario"}. {"Validate","Validar"}. {"vCard User Search","Procura de usuario en vCard"}. {"Virtual Hosts","Hosts Virtuais"}. +{"Visitors are not allowed to change their nicknames in this room","Os visitantes non están autorizados a cambiar os seus That alcumes nesta sala"}. +{"Visitors are not allowed to send messages to all occupants","Os visitantes non poden enviar mensaxes a todos os ocupantes"}. {"Wednesday","Mércores"}. {"When to send the last published item","Cando enviar o último elemento publicado"}. {"Whether to allow subscriptions","Permitir subscripciones"}. +{"You have been banned from this room","fuches bloqueado nesta sala"}. +{"You must fill in field \"Nickname\" in the form","Debes encher o campo \"Alcumo\" no formulario"}. {"You need an x:data capable client to configure mod_irc settings","Necesitas un cliente con soporte de x:data para configurar as opcións de mod_irc"}. {"You need an x:data capable client to configure room","Necesitas un cliente con soporte de x:data para configurar a sala"}. {"You need an x:data capable client to search","Necesitas un cliente con soporte de x:data para poder buscar"}. +{"Your contact offline message queue is full. The message has been discarded.","A túa cola de mensaxes diferidas de contactos está chea. A mensaxe descartouse."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","As súas mensaxes a ~s encóntranse bloqueadas. Para desbloquear, visite ~s"}. diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index 50b23c1b348..c5cfabc003b 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -7,50 +7,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Galician (galego)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "É obrigatorio usar STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Non se proporcionou recurso" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Substituído por unha nova conexión" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "foi expulsado" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Introduza o texto que ves" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "As súas mensaxes a ~s encóntranse bloqueadas. Para desbloquear, visite ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é válido." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Usuario" @@ -59,9 +63,9 @@ msgstr "Usuario" msgid "Server" msgstr "Servidor ~b" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Contrasinal" @@ -78,279 +82,280 @@ msgstr "Non autorizado" msgid "ejabberd Web Admin" msgstr "Ejabberd Administrador Web" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administración" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Control de Acceso" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Enviado" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Mal formato" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Cru" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Eliminar os seleccionados" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Regras de Acceso" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configuración das Regra de Acceso ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Hosts Virtuais" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuarios" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuarios conectados" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Última actividade dos usuarios" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Último mes" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Último ano" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Toda a actividade" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Táboa Ordinaria" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Táboa Integral" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Non atopado" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo non atopado" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Engadir novo" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuarios rexistrados" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Engadir usuario" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Mensaxes diferidas" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuarios rexistrados:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Usuarios conectados:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Conexións S2S saíntes:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Servidores S2S saíntes:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Conexións S2S saíntes:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Ningún" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Cambiar contrasinal" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Usuario " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Contrasinal:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar usuario" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Sen datos" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos funcionando" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos detidos" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nodo " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de datos" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Gardar copia de seguridade" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Portos de escoita" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Deter" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Erro na chamada RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Táboas da base de datos en " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de almacenamiento" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Erro" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Copia de seguridade de " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -360,149 +365,149 @@ msgstr "" "Mnesia. Se está a utilizar o módulo de ODBC, tamén necesita unha copia de " "seguridade da súa base de datos SQL por separado." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Gardar copia de seguridade binaria:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Aceptar" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar inmediatamente copia de seguridade binaria:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar copia de seguridade binaria no seguinte reinicio de ejabberd " "(require menos memoria que se instantánea):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Gardar copia de seguridade en texto plano:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaurar copias de seguridade de texto plano inmediatamente:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuarios desde un fichero PIEFXIS" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importar usuario de fichero spool de jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar usuarios do directorio spool de jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Portos de escoita en " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Módulos en " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estatísticas de ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tempo desde o inicio:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tempo consumido de CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaccións finalizadas:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaccións abortadas:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaccións reiniciadas:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaccións rexistradas:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan de actualización" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Módulos Modificados" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de actualización" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de actualización a baixo nivel" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Comprobación de script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porto" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocolo" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opcións" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" @@ -788,8 +793,8 @@ msgstr "Regras de acceso" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -806,31 +811,31 @@ msgstr "Número de usuarios rexistrados" msgid "Number of online users" msgstr "Número de usuarios conectados" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Última conexión" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamaño da lista de contactos" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Direccións IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administración de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Acción no usuario" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propiedades" @@ -840,29 +845,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Acceso denegado pola política do servizo" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transporte IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Módulo de IRC para ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Necesitas un cliente con soporte de x:data para configurar as opcións de " "mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Rexistro en mod_irc para" -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -870,11 +887,11 @@ msgstr "" "Introduza o nome de usuario, codificaciones de carácter, portos e " "contrasinal que pretende utilizar a conectar a servidores de IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nome de usuario en IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -886,7 +903,7 @@ msgstr "" "\"codificación\", \"porto\", \"contrasinal\"}'. Este servizo utiliza por " "defecto a codificación \"~s\", porto ~p, sen contrasinal." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -894,35 +911,35 @@ msgstr "" "Exemplo: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parámetros de conexiones" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entrar en canle IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canle de IRC (non poñer o primeiro #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Únete á canle de IRC aquí." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Únete á canle de IRC con este IDE de Jabber: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC axustes" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -932,50 +949,81 @@ msgstr "" "ao conectar nos servidores de IRC. Presione 'Siguiente' para obtener más " "campos para rellenar Presione 'completo' para guardar axustes." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nome de usuario en IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Contrasinal ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Porto ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificación de servidor ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Só os moderadores están autorizados a cambiar o tema nesta sala" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Só os administradores do servizo teñen permiso para enviar mensaxes de " +"servizo" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Denegar crear a sala por política do servizo" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "A sala de conferencias non existe" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Rexistro do alcume en " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Introduce o alcume que queiras rexistrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Alcume" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "O alcume xa está rexistrado por outra persoa" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Debes encher o campo \"Alcumo\" no formulario" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" @@ -1003,147 +1051,206 @@ msgstr "Usuarios rexistrados" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configuración de la sala modificada" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "entra en la sala" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "sae da sala" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "foi bloqueado" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "foi expulsado debido a un cambio de afiliación" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "foi expulsado, porque a sala cambiouse a só-membros" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "foi expulsado por mor dun sistema de peche" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "cámbiase o nome a" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " puxo o asunto: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "Salas de charla" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Salas de charla" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Salas de charla" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Salas de charla" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Luns" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Martes" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mércores" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Xoves" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Venres" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sábado" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Domingo" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Xaneiro" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Febreiro" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Marzo" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Maio" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Xuño" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Xullo" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Setembro" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Outubro" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Decembro" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuración da Sala" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Ocupantes da sala" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Hase exedido o límite de tráfico" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Impedir o envio de mensaxes privadas á sala" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Permitir aos usuarios enviar invitacións" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Tipo de mensaxe incorrecta" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Non está permitido enviar mensaxes privadas do tipo \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "O receptor non está na sala de conferencia" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Non está permitido enviar mensaxes privadas" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Só os ocupantes poden enviar mensaxes á sala" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Só os ocupantes poden enviar solicitudes á sala" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Nesta sala non se permiten solicitudes aos membros da sala" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1151,215 +1258,289 @@ msgstr "" "Só os moderadores e os participantes se lles permite cambiar o tema nesta " "sala" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Só os moderadores están autorizados a cambiar o tema nesta sala" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Os visitantes non poden enviar mensaxes a todos os ocupantes" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "" +"Os visitantes non están autorizados a cambiar os seus That alcumes nesta sala" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Ese alcume que xa está en uso por outro ocupante" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "fuches bloqueado nesta sala" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Necesitas ser membro desta sala para poder entrar" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Necesítase contrasinal para entrar nesta sala" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +#, fuzzy +msgid "Unable to generate a CAPTCHA" +msgstr "Non se pode xerar un CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Contrasinal incorrecta" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Necesítase privilexios de administrador" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Necesítase privilexios de moderador" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s non é válido" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "O alcume ~s non existe na sala" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliación non válida: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Rol non válido: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Requírense privilexios de propietario da sala" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Configuración para a sala ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descrición da sala" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Sala permanente" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Sala publicamente visible" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "A lista de participantes é pública" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Protexer a sala con contrasinal" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número máximo de ocupantes" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sen límite" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Os Jabber ID reais poden velos" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "só moderadores" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "calquera" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "só moderadores" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Sala só para membros" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Facer sala moderada" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Os usuarios son participantes por defecto" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permitir aos usuarios cambiar o asunto" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permitir aos usuarios enviar mensaxes privadas" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir aos usuarios enviar mensaxes privadas" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permitir aos usuarios consultar a outros usuarios" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permitir aos usuarios enviar invitacións" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permitir aos visitantes enviar texto de estado nas actualizacións depresenza" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Permitir aos visitantes cambiarse o alcume" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir aos usuarios enviar invitacións" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Protexer a sala con CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Gardar históricos" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar a sala" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Usuario " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s invítache á sala ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "a contrasinal é" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"A túa cola de mensaxes diferidas de contactos está chea. A mensaxe " +"descartouse." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Cola de mensaxes diferidas de ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Data" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Para" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paquete" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Mensaxes sen conexión:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Borrar Todas as Mensaxes Sen conexión" @@ -1367,118 +1548,132 @@ msgstr "Borrar Todas as Mensaxes Sen conexión" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publicar-Subscribir" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo de Publicar-Subscribir de ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Petición de subscriptor de PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Decidir se aprobar a subscripción desta entidade." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Nodo IDE" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Dirección do subscriptor" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Desexas permitir a este JabberID que se subscriba a este nodo PubSub?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads xunto coas notificacións de eventos" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entregar notificacións de eventos" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscriptores cando cambia a configuración do nodo" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscriptores cando o nodo bórrase" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscriptores cando os elementos bórranse do nodo" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Persistir elementos ao almacenar" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nome para o nodo" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persisten" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permitir subscripciones" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especifica o modelo de acceso" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Lista de grupos autorizados a subscribir" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar o modelo do publicante" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Especifica o modelo de acceso" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Máximo tamaño do payload en bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Cando enviar o último elemento publicado" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Só enviar notificacións aos usuarios dispoñibles" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "As coleccións coas que un nodo está afiliado" -#: mod_register.erl:250 +#: mod_register.erl:209 +#, fuzzy +msgid "The CAPTCHA verification has failed" +msgstr "O CAPTCHA é válido." + +#: mod_register.erl:253 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Escolle un nome de usuario e contrasinal para rexistrarche neste servidor" +#: mod_register.erl:373 mod_register.erl:421 +#, fuzzy +msgid "The password is too weak" +msgstr "a contrasinal é" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Os usuarios non están autorizados a rexistrar contas con tanta rapidez" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1552,8 +1747,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1591,60 +1786,60 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscripción" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Borrar" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contactos de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Engadir ID Jabber" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contactos" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Grupos Compartidos" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nome:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descrición:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membros:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Mostrar grupos:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " @@ -1720,46 +1915,20 @@ msgstr "Buscar resultados por " msgid "Fill in fields to search for any matching Jabber User" msgstr "Rechea campos para buscar usuarios Jabber que concuerden" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Servidores S2S saíntes:" + #~ msgid "Delete" #~ msgstr "Eliminar" #~ msgid "This room is not anonymous" #~ msgstr "Sala non anónima" -#~ msgid "Access denied by service policy" -#~ msgstr "Acceso denegado pola política do servizo" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Só os administradores do servizo teñen permiso para enviar mensaxes de " -#~ "servizo" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Denegar crear a sala por política do servizo" - -#~ msgid "Conference room does not exist" -#~ msgstr "A sala de conferencias non existe" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "O alcume xa está rexistrado por outra persoa" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Debes encher o campo \"Alcumo\" no formulario" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Hase exedido o límite de tráfico" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Este participante é expulsado da sala, xa que enviou unha mensaxe de erro" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Impedir o envio de mensaxes privadas á sala" - -#~ msgid "Improper message type" -#~ msgstr "Tipo de mensaxe incorrecta" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1767,81 +1936,12 @@ msgstr "Rechea campos para buscar usuarios Jabber que concuerden" #~ "Este participante é expulsado da sala, porque el enviou unha mensaxe de " #~ "erro a outro participante" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Non está permitido enviar mensaxes privadas do tipo \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "O receptor non está na sala de conferencia" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Non está permitido enviar mensaxes privadas" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Só os ocupantes poden enviar mensaxes á sala" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Só os ocupantes poden enviar solicitudes á sala" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Nesta sala non se permiten solicitudes aos membros da sala" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Os visitantes non poden enviar mensaxes a todos os ocupantes" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Este participante é expulsado da sala, porque el enviou un erro de " #~ "presenza" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Os visitantes non están autorizados a cambiar os seus That alcumes nesta " -#~ "sala" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Ese alcume que xa está en uso por outro ocupante" - -#~ msgid "You have been banned from this room" -#~ msgstr "fuches bloqueado nesta sala" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Necesitas ser membro desta sala para poder entrar" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Necesítase contrasinal para entrar nesta sala" - -#, fuzzy -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Non se pode xerar un CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Contrasinal incorrecta" - -#~ msgid "Administrator privileges required" -#~ msgstr "Necesítase privilexios de administrador" - -#~ msgid "Moderator privileges required" -#~ msgstr "Necesítase privilexios de moderador" - -#~ msgid "Owner privileges required" -#~ msgstr "Requírense privilexios de propietario da sala" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "A túa cola de mensaxes diferidas de contactos está chea. A mensaxe " -#~ "descartouse." - -#, fuzzy -#~ msgid "The password is too weak" -#~ msgstr "a contrasinal é" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "" -#~ "Os usuarios non están autorizados a rexistrar contas con tanta rapidez" - #, fuzzy #~ msgid "CAPTCHA test failed" #~ msgstr "O CAPTCHA é válido." diff --git a/priv/msgs/he.msg b/priv/msgs/he.msg index ae1946cf9c4..286fdd4fe00 100644 --- a/priv/msgs/he.msg +++ b/priv/msgs/he.msg @@ -1,30 +1,34 @@ %% -*- coding: latin-1 -*- +{"Accept","קבל"}. {"Access Configuration","תצורת גישה"}. {"Access Control List Configuration","תצורת רשימת בקרת גישה"}. {"Access control lists","רשימות בקרת גישה"}. {"Access Control Lists","רשימות בקרת גישה"}. +{"Access denied by service policy","גישה נדחתה על ידי פוליסת שירות"}. {"Access rules","כללי גישה"}. {"Access Rules","כללי גישה"}. {"Action on user","פעולה על משתמש"}. -{"Add Jabber ID","הוסף JID"}. +{"Add Jabber ID","הוסף מזהה Jabber"}. {"Add New","הוסף חדש"}. {"Add User","הוסף משתמש"}. {"Administration of ","ניהול של "}. {"Administration","הנהלה"}. +{"Administrator privileges required","נדרשות הרשאות מנהל"}. {"A friendly name for the node","שם ידידותי עבור הצומת"}. {"All activity","כל פעילות"}. -{"Allow this Jabber ID to subscribe to this pubsub node?","להתיר לכתובת JID זו להירשם לצומת PubSub זה?"}. +{"Allow this Jabber ID to subscribe to this pubsub node?","להתיר למזהה Jabber זה להירשם לצומת PubSub זה?"}. {"Allow users to change the subject","התר למשתמשים לשנות את הנושא"}. {"Allow users to query other users","התר למשתמשים לתשאל משתמשים אחרים"}. {"Allow users to send invites","התר למשתמשים לשלוח הזמנות"}. {"Allow users to send private messages","התר למשתמשים לשלוח הודעות פרטיות"}. {"Allow visitors to change nickname","התר למבקרים לשנות שם כינוי"}. {"Allow visitors to send private messages to","התר למבקרים לשלוח הודעות פרטיות אל"}. -{"Allow visitors to send status text in presence updates","התר למבקרים לשלוח טקסט מצב בעדכוני נוכחות"}. +{"Allow visitors to send status text in presence updates","התר למבקרים לשלוח טקסט מצב בתוך עדכוני נוכחות"}. {"Allow visitors to send voice requests","התר למבקרים לשלוח בקשות ביטוי"}. {"All Users","כל המשתמשים"}. {"Announcements","בשורות"}. {"anyone","לכל אחד"}. +{"A password is required to enter this room","נדרשת סיסמה כדי להיכנס אל חדר זה"}. {"April","אפריל"}. {"August","אוגוסט"}. {"Backup Management","ניהול גיבוי"}. @@ -38,17 +42,18 @@ {"Change User Password","שנה סיסמת משתמש"}. {"Characters not allowed:","תווים לא מורשים:"}. {"Chatroom configuration modified","תצורת חדר שיחה שונתה"}. -{"Chatroom is created","חדר שיחה הינו נוצר"}. +{"Chatroom is created","חדר שיחה נוצר כעת"}. {"Chatroom is destroyed","חדר שיחה הינו הרוס"}. -{"Chatroom is started","חדר שיחה הינו מותחל"}. +{"Chatroom is started","חדר שיחה מותחל כעת"}. {"Chatroom is stopped","חדר שיחה הינו מופסק"}. {"Chatrooms","חדרי שיחה"}. -{"Choose a username and password to register with this server","בחר שם משתמש וסיסמה להירשם עם שרת זה"}. +{"Choose a username and password to register with this server","בחר שם משתמש וסיסמה כדי להירשם בעזרת שרת זה"}. {"Choose modules to stop","בחר מודולים להפסקה"}. {"Choose storage type of tables","בחר טיפוס אחסון של טבלאות"}. -{"Choose whether to approve this entity's subscription.","בחר האם לאשר את המנוי של ישות זו."}. +{"Choose whether to approve this entity's subscription.","בחר האם לאשר את ההרשמה של ישות זו."}. {"City","עיר"}. {"Commands","פקודות"}. +{"Conference room does not exist","חדר ועידה לא קיים"}. {"Configuration of room ~s","תצורת חדר ~s"}. {"Configuration","תצורה"}. {"Connected Resources:","משאבים מחוברים:"}. @@ -59,13 +64,13 @@ {"Database Tables Configuration at ","תצורת טבלאות מסד נתונים אצל "}. {"Database","מסד נתונים"}. {"December","דצמבר"}. -{"Default users as participants","משתמשים משתמטים כמשתתפים"}. +{"Default users as participants","משתמשים שגרתיים כמשתתפים"}. {"Delete message of the day on all hosts","מחק את בשורת היום בכל המארחים"}. {"Delete message of the day","מחק את בשורת היום"}. {"Delete Selected","מחק נבחרות"}. {"Delete User","מחק משתמש"}. -{"Deliver event notifications","מסירת התראות אירוע"}. -{"Deliver payloads with event notifications","מסירת מטעני ייעוד (מטע״ד) יחד עם התראות אירוע"}. +{"Deliver event notifications","מסור התראות אירוע"}. +{"Deliver payloads with event notifications","מסור מטעני ייעוד (מטע״ד) יחד עם התראות אירוע"}. {"Description:","תיאור:"}. {"Disc only copy","העתק של תקליטור בלבד"}. {"Displayed Groups:","קבוצות מוצגות:"}. @@ -73,7 +78,7 @@ {"Dump Backup to Text File at ","השלך גיבוי לקובץ טקסט אצל "}. {"Dump to Text File","השלך לקובץ טקסט"}. {"Edit Properties","ערוך מאפיינים"}. -{"Either approve or decline the voice request.","או שתאשר או שתדחה את בקשת הביטוי."}. +{"Either approve or decline the voice request.","אשר או דחה בקשת ביטוי."}. {"ejabberd IRC module","מודול IRC של ejabberd"}. {"ejabberd MUC module","מודול MUC של ejabberd"}. {"ejabberd Multicast service","שירות שידור מרובב של ejabberd"}. @@ -88,25 +93,26 @@ {"Encoding for server ~b","קידוד עבור שרת ~b"}. {"End User Session","סיים סשן משתמש"}. {"Enter list of {Module, [Options]}","הזן רשימה של {מודול, [אפשרויות]}"}. -{"Enter nickname you want to register","הזן שם כינוי אשר ברצונך לרושמו"}. +{"Enter nickname you want to register","הזן שם כינוי אשר ברצונך לרשום"}. {"Enter path to backup file","הזן נתיב לקובץ גיבוי"}. {"Enter path to jabberd14 spool dir","הזן נתיב למדור סליל (spool dir) של jabberd14"}. {"Enter path to jabberd14 spool file","הזן נתיב לקובץ סליל (spool file) של jabberd14"}. {"Enter path to text file","הזן נתיב לקובץ טקסט"}. -{"Enter the text you see","הזן את הטקסט אותו הינך רואה"}. +{"Enter the text you see","הזן את הכיתוב שאתה רואה"}. {"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","הזן שם משתמש וקידודים בהם ברצונך להשתמש לצורך התחברות לשרתי IRC. לחץ 'הבא' כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לצורך התחברות לשרתי IRC"}. {"Erlang Jabber Server","שרת ג׳אבּר Erlang"}. {"Error","שגיאה"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. -{"Exclude Jabber IDs from CAPTCHA challenge","הוצא כתובות של Jabber מתוך אתגר CAPTCHA"}. -{"Export all tables as SQL queries to a file:","יצא את כל טבלאות בתור שאילתות SQL לתוך קובץ:"}. -{"Export data of all users in the server to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך בשרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):"}. +{"Exclude Jabber IDs from CAPTCHA challenge","הוצא כתובות Jabber מתוך אתגר CAPTCHA"}. +{"Export all tables as SQL queries to a file:","יצא את כל הטבלאות בתור שאילתות SQL לתוך קובץ:"}. +{"Export data of all users in the server to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך שרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","יצא מידע של כל המשתמשים שבתוך מארח לתוך קבצי PIEFXIS ‏(XEP-0227):"}. +{"Failed to extract JID from your voice request approval","נכשל לחלץ JID מתוך אישור בקשת הביטוי שלך"}. {"Family Name","שם משפחה"}. {"February","פברואר"}. {"Fill in fields to search for any matching Jabber User","מלא את שדות אלו כדי לחפש עבור כל משתמש Jabber מבוקש"}. -{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","מלא את התבניות כדי לחפש עבור כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה כדי להתאים למחרוזת-משנה)"}. +{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","מלא את הטופס כדי לחפש אחר כל משתמש Jabber מבוקש (באפשרותך להוסיף * בסוף שדה כדי להתאים למחרוזת-משנה)"}. {"Friday","יום שישי"}. {"From ~s","מאת ~s"}. {"From","מאת"}. @@ -126,8 +132,8 @@ {"has been kicked","נבעט/ה"}. {" has set the subject to: "," הגדיר/ה את הנושא אל: "}. {"Host","מארח"}. -{"If you don't see the CAPTCHA image here, visit the web page.","במידה ואינך רואה תמונת CAPTCHA כאן, בקר בעמוד הרשת."}. -{"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","אם ברצונך לציין פורטים, סיסמאות, קידודים אחרים עבור שרתים של IRC, מלא את רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, \"password\"}'. באופן משתמט שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה."}. +{"If you don't see the CAPTCHA image here, visit the web page.","אם אינך רואה תמונת CAPTCHA כאן, בקר בעמוד רשת."}. +{"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","אם ברצונך לציין פורטים, סיסמאות, קידודים אחרים עבור שרתים של IRC, מלא את רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, \"password\"}'. באופן שגרתי שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה."}. {"Import Directory","ייבוא מדור"}. {"Import File","ייבוא קובץ"}. {"Import user data from jabberd14 spool file:","יבא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:"}. @@ -136,6 +142,8 @@ {"Import users data from jabberd14 spool directory:","יבא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:"}. {"Import Users from Dir at ","ייבוא משתמשים מתוך מדור אצל "}. {"Import Users From jabberd14 Spool Files","יבא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14"}. +{"Improper message type","טיפוס הודעה לא מתאים"}. +{"Incorrect password","מילת מעבר שגויה"}. {"Invalid affiliation: ~s","סינוף שגוי: ~s"}. {"Invalid role: ~s","תפקיד שגוי: ~s"}. {"IP addresses","כתובות IP"}. @@ -143,10 +151,13 @@ {"IRC channel (don't put the first #)","ערוץ IRC (אל תשים סימן # ראשון)"}. {"IRC server","שרת IRC"}. {"IRC settings","הגדרות IRC"}. -{"IRC Transport","מוביל IRC"}. +{"IRC Transport","טרנספורט IRC"}. {"IRC username","שם משתמש IRC"}. {"IRC Username","שם משתמש IRC"}. {"is now known as","ידועה כעת בכינוי"}. +{"It is not allowed to send private messages of type \"groupchat\"","אין זה מותר לשלוח הודעות פרטיות מן טיפוס \"groupchat\""}. +{"It is not allowed to send private messages to the conference","אין זה מותר לשלוח הודעות פרטיות אל הועידה"}. +{"It is not allowed to send private messages","אין זה מותר לשלוח הודעות פרטיות"}. {"Jabber Account Registration","רישום חשבון Jabber"}. {"Jabber ID ~s is invalid","מזהה Jabber ‏~s הינו שגוי"}. {"Jabber ID","מזהה Jabber"}. @@ -167,24 +178,26 @@ {"List of modules to start","רשימה של מודולים להפעלה"}. {"List of rooms","רשימה של חדרים"}. {"Low level update script","תסריט עדכון Low level"}. -{"Make participants list public","הפוך רשימת משתתפים אל פומבית"}. -{"Make room CAPTCHA protected","הפוך חדר אל מוגן CAPTCHA"}. -{"Make room members-only","הפוך חדר אל חברים-בלבד"}. -{"Make room moderated","הפוך חדר אל מבוקר"}. -{"Make room password protected","הפוך חדר אל מוגן במילת מעבר"}. -{"Make room persistent","הפוך חדר אל קבוע"}. -{"Make room public searchable","הפוך חדר אל בר חיפוש פומבי"}. +{"Make participants list public","הפוך רשימת משתתפים לפומבית"}. +{"Make room CAPTCHA protected","הפוך חדר לחדר מוגן CAPTCHA"}. +{"Make room members-only","הפוך חדר לחדר עבור חברים-בלבד"}. +{"Make room moderated","הפוך חדר לחדר מבוקר"}. +{"Make room password protected","הפוך חדר לחדר מוגן במילת מעבר"}. +{"Make room persistent","הפוך חדר לחדר קבוע"}. +{"Make room public searchable","הפוך חדר לחדר שנתון לחיפוש פומבי"}. {"March","מרץ"}. {"Maximum Number of Occupants","מספר מרבי של נוכחים"}. {"Max # of items to persist","מספר מרבי של פריטים לקיבוע"}. {"Max payload size in bytes","גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte"}. {"May","מאי"}. +{"Membership is required to enter this room","נדרשת חברות כדי להיכנס אל חדר זה"}. {"Members:","חברים:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","שנן את הסיסמה שלך, או רשום אותה בנייר שמור במקום בטוח. אצל Jabber אין דרך אוטומטית לשחזר את הסיסמה שלך במידה וזו תישמט מתוך זיכרונך."}. {"Memory","זיכרון"}. {"Message body","גוף הודעה"}. {"Middle Name","שם אמצעי"}. {"Minimum interval between voice requests (in seconds)","תדירות מינימלית בין בקשות ביטוי (בשניות)"}. +{"Moderator privileges required","נדרשות הרשאות אחראי"}. {"moderators only","לאחראים בלבד"}. {"Modified modules","מודולים שהותאמו"}. {"Modules at ~p","מודולים אצל ~p"}. @@ -229,12 +242,16 @@ {"Only deliver notifications to available users","מסור התראות למשתמשים זמינים בלבד"}. {"Only moderators and participants are allowed to change the subject in this room","רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה"}. {"Only moderators are allowed to change the subject in this room","רק אחראים רשאים לשנות את הנושא בחדר זה"}. +{"Only moderators can approve voice requests","רק אחראים יכולים לאשר בקשות ביטוי"}. +{"Only occupants are allowed to send messages to the conference","רק נוכחים רשאים לשלוח הודעות אל הועידה"}. +{"Only occupants are allowed to send queries to the conference","רק נוכחים רשאים לשלוח שאילתות אל הועידה"}. +{"Only service administrators are allowed to send service messages","רק מנהלי שירות רשאים לשלוח הודעות שירות"}. {"Options","אפשרויות"}. {"Organization Name","שם ארגון"}. {"Organization Unit","יחידת איגוד"}. {"Outgoing s2s Connections:","חיבורי s2s יוצאים:"}. {"Outgoing s2s Connections","חיבורי s2s יוצאים"}. -{"Outgoing s2s Servers:","שרתי s2s יוצאים:"}. +{"Owner privileges required","נדרשות הרשאות בעלים"}. {"Packet","חבילת מידע"}. {"Password ~b","סיסמה ~b"}. {"Password Verification:","אימות סיסמה:"}. @@ -249,19 +266,22 @@ {"Persist items to storage","פריטים קבועים לאחסון"}. {"Ping","פינג"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","אנא שים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך בנפרד."}. +{"Please, wait for a while before sending new voice request","אנא, המתן לזמן מה לפני שליחת בקשת ביטוי חדשה"}. {"Pong","פונג"}. {"Port ~b","פורט ~b"}. {"Port","פורט"}. -{"Present real Jabber IDs to","הצג כתובות JID ממשיות"}. +{"Present real Jabber IDs to","הצג כתובות Jabber ממשיות"}. {"private, ","פרטי, "}. {"Protocol","פרוטוקול"}. {"Publish-Subscribe","‫Publish-Subscribe"}. {"PubSub subscriber request","בקשת מנוי PubSub"}. -{"Purge all items when the relevant publisher goes offline","טיהור כל הפריטים כאשר המפרסם הרלוונטי "}. +{"Purge all items when the relevant publisher goes offline","טהר את כל הפריטים כאשר המפרסם הרלוונטי הופך לבלתי מקוון"}. +{"Queries to the conference members are not allowed in this room","שאילתות אל חברי הועידה אינן מותרות בחדר זה"}. {"RAM and disc copy","העתק RAM וגם תקליטור"}. {"RAM copy","העתק RAM"}. {"Raw","גולמי"}. {"Really delete message of the day?","באמת למחוק את בשורת היום?"}. +{"Recipient is not in the conference room","מקבל אינו מצוי בחדר הועידה"}. {"Register a Jabber account","רשום חשבון Jabber"}. {"Registered nicknames","שמות כינוי רשומים"}. {"Registered Users:","משתמשים רשומים:"}. @@ -282,6 +302,7 @@ {"Restore plain text backup immediately:","שחזר גיבוי טקסט גלוי (plain text) לאלתר:"}. {"Restore","שחזר"}. {"Room Configuration","תצורת חדר"}. +{"Room creation is denied by service policy","יצירת חדר נדחתה על ידי פוליסת שירות"}. {"Room description","תיאור חדר"}. {"Room Occupants","נוכחי חדר"}. {"Room title","כותרת חדר"}. @@ -303,6 +324,7 @@ {"September","ספטמבר"}. {"Server ~b","שרת ~b"}. {"Server:","שרת:"}. +{"Server","שרת"}. {"Set message of the day and send to online users","קבע את בשורת היום ושלח למשתמשים מקוונים"}. {"Set message of the day on all hosts and send to online users","קבע את בשורת היום בכל המארחים ושלח למשתמשים מקוונים"}. {"Shared Roster Groups","קבוצות רשימה משותפות"}. @@ -310,10 +332,10 @@ {"Show Ordinary Table","הצג טבלה רגילה"}. {"Shut Down Service","כבה שירות"}. {"~s invites you to the room ~s","‫~s מזמינך לחדר ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה זו רק אם אתה סמוך כי המחשב שלך הינו מוגן."}. -{"Specify the access model","ציין את מודל הגישה"}. -{"Specify the event message type","ציין את טיפוס הודעת האירוע"}. -{"Specify the publisher model","ציין את מודל הפרסום"}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה זו רק אם אתה סמוך כי המחשב שלך הינו מוגן."}. +{"Specify the access model","ציין מודל גישה"}. +{"Specify the event message type","ציין טיפוס הודעת אירוע"}. +{"Specify the publisher model","ציין מודל פרסום"}. {"~s's Offline Messages Queue","תור הודעות לא מקוונות של ~s"}. {"Start Modules at ","התחל מודולים אצל "}. {"Start Modules","התחל מודולים"}. @@ -333,30 +355,37 @@ {"Subscriber Address","כתובת מנוי"}. {"Subscription","הרשמה"}. {"Sunday","יום ראשון"}. -{"The CAPTCHA is valid.","‏CAPTCHA הינה בתוקף."}. +{"That nickname is already in use by another occupant","שם כינוי זה כבר מצוי בשימוש על ידי נוכח אחר"}. +{"That nickname is registered by another person","שם כינוי זה הינו רשום על ידי מישהו אחר"}. +{"The CAPTCHA is valid.","‏CAPTCHA הינה תקפה."}. +{"The CAPTCHA verification has failed","אימות CAPTCHA נכשל"}. {"The collections with which a node is affiliated","האוספים עמם צומת מסונף"}. +{"The password is too weak","הסיסמה חלשה מדי"}. {"the password is","הסיסמה היא"}. {"The password of your Jabber account was successfully changed.","סיסמת חשבון Jabber שונתה בהצלחה."}. {"There was an error changing the password: ","אירעה שגיאה בשינוי הסיסמה: "}. {"There was an error creating the account: ","אירעה שגיאה ביצירת החשבון: "}. {"There was an error deleting the account: ","אירעה שגיאה במחיקת החשבון: "}. {"This IP address is blacklisted in ~s","כתובת IP זו רשומה ברשימה שחורה בתוך ~s"}. -{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","חלק זה אינו ער לרישיות: macbeth הינה זהה כשם MacBeth וגם Macbeth."}. -{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","עמוד זה מתיר ליצור חשבון Jabber בשרת Jabber זה. כתובת JID ‏(Jabber IDentifier) תגובש באופן של: username@server. נא לקרוא בזהירות את ההוראות למילוי השדות באופן נכון."}. -{"This page allows to unregister a Jabber account in this Jabber server.","עמוד זה מתיר לך לבטל רישום של חשבון Jabber בשרת Jabber זה."}. +{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","חלק זה אינו ער לרישיות: macbeth הינה זהה למחרוזת MacBeth וגם Macbeth."}. +{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","עמוד זה מתיר ליצור חשבון Jabber בשרת Jabber זה. כתובת JID ‏(Jabber IDentifier) תגובש באופן של: username@server. אנא קרא בזהירות את ההוראות למילוי נכון של השדות."}. +{"This page allows to unregister a Jabber account in this Jabber server.","עמוד זה מתיר לך לבטל רישום של חשבון Jabber בתוך שרת Jabber זה."}. {"Thursday","יום חמישי"}. {"Time delay","זמן שיהוי"}. {"Time","זמן"}. +{"Too many CAPTCHA requests","יותר מדי בקשות CAPTCHA"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה בשעה ~s UTC"}. {"Too many unacked stanzas","יותר מדי סטנזות בלי אישורי קבלה"}. {"To ~s","אל ~s"}. {"Total rooms","חדרים סה״כ"}. {"To","לכבוד"}. +{"Traffic rate limit is exceeded","מגבלת שיעור תעבורה נחצתה"}. {"Transactions Aborted:","טרנזקציות שבוטלו:"}. {"Transactions Committed:","טרנזקציות שבוצעו:"}. {"Transactions Logged:","טרנזקציות שנרשמו:"}. {"Transactions Restarted:","טרנזקציות שהותחלו מחדש:"}. {"Tuesday","יום שלישי"}. +{"Unable to generate a CAPTCHA","אין אפשרות להפיק CAPTCHA"}. {"Unauthorized","לא מורשה"}. {"Unregister a Jabber account","בטל רישום חשבון Jabber"}. {"Unregister","בטל רישום"}. @@ -371,6 +400,7 @@ {"User JID","‏JID משתמש"}. {"User Management","ניהול משתמשים"}. {"Username:","שם משתמש:"}. +{"Users are not allowed to register accounts so quickly","משתמשים אינם מורשים לרשום חשבונות כל כך במהירות"}. {"Users Last Activity","פעילות משתמשים אחרונה"}. {"User ~s","משתמש ~s"}. {"Users","משתמשים"}. @@ -378,16 +408,23 @@ {"Validate","הענק תוקף"}. {"vCard User Search","חיפוש משתמש vCard"}. {"Virtual Hosts","מארחים מדומים"}. +{"Visitors are not allowed to change their nicknames in this room","מבקרים אינם מורשים לשנות את שמות הכינויים שלהם בחדר זה"}. +{"Visitors are not allowed to send messages to all occupants","מבקרים אינם מורשים לשלוח הודעות אל כל הנוכחים"}. +{"Voice requests are disabled in this conference","בקשות ביטוי מנוטרלות בועידה זו"}. {"Voice request","בקשת ביטוי"}. {"Wednesday","יום רביעי"}. -{"When to send the last published item","מתי לשלוח פריט מפורסם אחרון"}. -{"Whether to allow subscriptions","האם להתיר מנויים"}. -{"You can later change your password using a Jabber client.","ביכולתך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber."}. -{"You need a client that supports x:data and CAPTCHA to register","עליך להשתמש בלקוח אשר תומך x:data וגם CAPTCHA בכדי להירשם"}. -{"You need a client that supports x:data to register the nickname","עליך להשתמש בלקוח אשר תומך x:data בכדי לרשום את שם הכינוי"}. -{"You need an x:data capable client to configure mod_irc settings","עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר הגדרות של mod_irc"}. -{"You need an x:data capable client to configure room","עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי להגדיר חדר"}. -{"You need an x:data capable client to search","עליך להשתמש בלקוח אשר מסוגל להבין x:data בכדי לחפש"}. +{"When to send the last published item","מתי לשלוח את הפריט המפורסם האחרון"}. +{"Whether to allow subscriptions","האם להתיר הרשמות"}. +{"You can later change your password using a Jabber client.","באפשרותך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber."}. +{"You have been banned from this room","נאסרת מן חדר זה"}. +{"You must fill in field \"Nickname\" in the form","עליך למלא את השדה \"שם כינוי\" בתוך התבנית"}. +{"You need a client that supports x:data and CAPTCHA to register","עליך להשתמש בלקוח אשר תומך x:data וגם CAPTCHA כדי להירשם"}. +{"You need a client that supports x:data to register the nickname","עליך להשתמש בלקוח אשר תומך x:data כדי לרשום את השם כינוי"}. +{"You need an x:data capable client to configure mod_irc settings","עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר הגדרות mod_irc"}. +{"You need an x:data capable client to configure room","עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר חדר"}. +{"You need an x:data capable client to search","עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי לחפש"}. +{"Your active privacy list has denied the routing of this stanza.","רשימת הפרטיות הפעילה שלך אסרה את הניתוב של סטנזה זו."}. +{"Your contact offline message queue is full. The message has been discarded.","תור הודעות קשר לא מקוונות הינו מלא. ההודעה סולקה."}. {"Your Jabber account was successfully created.","חשבון Jabber נוצר בהצלחה."}. {"Your Jabber account was successfully deleted.","חשבון Jabber נמחק בהצלחה."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s"}. diff --git a/priv/msgs/he.po b/priv/msgs/he.po index b215aff2241..0b9fefe5537 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -15,49 +15,53 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Source-Language: en\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "נדרש שימוש של STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "לא סופק משאב" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "הוחלף בחיבור חדש" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "נבעט/ה" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "רשימת הפרטיות הפעילה שלך אסרה את הניתוב של סטנזה זו." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "יותר מדי סטנזות בלי אישורי קבלה" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "הזן את הכיתוב שאתה רואה" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "ההודעות שלך לערוץ ~s הינן חסומות. כדי לבטל את חסימתן, בקר בכתובת ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "אם אינך רואה תמונת CAPTCHA כאן, בקר בעמוד רשת." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "עמוד רשת CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "‏CAPTCHA הינה תקפה." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "משתמש" @@ -65,9 +69,9 @@ msgstr "משתמש" msgid "Server" msgstr "שרת" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "סיסמה" @@ -84,277 +88,281 @@ msgstr "לא מורשה" msgid "ejabberd Web Admin" msgstr "מנהל רשת ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "הנהלה" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "רשימות בקרת גישה" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "נשלח" # פגום -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "פורמט רע" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "שלח" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "גולמי" # נבחרים -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "מחק נבחרות" # חוקי -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "כללי גישה" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s תצורת כללי גישה" # וירטואליים -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "מארחים מדומים" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "משתמשים" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 mod_configure.erl:524 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 +#: mod_configure.erl:524 msgid "Online Users" msgstr "משתמשים מקוונים" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "פעילות משתמשים אחרונה" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "משך זמן: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "חודש אחרון" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "שנה אחרונה" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "כל פעילות" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "הצג טבלה רגילה" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "הצג טבלה אינטגרלית" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 mod_muc_admin.erl:247 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 +#: mod_muc_admin.erl:247 msgid "Statistics" msgstr "סטטיסטיקה" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "לא נמצא" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "צומת לא נמצא" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "הוסף חדש" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "מארח" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "משתמשים רשומים" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "הוסף משתמש" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "הודעות לא מקוונות" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "פעילות אחרונה" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "אף פעם" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "מקוון" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "משתמשים רשומים:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "משתמשים מקוונים:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "חיבורי s2s יוצאים:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "שרתי s2s יוצאים:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "חיבורי s2s יוצאים:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "אין" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "שנה סיסמה" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "משתמש ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "משאבים מחוברים:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 mod_register_web.erl:475 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 +#: mod_register_web.erl:475 msgid "Password:" msgstr "סיסמה:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "הסר משתמש" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "אין מידע" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "צמתים" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "צמתים מורצים" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "צמתים שנפסקו" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "צומת ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "מסד נתונים" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "גיבוי" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "פורטים מואזנים" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "עדכן" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "אתחל" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "הפסק" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "מודולים" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "שגיאת קריאת RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "טבלאות מסד נתונים אצל ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "שם" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "טיפוס אחסון" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "אלמנטים" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "זיכרון" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "שגיאה" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "גיבוי של ~p" # האינטגרלי לחוד -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -364,144 +372,144 @@ msgstr "" "עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך " "בנפרד." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "אחסן גיבוי בינארי:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "אישור" # ללא דיחוי -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "שחזר גיבוי בינארי לאלתר:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "שחזר גיבוי בינארי לאחר האתחול הבא של ejabberd (מצריך פחות זיכרון):" # תמליל ברור -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "אחסן גיבוי טקסט גלוי (plain text):" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "שחזר גיבוי טקסט גלוי (plain text) לאלתר:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "יבא מידע משתמשים מתוך קובץ PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "יצא מידע של כל המשתמשים שבתוך שרת זה לתוך קבצי PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "יצא מידע של כל המשתמשים שבתוך מארח לתוך קבצי PIEFXIS ‏(XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "יצא את כל הטבלאות בתור שאילתות SQL לתוך קובץ:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "יבא נתוני משתמש מתוך קובץ סליל (spool file) של jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "יבא נתוני משתמשים מתוך מדור סליל (spool directory) של jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "פורטים מואזנים אצל " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "מודולים אצל ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "סטטיסטיקות של ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "זמן פעילות:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "זמן מחשב (CPU):" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "טרנזקציות שבוצעו:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "טרנזקציות שבוטלו:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "טרנזקציות שהותחלו מחדש:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "טרנזקציות שנרשמו:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "עדכון ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "תכנית עדכון" # adjusted -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "מודולים שהותאמו" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "תסריט עדכון" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "תסריט עדכון Low level" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "בדיקת תסריט" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "‫IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "פורט" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "פרוטוקול" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "מודול" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "אפשרויות" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "התחל" @@ -791,8 +799,8 @@ msgstr "כללי גישה" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "מזהה Jabber" @@ -809,31 +817,31 @@ msgstr "מספר של משתמשים רשומים" msgid "Number of online users" msgstr "מספר של משתמשים מקוונים" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "כניסה אחרונה" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "גודל רשימה" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "כתובות IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "משאבים" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "ניהול של " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "פעולה על משתמש" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "ערוך מאפיינים" @@ -845,27 +853,39 @@ msgstr "" "יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה " "בשעה ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "כתובת IP זו רשומה ברשימה שחורה בתוך ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "גישה נדחתה על ידי פוליסת שירות" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "טרנספורט IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "מודול IRC של ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר הגדרות mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "רישום בתוך mod_irc עבור " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -873,63 +893,60 @@ msgstr "" "הזן שם משתמש, קידודים, פורטים וסיסמאות בהם ברצונך להשתמש לצורך התחברות לשרתי " "IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "שם משתמש IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " -"servers, fill this list with values in format '{\"irc server\", " -"\"encoding\", port, \"password\"}'. By default this service use \"~s\" " -"encoding, port ~p, empty password." +"servers, fill this list with values in format '{\"irc server\", \"encoding" +"\", port, \"password\"}'. By default this service use \"~s\" encoding, port " +"~p, empty password." msgstr "" "אם ברצונך לציין פורטים, סיסמאות, קידודים אחרים עבור שרתים של IRC, מלא את " -"רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, " -"\"password\"}'. באופן שגרתי שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה " -"ריקה." +"רשימה זו עם ערכים בפורמט '{\"irc server\", \"encoding\", port, \"password" +"\"}'. באופן שגרתי שירות זה משתמש בקידוד \"~s\", פורט ~p, סיסמה ריקה." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" -"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, " -"{\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", " -"\"utf-8\"}]." +"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." +"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" -"דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, " -"{\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", " -"\"utf-8\"}]." +"דוגמא: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." +"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." # פרמטרי חיבור -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "פרמטרים של חיבור" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "הצטרף לערוץ IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "ערוץ IRC (אל תשים סימן # ראשון)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "שרת IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "הצטרף לערוץ IRC כאן." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "הצטרף לערוץ IRC במזהה Jabber זה: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "הגדרות IRC" # השלם -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -938,49 +955,80 @@ msgstr "" "הזן שם משתמש וקידודים בהם ברצונך להשתמש לצורך התחברות לשרתי IRC. לחץ 'הבא' " "כדי להשיג עוד שדות למילוי. לחץ 'סיים' כדי לשמור הגדרות." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "שם משתמש IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "סיסמה ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "פורט ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "קידוד עבור שרת ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "שרת ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "רק אחראים רשאים לשנות את הנושא בחדר זה" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "רק מנהלי שירות רשאים לשלוח הודעות שירות" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "יצירת חדר נדחתה על ידי פוליסת שירות" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "חדר ועידה לא קיים" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "חדרי שיחה" +#: mod_muc.erl:779 +#, fuzzy +msgid "Empty Rooms" +msgstr "חדרים" + # to register nickname -#: mod_muc.erl:997 +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "עליך להשתמש בלקוח אשר תומך x:data כדי לרשום את השם כינוי" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "רישום שם כינוי אצל " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "הזן שם כינוי אשר ברצונך לרשום" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 mod_vcard.erl:490 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "שם כינוי" -#: mod_muc.erl:1177 +# note: another person > someone else +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "שם כינוי זה הינו רשום על ידי מישהו אחר" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "עליך למלא את השדה \"שם כינוי\" בתוך התבנית" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "מודול MUC של ejabberd" @@ -1005,354 +1053,488 @@ msgstr "שמות כינוי רשומים" msgid "List of rooms" msgstr "רשימה של חדרים" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "תצורת חדר שיחה שונתה" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "נכנס/ת אל החדר" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "עוזב/ת את החדר" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "נאסר/ה" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "נבעט/ה משום שינוי סינוף" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "נבעט/ה משום שהחדר שונה אל חברים-בלבד" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "נבעט/ה משום כיבוי מערכת" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "ידועה כעת בכינוי" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " הגדיר/ה את הנושא אל: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "חדר שיחה נוצר כעת" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "חדר שיחה הינו הרוס" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "חדר שיחה מותחל כעת" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "חדר שיחה הינו מופסק" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "יום שני" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "יום שלישי" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "יום רביעי" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "יום חמישי" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "יום שישי" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "יום שבת" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "יום ראשון" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "ינואר" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "פברואר" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "מרץ" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "אפריל" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "מאי" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "יוני" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "יולי" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "אוגוסט" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "ספטמבר" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "אוקטובר" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "נובמבר" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "דצמבר" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "תצורת חדר" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "נוכחי חדר" -#: mod_muc_room.erl:998 +# נעברה +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "מגבלת שיעור תעבורה נחצתה" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "אין זה מותר לשלוח הודעות פרטיות אל הועידה" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "אנא, המתן לזמן מה לפני שליחת בקשת ביטוי חדשה" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "בקשות ביטוי מנוטרלות בועידה זו" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "נכשל לחלץ JID מתוך אישור בקשת הביטוי שלך" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "רק אחראים יכולים לאשר בקשות ביטוי" + +# הולם +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "טיפוס הודעה לא מתאים" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "אין זה מותר לשלוח הודעות פרטיות מן טיפוס \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "מקבל אינו מצוי בחדר הועידה" + +# אסור +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "אין זה מותר לשלוח הודעות פרטיות" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "רק נוכחים רשאים לשלוח הודעות אל הועידה" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "רק נוכחים רשאים לשלוח שאילתות אל הועידה" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "שאילתות אל חברי הועידה אינן מותרות בחדר זה" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "רק אחראים רשאים לשנות את הנושא בחדר זה" -#: mod_muc_room.erl:2752 +# רשאים +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "מבקרים אינם מורשים לשלוח הודעות אל כל הנוכחים" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "מבקרים אינם מורשים לשנות את שמות הכינויים שלהם בחדר זה" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "שם כינוי זה כבר מצוי בשימוש על ידי נוכח אחר" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "נאסרת מן חדר זה" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "נדרשת חברות כדי להיכנס אל חדר זה" + +# מילת־מעבר +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "נדרשת סיסמה כדי להיכנס אל חדר זה" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "יותר מדי בקשות CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "אין אפשרות להפיק CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "מילת מעבר שגויה" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "נדרשות הרשאות מנהל" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "נדרשות הרשאות אחראי" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "מזהה Jabber ‏~s הינו שגוי" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "שם כינוי ~s לא קיים בחדר" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "סינוף שגוי: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "תפקיד שגוי: ~s" +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "נדרשות הרשאות בעלים" + # תצורה של חדר -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "תצורת חדר ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "כותרת חדר" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "תיאור חדר" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "הפוך חדר לחדר קבוע" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "הפוך חדר לחדר שנתון לחיפוש פומבי" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "הפוך רשימת משתתפים לפומבית" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "הפוך חדר לחדר מוגן במילת מעבר" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "מספר מרבי של נוכחים" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "ללא הגבלה" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "הצג כתובות Jabber ממשיות" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "לאחראים בלבד" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "לכל אחד" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "לאחראים בלבד" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "הפוך חדר לחדר עבור חברים-בלבד" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "הפוך חדר לחדר מבוקר" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "משתמשים שגרתיים כמשתתפים" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "התר למשתמשים לשנות את הנושא" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "התר למשתמשים לשלוח הודעות פרטיות" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "התר למבקרים לשלוח הודעות פרטיות אל" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "אף אחד" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "התר למשתמשים לתשאל משתמשים אחרים" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "התר למשתמשים לשלוח הזמנות" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "התר למבקרים לשלוח טקסט מצב בתוך עדכוני נוכחות" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "התר למבקרים לשנות שם כינוי" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "התר למבקרים לשלוח בקשות ביטוי" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "תדירות מינימלית בין בקשות ביטוי (בשניות)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "הפוך חדר לחדר מוגן CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "אפשר אחסון הודעות" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "הוצא כתובות Jabber מתוך אתגר CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "אפשר רישום פעילות" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר חדר" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "מספר של נוכחים" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "פרטי, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "בקשת ביטוי" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "אשר או דחה בקשת ביטוי." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "‏JID משתמש" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "להעניק ביטוי לאישיות זו?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "‫~s מזמינך לחדר ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "הסיסמה היא" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "שידור מרובב" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "שירות שידור מרובב של ejabberd" -#: mod_offline.erl:783 +# תור הודעות לא מקוונות של הקשר שלך הינו +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "תור הודעות קשר לא מקוונות הינו מלא. ההודעה סולקה." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "תור הודעות לא מקוונות של ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "זמן" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "מאת" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "לכבוד" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "חבילת מידע" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "הודעות לא מקוונות:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "הסר את כל ההודעות הלא מקוונות" @@ -1360,117 +1542,130 @@ msgstr "הסר את כל ההודעות הלא מקוונות" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "מודול SOCKS5 Bytestreams של ejabberd" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "‫Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "מודול Publish-Subscribe של ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "בקשת מנוי PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "בחר האם לאשר את ההרשמה של ישות זו." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "מזהה צומת (NID)" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "כתובת מנוי" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "להתיר למזהה Jabber זה להירשם לצומת PubSub זה?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "מסור מטעני ייעוד (מטע״ד) יחד עם התראות אירוע" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "מסור התראות אירוע" # משתמשים רשומים -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "הודע מנויים כאשר תצורת הצומת משתנה" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "הודע מנויים כאשר הצומת נמחק" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "הודע מנויים כאשר פריטים מוסרים מתוך הצומת" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "פריטים קבועים לאחסון" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "שם ידידותי עבור הצומת" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "מספר מרבי של פריטים לקיבוע" # בין אם -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "האם להתיר הרשמות" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "ציין מודל גישה" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "קבוצות רשימה מורשות להירשם" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "ציין מודל פרסום" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "טהר את כל הפריטים כאשר המפרסם הרלוונטי הופך לבלתי מקוון" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "ציין טיפוס הודעת אירוע" # בבתים בבייטים (bytes) -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "גודל מרבי של מטען ייעוד (payload) ביחידות מידה של byte" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "מתי לשלוח את הפריט המפורסם האחרון" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "מסור התראות למשתמשים זמינים בלבד" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "האוספים עמם צומת מסונף" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "אימות CAPTCHA נכשל" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "עליך להשתמש בלקוח אשר תומך x:data וגם CAPTCHA כדי להירשם" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "בחר שם משתמש וסיסמה כדי להירשם בעזרת שרת זה" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "הסיסמה חלשה מדי" + +# כה מהר +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "משתמשים אינם מורשים לרשום חשבונות כל כך במהירות" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "חשבון Jabber נוצר בהצלחה." @@ -1544,12 +1739,10 @@ msgstr "אל תגלה את הסיסמה שלך לאף אחד, אפילו לא ל msgid "You can later change your password using a Jabber client." msgstr "באפשרותך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber." -# בוטח -# trust that your #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה " "זו רק אם אתה סמוך כי המחשב שלך הינו מוגן." @@ -1589,60 +1782,60 @@ msgstr "עמוד זה מתיר לך לבטל רישום של חשבון Jabber msgid "Unregister" msgstr "בטל רישום" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "הרשמה" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "ממתינות" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "קבוצות" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "הענק תוקף" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "הסר" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "רשימה של " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "הוסף מזהה Jabber" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "רשימה" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "קבוצות רשימה משותפות" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "שם:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "תיאור:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "חברים:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "קבוצות מוצגות:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "קבוצה " @@ -1720,6 +1913,9 @@ msgstr "תוצאות חיפוש עבור " msgid "Fill in fields to search for any matching Jabber User" msgstr "מלא את שדות אלו כדי לחפש עבור כל משתמש Jabber מבוקש" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "שרתי s2s יוצאים:" + #~ msgid "Code Update" #~ msgstr "עדכון קוד" @@ -1729,142 +1925,21 @@ msgstr "מלא את שדות אלו כדי לחפש עבור כל משתמש Jab #~ msgid "This room is not anonymous" #~ msgstr "חדר זה אינו אנונימי" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "רשימת הפרטיות הפעילה שלך אסרה את הניתוב של סטנזה זו." - -#~ msgid "Access denied by service policy" -#~ msgstr "גישה נדחתה על ידי פוליסת שירות" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "רק מנהלי שירות רשאים לשלוח הודעות שירות" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "יצירת חדר נדחתה על ידי פוליסת שירות" - -#~ msgid "Conference room does not exist" -#~ msgstr "חדר ועידה לא קיים" - -# note: another person > someone else -#~ msgid "That nickname is registered by another person" -#~ msgstr "שם כינוי זה הינו רשום על ידי מישהו אחר" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "עליך למלא את השדה \"שם כינוי\" בתוך התבנית" - -# נעברה -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "מגבלת שיעור תעבורה נחצתה" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "משתתף זה נבעט מתוך החדר מכיוון שהוא שלח הודעת שגיאה" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "אין זה מותר לשלוח הודעות פרטיות אל הועידה" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "אנא, המתן לזמן מה לפני שליחת בקשת ביטוי חדשה" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "בקשות ביטוי מנוטרלות בועידה זו" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "נכשל לחלץ JID מתוך אישור בקשת הביטוי שלך" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "רק אחראים יכולים לאשר בקשות ביטוי" - -# הולם -#~ msgid "Improper message type" -#~ msgstr "טיפוס הודעה לא מתאים" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "משתתף זה נבעט מתוך החדר משום שהוא שלח הודעת שגיאה אל משתתף אחר" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "אין זה מותר לשלוח הודעות פרטיות מן טיפוס \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "מקבל אינו מצוי בחדר הועידה" - -# אסור -#~ msgid "It is not allowed to send private messages" -#~ msgstr "אין זה מותר לשלוח הודעות פרטיות" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "רק נוכחים רשאים לשלוח הודעות אל הועידה" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "רק נוכחים רשאים לשלוח שאילתות אל הועידה" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "שאילתות אל חברי הועידה אינן מותרות בחדר זה" - -# רשאים -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "מבקרים אינם מורשים לשלוח הודעות אל כל הנוכחים" - # שגיאת נוכחות # נוכחות שגויה #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "משתתף זה נבעט מתוך החדר משום שהוא שלח נוכחות שגיאה" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "מבקרים אינם מורשים לשנות את שמות הכינויים שלהם בחדר זה" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "שם כינוי זה כבר מצוי בשימוש על ידי נוכח אחר" - -#~ msgid "You have been banned from this room" -#~ msgstr "נאסרת מן חדר זה" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "נדרשת חברות כדי להיכנס אל חדר זה" - -# מילת־מעבר -#~ msgid "A password is required to enter this room" -#~ msgstr "נדרשת סיסמה כדי להיכנס אל חדר זה" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "יותר מדי בקשות CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "אין אפשרות להפיק CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "מילת מעבר שגויה" - -#~ msgid "Administrator privileges required" -#~ msgstr "נדרשות הרשאות מנהל" - -#~ msgid "Moderator privileges required" -#~ msgstr "נדרשות הרשאות אחראי" - -#~ msgid "Owner privileges required" -#~ msgstr "נדרשות הרשאות בעלים" - -# תור הודעות לא מקוונות של הקשר שלך הינו -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "תור הודעות קשר לא מקוונות הינו מלא. ההודעה סולקה." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "אימות CAPTCHA נכשל" - -#~ msgid "The password is too weak" -#~ msgstr "הסיסמה חלשה מדי" - -# כה מהר -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "משתמשים אינם מורשים לרשום חשבונות כל כך במהירות" - -#~ msgid "Rooms" -#~ msgstr "חדרים" - #~ msgid "Notify owners about new subscribers and unsubscribers" #~ msgstr "הודע בעלים אודות מנויים חדשים ומנויים שביטלו מנוי" diff --git a/priv/msgs/id.msg b/priv/msgs/id.msg index c66234d1cd3..c0ffb8de4ea 100644 --- a/priv/msgs/id.msg +++ b/priv/msgs/id.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfigurasi Daftar Akses Pengendalian"}. {"Access Control Lists","Akses Daftar Pengendalian"}. {"Access control lists","Daftar Pengendalian Akses"}. +{"Access denied by service policy","Akses ditolak oleh kebijakan layanan"}. {"Access rules","Akses peraturan"}. {"Access Rules","Aturan Akses"}. {"Action on user","Tindakan pada pengguna"}. @@ -11,6 +12,7 @@ {"Add User","Tambah Pengguna"}. {"Administration","Administrasi"}. {"Administration of ","Administrasi"}. +{"Administrator privileges required","Hak istimewa Administrator dibutuhkan"}. {"A friendly name for the node","Nama yang dikenal untuk node"}. {"All activity","Semua aktifitas"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Izinkan ID Jabber ini untuk berlangganan pada node pubsub ini?"}. @@ -23,6 +25,7 @@ {"All Users","Semua Pengguna"}. {"Announcements","Pengumuman"}. {"anyone","Siapapun"}. +{"A password is required to enter this room","Diperlukan kata sandi untuk masuk ruangan ini"}. {"April","April"}. {"August","Agustus"}. {"Backup","Backup"}. @@ -46,6 +49,7 @@ {"Choose whether to approve this entity's subscription.","Pilih apakah akan menyetujui hubungan pertemanan ini."}. {"City","Kota"}. {"Commands","Perintah"}. +{"Conference room does not exist","Ruang Konferensi tidak ada"}. {"Configuration of room ~s","Pengaturan ruangan ~s"}. {"Configuration","Pengaturan"}. {"Connected Resources:","Sumber Daya Terhubung:"}. @@ -126,6 +130,8 @@ {"Import users data from jabberd14 spool directory:","Импорт пользовательских данных из буферной директории jabberd14:"}. {"Import Users from Dir at ","Impor Pengguna dari Dir di"}. {"Import Users From jabberd14 Spool Files","Impor Pengguna Dari jabberd14 Spool File"}. +{"Improper message type","Jenis pesan yang tidak benar"}. +{"Incorrect password","Kata sandi salah"}. {"Invalid affiliation: ~s","Afiliasi tidak valid: ~s"}. {"Invalid role: ~s","Peran tidak valid: ~s"}. {"IP addresses","Alamat IP"}. @@ -137,6 +143,9 @@ {"IRC username","Nama Pengguna IRC"}. {"IRC Username","Nama Pengguna IRC"}. {"is now known as","sekarang dikenal sebagai"}. +{"It is not allowed to send private messages","Hal ini tidak diperbolehkan untuk mengirim pesan pribadi"}. +{"It is not allowed to send private messages of type \"groupchat\"","Hal ini tidak diperbolehkan untuk mengirim pesan pribadi jenis \"groupchat \""}. +{"It is not allowed to send private messages to the conference","Hal ini tidak diperbolehkan untuk mengirim pesan pribadi ke konferensi"}. {"Jabber Account Registration","Pendaftaran Akun Jabber"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s tidak valid"}. @@ -169,10 +178,12 @@ {"Max payload size in bytes","Max kapasitas ukuran dalam bytes"}. {"May","Mei"}. {"Members:","Anggota:"}. +{"Membership is required to enter this room","Hanya Member yang dapat masuk ruangan ini"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Hafalkan kata sandi Anda, atau dicatat dan letakkan di tempat yang aman. Didalam Jabber tidak ada cara otomatis untuk mendapatkan kembali password Anda jika Anda lupa."}. {"Memory","Memori"}. {"Message body","Isi Pesan"}. {"Middle Name","Nama Tengah"}. +{"Moderator privileges required","Hak istimewa moderator dibutuhkan"}. {"moderators only","Hanya moderator"}. {"Modified modules","Modifikasi modul-modul"}. {"Module","Modul"}. @@ -212,12 +223,15 @@ {"Only deliver notifications to available users","Hanya mengirimkan pemberitahuan kepada pengguna yang tersedia"}. {"Only moderators and participants are allowed to change the subject in this room","Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan di ruangan ini"}. {"Only moderators are allowed to change the subject in this room","Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini"}. +{"Only occupants are allowed to send messages to the conference","Hanya penghuni yang diizinkan untuk mengirim pesan ke konferensi"}. +{"Only occupants are allowed to send queries to the conference","Hanya penghuni diizinkan untuk mengirim permintaan ke konferensi"}. +{"Only service administrators are allowed to send service messages","Layanan hanya diperuntukan kepada administrator yang diizinkan untuk mengirim layanan pesan"}. {"Options","Pilihan-pilihan"}. {"Organization Name","Nama Organisasi"}. {"Organization Unit","Unit Organisasi"}. {"Outgoing s2s Connections","Koneksi Keluar s2s"}. {"Outgoing s2s Connections:","Koneksi s2s yang keluar:"}. -{"Outgoing s2s Servers:","Layanan s2s yang keluar:"}. +{"Owner privileges required","Hak istimewa owner dibutuhkan"}. {"Packet","Paket"}. {"Password ~b","Kata Sandi ~b"}. {"Password:","Kata Sandi:"}. @@ -240,10 +254,12 @@ {"Publish-Subscribe","Setujui-Pertemanan"}. {"PubSub subscriber request","Permintaan pertemanan PubSub"}. {"Purge all items when the relevant publisher goes offline","Bersihkan semua item ketika penerbit yang relevan telah offline"}. +{"Queries to the conference members are not allowed in this room","Permintaan untuk para anggota konferensi tidak diperbolehkan di ruangan ini"}. {"RAM and disc copy","RAM dan disc salinan"}. {"RAM copy","Salinan RAM"}. {"Raw","mentah"}. {"Really delete message of the day?","Benar-benar ingin menghapus pesan harian?"}. +{"Recipient is not in the conference room","Penerima tidak berada di ruangan konferensi"}. {"Register a Jabber account","Daftarkan sebuah akun jabber"}. {"Registered Users:","Pengguna Terdaftar:"}. {"Registered Users","Pengguna Terdaftar"}. @@ -263,6 +279,7 @@ {"Restore","Mengembalikan"}. {"Restore plain text backup immediately:","Segera mengembalikan cadangan teks biasa:"}. {"Room Configuration","Konfigurasi Ruangan"}. +{"Room creation is denied by service policy","Pembuatan Ruangan ditolak oleh kebijakan layanan"}. {"Room description","Keterangan ruangan"}. {"Room Occupants","Penghuni Ruangan"}. {"Room title","Nama Ruangan"}. @@ -291,7 +308,7 @@ {"Show Ordinary Table","Tampilkan Tabel Normal"}. {"Shut Down Service","Shut Down Layanan"}. {"~s invites you to the room ~s","~s mengundang anda ke ruangan ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan fitur itu hanya jika Anda mempercayai komputer Anda aman."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan fitur itu hanya jika Anda mempercayai komputer Anda aman."}. {"Specify the access model","Tentukan model akses"}. {"Specify the event message type","Tentukan jenis acara pesan"}. {"Specify the publisher model","Tentukan model penerbitan"}. @@ -314,9 +331,13 @@ {"Subscriber Address","Alamat Pertemanan"}. {"Subscription","Berlangganan"}. {"Sunday","Minggu"}. +{"That nickname is already in use by another occupant","Julukan itu sudah digunakan oleh penghuni lain"}. +{"That nickname is registered by another person","Julukan tersebut telah didaftarkan oleh orang lain"}. {"The CAPTCHA is valid.","Captcha ini benar."}. +{"The CAPTCHA verification has failed","Verifikasi CAPTCHA telah gagal"}. {"The collections with which a node is affiliated","Koleksi dengan yang berafiliasi dengan sebuah node"}. {"the password is","kata sandi yaitu:"}. +{"The password is too weak","Kata sandi terlalu lemah"}. {"The password of your Jabber account was successfully changed.","Kata sandi pada akun Jabber Anda telah berhasil diubah."}. {"There was an error changing the password: ","Ada kesalahan dalam mengubah password:"}. {"There was an error creating the account: ","Ada kesalahan saat membuat akun:"}. @@ -329,11 +350,13 @@ {"Time","Waktu"}. {"To","Kepada"}. {"To ~s","Kepada ~s"}. +{"Traffic rate limit is exceeded","Lalu lintas melebihi batas"}. {"Transactions Aborted:","Transaksi yang dibatalkan:"}. {"Transactions Committed:","Transaksi yang dilakukan:"}. {"Transactions Logged:","Transaksi yang ditempuh:"}. {"Transactions Restarted:","Transaksi yang dijalankan ulang:"}. {"Tuesday","Selasa"}. +{"Unable to generate a CAPTCHA","Tidak dapat menghasilkan CAPTCHA"}. {"Unauthorized","Ditolak"}. {"Unregister a Jabber account","Nonaktifkan akun jabber"}. {"Unregister","Nonaktifkan"}. @@ -347,20 +370,27 @@ {"User Management","Manajemen Pengguna"}. {"Username:","Nama Pengguna:"}. {"User","Pengguna"}. +{"Users are not allowed to register accounts so quickly","Pengguna tidak diperkenankan untuk mendaftar akun begitu cepat"}. {"Users Last Activity","Aktifitas terakhir para pengguna"}. {"Users","Pengguna"}. {"Validate","Mengesahkan"}. {"vCard User Search","vCard Pencarian Pengguna"}. {"Virtual Hosts","Virtual Hosts"}. +{"Visitors are not allowed to change their nicknames in this room","Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini"}. +{"Visitors are not allowed to send messages to all occupants","Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni"}. {"Wednesday","Rabu"}. {"When to send the last published item","Ketika untuk mengirim item terakhir yang dipublikasikan"}. {"Whether to allow subscriptions","Apakah diperbolehkan untuk berlangganan"}. {"You can later change your password using a Jabber client.","Anda dapat mengubah kata sandi anda dilain waktu dengan menggunakan klien Jabber."}. +{"You have been banned from this room","Anda telah diblokir dari ruangan ini"}. +{"You must fill in field \"Nickname\" in the form","Anda harus mengisi kolom \"Julukan\" dalam formulir"}. {"You need a client that supports x:data and CAPTCHA to register","Anda memerlukan klien yang mendukung x:data dan CAPTCHA untuk mendaftar"}. {"You need a client that supports x:data to register the nickname","Anda memerlukan klien yang mendukung x:data untuk mendaftar julukan"}. {"You need an x:data capable client to configure mod_irc settings","Anda memerlukan x:data klien untuk mampu mengkonfigurasi pengaturan mod_irc"}. {"You need an x:data capable client to configure room","Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan"}. {"You need an x:data capable client to search","Anda memerlukan x:data klien untuk melakukan pencarian"}. +{"Your active privacy list has denied the routing of this stanza.","Daftar privasi aktif Anda telah menolak routing ztanza ini"}. +{"Your contact offline message queue is full. The message has been discarded.","Kontak offline Anda pada antrian pesan sudah penuh. Pesan telah dibuang."}. {"Your Jabber account was successfully created.","Jabber akun Anda telah sukses dibuat"}. {"Your Jabber account was successfully deleted.","Jabber akun Anda berhasil dihapus."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Pesan Anda untuk ~s sedang diblokir. Untuk membuka blokir tersebut, kunjungi ~s"}. diff --git a/priv/msgs/id.po b/priv/msgs/id.po index 67b4018d188..bd774603922 100644 --- a/priv/msgs/id.po +++ b/priv/msgs/id.po @@ -11,52 +11,56 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Indonesian (Bahasa Indonesia)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Penggunaan STARTTLS diperlukan" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Tidak ada sumber daya yang disediakan" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Diganti dengan koneksi baru" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "telah dikick" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Daftar privasi aktif Anda telah menolak routing ztanza ini" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Masukkan teks yang Anda lihat" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Pesan Anda untuk ~s sedang diblokir. Untuk membuka blokir tersebut, kunjungi " "~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "Jika Anda tidak melihat gambar CAPTCHA disini, silahkan kunjungi halaman web." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA laman web" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Captcha ini benar." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Pengguna" @@ -65,9 +69,9 @@ msgstr "Pengguna" msgid "Server" msgstr "Layanan:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Sandi" @@ -84,279 +88,280 @@ msgstr "Ditolak" msgid "ejabberd Web Admin" msgstr "Admin Web ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrasi" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Akses Daftar Pengendalian" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Ulangi masukan" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Format yang buruk" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Serahkan" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "mentah" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Hapus Yang Terpilih" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Aturan Akses" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s aturan akses konfigurasi" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtual Hosts" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Pengguna" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Pengguna Yang Online" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Aktifitas terakhir para pengguna" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periode:" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Akhir bulan" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Akhir tahun" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Semua aktifitas" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Tampilkan Tabel Normal" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Tampilkan Tabel Terpisah" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistik" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Tidak Ditemukan" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Node tidak ditemukan" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Tambah Baru" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Pengguna Terdaftar" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Tambah Pengguna" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Pesan Offline" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Aktifitas Terakhir" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Tidak Pernah" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Pengguna Terdaftar:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Pengguna Online:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Koneksi s2s yang keluar:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Layanan s2s yang keluar:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Koneksi s2s yang keluar:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Tak satupun" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Ubah Kata Sandi" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Pengguna" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Sumber Daya Terhubung:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Kata Sandi:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Hapus Pengguna" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Tidak Ada Data" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Node-node" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Menjalankan Node" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Menghentikan node" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Node" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Backup" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Port Terdeteksi" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Memperbarui" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Jalankan Ulang" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Hentikan" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modul" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Panggilan Kesalahan RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabel Database pada" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nama" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Jenis Penyimpanan" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elemen-elemen" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memori" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Kesalahan" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Cadangan dari" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -366,146 +371,146 @@ msgstr "" "database. Jika Anda menggunakan modul ODBC, anda juga perlu untuk membuat " "cadangan database SQL Anda secara terpisah." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Penyimpanan cadangan yang berpasangan:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "YA" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Segera mengembalikan cadangan yang berpasangan:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Mengembalikan cadangan yang berpasanagn setelah ejabberd berikutnya " "dijalankan ulang (memerlukan memori lebih sedikit):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Simpan cadangan teks biasa:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Segera mengembalikan cadangan teks biasa:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "impor data-data pengguna dari sebuah PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Ekspor data dari semua pengguna pada layanan ke berkas PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Ekspor data pengguna pada sebuah host ke berkas PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Impor data pengguna dari sekumpulan berkas jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Импорт пользовательских данных из буферной директории jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Mendeteksi Port-port di" -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "modul-modul di" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "statistik dari ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Sampai saat:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Waktu CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaksi yang dilakukan:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaksi yang dibatalkan:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaksi yang dijalankan ulang:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaksi yang ditempuh:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Memperbarui " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Rencana Perubahan" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Modifikasi modul-modul" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Perbarui naskah" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Perbaruan naskah tingkat rendah" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Periksa naskah" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Pilihan-pilihan" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Mulai" @@ -791,8 +796,8 @@ msgstr "Akses peraturan" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -809,31 +814,31 @@ msgstr "Jumlah pengguna terdaftar" msgid "Number of online users" msgstr "Jumlah pengguna online" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Terakhir Login" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Ukuran Daftar Kontak" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Alamat IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Sumber daya" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrasi" -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Tindakan pada pengguna" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Ganti Properti" @@ -843,28 +848,40 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Akses ditolak oleh kebijakan layanan" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Anda memerlukan x:data klien untuk mampu mengkonfigurasi pengaturan mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Pendaftaran di mod_irc untuk" -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -872,11 +889,11 @@ msgstr "" "Masukkan username, pengkodean, port dan sandi yang ingin Anda gunakan untuk " "menghubungkan ke layanan IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nama Pengguna IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -888,7 +905,7 @@ msgstr "" "\", \"encoding \", port, \"sandi \"}'. Secara default ini menggunakan " "layanan \"~s \" pengkodean, port ~p, kata sandi kosong." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -896,35 +913,35 @@ msgstr "" "Contoh: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parameter Koneksi" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Gabung channel IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Channel IRC (tidak perlu menempatkan # sebelumnya)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Layanan IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Gabung ke channel IRC disini" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Gabung ke channel IRC dengan Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Pengaturan IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -934,48 +951,80 @@ msgstr "" "ke layanan IRC. Tekan 'Selanjutnya' untuk mendapatkan lagi formulir kemudian " "Tekan 'Lengkap' untuk menyimpan pengaturan." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nama Pengguna IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Kata Sandi ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Pengkodean untuk layanan ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Layanan ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "" +"Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Layanan hanya diperuntukan kepada administrator yang diizinkan untuk " +"mengirim layanan pesan" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Pembuatan Ruangan ditolak oleh kebijakan layanan" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Ruang Konferensi tidak ada" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Ruangan Chat" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Anda memerlukan klien yang mendukung x:data untuk mendaftar julukan" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Pendaftaran Julukan pada" -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Masukkan nama julukan Anda jika ingin mendaftar" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Nama Julukan" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Julukan tersebut telah didaftarkan oleh orang lain" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Anda harus mengisi kolom \"Julukan\" dalam formulir" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC Module" @@ -1003,143 +1052,204 @@ msgstr "Pengguna Terdaftar" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Konfigurasi ruang chat diubah" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "bergabung ke ruangan" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "meninggalkan ruangan" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "telah dibanned" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "telah dikick karena perubahan afiliasi" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "telah dikick karena ruangan telah diubah menjadi hanya untuk member" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "telah dikick karena sistem shutdown" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "sekarang dikenal sebagai" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr "telah menetapkan topik yaitu:" -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Ruang chat telah dibuat" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Ruang chat dilenyapkan" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Ruang chat dimulai" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Ruang chat dihentikan" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Senin" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Selasa" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Rabu" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Kamis" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Jumat" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sabtu" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Minggu" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Januari" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Februari" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Maret" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "April" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Mei" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Agustus" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "September" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Nopember" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Desember" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Konfigurasi Ruangan" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Penghuni Ruangan" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Lalu lintas melebihi batas" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi ke konferensi" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Perbolehkan pengguna mengirimkan undangan" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Jenis pesan yang tidak benar" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"Hal ini tidak diperbolehkan untuk mengirim pesan pribadi jenis \"groupchat \"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Penerima tidak berada di ruangan konferensi" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Hanya penghuni yang diizinkan untuk mengirim pesan ke konferensi" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Hanya penghuni diizinkan untuk mengirim permintaan ke konferensi" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Permintaan untuk para anggota konferensi tidak diperbolehkan di ruangan ini" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1147,215 +1257,286 @@ msgstr "" "Hanya moderator dan peserta yang diizinkan untuk mengganti topik pembicaraan " "di ruangan ini" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "" "Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Julukan itu sudah digunakan oleh penghuni lain" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Anda telah diblokir dari ruangan ini" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Hanya Member yang dapat masuk ruangan ini" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Diperlukan kata sandi untuk masuk ruangan ini" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Tidak dapat menghasilkan CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Kata sandi salah" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Hak istimewa Administrator dibutuhkan" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Hak istimewa moderator dibutuhkan" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s tidak valid" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Nama Julukan ~s tidak berada di dalam ruangan" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliasi tidak valid: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Peran tidak valid: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Hak istimewa owner dibutuhkan" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Pengaturan ruangan ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Nama Ruangan" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Keterangan ruangan" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Buat ruangan menjadi permanent" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Buat ruangan dapat dicari" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Buat daftar participant diketahui oleh public" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Buat ruangan yang dilindungi dengan kata sandi" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maksimum Jumlah Penghuni" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Tidak terbatas" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Tampilkan Jabber ID secara lengkap" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "Hanya moderator" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "Siapapun" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "Hanya moderator" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Buat ruangan hanya untuk member saja" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Buat ruangan hanya untuk moderator saja" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "pengguna pertama kali masuk sebagai participant" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Perbolehkan pengguna untuk mengganti topik" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "perbolehkan pengguna mengirimkan pesan ke pengguna lain secara pribadi" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Perbolehkan pengguna untuk mengetahui pengguna lain" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Perbolehkan pengguna mengirimkan undangan" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Izinkan pengunjung untuk mengirim teks status terbaru" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Perbolehkan visitor mengganti nama julukan" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Perbolehkan pengguna mengirimkan undangan" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Buat ruangan dilindungi dengan CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Aktifkan catatan" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Jumlah Penghuni" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "pribadi, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Pengguna" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s mengundang anda ke ruangan ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "kata sandi yaitu:" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Kontak offline Anda pada antrian pesan sudah penuh. Pesan telah dibuang." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Antrian Pesan Offline ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Waktu" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Dari" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Kepada" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Pesan Offline:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Hapus Semua Pesan Offline" @@ -1363,115 +1544,127 @@ msgstr "Hapus Semua Pesan Offline" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "modul ejabberd SOCKS5 Bytestreams" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Setujui-Pertemanan" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Modul ejabberd Setujui-Pertemanan" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Permintaan pertemanan PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Pilih apakah akan menyetujui hubungan pertemanan ini." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID Node" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Alamat Pertemanan" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Izinkan ID Jabber ini untuk berlangganan pada node pubsub ini?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Memberikan muatan dengan pemberitahuan acara" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Memberikan pemberitahuan acara" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Beritahu pelanggan ketika ada perubahan konfigurasi node" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Beritahu pelanggan ketika node dihapus" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Beritahu pelanggan ketika item tersebut dikeluarkan dari node" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Pertahankan item ke penyimpanan" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Nama yang dikenal untuk node" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Max item untuk bertahan" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Apakah diperbolehkan untuk berlangganan" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Tentukan model akses" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kelompok kontak yang diizinkan untuk berlangganan" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Tentukan model penerbitan" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Bersihkan semua item ketika penerbit yang relevan telah offline" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Tentukan jenis acara pesan" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Max kapasitas ukuran dalam bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Ketika untuk mengirim item terakhir yang dipublikasikan" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Hanya mengirimkan pemberitahuan kepada pengguna yang tersedia" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Koleksi dengan yang berafiliasi dengan sebuah node" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Verifikasi CAPTCHA telah gagal" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Anda memerlukan klien yang mendukung x:data dan CAPTCHA untuk mendaftar" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Pilih nama pengguna dan kata sandi untuk mendaftar dengan layanan ini" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Kata sandi terlalu lemah" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Pengguna tidak diperkenankan untuk mendaftar akun begitu cepat" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Jabber akun Anda telah sukses dibuat" @@ -1552,8 +1745,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Beberapa klien Jabber dapat menyimpan password di komputer Anda. Gunakan " "fitur itu hanya jika Anda mempercayai komputer Anda aman." @@ -1594,60 +1787,60 @@ msgstr "" msgid "Unregister" msgstr "Nonaktifkan" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Berlangganan" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Tertunda" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grup" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Mengesahkan" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Menghapus" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontak dari" -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Tambah Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Kontak" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Berbagi grup kontak" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nama:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Keterangan:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Anggota:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Tampilkan Grup:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grup" @@ -1723,49 +1916,19 @@ msgstr "Hasil Pencarian untuk" msgid "Fill in fields to search for any matching Jabber User" msgstr "Isi kolom untuk mencari pengguna Jabber yang sama" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Layanan s2s yang keluar:" + #~ msgid "Delete" #~ msgstr "Hapus" #~ msgid "This room is not anonymous" #~ msgstr "Ruangan ini tidak dikenal" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Daftar privasi aktif Anda telah menolak routing ztanza ini" - -#~ msgid "Access denied by service policy" -#~ msgstr "Akses ditolak oleh kebijakan layanan" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Layanan hanya diperuntukan kepada administrator yang diizinkan untuk " -#~ "mengirim layanan pesan" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Pembuatan Ruangan ditolak oleh kebijakan layanan" - -#~ msgid "Conference room does not exist" -#~ msgstr "Ruang Konferensi tidak ada" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Julukan tersebut telah didaftarkan oleh orang lain" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Anda harus mengisi kolom \"Julukan\" dalam formulir" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Lalu lintas melebihi batas" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "Peserta ini dikick dari ruangan karena dia mengirim pesan kesalahan" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "" -#~ "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi ke konferensi" - -#~ msgid "Improper message type" -#~ msgstr "Jenis pesan yang tidak benar" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1773,82 +1936,11 @@ msgstr "Isi kolom untuk mencari pengguna Jabber yang sama" #~ "Participant ini dikick dari ruangan karena ia mengirim pesan kesalahan ke " #~ "participant lain" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi jenis " -#~ "\"groupchat \"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Penerima tidak berada di ruangan konferensi" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Hanya penghuni yang diizinkan untuk mengirim pesan ke konferensi" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Hanya penghuni diizinkan untuk mengirim permintaan ke konferensi" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Permintaan untuk para anggota konferensi tidak diperbolehkan di ruangan " -#~ "ini" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Visitor tidak diperbolehkan untuk mengirim pesan ke semua penghuni" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Participant ini dikick dari ruangan karena ia mengirim kehadiran kesalahan" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Visitor tidak diperbolehkan untuk mengubah nama julukan di ruangan ini" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Julukan itu sudah digunakan oleh penghuni lain" - -#~ msgid "You have been banned from this room" -#~ msgstr "Anda telah diblokir dari ruangan ini" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Hanya Member yang dapat masuk ruangan ini" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Diperlukan kata sandi untuk masuk ruangan ini" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Tidak dapat menghasilkan CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Kata sandi salah" - -#~ msgid "Administrator privileges required" -#~ msgstr "Hak istimewa Administrator dibutuhkan" - -#~ msgid "Moderator privileges required" -#~ msgstr "Hak istimewa moderator dibutuhkan" - -#~ msgid "Owner privileges required" -#~ msgstr "Hak istimewa owner dibutuhkan" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Kontak offline Anda pada antrian pesan sudah penuh. Pesan telah dibuang." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Verifikasi CAPTCHA telah gagal" - -#~ msgid "The password is too weak" -#~ msgstr "Kata sandi terlalu lemah" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Pengguna tidak diperkenankan untuk mendaftar akun begitu cepat" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Проверка капчи прошла успешно." diff --git a/priv/msgs/it.msg b/priv/msgs/it.msg index b29c8fb0c64..3dc7d8336c3 100644 --- a/priv/msgs/it.msg +++ b/priv/msgs/it.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Configurazione dei diritti di accesso (ACL)"}. {"Access control lists","Diritti di accesso (ACL)"}. {"Access Control Lists","Diritti di accesso (ACL)"}. +{"Access denied by service policy","Accesso impedito dalle politiche del servizio"}. {"Access rules","Regole di accesso"}. {"Access Rules","Regole di accesso"}. {"Action on user","Azione sull'utente"}. @@ -11,6 +12,7 @@ {"Add User","Aggiungere un utente"}. {"Administration","Amministrazione"}. {"Administration of ","Amministrazione di "}. +{"Administrator privileges required","Necessari i privilegi di amministratore"}. {"A friendly name for the node","Un nome comodo per il nodo"}. {"All activity","Tutta l'attività"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Consentire a questo Jabber ID l'iscrizione a questo nodo pubsub?"}. @@ -25,6 +27,7 @@ {"All Users","Tutti gli utenti"}. {"Announcements","Annunci"}. {"anyone","tutti"}. +{"A password is required to enter this room","Per entrare in questa stanza è prevista una password"}. {"April","Aprile"}. {"August","Agosto"}. {"Backup Management","Gestione dei salvataggi"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","Scegliere se approvare l'iscrizione per questa entità"}. {"City","Città"}. {"Commands","Comandi"}. +{"Conference room does not exist","La stanza per conferenze non esiste"}. {"Configuration","Configurazione"}. {"Configuration of room ~s","Configurazione per la stanza ~s"}. {"Connected Resources:","Risorse connesse:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","Escludi degli ID Jabber dal passaggio CAPTCHA"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Esportare i dati di tutti gli utenti nel server in file PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Esportare i dati degli utenti di un host in file PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Impossibile estrarre il JID dall'approvazione della richiesta di parola"}. {"Family Name","Cognome"}. {"February","Febbraio"}. {"Fill in fields to search for any matching Jabber User","Riempire i campi per la ricerca di utenti Jabber corrispondenti ai criteri"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","Importare i dati utenti da directory di spool di jabberd14:"}. {"Import Users from Dir at ","Importare utenti dalla directory "}. {"Import Users From jabberd14 Spool Files","Importare utenti da file di spool di jabberd14"}. +{"Improper message type","Tipo di messaggio non corretto"}. +{"Incorrect password","Password non esatta"}. {"Invalid affiliation: ~s","Affiliazione non valida: ~s"}. {"Invalid role: ~s","Ruolo non valido: ~s"}. {"IP addresses","Indirizzi IP"}. @@ -142,6 +149,9 @@ {"IRC username","Nome utente IRC"}. {"IRC Username","Nome utente IRC"}. {"is now known as","è ora conosciuta/o come"}. +{"It is not allowed to send private messages","Non è consentito l'invio di messaggi privati"}. +{"It is not allowed to send private messages of type \"groupchat\"","Non è consentito l'invio di messaggi privati di tipo \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Non è consentito l'invio di messaggi privati alla conferenza"}. {"Jabber Account Registration","Registrazione account Jabber"}. {"Jabber ID","Jabber ID (Jabber ID)"}. {"Jabber ID ~s is invalid","Il Jabber ID ~s non è valido"}. @@ -173,12 +183,14 @@ {"Max # of items to persist","Numero massimo di elementi da conservare persistentemente"}. {"Max payload size in bytes","Dimensione massima del contenuto del messaggio in byte"}. {"May","Maggio"}. +{"Membership is required to enter this room","Per entrare in questa stanza è necessario essere membro"}. {"Members:","Membri:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memorizza la password, o scrivila su un foglio di carta da conservare in un luogo sicuro. Jabber non prevede una modalità automatica per il recupero di una password dimenticata."}. {"Memory","Memoria"}. {"Message body","Corpo del messaggio"}. {"Middle Name","Altro nome"}. {"Minimum interval between voice requests (in seconds)","Intervallo minimo fra due richieste di parola (in secondi)"}. +{"Moderator privileges required","Necessari i privilegi di moderatore"}. {"moderators only","moderatori soltanto"}. {"Modified modules","Moduli modificati"}. {"Module","Modulo"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","Inviare le notifiche solamente agli utenti disponibili"}. {"Only moderators and participants are allowed to change the subject in this room","La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori e ai partecipanti"}. {"Only moderators are allowed to change the subject in this room","La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori"}. +{"Only moderators can approve voice requests","Soltanto i moderatori possono approvare richieste di parola"}. +{"Only occupants are allowed to send messages to the conference","L'invio di messaggi alla conferenza è consentito soltanto ai presenti"}. +{"Only occupants are allowed to send queries to the conference","L'invio di query alla conferenza è consentito ai soli presenti"}. +{"Only service administrators are allowed to send service messages","L'invio di messaggi di servizio è consentito solamente agli amministratori del servizio"}. {"Options","Opzioni"}. {"Organization Name","Nome dell'organizzazione"}. {"Organization Unit","Unità dell'organizzazione"}. {"Outgoing s2s Connections:","Connessioni s2s in uscita:"}. {"Outgoing s2s Connections","Connessioni s2s in uscita"}. -{"Outgoing s2s Servers:","Server s2s in uscita"}. +{"Owner privileges required","Necessari i privilegi di proprietario"}. {"Packet","Pacchetto"}. {"Password ~b","Password ~b"}. {"Password:","Password:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","Conservazione persistente degli elementi"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","N.B.: Queste opzioni comportano il salvataggio solamente del database interno Mnesia. Se si sta utilizzando il modulo ODBC, è necessario salvare anche il proprio database SQL separatamente."}. +{"Please, wait for a while before sending new voice request","Attendi qualche istante prima di inviare una nuova richiesta di parola"}. {"Pong","Pong"}. {"Port ~b","Porta ~b"}. {"Port","Porta"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","Pubblicazione-Iscrizione"}. {"PubSub subscriber request","Richiesta di iscrizione per PubSub"}. {"Purge all items when the relevant publisher goes offline","Cancella tutti gli elementi quando chi li ha pubblicati non è più online"}. +{"Queries to the conference members are not allowed in this room","In questa stanza non sono consentite query ai membri della conferenza"}. {"RAM and disc copy","Copia in memoria (RAM) e su disco"}. {"RAM copy","Copia in memoria (RAM)"}. {"Raw","Grezzo"}. {"Really delete message of the day?","Si conferma l'eliminazione del messaggio del giorno (MOTD)?"}. +{"Recipient is not in the conference room","Il destinatario non è nella stanza per conferenze"}. {"Register a Jabber account","Registra un account Jabber"}. {"Registered Users:","Utenti registrati:"}. {"Registered Users","Utenti registrati"}. @@ -270,6 +289,7 @@ {"Restore plain text backup immediately:","Recuperare un salvataggio come semplice testo adesso:"}. {"Restore","Recuperare"}. {"Room Configuration","Configurazione della stanza"}. +{"Room creation is denied by service policy","La creazione di stanze è impedita dalle politiche del servizio"}. {"Room description","Descrizione della stanza"}. {"Room Occupants","Presenti nella stanza"}. {"Room title","Titolo della stanza"}. @@ -298,7 +318,7 @@ {"Show Ordinary Table","Mostrare la tabella normale"}. {"Shut Down Service","Terminare il servizio"}. {"~s invites you to the room ~s","~s ti invita nella stanza ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Alcuni client Jabber possono conservare la password nel tuo computer. Utilizza tale funzione soltanto se ritieni che il tuo computer sia sicuro."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alcuni client Jabber possono conservare la password nel tuo computer. Utilizza tale funzione soltanto se ritieni che il tuo computer sia sicuro."}. {"Specify the access model","Specificare il modello di accesso"}. {"Specify the event message type","Specificare il tipo di messaggio di evento"}. {"Specify the publisher model","Definire il modello di pubblicazione"}. @@ -321,9 +341,13 @@ {"Subscriber Address","Indirizzo dell'iscritta/o"}. {"Subscription","Iscrizione"}. {"Sunday","Domenica"}. +{"That nickname is already in use by another occupant","Il nickname è già in uso all'interno della conferenza"}. +{"That nickname is registered by another person","Questo nickname è registrato da un'altra persona"}. {"The CAPTCHA is valid.","Il CAPTCHA è valido."}. +{"The CAPTCHA verification has failed","La verifica del CAPTCHA ha avuto esito negativo"}. {"The collections with which a node is affiliated","Le collezioni a cui è affiliato un nodo"}. {"the password is","la password è"}. +{"The password is too weak","La password è troppo debole"}. {"The password of your Jabber account was successfully changed.","Il cambio di password del tuo account Jabber è andato a buon fine."}. {"There was an error changing the password: ","Si è verificato un errore nel cambio di password: "}. {"There was an error creating the account: ","Si è verificato un errore nella creazione dell'account: "}. @@ -335,12 +359,15 @@ {"Time delay","Ritardo"}. {"Time","Ora"}. {"To","A"}. +{"Too many CAPTCHA requests","Troppe richieste CAPTCHA"}. {"To ~s","A ~s"}. +{"Traffic rate limit is exceeded","Limite di traffico superato"}. {"Transactions Aborted:","Transazioni abortite:"}. {"Transactions Committed:","Transazioni avvenute:"}. {"Transactions Logged:","Transazioni con log:"}. {"Transactions Restarted:","Transazioni riavviate:"}. {"Tuesday","Martedì"}. +{"Unable to generate a CAPTCHA","Impossibile generare un CAPTCHA"}. {"Unauthorized","Non autorizzato"}. {"Unregister a Jabber account","Elimina un account Jabber"}. {"Unregister","Elimina"}. @@ -354,22 +381,30 @@ {"User JID","JID utente"}. {"User Management","Gestione degli utenti"}. {"Username:","Nome utente:"}. +{"Users are not allowed to register accounts so quickly","Non è consentito agli utenti registrare account così rapidamente"}. {"Users Last Activity","Ultima attività degli utenti"}. {"Users","Utenti"}. {"User","Utente"}. {"Validate","Validare"}. {"vCard User Search","Ricerca di utenti per vCard"}. {"Virtual Hosts","Host Virtuali"}. +{"Visitors are not allowed to change their nicknames in this room","Non è consentito ai visitatori cambiare il nickname in questa stanza"}. +{"Visitors are not allowed to send messages to all occupants","Non è consentito ai visitatori l'invio di messaggi a tutti i presenti"}. {"Voice request","Richiesta di parola"}. +{"Voice requests are disabled in this conference","In questa conferenza le richieste di parola sono escluse"}. {"Wednesday","Mercoledì"}. {"When to send the last published item","Quando inviare l'ultimo elemento pubblicato"}. {"Whether to allow subscriptions","Consentire iscrizioni?"}. {"You can later change your password using a Jabber client.","Potrai in seguito cambiare la password utilizzando un client Jabber."}. +{"You have been banned from this room","Sei stata/o bandita/o da questa stanza"}. +{"You must fill in field \"Nickname\" in the form","Si deve riempire il campo \"Nickname\" nel modulo"}. {"You need a client that supports x:data and CAPTCHA to register","La registrazione richiede un client che supporti x:data e CAPTCHA"}. {"You need a client that supports x:data to register the nickname","Per registrare il nickname è necessario un client che supporti x:data"}. {"You need an x:data capable client to configure mod_irc settings","Per la configurazione del modulo IRC è necessario un client che supporti x:data"}. {"You need an x:data capable client to configure room","Per la configurazione della stanza è necessario un client che supporti x:data"}. {"You need an x:data capable client to search","Per effettuare ricerche è necessario un client che supporti x:data"}. +{"Your active privacy list has denied the routing of this stanza.","In base alla tua attuale lista privacy questa stanza è stata esclusa dalla navigazione."}. +{"Your contact offline message queue is full. The message has been discarded.","La coda dei messaggi offline del contatto è piena. Il messaggio è stato scartato"}. {"Your Jabber account was successfully created.","La creazione del tuo account Jabber è andata a buon fine."}. {"Your Jabber account was successfully deleted.","La cancellazione del tuo account Jabber è andata a buon fine."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","I messaggi verso ~s sono bloccati. Per sbloccarli, visitare ~s"}. diff --git a/priv/msgs/it.po b/priv/msgs/it.po index 1c703633dff..e69d6ed9095 100644 --- a/priv/msgs/it.po +++ b/priv/msgs/it.po @@ -15,49 +15,55 @@ msgstr "" "X-Generator: Lokalize 1.2\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Utilizzo di STARTTLS obbligatorio" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nessuna risorsa fornita" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Sostituito da una nuova connessione" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "è stata/o espulsa/o" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" +"In base alla tua attuale lista privacy questa stanza è stata esclusa dalla " +"navigazione." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Immettere il testo visibile" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "I messaggi verso ~s sono bloccati. Per sbloccarli, visitare ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Se qui non vedi l'immagine CAPTCHA, visita la pagina web." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Pagina web CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Il CAPTCHA è valido." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Utente" @@ -66,9 +72,9 @@ msgstr "Utente" msgid "Server" msgstr "Server:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Password" @@ -85,279 +91,280 @@ msgstr "Non autorizzato" msgid "ejabberd Web Admin" msgstr "Amministrazione web ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Amministrazione" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Diritti di accesso (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Inviato" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Formato non valido" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Inviare" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Grezzo" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Eliminare gli elementi selezionati" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Regole di accesso" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configurazione delle regole di accesso per ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Host Virtuali" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Utenti" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Utenti online" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Ultima attività degli utenti" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periodo:" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Ultimo mese" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Ultimo anno" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tutta l'attività" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrare la tabella normale" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrare la tabella integrale" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistiche" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Non trovato" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo non trovato" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Aggiungere nuovo" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Utenti registrati" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Aggiungere un utente" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Messaggi offline" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Ultima attività" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Mai" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Utenti registrati:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Utenti connessi:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Connessioni s2s in uscita:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Server s2s in uscita" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Connessioni s2s in uscita:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nessuno" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Modificare la password" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Utente " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Risorse connesse:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Password:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminare l'utente" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Nessuna informazione" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodi" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodi attivi" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodi arrestati" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nodo " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Salvare" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Porte in ascolto" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aggiornare" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Riavviare" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Arrestare" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduli" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Errore di chiamata RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelle del database su " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo di conservazione" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementi" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memoria" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Errore" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Salvataggio di " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -367,146 +374,146 @@ msgstr "" "interno Mnesia. Se si sta utilizzando il modulo ODBC, è necessario salvare " "anche il proprio database SQL separatamente." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Conservare un salvataggio binario:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Recuperare un salvataggio binario adesso:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Recuperare un salvataggio binario dopo il prossimo riavvio di ejabberd " "(necessita di meno memoria):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Conservare un salvataggio come semplice testo:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Recuperare un salvataggio come semplice testo adesso:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importare i dati utenti da un file PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Esportare i dati di tutti gli utenti nel server in file PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Esportare i dati degli utenti di un host in file PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importare i dati utente da file di spool di jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importare i dati utenti da directory di spool di jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Porte in ascolto su " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduli su " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistiche di ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tempo dall'avvio:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tempo CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transazioni avvenute:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transazioni abortite:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transazioni riavviate:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transazioni con log:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Aggiornare " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Piano di aggiornamento" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Moduli modificati" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script di aggiornamento" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script di aggiornamento di basso livello" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Verifica dello script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porta" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocollo" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modulo" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opzioni" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Avviare" @@ -795,8 +802,8 @@ msgstr "Regole di accesso" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID (Jabber ID)" @@ -813,31 +820,31 @@ msgstr "Numero di utenti registrati" msgid "Number of online users" msgstr "Numero di utenti online" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Ultimo accesso" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Dimensione della lista dei contatti" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Indirizzi IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Risorse" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Amministrazione di " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Azione sull'utente" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Modificare le proprietà" @@ -847,29 +854,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Accesso impedito dalle politiche del servizio" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transport IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Modulo IRC per ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Per la configurazione del modulo IRC è necessario un client che supporti x:" "data" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registrazione in mod_irc per " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -877,11 +896,11 @@ msgstr "" "Immettere il nome utente, le codifiche, le porte e le password che si " "desidera utilizzare per la connessione ai server IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nome utente IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -893,7 +912,7 @@ msgstr "" "\", \"codifica\", porta, \"password\"}'. Per default questo servizio " "utilizza la codifica \"~s\", la porta ~p, la password vuota." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -901,35 +920,35 @@ msgstr "" "Esempio: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"segreto\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.serverdiprova.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parametri delle connessioni" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Entra nel canale IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canale IRC (senza il # iniziale)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Server IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Entra nel canale IRC qui." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Entra nel canale IRC in questo ID Jabber: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Impostazioni IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -939,48 +958,80 @@ msgstr "" "connessione ai server IRC. Premere \"Avanti\" per vedere i successivi campi " "da compilare. Premere \"Fatto\" per salvare le impostazioni." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nome utente IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Password ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Porta ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codifica per il server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "" +"La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"L'invio di messaggi di servizio è consentito solamente agli amministratori " +"del servizio" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "La creazione di stanze è impedita dalle politiche del servizio" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "La stanza per conferenze non esiste" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Stanze" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Per registrare il nickname è necessario un client che supporti x:data" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registrazione di un nickname su " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Immettere il nickname che si vuole registrare" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Nickname" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Questo nickname è registrato da un'altra persona" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Si deve riempire il campo \"Nickname\" nel modulo" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Modulo MUC per ejabberd" @@ -1008,143 +1059,202 @@ msgstr "Utenti registrati" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configurazione della stanza modificata" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "entra nella stanza" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "esce dalla stanza" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "è stata/o bandita/o" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "è stato espulso a causa di un cambiamento di appartenenza" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "è stato espulso per la limitazione della stanza ai soli membri" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "è stato espulso a causa dello spegnimento del sistema" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "è ora conosciuta/o come" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ha modificato l'oggetto in: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "La stanza è creata" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "La stanza è eliminata" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "La stanza è avviata" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "La stanza è arrestata" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Lunedì" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Martedì" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Mercoledì" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Giovedì" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Venerdì" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sabato" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Domenica" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Gennaio" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Febbraio" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Marzo" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Aprile" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Maggio" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Giugno" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Luglio" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Settembre" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Ottobre" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Novembre" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Dicembre" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configurazione della stanza" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Presenti nella stanza" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Limite di traffico superato" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Non è consentito l'invio di messaggi privati alla conferenza" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Attendi qualche istante prima di inviare una nuova richiesta di parola" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "In questa conferenza le richieste di parola sono escluse" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" +"Impossibile estrarre il JID dall'approvazione della richiesta di parola" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Soltanto i moderatori possono approvare richieste di parola" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Tipo di messaggio non corretto" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Non è consentito l'invio di messaggi privati di tipo \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Il destinatario non è nella stanza per conferenze" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Non è consentito l'invio di messaggi privati" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "L'invio di messaggi alla conferenza è consentito soltanto ai presenti" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "L'invio di query alla conferenza è consentito ai soli presenti" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "In questa stanza non sono consentite query ai membri della conferenza" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1152,215 +1262,287 @@ msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai " "moderatori e ai partecipanti" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Non è consentito ai visitatori l'invio di messaggi a tutti i presenti" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Non è consentito ai visitatori cambiare il nickname in questa stanza" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Il nickname è già in uso all'interno della conferenza" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Sei stata/o bandita/o da questa stanza" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Per entrare in questa stanza è necessario essere membro" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Per entrare in questa stanza è prevista una password" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Troppe richieste CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Impossibile generare un CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Password non esatta" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Necessari i privilegi di amministratore" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Necessari i privilegi di moderatore" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Il Jabber ID ~s non è valido" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Il nickname ~s non esiste nella stanza" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Affiliazione non valida: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ruolo non valido: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Necessari i privilegi di proprietario" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Configurazione per la stanza ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Titolo della stanza" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descrizione della stanza" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Rendere la stanza persistente" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Rendere la sala visibile al pubblico" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Rendere pubblica la lista dei partecipanti" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Rendere la stanza protetta da password" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Numero massimo di occupanti" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Nessun limite" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Rendere visibile il Jabber ID reale a" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderatori soltanto" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "tutti" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "moderatori soltanto" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Rendere la stanza riservata ai membri" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Rendere la stanza moderata" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Definire per default gli utenti come partecipanti" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Consentire agli utenti di cambiare l'oggetto" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Consentire agli utenti l'invio di messaggi privati" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Consentire agli ospiti l'invio di messaggi privati a" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "nessuno" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Consentire agli utenti query verso altri utenti" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Consentire agli utenti l'invio di inviti" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Consentire ai visitatori l'invio di testo sullo stato in aggiornamenti sulla " "presenza" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Consentire ai visitatori di cambiare il nickname" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Consentire agli ospiti l'invio di richieste di parola" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Intervallo minimo fra due richieste di parola (in secondi)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Rendere la stanza protetta da CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Escludi degli ID Jabber dal passaggio CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Abilitare i log" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Per la configurazione della stanza è necessario un client che supporti x:data" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Numero di presenti" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privato, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Richiesta di parola" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Approva oppure respingi la richiesta di parola." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID utente" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Dare parola a questa persona?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s ti invita nella stanza ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "la password è" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"La coda dei messaggi offline del contatto è piena. Il messaggio è stato " +"scartato" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Coda di ~s messaggi offline" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Ora" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Da" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "A" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pacchetto" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Messaggi offline:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Eliminare tutti i messaggi offline" @@ -1368,117 +1550,129 @@ msgstr "Eliminare tutti i messaggi offline" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Modulo SOCKS5 Bytestreams per ejabberd" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Pubblicazione-Iscrizione" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Modulo Pubblicazione/Iscrizione (PubSub) per ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Richiesta di iscrizione per PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Scegliere se approvare l'iscrizione per questa entità" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID del nodo" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Indirizzo dell'iscritta/o" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Consentire a questo Jabber ID l'iscrizione a questo nodo pubsub?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Inviare il contenuto del messaggio con la notifica dell'evento" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Inviare notifiche degli eventi" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notificare gli iscritti quando la configurazione del nodo cambia" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificare gli iscritti quando il nodo è cancellato" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Notificare gli iscritti quando sono eliminati degli elementi dal nodo" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Conservazione persistente degli elementi" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Un nome comodo per il nodo" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Numero massimo di elementi da conservare persistentemente" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Consentire iscrizioni?" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Specificare il modello di accesso" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Gruppi roster abilitati alla registrazione" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Definire il modello di pubblicazione" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Cancella tutti gli elementi quando chi li ha pubblicati non è più online" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Specificare il tipo di messaggio di evento" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Dimensione massima del contenuto del messaggio in byte" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Quando inviare l'ultimo elemento pubblicato" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Inviare le notifiche solamente agli utenti disponibili" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Le collezioni a cui è affiliato un nodo" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "La verifica del CAPTCHA ha avuto esito negativo" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "La registrazione richiede un client che supporti x:data e CAPTCHA" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Scegliere un nome utente e una password per la registrazione con questo " "server" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "La password è troppo debole" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Non è consentito agli utenti registrare account così rapidamente" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "La creazione del tuo account Jabber è andata a buon fine." @@ -1557,8 +1751,8 @@ msgstr "Potrai in seguito cambiare la password utilizzando un client Jabber." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Alcuni client Jabber possono conservare la password nel tuo computer. " "Utilizza tale funzione soltanto se ritieni che il tuo computer sia sicuro." @@ -1599,60 +1793,60 @@ msgstr "" msgid "Unregister" msgstr "Elimina" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Iscrizione" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Gruppi" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validare" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Eliminare" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista dei contatti di " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Aggiungere un Jabber ID (Jabber ID)" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Lista dei contatti" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Gruppi di liste di contatti comuni" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nome:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descrizione:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membri:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Gruppi visualizzati:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Gruppo " @@ -1729,66 +1923,21 @@ msgid "Fill in fields to search for any matching Jabber User" msgstr "" "Riempire i campi per la ricerca di utenti Jabber corrispondenti ai criteri" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Server s2s in uscita" + #~ msgid "Delete" #~ msgstr "Eliminare" #~ msgid "This room is not anonymous" #~ msgstr "Questa stanza non è anonima" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "In base alla tua attuale lista privacy questa stanza è stata esclusa " -#~ "dalla navigazione." - -#~ msgid "Access denied by service policy" -#~ msgstr "Accesso impedito dalle politiche del servizio" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "L'invio di messaggi di servizio è consentito solamente agli " -#~ "amministratori del servizio" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "La creazione di stanze è impedita dalle politiche del servizio" - -#~ msgid "Conference room does not exist" -#~ msgstr "La stanza per conferenze non esiste" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Questo nickname è registrato da un'altra persona" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Si deve riempire il campo \"Nickname\" nel modulo" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Limite di traffico superato" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Partecipante espulso dalla stanza perché ha inviato un messaggio non " #~ "valido" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Non è consentito l'invio di messaggi privati alla conferenza" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "" -#~ "Attendi qualche istante prima di inviare una nuova richiesta di parola" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "In questa conferenza le richieste di parola sono escluse" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "" -#~ "Impossibile estrarre il JID dall'approvazione della richiesta di parola" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Soltanto i moderatori possono approvare richieste di parola" - -#~ msgid "Improper message type" -#~ msgstr "Tipo di messaggio non corretto" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1796,86 +1945,12 @@ msgstr "" #~ "Partecipante espulso dalla stanza perché ha inviato un messaggio non " #~ "valido a un altro partecipante" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Non è consentito l'invio di messaggi privati di tipo \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Il destinatario non è nella stanza per conferenze" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Non è consentito l'invio di messaggi privati" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "" -#~ "L'invio di messaggi alla conferenza è consentito soltanto ai presenti" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "L'invio di query alla conferenza è consentito ai soli presenti" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "In questa stanza non sono consentite query ai membri della conferenza" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "" -#~ "Non è consentito ai visitatori l'invio di messaggi a tutti i presenti" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Partecipante espulso dalla stanza perché ha inviato una presenza non " #~ "valido" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Non è consentito ai visitatori cambiare il nickname in questa stanza" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Il nickname è già in uso all'interno della conferenza" - -#~ msgid "You have been banned from this room" -#~ msgstr "Sei stata/o bandita/o da questa stanza" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Per entrare in questa stanza è necessario essere membro" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Per entrare in questa stanza è prevista una password" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Troppe richieste CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Impossibile generare un CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Password non esatta" - -#~ msgid "Administrator privileges required" -#~ msgstr "Necessari i privilegi di amministratore" - -#~ msgid "Moderator privileges required" -#~ msgstr "Necessari i privilegi di moderatore" - -#~ msgid "Owner privileges required" -#~ msgstr "Necessari i privilegi di proprietario" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "La coda dei messaggi offline del contatto è piena. Il messaggio è stato " -#~ "scartato" - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "La verifica del CAPTCHA ha avuto esito negativo" - -#~ msgid "The password is too weak" -#~ msgstr "La password è troppo debole" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Non è consentito agli utenti registrare account così rapidamente" - #, fuzzy #~ msgid "CAPTCHA test failed" #~ msgstr "Il CAPTCHA è valido." diff --git a/priv/msgs/ja.msg b/priv/msgs/ja.msg index d9dcf05751b..d6a9a0a4bfa 100644 --- a/priv/msgs/ja.msg +++ b/priv/msgs/ja.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","アクセスコントロールリスト設定"}. {"Access control lists","アクセスコントロールリスト"}. {"Access Control Lists","アクセスコントロールリスト"}. +{"Access denied by service policy","サービスポリシーによってアクセスが禁止されました"}. {"Access rules","アクセスルール"}. {"Access Rules","アクセスルール"}. {"Action on user","ユーザー操作"}. @@ -11,6 +12,7 @@ {"Add User","ユーザーを追加"}. {"Administration of ","管理: "}. {"Administration","管理"}. +{"Administrator privileges required","管理者権限が必要です"}. {"A friendly name for the node","ノードのフレンドリネーム"}. {"All activity","すべて"}. {"Allow this Jabber ID to subscribe to this pubsub node?","この Jabber ID に、この pubsubノードの購読を許可しますか ?"}. @@ -25,6 +27,7 @@ {"All Users","全ユーザー"}. {"Announcements","アナウンス"}. {"anyone","誰にでも"}. +{"A password is required to enter this room","このチャットルームに入るにはパスワードが必要です"}. {"April","4月"}. {"August","8月"}. {"Backup","バックアップ"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","このエントリを承認するかどうかを選択してください"}. {"City","都道府県"}. {"Commands","コマンド"}. +{"Conference room does not exist","会議室は存在しません"}. {"Configuration of room ~s","チャットルーム ~s の設定"}. {"Configuration","設定"}. {"Connected Resources:","接続リソース:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","すべてのテーブルをSQL形式でファイルにエクスポート: "}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","サーバーにあるすべてのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","ホストのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","発言権要求の承認から JID を取り出すことに失敗しました"}. {"Family Name","姓"}. {"February","2月"}. {"Fill in fields to search for any matching Jabber User","項目を入力してユーザーを検索してください"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","ユーザーデータを jabberd14 Spool ディレクトリからインポート:"}. {"Import Users from Dir at ","ディレクトリからユーザーをインポート: "}. {"Import Users From jabberd14 Spool Files","jabberd14 Spool ファイルからユーザーをインポート"}. +{"Improper message type","誤ったメッセージタイプです"}. +{"Incorrect password","パスワードが違います"}. {"Invalid affiliation: ~s","無効な分掌です: ~s"}. {"Invalid role: ~s","無効な役です: ~s"}. {"IP addresses","IP アドレス"}. @@ -147,6 +154,9 @@ {"IRC username","IRC ユーザー名"}. {"IRC Username","IRC ユーザー名"}. {"is now known as","は名前を変更しました: "}. +{"It is not allowed to send private messages of type \"groupchat\"","種別が\"groupchat\" であるプライベートメッセージを送信することはできません"}. +{"It is not allowed to send private messages to the conference","この会議にプライベートメッセージを送信することはできません"}. +{"It is not allowed to send private messages","プライベートメッセージを送信することはできません"}. {"Jabber Account Registration","Jabber アカウント登録"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s は無効です"}. @@ -180,11 +190,13 @@ {"Max payload size in bytes","最大ぺイロードサイズ (byte)"}. {"May","5月"}. {"Members:","メンバー:"}. +{"Membership is required to enter this room","このチャットルームに入るにはメンバーでなければなりません"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","パスワードは記憶するか、紙に書いて安全な場所に保管してください。もしあなたがパスワードを忘れてしまった場合、Jabber ではパスワードのリカバリを自動的に行うことはできません。"}. {"Memory","メモリ"}. {"Message body","本文"}. {"Middle Name","ミドルネーム"}. {"Minimum interval between voice requests (in seconds)","発言権の要求の最小時間間隔 (秒)"}. +{"Moderator privileges required","モデレーター権限が必要です"}. {"moderators only","モデレーターにのみ"}. {"Modified modules","更新されたモジュール"}. {"Module","モジュール"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","有効なユーザーにのみ告知を送信する"}. {"Only moderators and participants are allowed to change the subject in this room","モデレーターと参加者のみがチャットルームの件名を変更できます"}. {"Only moderators are allowed to change the subject in this room","モデレーターのみがチャットルームの件名を変更できます"}. +{"Only moderators can approve voice requests","モデレーターだけが発言権の要求を承認できます"}. +{"Only occupants are allowed to send messages to the conference","在室者のみがこの会議にメッセージを送ることができます"}. +{"Only occupants are allowed to send queries to the conference","在室者のみが会議にクエリーを送信することができます"}. +{"Only service administrators are allowed to send service messages","サービス管理者のみがサービスメッセージを送信できます"}. {"Options","オプション"}. {"Organization Name","会社名"}. {"Organization Unit","部署名"}. {"Outgoing s2s Connections:","外向き s2s コネクション:"}. {"Outgoing s2s Connections","外向き s2s コネクション"}. -{"Outgoing s2s Servers:","外向き s2s サービス:"}. +{"Owner privileges required","主宰者の権限が必要です"}. {"Packet","パケット"}. {"Password:","パスワード"}. {"Password","パスワード"}. @@ -249,6 +265,7 @@ {"Persist items to storage","アイテムをストレージに保存する"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","これらのオプションは組み込みの Mnesia データーベースのバックアップのみを行うことに注意してください。もし ODBC モジュールを使用している場合は、SQL データーベースのバックアップを別に行う必要があります。"}. +{"Please, wait for a while before sending new voice request","新しい発言権の要求を送るまで少し間をおいてください"}. {"Pong","Pong"}. {"Port","ポート"}. {"Port ~b","ポート ~b"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Publish-Subscribe"}. {"PubSub subscriber request","PubSub 購読者のリクエスト"}. {"Purge all items when the relevant publisher goes offline","公開者がオフラインになるときに、すべてのアイテムを削除"}. +{"Queries to the conference members are not allowed in this room","このチャットルームでは、会議のメンバーへのクエリーは禁止されています"}. {"RAM and disc copy","RAM, ディスクコピー"}. {"RAM copy","RAM コピー"}. {"Raw","Raw"}. {"Really delete message of the day?","本当にお知らせメッセージを削除しますか ?"}. +{"Recipient is not in the conference room","受信者はこの会議室にいません"}. {"Register a Jabber account","Jabber アカウントを登録"}. {"Registered nicknames","登録ニックネーム"}. {"Registered Users:","登録ユーザー:"}. @@ -282,6 +301,7 @@ {"Restore binary backup immediately:","直ちにバイナリバックアップからリストア:"}. {"Restore plain text backup immediately:","直ちにプレーンテキストバックアップからリストア:"}. {"Room Configuration","チャットルームの設定"}. +{"Room creation is denied by service policy","サービスポリシーによってチャットルームの作成が禁止されています"}. {"Room description","チャットルームの説明"}. {"Room Occupants","在室者"}. {"Room title","チャットルームのタイトル"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","通常の表を表示"}. {"Shut Down Service","サービスを停止"}. {"~s invites you to the room ~s","~s はあなたをチャットルーム ~s に招待しています"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Jabber クライアントはコンピューターにパスワードを記憶できます。コンピューターが安全であると信頼できる場合にのみ、この機能を使用してください。"}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Jabber クライアントはコンピューターにパスワードを記憶できます。コンピューターが安全であると信頼できる場合にのみ、この機能を使用してください。"}. {"Specify the access model","アクセスモデルを設定する"}. {"Specify the event message type","イベントメッセージ種別を設定"}. {"Specify the publisher model","公開モデルを指定する"}. @@ -333,9 +353,13 @@ {"Subscriber Address","購読者のアドレス"}. {"Subscription","認可"}. {"Sunday","日曜日"}. +{"That nickname is already in use by another occupant","そのニックネームは既にほかの在室者によって使用されています"}. +{"That nickname is registered by another person","ニックネームはほかの人によって登録されています"}. {"The CAPTCHA is valid.","CAPTCHA は有効です。"}. +{"The CAPTCHA verification has failed","CAPTCHA 検証は失敗しました"}. {"The collections with which a node is affiliated","提携されたノードの集合です"}. {"the password is","パスワードは"}. +{"The password is too weak","このパスワードは単純過ぎます"}. {"The password of your Jabber account was successfully changed.","Jabber アカウントのパスワード変更に成功しました。"}. {"There was an error changing the password: ","パスワードの変更中にエラーが発生しました: "}. {"There was an error creating the account: ","アカウントの作成中にエラーが発生しました: "}. @@ -347,16 +371,19 @@ {"Thursday","木曜日"}. {"Time delay","遅延時間"}. {"Time","時間"}. +{"Too many CAPTCHA requests","CAPTCHA 要求が多すぎます"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。"}. {"Too many unacked stanzas","多くのスタンザが応答していません"}. {"To ~s","宛先 ~s"}. {"Total rooms","チャットルーム数"}. {"To","宛先"}. +{"Traffic rate limit is exceeded","トラフィックレートの制限を超えました"}. {"Transactions Aborted:","トランザクションの失敗:"}. {"Transactions Committed:","トランザクションのコミット:"}. {"Transactions Logged:","トランザクションのログ: "}. {"Transactions Restarted:","トランザクションの再起動:"}. {"Tuesday","火曜日"}. +{"Unable to generate a CAPTCHA","CAPTCHA を生成できません"}. {"Unauthorized","認証されていません"}. {"Unregister a Jabber account","Jabber アカウントを削除"}. {"Unregister","削除"}. @@ -373,21 +400,29 @@ {"User Management","ユーザー管理"}. {"Username:","ユーザー名:"}. {"Users","ユーザー"}. +{"Users are not allowed to register accounts so quickly","それほど速くアカウントを登録することはできません"}. {"Users Last Activity","ユーザーの活動履歴"}. {"User ~s","ユーザー ~s"}. {"Validate","検証"}. {"vCard User Search","vCard検索"}. {"Virtual Hosts","バーチャルホスト"}. +{"Visitors are not allowed to change their nicknames in this room","傍聴者はこのチャットルームでニックネームを変更することはできません"}. +{"Visitors are not allowed to send messages to all occupants","傍聴者はすべての在室者にメッセージを送信することはできません"}. +{"Voice requests are disabled in this conference","この会議では、発言権の要求はできません"}. {"Voice request","発言権を要求"}. {"Wednesday","水曜日"}. {"When to send the last published item","最後の公開アイテムを送信するタイミングで"}. {"Whether to allow subscriptions","購読を許可するかどうか"}. {"You can later change your password using a Jabber client.","あなたは後で Jabber クライアントを使用してパスワードを変更できます。"}. +{"You have been banned from this room","あなたはこのチャットルームからバンされています"}. +{"You must fill in field \"Nickname\" in the form","フォームの\"ニックネーム\"欄を入力する必要があります"}. {"You need a client that supports x:data and CAPTCHA to register","登録を行うには x:data と CAPTCHA をサポートするクライアントが必要です"}. {"You need a client that supports x:data to register the nickname","ニックネームを登録するには x:data をサポートするクライアントが必要です"}. {"You need an x:data capable client to configure mod_irc settings","mod_irc の設定には x:data をサポートするクライアントが必要です"}. {"You need an x:data capable client to configure room","チャットルームを設定するには x:data をサポートするクライアントが必要です"}. {"You need an x:data capable client to search","検索を行うためには x:data をサポートするクライアントが必要です"}. +{"Your active privacy list has denied the routing of this stanza.","あなたのプライバシーリストはこのスタンザのルーティングを拒否しました。"}. +{"Your contact offline message queue is full. The message has been discarded.","相手先のオフラインメッセージキューが一杯です。このメッセージは破棄されます。"}. {"Your Jabber account was successfully created.","Jabber アカウントの作成に成功しました。"}. {"Your Jabber account was successfully deleted.","Jabber アカウントの削除に成功しました。"}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","~s 宛のメッセージはブロックされています。解除するにはこちらを見てください ~s"}. diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index 0434da69995..e405db64769 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -10,51 +10,55 @@ msgstr "" "X-Additional-Translator: Tsukasa Hamano \n" "X-Additional-Translator: Mako N \n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "STARTTLS の使用が必要です" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "リソースが提供されませんでした" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "新しいコネクションによって置き換えられました" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "はキックされました" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "あなたのプライバシーリストはこのスタンザのルーティングを拒否しました。" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "多くのスタンザが応答していません" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "見えているテキストを入力してください" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "~s 宛のメッセージはブロックされています。解除するにはこちらを見てください ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "ここに CAPTCHA 画像が表示されない場合、ウェブページを参照してください。" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA ウェブページ" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "CAPTCHA は有効です。" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "ユーザー" @@ -63,9 +67,9 @@ msgstr "ユーザー" msgid "Server" msgstr "サーバー:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "パスワード" @@ -82,275 +86,276 @@ msgstr "認証されていません" msgid "ejabberd Web Admin" msgstr "ejabberd ウェブ管理" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "管理" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "アクセスコントロールリスト" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "送信完了" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "不正なフォーマット" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "送信" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Raw" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "選択した項目を削除" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "アクセスルール" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s アクセスルール設定" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "バーチャルホスト" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "ユーザー" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "オンラインユーザー" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "ユーザーの活動履歴" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "期間: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "先月" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "去年" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "すべて" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "通常の表を表示" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "累積の表を表示" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "統計" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "見つかりません" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "ノードが見つかりません" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "新規追加" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "ホスト" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "登録ユーザー" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "ユーザーを追加" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "オフラインメッセージ" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "活動履歴" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "なし" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "オンライン" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "登録ユーザー:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "オンラインユーザー:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "外向き s2s コネクション:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "外向き s2s サービス:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "外向き s2s コネクション:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "なし" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "パスワードを変更" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "ユーザー ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "接続リソース:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "パスワード" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "ユーザーを削除" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "データなし" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "ノード" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "起動ノード" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "停止ノード" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "ノード ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "データーベース" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "バックアップ" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Listen ポート" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "更新" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "再起動" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "停止" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "モジュール" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC 呼び出しエラー" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "データーベーステーブル: ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "名" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "ストレージタイプ" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "要素" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "メモリ" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "エラー" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "バックアップ: ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -360,143 +365,143 @@ msgstr "" "ことに注意してください。もし ODBC モジュールを使用している場合は、SQL デー" "ターベースのバックアップを別に行う必要があります。" -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "バイナリバックアップを保存:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "直ちにバイナリバックアップからリストア:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "ejabberd の再起動時にバイナリバックアップからリストア (メモリ少):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "プレーンテキストバックアップを保存:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "直ちにプレーンテキストバックアップからリストア:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "ユーザーデータを PIEFXIS ファイルからインポート (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "サーバーにあるすべてのユーザーデータを PIEFXIS ファイルにエクスポート " "(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "ホストのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "すべてのテーブルをSQL形式でファイルにエクスポート: " -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "ユーザーデータを jabberd14 Spool ファイルからインポート:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "ユーザーデータを jabberd14 Spool ディレクトリからインポート:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Listen ポート " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "モジュール ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "~p の統計" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "起動時間:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU時間:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "トランザクションのコミット:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "トランザクションの失敗:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "トランザクションの再起動:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "トランザクションのログ: " -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "更新 ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "更新計画" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "更新されたモジュール" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "スクリプトの更新" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "低レベル更新スクリプト" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "スクリプトチェック" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "ポート" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "プロトコル" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "モジュール" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "オプション" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "開始" @@ -781,8 +786,8 @@ msgstr "アクセスルール" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -799,31 +804,31 @@ msgstr "登録ユーザー数" msgid "Number of online users" msgstr "オンラインユーザー数" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "最終ログイン" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "名簿サイズ" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP アドレス" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "リソース" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "管理: " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "ユーザー操作" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "プロパティを編集" @@ -834,27 +839,39 @@ msgid "" msgstr "" "~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "このIPアドレスはアクセスを禁止されています ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "サービスポリシーによってアクセスが禁止されました" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRCトランスポート" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC module" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "mod_irc の設定には x:data をサポートするクライアントが必要です" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "mod_irc での登録: " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -862,11 +879,11 @@ msgstr "" "IRC サーバーに接続先するために使用するユーザー名、文字エンコーディング、ポー" "ト、パスワードを入力してください" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC ユーザー名" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -878,7 +895,7 @@ msgstr "" "デフォルトでエンコーディングは \"~s\" を使用し、ポートは ~p、パスワードは空に" "なっています。" -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -886,35 +903,35 @@ msgstr "" "例: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net" "\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "接続パラメーター" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "IRC チャンネルに参加" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC チャンネル (先頭に#は不要)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC サーバー" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "この IRC チャンネルに参加します。" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Jabber ID: ~s でこの IRC チャンネルに参加" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC 設定" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -924,48 +941,77 @@ msgstr "" "さい。'Next' を押して次の項目に進みます。'Complete' を押すと設定が保存されま" "す。" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC ユーザー名" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "パスワード ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "ポート ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "サーバーのエンコーディング ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "サーバー ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "モデレーターのみがチャットルームの件名を変更できます" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "サービス管理者のみがサービスメッセージを送信できます" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "サービスポリシーによってチャットルームの作成が禁止されています" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "会議室は存在しません" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "チャットルーム" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "ニックネームを登録するには x:data をサポートするクライアントが必要です" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "ニックネーム登録: " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "登録するニックネームを入力してください" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "ニックネーム" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "ニックネームはほかの人によって登録されています" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "フォームの\"ニックネーム\"欄を入力する必要があります" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUCモジュール" @@ -990,354 +1036,484 @@ msgstr "登録ニックネーム" msgid "List of rooms" msgstr "チャットルームの一覧" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "チャットルームの設定が変更されました" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "がチャットルームに参加しました" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "がチャットルームから退出しました" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "はバンされました" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "は分掌が変更されたためキックされました" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "はチャットルームがメンバー制に変更されたためキックされました" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "はシステムシャットダウンのためキックされました" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "は名前を変更しました: " -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " は件名を設定しました: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "チャットルームを作りました" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "チャットルームを終了しました" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "チャットルームを開始しました" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "チャットルームを停止しました" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "月曜日" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "火曜日" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "水曜日" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "木曜日" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "金曜日" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "土曜日" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "日曜日" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "1月" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "2月" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "3月" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "4月" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "5月" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "6月" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "7月" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "8月" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "9月" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "10月" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "11月" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "12月" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "チャットルームの設定" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "在室者" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "トラフィックレートの制限を超えました" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "この会議にプライベートメッセージを送信することはできません" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "新しい発言権の要求を送るまで少し間をおいてください" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "この会議では、発言権の要求はできません" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "発言権要求の承認から JID を取り出すことに失敗しました" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "モデレーターだけが発言権の要求を承認できます" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "誤ったメッセージタイプです" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"種別が\"groupchat\" であるプライベートメッセージを送信することはできません" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "受信者はこの会議室にいません" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "プライベートメッセージを送信することはできません" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "在室者のみがこの会議にメッセージを送ることができます" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "在室者のみが会議にクエリーを送信することができます" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "このチャットルームでは、会議のメンバーへのクエリーは禁止されています" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "モデレーターと参加者のみがチャットルームの件名を変更できます" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "モデレーターのみがチャットルームの件名を変更できます" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "傍聴者はすべての在室者にメッセージを送信することはできません" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "傍聴者はこのチャットルームでニックネームを変更することはできません" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "そのニックネームは既にほかの在室者によって使用されています" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "あなたはこのチャットルームからバンされています" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "このチャットルームに入るにはメンバーでなければなりません" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "このチャットルームに入るにはパスワードが必要です" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "CAPTCHA 要求が多すぎます" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "CAPTCHA を生成できません" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "パスワードが違います" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "管理者権限が必要です" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "モデレーター権限が必要です" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s は無効です" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "ニックネーム ~s はこのチャットルームにいません" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "無効な分掌です: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "無効な役です: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "主宰者の権限が必要です" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "チャットルーム ~s の設定" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "チャットルームのタイトル" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "チャットルームの説明" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "チャットルームを永続化" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "チャットルームを検索可" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "参加者一覧を公開" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "チャットルームをパスワードで保護" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "最大在室者数" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "制限なし" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "本当の Jabber ID を公開" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "モデレーターにのみ" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "誰にでも" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "モデレーターにのみ" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "チャットルームをメンバーのみに制限" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "チャットルームをモデレート化" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "デフォルトのユーザーは参加者" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "ユーザーによる件名の変更を許可" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "ユーザーによるプライベートメッセージの送信を許可" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "傍聴者によるプライベートメッセージの送信を次の相手に許可" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "誰にも許可しない" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "ユーザーによる他のユーザーへのクエリーを許可" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "ユーザーによる招待を許可" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "傍聴者によるプレゼンス更新のステータス文の送信を許可" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "傍聴者のニックネームの変更を許可" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "傍聴者による発言権の要求を許可" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "発言権の要求の最小時間間隔 (秒)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "チャットルームを CAPTCHA で保護" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "メッセージアーカイブを有効化" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA 試験を免除する Jabber ID" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "ロギングを有効" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "チャットルームを設定するには x:data をサポートするクライアントが必要です" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "在室者の数" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "プライベート、" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "発言権を要求" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "発言権の要求を承認または却下します。" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "ユーザー JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "この人に発言権を与えますか ?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s はあなたをチャットルーム ~s に招待しています" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "パスワードは" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "マルチキャスト" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberdマルチキャストサービス" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"相手先のオフラインメッセージキューが一杯です。このメッセージは破棄されます。" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s' のオフラインメッセージキュー" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "時間" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "差出人" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "宛先" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "パケット" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "オフラインメッセージ:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "すべてのオフラインメッセージを削除" @@ -1345,114 +1521,126 @@ msgstr "すべてのオフラインメッセージを削除" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams モジュール" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe モジュール" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub 購読者のリクエスト" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "このエントリを承認するかどうかを選択してください" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ノードID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "購読者のアドレス" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "この Jabber ID に、この pubsubノードの購読を許可しますか ?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "イベント通知と同時にペイロードを配送する" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "イベント通知を配送する" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "ノード設定に変更があった時に購読者へ通知する" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "ノードが削除された時に購読者へ通知する" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "アイテムがノードから消された時に購読者へ通知する" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "アイテムをストレージに保存する" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "ノードのフレンドリネーム" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "アイテムの最大保存数" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "購読を許可するかどうか" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "アクセスモデルを設定する" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "名簿グループは購読を許可しました" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "公開モデルを指定する" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "公開者がオフラインになるときに、すべてのアイテムを削除" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "イベントメッセージ種別を設定" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "最大ぺイロードサイズ (byte)" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "最後の公開アイテムを送信するタイミングで" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "有効なユーザーにのみ告知を送信する" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "提携されたノードの集合です" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "CAPTCHA 検証は失敗しました" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "登録を行うには x:data と CAPTCHA をサポートするクライアントが必要です" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "サーバーに登録するユーザー名とパスワードを選択してください" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "このパスワードは単純過ぎます" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "それほど速くアカウントを登録することはできません" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Jabber アカウントの作成に成功しました。" @@ -1530,8 +1718,8 @@ msgstr "あなたは後で Jabber クライアントを使用してパスワー #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Jabber クライアントはコンピューターにパスワードを記憶できます。コンピューター" "が安全であると信頼できる場合にのみ、この機能を使用してください。" @@ -1570,60 +1758,60 @@ msgstr "ここはこの Jabber サーバーのアカウントを削除するペ msgid "Unregister" msgstr "削除" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "認可" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "保留" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "グループ" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "検証" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "削除" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "名簿: " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber ID を追加" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "名簿" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "共有名簿グループ" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "名前:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "説明:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "メンバー:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "表示グループ" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "グループ" @@ -1699,141 +1887,29 @@ msgstr "検索結果: " msgid "Fill in fields to search for any matching Jabber User" msgstr "項目を入力してユーザーを検索してください" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "外向き s2s サービス:" + #~ msgid "Delete" #~ msgstr "削除" #~ msgid "This room is not anonymous" #~ msgstr "このチャットルームは非匿名です" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "あなたのプライバシーリストはこのスタンザのルーティングを拒否しました。" - -#~ msgid "Access denied by service policy" -#~ msgstr "サービスポリシーによってアクセスが禁止されました" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "サービス管理者のみがサービスメッセージを送信できます" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "サービスポリシーによってチャットルームの作成が禁止されています" - -#~ msgid "Conference room does not exist" -#~ msgstr "会議室は存在しません" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "ニックネームはほかの人によって登録されています" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "フォームの\"ニックネーム\"欄を入力する必要があります" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "トラフィックレートの制限を超えました" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "エラーメッセージを送信したため、この参加者はキックされました" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "この会議にプライベートメッセージを送信することはできません" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "新しい発言権の要求を送るまで少し間をおいてください" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "この会議では、発言権の要求はできません" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "発言権要求の承認から JID を取り出すことに失敗しました" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "モデレーターだけが発言権の要求を承認できます" - -#~ msgid "Improper message type" -#~ msgstr "誤ったメッセージタイプです" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "" #~ "他の参加者にエラーメッセージを送信したため、この参加者はキックされました" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "種別が\"groupchat\" であるプライベートメッセージを送信することはできません" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "受信者はこの会議室にいません" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "プライベートメッセージを送信することはできません" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "在室者のみがこの会議にメッセージを送ることができます" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "在室者のみが会議にクエリーを送信することができます" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "このチャットルームでは、会議のメンバーへのクエリーは禁止されています" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "傍聴者はすべての在室者にメッセージを送信することはできません" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "エラープレゼンスを送信したため、この参加者はキックされました" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "傍聴者はこのチャットルームでニックネームを変更することはできません" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "そのニックネームは既にほかの在室者によって使用されています" - -#~ msgid "You have been banned from this room" -#~ msgstr "あなたはこのチャットルームからバンされています" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "このチャットルームに入るにはメンバーでなければなりません" - -#~ msgid "A password is required to enter this room" -#~ msgstr "このチャットルームに入るにはパスワードが必要です" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "CAPTCHA 要求が多すぎます" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "CAPTCHA を生成できません" - -#~ msgid "Incorrect password" -#~ msgstr "パスワードが違います" - -#~ msgid "Administrator privileges required" -#~ msgstr "管理者権限が必要です" - -#~ msgid "Moderator privileges required" -#~ msgstr "モデレーター権限が必要です" - -#~ msgid "Owner privileges required" -#~ msgstr "主宰者の権限が必要です" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "相手先のオフラインメッセージキューが一杯です。このメッセージは破棄されま" -#~ "す。" - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "CAPTCHA 検証は失敗しました" - -#~ msgid "The password is too weak" -#~ msgstr "このパスワードは単純過ぎます" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "それほど速くアカウントを登録することはできません" - #~ msgid "ejabberd virtual hosts" #~ msgstr "ejabberd バーチャルホスト" diff --git a/priv/msgs/nl.msg b/priv/msgs/nl.msg index c93584cc51d..8bb1c0ebf5a 100644 --- a/priv/msgs/nl.msg +++ b/priv/msgs/nl.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Instellingen van access control lists"}. {"Access control lists","Access control lists"}. {"Access Control Lists","Access control lists"}. +{"Access denied by service policy","De toegang werd geweigerd door het beleid van deze dienst"}. {"Access rules","Access rules"}. {"Access Rules","Access rules"}. {"Action on user","Actie op gebruiker"}. @@ -11,6 +12,7 @@ {"Add User","Gebruiker toevoegen"}. {"Administration","Beheer"}. {"Administration of ","Beheer van "}. +{"Administrator privileges required","U hebt beheerdersprivileges nodig"}. {"A friendly name for the node","Bijnaam voor deze knoop"}. {"All activity","Alle activiteit"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Deze gebruiker toestaan te abonneren op deze pubsub node?"}. @@ -25,6 +27,7 @@ {"All Users","Alle gebruikers"}. {"Announcements","Mededelingen"}. {"anyone","iedereen"}. +{"A password is required to enter this room","U hebt een wachtwoord nodig om deze chatruimte te kunnen betreden"}. {"April","April"}. {"August","Augustus"}. {"Backup","Backup"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Beslis of dit verzoek tot abonneren zal worden goedgekeurd"}. {"City","Plaats"}. {"Commands","Commando's"}. +{"Conference room does not exist","De chatruimte bestaat niet"}. {"Configuration","Instellingen"}. {"Configuration of room ~s","Instellingen van chatruimte ~s"}. {"Connected Resources:","Verbonden bronnen:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Exporteer alle tabellen als SQL-queries naar een bestand:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exporteer data van alle gebruikers in de server naar PIEFXIS-bestanden (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exporteer data van alle gebruikers van een host naar PIEXFIS-bestanden (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Er kon geen JID worden ontleend uit deze stemaanvraag"}. {"Family Name","Achternaam"}. {"February","Februari"}. {"Fill in fields to search for any matching Jabber User","Vul de velden in om te zoeken naar Jabber-gebruikers op deze server"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importeer gebruikersdata via spool-bestanden van jabberd14"}. {"Import Users from Dir at ","Gebruikers importeren vanaf directory op "}. {"Import Users From jabberd14 Spool Files","Importeer gebruikers via spool-bestanden van jabberd14"}. +{"Improper message type","Onjuist berichttype"}. +{"Incorrect password","Foutief wachtwoord"}. {"Invalid affiliation: ~s","Ongeldige affiliatie: ~s"}. {"Invalid role: ~s","Ongeldige rol: ~s"}. {"IP addresses","IP-adres"}. @@ -147,6 +154,9 @@ {"IRC username","Gebruikersnaam voor IRC"}. {"IRC Username","Gebruikersnaam voor IRC:"}. {"is now known as","heet nu"}. +{"It is not allowed to send private messages","Het is niet toegestaan priveberichten te sturen"}. +{"It is not allowed to send private messages of type \"groupchat\"","Er mogen geen privéberichten van het type \"groupchat\" worden verzonden"}. +{"It is not allowed to send private messages to the conference","Er mogen geen privéberichten naar de chatruimte worden verzonden"}. {"Jabber Account Registration","Jabber-account registratie"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","De Jabber ID ~s is ongeldig"}. @@ -180,11 +190,13 @@ {"Max payload size in bytes","Maximumgrootte van bericht in bytes"}. {"May","Mei"}. {"Members:","Groepsleden:"}. +{"Membership is required to enter this room","U moet lid zijn om deze chatruimte te kunnen betreden"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Onthou het wachtwoord, of schrijf het op en bewaar het op een veilige plaats. Met Jabber is er geen geautomatiseerde manier om het wachtwoord terug te halen als U het vergeet."}. {"Memory","Geheugen"}. {"Message body","Bericht"}. {"Middle Name","Tussennaam"}. {"Minimum interval between voice requests (in seconds)","Minimale interval tussen stemaanvragen (in seconden)"}. +{"Moderator privileges required","U hebt moderatorprivileges nodig"}. {"moderators only","moderators"}. {"Modified modules","Gewijzigde modules"}. {"Module","Module"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Notificaties alleen verzenden naar online gebruikers"}. {"Only moderators and participants are allowed to change the subject in this room","Alleen moderators en deelnemers mogen het onderwerp van deze chatruimte veranderen"}. {"Only moderators are allowed to change the subject in this room","Alleen moderators mogen het onderwerp van deze chatruimte veranderen"}. +{"Only moderators can approve voice requests","Alleen moderators kunnen stemaanvragen goedkeuren"}. +{"Only occupants are allowed to send messages to the conference","Alleen aanwezigen mogen berichten naar de chatruimte verzenden"}. +{"Only occupants are allowed to send queries to the conference","Alleen aanwezigen mogen verzoeken verzenden naar de chatruimte"}. +{"Only service administrators are allowed to send service messages","Alleen beheerders van deze dienst mogen mededelingen verzenden naar alle chatruimtes"}. {"Options","Opties"}. {"Organization Name","Organisatie"}. {"Organization Unit","Afdeling"}. {"Outgoing s2s Connections:","Uitgaande s2s-verbindingen:"}. {"Outgoing s2s Connections","Uitgaande s2s-verbindingen"}. -{"Outgoing s2s Servers:","Uitgaande s2s-verbindingen:"}. +{"Owner privileges required","U hebt eigenaarsprivileges nodig"}. {"Packet","Pakket"}. {"Password ~b","Wachtwoord ~b"}. {"Password Verification:","Wachtwoord Bevestiging:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Items in het geheugen bewaren"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Merk op dat volgende opties enkel backups maken van de ingebouwde database Mnesia. Als U de ODBC module gebruikt dan moeten daarvan afzonderlijke backups gemaakt worden."}. +{"Please, wait for a while before sending new voice request","Wacht s.v.p. met het maken van een nieuwe stemaanvraag."}. {"Pong","Pong"}. {"Port ~b","Poort ~b"}. {"Port","Poort"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Publish-Subscribe"}. {"PubSub subscriber request","PubSub abonnee verzoek"}. {"Purge all items when the relevant publisher goes offline","Verwijder alle items wanneer de gerelateerde publiceerder offline gaat"}. +{"Queries to the conference members are not allowed in this room","Er mogen geen verzoeken verzenden worden naar deelnemers in deze chatruimte"}. {"RAM and disc copy","RAM en harde schijf"}. {"RAM copy","RAM"}. {"Raw","Ruw"}. {"Really delete message of the day?","Wilt u het bericht van de dag verwijderen?"}. +{"Recipient is not in the conference room","De ontvanger is niet in de chatruimte"}. {"Register a Jabber account","Registreer een Jabber-account"}. {"Registered nicknames","Geregistreerde gebruikersnamen"}. {"Registered Users:","Geregistreerde gebruikers:"}. @@ -282,6 +301,7 @@ {"Restore binary backup immediately:","Binaire backup direct herstellen:"}. {"Restore plain text backup immediately:","Backup in een tekstbestand direct herstellen:"}. {"Room Configuration","Instellingen van de chatruimte"}. +{"Room creation is denied by service policy","De aanmaak van de chatruimte is verhinderd door de instellingen van deze server"}. {"Room description","Beschrijving"}. {"Room Occupants","Aantal aanwezigen"}. {"Room title","Naam van de chatruimte"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Deel van tabel laten zien"}. {"Shut Down Service","Stop Service"}. {"~s invites you to the room ~s","~s nodigt je uit voor het groepsgesprek ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Sommige Jabber-clienten kunnen het wachtwoord opslaan op Uw computer. Gebruik deze mogelijkheid alleen als U vertrouwd dat Uw computer afdoende beveiligd is."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Sommige Jabber-clienten kunnen het wachtwoord opslaan op Uw computer. Gebruik deze mogelijkheid alleen als U vertrouwd dat Uw computer afdoende beveiligd is."}. {"Specify the access model","Geef toegangsmodel"}. {"Specify the event message type","Geef type van eventbericht"}. {"Specify the publisher model","Publicatietype opgeven"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Abonnee Adres"}. {"Subscription","Inschrijving"}. {"Sunday","Zondag"}. +{"That nickname is already in use by another occupant","Deze bijnaam is al in gebruik door een andere aanwezige"}. +{"That nickname is registered by another person","Deze bijnaam is al geregistreerd door iemand anders"}. {"The CAPTCHA is valid.","De geautomatiseerde Turing-test is geslaagd."}. +{"The CAPTCHA verification has failed","De CAPTCHA-verificatie is mislukt"}. {"The collections with which a node is affiliated","De collecties waar een node mee is gerelateerd"}. {"the password is","het wachtwoord is"}. +{"The password is too weak","Het wachtwoord is te zwak"}. {"The password of your Jabber account was successfully changed.","Het wachtwoord van Uw Jabber-account is succesvol veranderd."}. {"There was an error changing the password: ","Er was een fout bij het veranderen van het wachtwoord:"}. {"There was an error creating the account: ","Er was een fout bij het creeern van de account:"}. @@ -348,15 +372,18 @@ {"Time delay","Vertraging"}. {"Time","Tijd"}. {"To","Aan"}. +{"Too many CAPTCHA requests","Te veel CAPTCHA-aanvragen"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Te veel (~p) mislukte authenticatie-pogingen van dit IP-adres (~s). Dit adres zal worden gedeblokkeerd om ~s UTC"}. {"Too many unacked stanzas","Te veel niet-bevestigde stanzas"}. {"To ~s","Naar ~s"}. {"Total rooms","Aantal groepsgesprekken"}. +{"Traffic rate limit is exceeded","Dataverkeerslimiet overschreden"}. {"Transactions Aborted:","Afgebroken transacties:"}. {"Transactions Committed:","Bevestigde transacties:"}. {"Transactions Logged:","Gelogde transacties:"}. {"Transactions Restarted:","Herstarte transacties:"}. {"Tuesday","Dinsdag"}. +{"Unable to generate a CAPTCHA","Het generen van een CAPTCHA is mislukt"}. {"Unauthorized","Niet geautoriseerd"}. {"Unregister a Jabber account","Opheffen van Jabber-account"}. {"Unregister","Opheffen"}. @@ -372,22 +399,30 @@ {"User JID","JID Gebruiker"}. {"User Management","Gebruikersbeheer"}. {"Username:","Gebruikersnaam:"}. +{"Users are not allowed to register accounts so quickly","Het is gebruikers niet toegestaan zo snel achter elkaar te registreren"}. {"User ~s","Gebruiker ~s"}. {"Users","Gebruikers"}. {"Users Last Activity","Laatste activiteit van gebruikers"}. {"Validate","Bevestigen"}. {"vCard User Search","Gebruikers zoeken"}. {"Virtual Hosts","Virtuele hosts"}. +{"Visitors are not allowed to change their nicknames in this room","Het is bezoekers niet toegestaan hun naam te veranderen in dit kanaal"}. +{"Visitors are not allowed to send messages to all occupants","Bezoekers mogen geen berichten verzenden naar alle aanwezigen"}. +{"Voice requests are disabled in this conference","Stemaanvragen zijn uitgeschakeld voor deze chatruimte"}. {"Voice request","Stemaanvraag"}. {"Wednesday","Woensdag"}. {"When to send the last published item","Wanneer het laatst gepubliceerde item verzonden moet worden"}. {"Whether to allow subscriptions","Abonnementsaanvraag toestaan"}. {"You can later change your password using a Jabber client.","U can het wachtwoord later veranderen met een Jabber-client."}. +{"You have been banned from this room","U werd verbannen uit deze chatruimte"}. +{"You must fill in field \"Nickname\" in the form","U moet het veld \"bijnaam\" invullen"}. {"You need a client that supports x:data and CAPTCHA to register","U hebt een client nodig die x:data en CAPTCHA ondersteunt om een bijnaam te registreren"}. {"You need a client that supports x:data to register the nickname","U hebt een client nodig die x:data ondersteunt om een bijnaam te registreren"}. {"You need an x:data capable client to configure mod_irc settings","U hebt een client nodig die x:data ondersteunt om dit IRC-transport in te stellen"}. {"You need an x:data capable client to configure room","U hebt een client nodig die x:data ondersteunt om deze chatruimte in te stellen"}. {"You need an x:data capable client to search","U hebt een client nodig die x:data ondersteunt om te zoeken"}. +{"Your active privacy list has denied the routing of this stanza.","Uw actieve privacy-lijst verbied het routeren van dit stanza."}. +{"Your contact offline message queue is full. The message has been discarded.","Te veel offline berichten voor dit contactpersoon. Het bericht is niet opgeslagen."}. {"Your Jabber account was successfully created.","Uw Jabber-account is succesvol gecreeerd."}. {"Your Jabber account was successfully deleted.","Uw Jabber-account is succesvol verwijderd."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Uw berichten aan ~s worden geblokkeerd. Om ze te deblokkeren, ga naar ~s"}. diff --git a/priv/msgs/nl.po b/priv/msgs/nl.po index 2ef3024735e..f707892ebf4 100644 --- a/priv/msgs/nl.po +++ b/priv/msgs/nl.po @@ -13,50 +13,54 @@ msgstr "" "X-Additional-Translator: Sander Devrieze\n" "X-Generator: Poedit 1.6.10\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Gebruik van STARTTLS is vereist" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Geen bron opgegeven" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Vervangen door een nieuwe verbinding" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "is weggestuurd" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Uw actieve privacy-lijst verbied het routeren van dit stanza." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Te veel niet-bevestigde stanzas" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Voer de getoonde tekst in" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Uw berichten aan ~s worden geblokkeerd. Om ze te deblokkeren, ga naar ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Als U het CAPTCHA-plaatje niet ziet, bezoek dan de webpagina." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA webpagina." -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "De geautomatiseerde Turing-test is geslaagd." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Gebruiker" @@ -65,9 +69,9 @@ msgstr "Gebruiker" msgid "Server" msgstr "Server:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Wachtwoord" @@ -84,275 +88,276 @@ msgstr "Niet geautoriseerd" msgid "ejabberd Web Admin" msgstr "ejabberd Webbeheer" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Beheer" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Access control lists" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Verzonden" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Verkeerd formaat" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Verzenden" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ruw" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Geselecteerde verwijderen" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Access rules" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Access rules op ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuele hosts" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Gebruikers" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Online gebruikers" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Laatste activiteit van gebruikers" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periode: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Afgelopen maand" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Afgelopen jaar" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Alle activiteit" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Deel van tabel laten zien" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Volledige tabel laten zien" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistieken" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Niet gevonden" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Node niet gevonden" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Toevoegen" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Geregistreerde gebruikers" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Gebruiker toevoegen" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Offline berichten" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Laatste activiteit" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nooit" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Geregistreerde gebruikers:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Online gebruikers:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Uitgaande s2s-verbindingen:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" msgstr "Uitgaande s2s-verbindingen:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Geen" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Wachtwoord wijzigen" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Gebruiker ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Verbonden bronnen:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Wachtwoord:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Gebruiker verwijderen" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Geen gegevens" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodes" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Draaiende nodes" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Gestopte nodes" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Node ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Backup" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Openstaande poorten" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Bijwerken" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Herstarten" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppen" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC-oproepfout" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Databasetabellen van ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Naam" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Opslagmethode" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementen" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Geheugen" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Fout" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Backup maken van ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -362,146 +367,146 @@ msgstr "" "Mnesia. Als U de ODBC module gebruikt dan moeten daarvan afzonderlijke " "backups gemaakt worden." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Binaire backup maken:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Binaire backup direct herstellen:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Binaire backup herstellen na herstart van ejabberd (vereist minder geheugen):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Backup naar een tekstbestand schrijven:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Backup in een tekstbestand direct herstellen:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importeer gebruikersdata van een PIEFXIS-bestand (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exporteer data van alle gebruikers in de server naar PIEFXIS-bestanden " "(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exporteer data van alle gebruikers van een host naar PIEXFIS-bestanden " "(XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Exporteer alle tabellen als SQL-queries naar een bestand:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importeer gebruikersdata via spool-bestanden van jabberd14" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importeer gebruikersdata via spool-bestanden van jabberd14" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Openstaande poorten op " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Modules op ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistieken van ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Processortijd:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Bevestigde transacties:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Afgebroken transacties:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Herstarte transacties:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Gelogde transacties:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Opwaarderen van ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan voor de opwaardering" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Gewijzigde modules" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script voor de opwaardering" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Lowlevel script voor de opwaardering" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Controle van script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Poort" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opties" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Starten" @@ -788,8 +793,8 @@ msgstr "Access rules" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -806,31 +811,31 @@ msgstr "Aantal Geregistreerde Gebruikers" msgid "Number of online users" msgstr "Aantal Aanwezige Gebruikers" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Laatste Aanmelding" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Contactlijst Groote" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP-adres" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Bronnen" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Beheer van " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Actie op gebruiker" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Eigenschappen bewerken" @@ -842,29 +847,41 @@ msgstr "" "Te veel (~p) mislukte authenticatie-pogingen van dit IP-adres (~s). Dit " "adres zal worden gedeblokkeerd om ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Dit IP-adres is geblokkeerd in ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "De toegang werd geweigerd door het beleid van deze dienst" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC-transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd's IRC-module" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "U hebt een client nodig die x:data ondersteunt om dit IRC-transport in te " "stellen" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registratie van " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -872,11 +889,11 @@ msgstr "" "Voer de gebruikersnaam, coderingen, poorten en wachtwoorden in die U wilt " "gebruiken voor het verbinden met IRC-servers" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Gebruikersnaam voor IRC:" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -888,7 +905,7 @@ msgstr "" "\", \"codering\", poort, \"wachtwoord\"}'. Standaard gebruikt deze service " "de codering \"~s\", poort ~p, leeg wachtwoord." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -896,35 +913,35 @@ msgstr "" "Voorbeeld: [{\"irc.example.org\", \"koi8-r\", 6667, \"geheim\"}, {\"vendetta." "example.net\", \"iso8859-1\", 7000}, {irc,testserver.nl\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Verbindingsparameters" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Ga IRC kanaal binnen" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanaal (zonder eerste #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-server" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Ga het IRC kanaal binnen" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Ga het IRC kanaal van deze Jabber ID binnen: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC instellingen" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -934,49 +951,82 @@ msgstr "" "verbindingen met IRC-servers. Klik op 'Volgende' om meer velden aan te " "maken. Klik op \"Voltooi' om de instellingen op te slaan." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Gebruikersnaam voor IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Wachtwoord ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Poort ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Karakterset voor server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Alleen moderators mogen het onderwerp van deze chatruimte veranderen" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Alleen beheerders van deze dienst mogen mededelingen verzenden naar alle " +"chatruimtes" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "" +"De aanmaak van de chatruimte is verhinderd door de instellingen van deze " +"server" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "De chatruimte bestaat niet" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Groepsgesprekken" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "U hebt een client nodig die x:data ondersteunt om een bijnaam te registreren" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registratie van een bijnaam op " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Voer de bijnaam in die u wilt registreren" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Bijnaam" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Deze bijnaam is al geregistreerd door iemand anders" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "U moet het veld \"bijnaam\" invullen" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd's MUC module" @@ -1001,145 +1051,205 @@ msgstr "Geregistreerde gebruikersnamen" msgid "List of rooms" msgstr "Lijst van groepsgesprekken" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "De instellingen van de chatruimte werden veranderd" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "betrad de chatruimte" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "verliet de chatruimte" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "is verbannen" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "is weggestuurd vanwege een affiliatieverandering" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" "is weggestuurd omdat de chatruimte vanaf heden alleen toegankelijk is voor " "leden" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "is weggestuurd omdat het systeem gestopt wordt" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "heet nu" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " veranderde het onderwerp in: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Gespreksruimte gecreëerd" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Gespreksruimte vernietigd" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Gespreksruimte gestart" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Gespreksruimte gestopt" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Maandag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Dinsdag" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Woensdag" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Donderdag" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Vrijdag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Zaterdag" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Zondag" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Januari" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Februari" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Maart" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "April" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Mei" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Augustus" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "September" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "November" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "December" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Instellingen van de chatruimte" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Dataverkeerslimiet overschreden" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Er mogen geen privéberichten naar de chatruimte worden verzonden" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Wacht s.v.p. met het maken van een nieuwe stemaanvraag." + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Stemaanvragen zijn uitgeschakeld voor deze chatruimte" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Er kon geen JID worden ontleend uit deze stemaanvraag" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Alleen moderators kunnen stemaanvragen goedkeuren" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Onjuist berichttype" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"Er mogen geen privéberichten van het type \"groupchat\" worden verzonden" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "De ontvanger is niet in de chatruimte" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Het is niet toegestaan priveberichten te sturen" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Alleen aanwezigen mogen berichten naar de chatruimte verzenden" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Alleen aanwezigen mogen verzoeken verzenden naar de chatruimte" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Er mogen geen verzoeken verzenden worden naar deelnemers in deze chatruimte" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1147,213 +1257,285 @@ msgstr "" "Alleen moderators en deelnemers mogen het onderwerp van deze chatruimte " "veranderen" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Alleen moderators mogen het onderwerp van deze chatruimte veranderen" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Bezoekers mogen geen berichten verzenden naar alle aanwezigen" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Het is bezoekers niet toegestaan hun naam te veranderen in dit kanaal" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Deze bijnaam is al in gebruik door een andere aanwezige" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "U werd verbannen uit deze chatruimte" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "U moet lid zijn om deze chatruimte te kunnen betreden" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "U hebt een wachtwoord nodig om deze chatruimte te kunnen betreden" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Te veel CAPTCHA-aanvragen" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Het generen van een CAPTCHA is mislukt" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Foutief wachtwoord" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "U hebt beheerdersprivileges nodig" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "U hebt moderatorprivileges nodig" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "De Jabber ID ~s is ongeldig" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "De bijnaam ~s bestaat niet in deze chatruimte" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ongeldige affiliatie: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ongeldige rol: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "U hebt eigenaarsprivileges nodig" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Instellingen van chatruimte ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Naam van de chatruimte" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Beschrijving" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Chatruimte blijvend maken" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Chatruimte doorzoekbaar maken" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Deelnemerslijst publiek maken" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Chatruimte beveiligen met een wachtwoord" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maximum aantal aanwezigen" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Geen limiet" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Jabber ID's kunnen achterhaald worden door" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderators" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "iedereen" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "moderators" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Chatruimte enkel toegankelijk maken voor leden" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Chatruimte gemodereerd maken" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Gebruikers standaard instellen als deelnemers" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Sta gebruikers toe het onderwerp te veranderen" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Gebruikers mogen privéberichten verzenden" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Gebruikers mogen privéberichten verzenden aan" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "niemand" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Gebruikers mogen naar andere gebruikers verzoeken verzenden" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Gebruikers mogen uitnodigingen verzenden" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Sta bezoekers toe hun statusbericht in te stellen" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Sta bezoekers toe hun naam te veranderen" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Gebruikers mogen stemaanvragen verzenden" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimale interval tussen stemaanvragen (in seconden)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Chatruimte beveiligen met een geautomatiseerde Turing test" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Zet bericht-archivering aan" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Geen CAPTCHA test voor Jabber IDs" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Logs aanzetten" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "U hebt een client nodig die x:data ondersteunt om deze chatruimte in te " "stellen" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Stemaanvraag" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Keur stemaanvraag goed of af." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID Gebruiker" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Stemaanvraag honoreren voor deze persoon?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s nodigt je uit voor het groepsgesprek ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "het wachtwoord is" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast service" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Te veel offline berichten voor dit contactpersoon. Het bericht is niet " +"opgeslagen." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "offline berichten van ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Tijd" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Van" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Aan" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pakket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline berichten:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Verwijder alle offline berichten" @@ -1361,117 +1543,129 @@ msgstr "Verwijder alle offline berichten" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe module" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub abonnee verzoek" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Beslis of dit verzoek tot abonneren zal worden goedgekeurd" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Node ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonnee Adres" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Deze gebruiker toestaan te abonneren op deze pubsub node?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Berichten bezorgen samen met gebeurtenisnotificaties" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Gebeurtenisbevestigingen Sturen" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Abonnees informeren wanneer de instellingen van de node veranderen" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Abonnees informeren wanneer de node verwijderd word" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Abonnees informeren wanneer items verwijderd worden uit de node" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Items in het geheugen bewaren" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Bijnaam voor deze knoop" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maximum aantal in het geheugen te bewaren items" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Abonnementsaanvraag toestaan" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Geef toegangsmodel" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Contactlijst-groepen die mogen abonneren" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Publicatietype opgeven" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Verwijder alle items wanneer de gerelateerde publiceerder offline gaat" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Geef type van eventbericht" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximumgrootte van bericht in bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Wanneer het laatst gepubliceerde item verzonden moet worden" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Notificaties alleen verzenden naar online gebruikers" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "De collecties waar een node mee is gerelateerd" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "De CAPTCHA-verificatie is mislukt" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "U hebt een client nodig die x:data en CAPTCHA ondersteunt om een bijnaam te " "registreren" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Kies een gebruikersnaam en een wachtwoord om u te registreren op deze server" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Het wachtwoord is te zwak" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Het is gebruikers niet toegestaan zo snel achter elkaar te registreren" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Uw Jabber-account is succesvol gecreeerd." @@ -1550,8 +1744,8 @@ msgstr "U can het wachtwoord later veranderen met een Jabber-client." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Sommige Jabber-clienten kunnen het wachtwoord opslaan op Uw computer. " "Gebruik deze mogelijkheid alleen als U vertrouwd dat Uw computer afdoende " @@ -1593,60 +1787,60 @@ msgstr "" msgid "Unregister" msgstr "Opheffen" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Inschrijving" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Bezig" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Groepen" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Bevestigen" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Verwijderen" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Roster van " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber ID toevoegen" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Roster" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Gedeelde rostergroepen" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Naam:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beschrijving:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Groepsleden:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Weergegeven groepen:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Groep " @@ -1722,64 +1916,21 @@ msgstr "Zoekresultaten voor " msgid "Fill in fields to search for any matching Jabber User" msgstr "Vul de velden in om te zoeken naar Jabber-gebruikers op deze server" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Uitgaande s2s-verbindingen:" + #~ msgid "Delete" #~ msgstr "Verwijderen" #~ msgid "This room is not anonymous" #~ msgstr "Deze chatruimte is niet anoniem" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Uw actieve privacy-lijst verbied het routeren van dit stanza." - -#~ msgid "Access denied by service policy" -#~ msgstr "De toegang werd geweigerd door het beleid van deze dienst" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Alleen beheerders van deze dienst mogen mededelingen verzenden naar alle " -#~ "chatruimtes" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "" -#~ "De aanmaak van de chatruimte is verhinderd door de instellingen van deze " -#~ "server" - -#~ msgid "Conference room does not exist" -#~ msgstr "De chatruimte bestaat niet" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Deze bijnaam is al geregistreerd door iemand anders" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "U moet het veld \"bijnaam\" invullen" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Dataverkeerslimiet overschreden" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Deze deelnemer wordt weggestuurd vanwege het sturen van een " #~ "foutmeldingsbericht" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Er mogen geen privéberichten naar de chatruimte worden verzonden" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Wacht s.v.p. met het maken van een nieuwe stemaanvraag." - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Stemaanvragen zijn uitgeschakeld voor deze chatruimte" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Er kon geen JID worden ontleend uit deze stemaanvraag" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Alleen moderators kunnen stemaanvragen goedkeuren" - -#~ msgid "Improper message type" -#~ msgstr "Onjuist berichttype" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1787,87 +1938,12 @@ msgstr "Vul de velden in om te zoeken naar Jabber-gebruikers op deze server" #~ "Deze deelnemer wordt weggestuurd vanwege het sturen van een " #~ "foutmeldingsbericht aan een andere deelnemer" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Er mogen geen privéberichten van het type \"groupchat\" worden verzonden" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "De ontvanger is niet in de chatruimte" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Het is niet toegestaan priveberichten te sturen" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Alleen aanwezigen mogen berichten naar de chatruimte verzenden" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Alleen aanwezigen mogen verzoeken verzenden naar de chatruimte" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Er mogen geen verzoeken verzenden worden naar deelnemers in deze " -#~ "chatruimte" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Bezoekers mogen geen berichten verzenden naar alle aanwezigen" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Deze deelnemer wordt weggestuurd vanwege het sturen van een foutmelding-" #~ "aanwezigheid" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Het is bezoekers niet toegestaan hun naam te veranderen in dit kanaal" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Deze bijnaam is al in gebruik door een andere aanwezige" - -#~ msgid "You have been banned from this room" -#~ msgstr "U werd verbannen uit deze chatruimte" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "U moet lid zijn om deze chatruimte te kunnen betreden" - -#~ msgid "A password is required to enter this room" -#~ msgstr "U hebt een wachtwoord nodig om deze chatruimte te kunnen betreden" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Te veel CAPTCHA-aanvragen" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Het generen van een CAPTCHA is mislukt" - -#~ msgid "Incorrect password" -#~ msgstr "Foutief wachtwoord" - -#~ msgid "Administrator privileges required" -#~ msgstr "U hebt beheerdersprivileges nodig" - -#~ msgid "Moderator privileges required" -#~ msgstr "U hebt moderatorprivileges nodig" - -#~ msgid "Owner privileges required" -#~ msgstr "U hebt eigenaarsprivileges nodig" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Te veel offline berichten voor dit contactpersoon. Het bericht is niet " -#~ "opgeslagen." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "De CAPTCHA-verificatie is mislukt" - -#~ msgid "The password is too weak" -#~ msgstr "Het wachtwoord is te zwak" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "" -#~ "Het is gebruikers niet toegestaan zo snel achter elkaar te registreren" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "De geautomatiseerde Turing-test is geslaagd." diff --git a/priv/msgs/no.msg b/priv/msgs/no.msg index 81a591ad7e0..e8ae741b3cf 100644 --- a/priv/msgs/no.msg +++ b/priv/msgs/no.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfigurasjon for Tilgangskontroll lister"}. {"Access Control Lists","Tilgangskontrollister"}. {"Access control lists","Tilgangskontroll lister"}. +{"Access denied by service policy","Tilgang nektes på grunn av en tjeneste regel"}. {"Access rules","Tilgangsregler"}. {"Access Rules","Tilgangsregler"}. {"Action on user","Handling på bruker"}. @@ -11,6 +12,7 @@ {"Add User","Legg til Bruker"}. {"Administration","Administrasjon"}. {"Administration of ","Administrasjon av "}. +{"Administrator privileges required","Administratorprivilegier kreves"}. {"A friendly name for the node","Et vennlig navn for noden"}. {"All activity","All aktivitet"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Tillat denne Jabber ID å abonnere på denne pubsub "}. @@ -25,6 +27,7 @@ {"All Users","Alle Brukere"}. {"Announcements","Kunngjøringer"}. {"anyone","hvem som helst"}. +{"A password is required to enter this room","Et passord kreves for tilgang til samtalerommet"}. {"April","april"}. {"August","august"}. {"Backup Management","Håndtere Sikkerehetskopiering"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","Velg om du vil godkjenne denne eksistensens abonement"}. {"City","By"}. {"Commands","Kommandoer"}. +{"Conference room does not exist","Konferanserommet finnes ikke"}. {"Configuration","Konfigurasjon"}. {"Configuration of room ~s","Konfigurasjon for rom ~s"}. {"Connected Resources:","Tilkoblede Ressurser:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","Ekskluder Jabber IDer fra CAPTCHA utfordring"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Eksporter data om alle brukere i en server til PIEFXIS filer"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Eksporter data om alle brukere i en host til PIEFXIS filer (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Feilet i forsøk på å hente JID fra din lyd forespørsel godkjenning"}. {"Family Name","Etternavn"}. {"February","februar"}. {"Fill in fields to search for any matching Jabber User","Fyll inn felt for å søke etter Jabber brukere"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","Importer brukeres data fra jabberd14 spoolfil katalog:"}. {"Import Users from Dir at ","Importer Brukere fra Katalog på "}. {"Import Users From jabberd14 Spool Files","Importer Brukere Fra jabberd14 Spoolfiler"}. +{"Improper message type","Feilaktig meldingstype"}. +{"Incorrect password","Feil passord"}. {"Invalid affiliation: ~s","Ugyldig rang: ~s"}. {"Invalid role: ~s","Ugyldig rolle: ~s"}. {"IP addresses","IP adresser"}. @@ -142,6 +149,9 @@ {"IRC username","IRC brukernavn"}. {"IRC Username","IRC Brukernavn"}. {"is now known as","er nå kjent som"}. +{"It is not allowed to send private messages","Det er ikke tillatt å sende private meldinger"}. +{"It is not allowed to send private messages of type \"groupchat\"","Det er ikke tillatt å sende private meldinger med typen "}. +{"It is not allowed to send private messages to the conference","Det er ikke tillatt å sende private meldinger til "}. {"Jabber Account Registration","Jabber Konto Registrering"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Ugyldig Jabber ID ~s"}. @@ -173,12 +183,14 @@ {"Max # of items to persist","Høyeste # elementer som skal lagres"}. {"Max payload size in bytes","Største innholdsstørrelse i byte"}. {"May","mai"}. +{"Membership is required to enter this room","Medlemskap kreves for tilgang til samtalerommet"}. {"Members:","Medlemmer:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Husk passordet, eller skriv det ned på et papir lagret på et trygt sted. I Jabber er det ingen automatisert måte å gjenskape passordet om du glemmer det. "}. {"Memory","Minne"}. {"Message body","Meldingskropp"}. {"Middle Name","Mellomnavn"}. {"Minimum interval between voice requests (in seconds)","Minimums interval mellom lyd forespørsler (i sekunder)"}. +{"Moderator privileges required","Redaktørprivilegier kreves"}. {"moderators only","kun for redaktører"}. {"Modified modules","Endrede moduler"}. {"Module","Modul"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","Send kunngjøringer bare til tilgjengelige brukere"}. {"Only moderators and participants are allowed to change the subject in this room","Bare redaktører og deltakere kan endre emnet i dette rommet"}. {"Only moderators are allowed to change the subject in this room","Bare ordstyrer tillates å endre emnet i dette rommet"}. +{"Only moderators can approve voice requests","Bare ordstyrer kan godkjenne lyd forespørsler"}. +{"Only occupants are allowed to send messages to the conference","Bare deltakere får sende normale meldinger til konferansen"}. +{"Only occupants are allowed to send queries to the conference","Bare deltakere er tillatt å sende forespørsler til "}. +{"Only service administrators are allowed to send service messages","Bare tjeneste administratorer er tilatt å sende tjeneste "}. {"Options","Alternativer"}. {"Organization Name","Organisasjonsnavn"}. {"Organization Unit","Organisasjonsenhet"}. {"Outgoing s2s Connections:","Utgående s2s Koblinger"}. {"Outgoing s2s Connections","Utgående s2s Koblinger"}. -{"Outgoing s2s Servers:","Utgående s2s Tjenere"}. +{"Owner privileges required","Eierprivilegier kreves"}. {"Packet","Pakke"}. {"Password ~b","Passord ~b"}. {"Password:","Passord:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","Vedvarende elementer til lagring"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Merk at disse valgene vil bare sikkerhetskopiere den innebygde Mnesia databasen. Dersom du bruker ODBC modulen må du også ta backup av din SQL database."}. +{"Please, wait for a while before sending new voice request","Vennligst vent en stund før du sender en ny lyd forespørsel"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","Publish-Subscribe"}. {"PubSub subscriber request","PubSub abonements forespørsel"}. {"Purge all items when the relevant publisher goes offline","Rydd alle elementer når den aktuelle utgiveren logger av"}. +{"Queries to the conference members are not allowed in this room","Forespørsler til konferanse medlemmene er ikke tillat i dette rommet"}. {"RAM and disc copy","RAM og diskkopi"}. {"RAM copy","RAM kopi"}. {"Raw","Rå"}. {"Really delete message of the day?","Virkelig slette melding for dagen?"}. +{"Recipient is not in the conference room","Mottakeren er ikke i konferanserommet"}. {"Register a Jabber account","Registrer en Jabber konto"}. {"Registered Users:","Registrerte Brukere:"}. {"Registered Users","Registrerte Brukere"}. @@ -270,6 +289,7 @@ {"Restore","Gjenopprett"}. {"Restore plain text backup immediately:","Gjenopprette rentekst sikkerhetskopi umiddelbart:"}. {"Room Configuration","Rom Konfigurasjon"}. +{"Room creation is denied by service policy","Oppretting av rom nektes av en tjenste regel"}. {"Room description","Rom beskrivelse"}. {"Room Occupants","Samtalerom Deltakere"}. {"Room title","Romtittel"}. @@ -298,7 +318,7 @@ {"Show Ordinary Table","Vis Ordinær Tabell"}. {"Shut Down Service","Avslutt Tjeneste"}. {"~s invites you to the room ~s","~s inviterer deg til rommet ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Noen Jabber klienter kan lagre passordet på datamaskinen. Bruk bare den funksjonen dersom du er sikker på at maskinen er trygg."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Noen Jabber klienter kan lagre passordet på datamaskinen. Bruk bare den funksjonen dersom du er sikker på at maskinen er trygg."}. {"Specify the access model","Spesifiser aksess modellen"}. {"Specify the event message type","Spesifiser hendelsesbeskjed type"}. {"Specify the publisher model","Angi publiserings modell"}. @@ -321,9 +341,13 @@ {"Subscriber Address","Abonnements Adresse"}. {"Subscription","Abonnement"}. {"Sunday","søndag"}. +{"That nickname is already in use by another occupant","Det kallenavnet er allerede i bruk av en annen deltaker"}. +{"That nickname is registered by another person","Det kallenavnet er registrert av en annen person"}. {"The CAPTCHA is valid.","Captchaen er ikke gyldig"}. +{"The CAPTCHA verification has failed","CAPTCHA godkjenningen har feilet"}. {"The collections with which a node is affiliated","Samlingene som en node er assosiert med"}. {"the password is","passordet er"}. +{"The password is too weak","Passordet er for svakt"}. {"The password of your Jabber account was successfully changed.","Passordet for din Jabber konto ble endret."}. {"There was an error changing the password: ","En feil skjedde under endring av passordet:"}. {"There was an error creating the account: ","En feil skjedde under oppretting av kontoen:"}. @@ -334,13 +358,16 @@ {"Thursday","torsdag"}. {"Time delay","Tids forsinkelse"}. {"Time","Tid"}. +{"Too many CAPTCHA requests","For mange CAPTCHA forespørsler"}. {"To ~s","Til ~s"}. {"To","Til"}. +{"Traffic rate limit is exceeded","Trafikkmengde grense overskredet"}. {"Transactions Aborted:","Avbrutte Transasksjoner:"}. {"Transactions Committed:","Sendte Transaksjoner:"}. {"Transactions Logged:","Loggede Transasksjoner:"}. {"Transactions Restarted:","Omstartede Transasksjoner:"}. {"Tuesday","tirsdag"}. +{"Unable to generate a CAPTCHA","Umulig å generere en CAPTCHA"}. {"Unauthorized","Uautorisert"}. {"Unregister a Jabber account","Avregistrer en Jabber konto"}. {"Unregister","Avregistrer"}. @@ -355,21 +382,29 @@ {"User JID","Bruker JID"}. {"User Management","Bruker Behandling"}. {"Username:","Brukernavn:"}. +{"Users are not allowed to register accounts so quickly","Brukere får ikke lov til registrere kontoer så fort"}. {"Users","Brukere"}. {"Users Last Activity","Brukers Siste Aktivitet"}. {"Validate","Bekrefte gyldighet"}. {"vCard User Search","vCard Bruker Søk"}. {"Virtual Hosts","Virtuella Maskiner"}. +{"Visitors are not allowed to change their nicknames in this room","Besøkende får ikke lov å endre kallenavn i dette "}. +{"Visitors are not allowed to send messages to all occupants","Besøkende får ikke sende meldinger til alle deltakere"}. {"Voice request","Lyd forespørsel"}. +{"Voice requests are disabled in this conference","Lyd forespørsler er blokkert i denne konferansen"}. {"Wednesday","onsdag"}. {"When to send the last published item","Når skal siste publiserte artikkel sendes"}. {"Whether to allow subscriptions","Om man skal tillate abonnenter"}. {"You can later change your password using a Jabber client.","Du kan når som helst endre passordet via en Jabber klient."}. +{"You have been banned from this room","Du har blitt bannlyst i dette rommet."}. +{"You must fill in field \"Nickname\" in the form","Du må fylle inn feltet \"Nickname\" i skjemaet"}. {"You need a client that supports x:data and CAPTCHA to register","Du trenger en klient som støtter x:data og CAPTCHA for registrering "}. {"You need a client that supports x:data to register the nickname","Du trenger en klient som støtter x:data for å registrere kallenavnet"}. {"You need an x:data capable client to configure mod_irc settings","Du trenger en x:data kompatibel klient for å konfigurere mod_irc instillinger"}. {"You need an x:data capable client to configure room","Du trenger en klient som støtter x:data for å "}. {"You need an x:data capable client to search","Du tregner en klient som støtter x:data for å kunne "}. +{"Your active privacy list has denied the routing of this stanza.","Din aktive privat liste har blokkert rutingen av denne strofen."}. +{"Your contact offline message queue is full. The message has been discarded.","Kontaktens frakoblede meldingskø er full. Meldingen har blitt kassert."}. {"Your Jabber account was successfully created.","Din Jabber konto ble opprettet"}. {"Your Jabber account was successfully deleted.","Dni Jabber konto er blitt sltettet."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Dine meldinger til ~s blir blokkert. For å åpne igjen, besøk ~s"}. diff --git a/priv/msgs/no.po b/priv/msgs/no.po index bf768a914d2..f3cfe7f338b 100644 --- a/priv/msgs/no.po +++ b/priv/msgs/no.po @@ -11,49 +11,53 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Norwegian (bokmål)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Bruk av STARTTLS kreves" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Ingen ressurs angitt" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Erstattet av en ny tilkobling" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "har blitt kastet ut" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Din aktive privat liste har blokkert rutingen av denne strofen." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Skriv inn teksten du ser" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Dine meldinger til ~s blir blokkert. For å åpne igjen, besøk ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Dersom du ikke ser CAPTCHA bilde her, besøk web siden. " -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA web side" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Captchaen er ikke gyldig" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Bruker" @@ -62,9 +66,9 @@ msgstr "Bruker" msgid "Server" msgstr "Server:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Passord" @@ -81,279 +85,280 @@ msgstr "Uautorisert" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrasjon" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Tilgangskontrollister" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Innsendt" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Feil format" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Send" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Rå" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Slett valgte" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Tilgangsregler" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "tilgangsregel konfigurasjon for ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuella Maskiner" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Brukere" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Tilkoblede Brukere" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Brukers Siste Aktivitet" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periode: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Siste måned" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Siste året" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "All aktivitet" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Vis Ordinær Tabell" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Vis Integral Tabell" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistikk" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Finnes Ikke" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Noden finnes ikke" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Legg til ny" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Maskin" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrerte Brukere" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Legg til Bruker" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Frakoblede Meldinger" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Siste Aktivitet" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Aldri" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Tilkoblet" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrerte Brukere:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Tilkoblede Brukere:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Utgående s2s Koblinger" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Utgående s2s Tjenere" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Utgående s2s Koblinger" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Ingen" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Endre Passord" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Bruker " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Tilkoblede Ressurser:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Passord:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Fjern Bruker" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Ingen Data" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Noder" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Kjørende Noder" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Stoppede Noder" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Node " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Database" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sikkerhetskopier" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Lyttende Porter" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Oppdatere" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Starte på nytt" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppe" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduler" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC Kall Feil" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Database Tabeller på " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Navn" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Lagringstype" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementer" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Minne" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Feil" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Sikkerhetskopi av " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -363,144 +368,144 @@ msgstr "" "databasen. Dersom du bruker ODBC modulen må du også ta backup av din SQL " "database." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Lagre binær sikkerhetskopi:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Gjenopprette binær backup umiddelbart:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Gjenopprette binær backup etter neste ejabberd omstart (krever mindre minne):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Lagre rentekst sikkerhetskopi:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Gjenopprette rentekst sikkerhetskopi umiddelbart:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importer brukeres data fra en PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "Eksporter data om alle brukere i en server til PIEFXIS filer" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Eksporter data om alle brukere i en host til PIEFXIS filer (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importer bruker data fra jabberd14 spoolfiler:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importer brukeres data fra jabberd14 spoolfil katalog:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Lyttende Porter på " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduler på " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistikk for ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Oppetid:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU Tid:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Sendte Transaksjoner:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Avbrutte Transasksjoner:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Omstartede Transasksjoner:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Loggede Transasksjoner:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Oppdater " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Oppdaterings plan" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Endrede moduler" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Oppdaterings skript" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Lavnivå oppdaterings skript" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Skript sjekk" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokoll" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Alternativer" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Start" @@ -785,8 +790,8 @@ msgstr "Tilgangsregler" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -803,31 +808,31 @@ msgstr "Antall registrerte brukere" msgid "Number of online users" msgstr "Antall tilkoblede brukere" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Siste pålogging" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Kontaktliste størrelse" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresser" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Ressurser" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrasjon av " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Handling på bruker" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Redigere Egenskaper" @@ -837,28 +842,40 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Tilgang nektes på grunn av en tjeneste regel" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Du trenger en x:data kompatibel klient for å konfigurere mod_irc instillinger" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registrering i mod_irc for " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -866,11 +883,11 @@ msgstr "" "Skriv brukernavn, tekstkoding, porter og passord du ønsker å bruke for " "tilkobling til IRC servere" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC Brukernavn" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -881,7 +898,7 @@ msgstr "" "liste med verdier i formatet '{\"irc server\", \"encoding\", port, \"password" "\"}'. Denne tjenesten bruker \"~s\" som standard, port ~p, empty password." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -889,35 +906,35 @@ msgstr "" "Eksempel: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Tilkoblings parametere" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Bli med i IRC kanal" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanal (ikke skriv den første #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC server" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Bli med i IRC kanalen her. " -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Bli med i IRC kanalen med denne Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC instillinger" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -927,48 +944,77 @@ msgstr "" "Trykk 'Neste' for å få flere felt for å fylle i. Trykk 'Fullfør' for å lagre " "innstillingene." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC brukernavn" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Passord ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Tekstkoding for server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Bare ordstyrer tillates å endre emnet i dette rommet" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Bare tjeneste administratorer er tilatt å sende tjeneste " + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Oppretting av rom nektes av en tjenste regel" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Konferanserommet finnes ikke" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Samtalerom" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Du trenger en klient som støtter x:data for å registrere kallenavnet" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registrer Kallenavn på " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Skriv inn kallenavnet du ønsker å registrere" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Kallenavn" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Det kallenavnet er registrert av en annen person" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Du må fylle inn feltet \"Nickname\" i skjemaet" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -996,354 +1042,482 @@ msgstr "Registrerte Brukere" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Samtalerommets konfigurasjon er endret" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "kommer inn i rommet" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "forlater rommet" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "har blitt bannlyst" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "har blitt kastet ut på grunn av en tilknytnings endring" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" "har blitt kastet ut på grunn av at rommet er endret til kun-for-medlemmer" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "har blitt kastet ut på grunn av at systemet avslutter" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "er nå kjent som" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " har satt emnet til: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Samtalerom er opprettet" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Samtalerom er fjernet" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Samtalerom er startet" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Samtalerom er stoppet" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "mandag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "tirsdag" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "onsdag" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "torsdag" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "fredag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "lørdag" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "søndag" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "januar" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "februar" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "mars" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "april" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "mai" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "juni" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "juli" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "august" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "september" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "oktober" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "november" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "desember" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Rom Konfigurasjon" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Samtalerom Deltakere" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Trafikkmengde grense overskredet" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Det er ikke tillatt å sende private meldinger til " + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Vennligst vent en stund før du sender en ny lyd forespørsel" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Lyd forespørsler er blokkert i denne konferansen" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Feilet i forsøk på å hente JID fra din lyd forespørsel godkjenning" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Bare ordstyrer kan godkjenne lyd forespørsler" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Feilaktig meldingstype" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Det er ikke tillatt å sende private meldinger med typen " + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Mottakeren er ikke i konferanserommet" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Det er ikke tillatt å sende private meldinger" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Bare deltakere får sende normale meldinger til konferansen" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Bare deltakere er tillatt å sende forespørsler til " + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Forespørsler til konferanse medlemmene er ikke tillat i dette rommet" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Bare redaktører og deltakere kan endre emnet i dette rommet" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Bare ordstyrer tillates å endre emnet i dette rommet" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Besøkende får ikke sende meldinger til alle deltakere" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Besøkende får ikke lov å endre kallenavn i dette " + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Det kallenavnet er allerede i bruk av en annen deltaker" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Du har blitt bannlyst i dette rommet." + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Medlemskap kreves for tilgang til samtalerommet" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Et passord kreves for tilgang til samtalerommet" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "For mange CAPTCHA forespørsler" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Umulig å generere en CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Feil passord" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Administratorprivilegier kreves" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Redaktørprivilegier kreves" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Ugyldig Jabber ID ~s" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Kallenavn ~s eksisterer ikke i dette rommet" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ugyldig rang: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ugyldig rolle: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Eierprivilegier kreves" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Konfigurasjon for rom ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Romtittel" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Rom beskrivelse" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Gjør rommet permanent" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Gjør rommet offentlig søkbart" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Gjør deltakerlisten offentlig" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Passordbeskytt rommet" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maksimum Antall Deltakere" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ingen grense" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Presenter ekte Jabber IDer til" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "kun for redaktører" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "hvem som helst" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "kun for redaktører" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Gjør rommet tilgjengelig kun for medlemmer" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Gjør rommet redaktørstyrt" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Standard brukere som deltakere" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Tillat brukere å endre emne" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Tillat brukere å sende private meldinger" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Tillat brukere å sende private meldinger til" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "ingen" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Tillat brukere å sende forespørsel til andre brukere" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Tillat brukere å sende invitasjoner" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Tillat besøkende å sende status tekst i " -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Tillat besøkende å endre kallenavn" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Tillat brukere å sende lyd forespørsler" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimums interval mellom lyd forespørsler (i sekunder)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Gjør rommet CAPTCHA beskyttet" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Ekskluder Jabber IDer fra CAPTCHA utfordring" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Slå på logging" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Du trenger en klient som støtter x:data for å " -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Antall deltakere" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Lyd forespørsel" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Enten godkjenn eller forby lyd forespørselen" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Bruker JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Gi lyd til denne personen?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s inviterer deg til rommet ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "passordet er" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "Kontaktens frakoblede meldingskø er full. Meldingen har blitt kassert." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~ss kø for Frakoblede Meldinger" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Tid" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Fra" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Til" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pakke" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Frakoblede Meldinger:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Fjern Alle Frakoblede Meldinger" @@ -1351,114 +1525,126 @@ msgstr "Fjern Alle Frakoblede Meldinger" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub abonements forespørsel" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Velg om du vil godkjenne denne eksistensens abonement" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Node ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Abonnements Adresse" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Tillat denne Jabber ID å abonnere på denne pubsub " -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Send innhold sammen med kunngjøringer" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Lever begivenhets kunngjøringer" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Informer abonnenter når node konfigurasjonen endres" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Informer abonnenter når noden slettes" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Informer abonnenter når elementer fjernes fra noden" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Vedvarende elementer til lagring" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Et vennlig navn for noden" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Høyeste # elementer som skal lagres" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Om man skal tillate abonnenter" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Spesifiser aksess modellen" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Kontaktliste grupper som tillates å abonnere" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Angi publiserings modell" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Rydd alle elementer når den aktuelle utgiveren logger av" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Spesifiser hendelsesbeskjed type" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Største innholdsstørrelse i byte" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Når skal siste publiserte artikkel sendes" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Send kunngjøringer bare til tilgjengelige brukere" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Samlingene som en node er assosiert med" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "CAPTCHA godkjenningen har feilet" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Du trenger en klient som støtter x:data og CAPTCHA for registrering " -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Velg et brukernavn og passord for å registrere på " +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Passordet er for svakt" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Brukere får ikke lov til registrere kontoer så fort" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Din Jabber konto ble opprettet" @@ -1537,8 +1723,8 @@ msgstr "Du kan når som helst endre passordet via en Jabber klient." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Noen Jabber klienter kan lagre passordet på datamaskinen. Bruk bare den " "funksjonen dersom du er sikker på at maskinen er trygg." @@ -1578,60 +1764,60 @@ msgstr "" msgid "Unregister" msgstr "Avregistrer" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Abonnement" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Ventende" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupper" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Bekrefte gyldighet" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Fjern" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktliste for " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Legg til Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktliste" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Delte Kontaktgrupper" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Navn:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beskrivelse:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Medlemmer:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Viste grupper:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Gruppe " @@ -1707,59 +1893,20 @@ msgstr "Søke Resultater for " msgid "Fill in fields to search for any matching Jabber User" msgstr "Fyll inn felt for å søke etter Jabber brukere" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Utgående s2s Tjenere" + #~ msgid "Delete" #~ msgstr "Slett" #~ msgid "This room is not anonymous" #~ msgstr "Dette rommet er ikke anonymt" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Din aktive privat liste har blokkert rutingen av denne strofen." - -#~ msgid "Access denied by service policy" -#~ msgstr "Tilgang nektes på grunn av en tjeneste regel" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Bare tjeneste administratorer er tilatt å sende tjeneste " - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Oppretting av rom nektes av en tjenste regel" - -#~ msgid "Conference room does not exist" -#~ msgstr "Konferanserommet finnes ikke" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Det kallenavnet er registrert av en annen person" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Du må fylle inn feltet \"Nickname\" i skjemaet" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Trafikkmengde grense overskredet" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Denne deltakeren er kastet ut av rommet fordi han sendte en feilmelding" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Det er ikke tillatt å sende private meldinger til " - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Vennligst vent en stund før du sender en ny lyd forespørsel" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Lyd forespørsler er blokkert i denne konferansen" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Feilet i forsøk på å hente JID fra din lyd forespørsel godkjenning" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Bare ordstyrer kan godkjenne lyd forespørsler" - -#~ msgid "Improper message type" -#~ msgstr "Feilaktig meldingstype" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1767,82 +1914,12 @@ msgstr "Fyll inn felt for å søke etter Jabber brukere" #~ "Denne deltakeren er kastet ut av rommet fordi han sendte en feilmelding " #~ "til en annen deltaker" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Det er ikke tillatt å sende private meldinger med typen " - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Mottakeren er ikke i konferanserommet" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Det er ikke tillatt å sende private meldinger" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Bare deltakere får sende normale meldinger til konferansen" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Bare deltakere er tillatt å sende forespørsler til " - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Forespørsler til konferanse medlemmene er ikke tillat i dette rommet" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Besøkende får ikke sende meldinger til alle deltakere" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Denne deltakeren er kastet ut av rommet fordi han sendte feil " #~ "tilstederværelse" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Besøkende får ikke lov å endre kallenavn i dette " - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Det kallenavnet er allerede i bruk av en annen deltaker" - -#~ msgid "You have been banned from this room" -#~ msgstr "Du har blitt bannlyst i dette rommet." - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Medlemskap kreves for tilgang til samtalerommet" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Et passord kreves for tilgang til samtalerommet" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "For mange CAPTCHA forespørsler" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Umulig å generere en CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Feil passord" - -#~ msgid "Administrator privileges required" -#~ msgstr "Administratorprivilegier kreves" - -#~ msgid "Moderator privileges required" -#~ msgstr "Redaktørprivilegier kreves" - -#~ msgid "Owner privileges required" -#~ msgstr "Eierprivilegier kreves" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Kontaktens frakoblede meldingskø er full. Meldingen har blitt kassert." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "CAPTCHA godkjenningen har feilet" - -#~ msgid "The password is too weak" -#~ msgstr "Passordet er for svakt" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Brukere får ikke lov til registrere kontoer så fort" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Captchaen er ikke gyldig" diff --git a/priv/msgs/pl.msg b/priv/msgs/pl.msg index 73eceee2bb8..4bab696cfcb 100644 --- a/priv/msgs/pl.msg +++ b/priv/msgs/pl.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfiguracja listy dostępowej"}. {"Access Control Lists","Lista dostępowa"}. {"Access control lists","Listy dostępowe"}. +{"Access denied by service policy","Dostęp zabroniony zgodnie z zasadami usługi"}. {"Access rules","Reguły dostępu"}. {"Access Rules","Zasady dostępu"}. {"Action on user","Wykonaj na użytkowniku"}. @@ -11,6 +12,7 @@ {"Add User","Dodaj użytkownika"}. {"Administration","Administracja"}. {"Administration of ","Zarządzanie "}. +{"Administrator privileges required","Wymagane uprawnienia administratora"}. {"A friendly name for the node","Przyjazna nazwa węzła"}. {"All activity","Cała aktywność"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Pozwól temu Jabber ID na zapisanie się do tego węzła PubSub"}. @@ -25,6 +27,7 @@ {"All Users","Wszyscy użytkownicy"}. {"Announcements","Powiadomienia"}. {"anyone","wszystkich"}. +{"A password is required to enter this room","Aby wejść do pokoju wymagane jest hasło"}. {"April","Kwiecień"}. {"August","Sierpień"}. {"Backup Management","Zarządzanie kopiami zapasowymi"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Wybierz, czy akceptować subskrypcję tej jednostki"}. {"City","Miasto"}. {"Commands","Polecenia"}. +{"Conference room does not exist","Pokój konferencyjny nie istnieje"}. {"Configuration","Konfiguracja"}. {"Configuration of room ~s","Konfiguracja pokoju ~s"}. {"Connected Resources:","Zasoby zalogowane:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Wyeksportuj wszystkie tabele jako zapytania SQL do pliku:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Eksportuj dane wszystkich użytkowników serwera do plików w formacie PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Eksportuj dane użytkowników z hosta do plików w formacie PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Nie udało się wydobyć JID-u z twojego żądania"}. {"Family Name","Nazwisko"}. {"February","Luty"}. {"Fill in fields to search for any matching Jabber User","Wypełnij pola aby znaleźć pasujących użytkowników Jabbera"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importuj użytkowników z katalogu roboczego serwera jabberd14"}. {"Import Users from Dir at ","Importuj użytkowników z katalogu na "}. {"Import Users From jabberd14 Spool Files","Importuj użytkowników z plików roboczych serwera jabberd14"}. +{"Improper message type","Nieprawidłowy typ wiadomości"}. +{"Incorrect password","Nieprawidłowe hasło"}. {"Invalid affiliation: ~s","Nieprawidłowa przynależność: ~s"}. {"Invalid role: ~s","Nieprawidłowa rola: ~s"}. {"IP addresses","Adresy IP"}. @@ -147,6 +154,9 @@ {"IRC username","Nazwa użytkownika IRC"}. {"IRC Username","Nazwa użytkownika IRC"}. {"is now known as","jest teraz znany jako"}. +{"It is not allowed to send private messages of type \"groupchat\"","Nie można wysyłać prywatnych wiadomości typu \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Nie wolno wysyłac prywatnych wiadomości na konferencję"}. +{"It is not allowed to send private messages","Wysyłanie prywatnych wiadomości jest zabronione"}. {"Jabber Account Registration","Zakładanie konta Jabber"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s jest niepoprawny"}. @@ -180,11 +190,13 @@ {"Max payload size in bytes","Maksymalna wielkość powiadomienia w bajtach"}. {"May","Maj"}. {"Members:","Członkowie:"}. +{"Membership is required to enter this room","Musisz być na liście członków tego pokoju aby do niego wejść"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Zapamiętaj swoje hasło lub zapisz je na kartce i zachowaj w bezpiecznym miejscu. Na Jabberze nie ma zautomatyzowanego systemu odzyskiwania haseł."}. {"Memory","Pamięć"}. {"Message body","Treść wiadomości"}. {"Middle Name","Drugie imię"}. {"Minimum interval between voice requests (in seconds)","Minimalny odstęp między żądaniami głosowymi (w sekundach)"}. +{"Moderator privileges required","Wymagane uprawnienia moderatora"}. {"moderators only","tylko moderatorzy"}. {"Modified modules","Zmodyfikowane moduły"}. {"Module","Moduł"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Dostarczaj powiadomienia tylko dostępnym użytkownikom"}. {"Only moderators and participants are allowed to change the subject in this room","Tylko moderatorzy i uczestnicy mogą zmienić temat tego pokoju"}. {"Only moderators are allowed to change the subject in this room","Tylko moderatorzy mogą zmienić temat tego pokoju"}. +{"Only moderators can approve voice requests","Tylko moderatorzy mogą zatwierdzać żądania głosowe"}. +{"Only occupants are allowed to send messages to the conference","Tylko uczestnicy mogą wysyłać wiadomości na konferencję"}. +{"Only occupants are allowed to send queries to the conference","Tylko uczestnicy mogą wysyłać zapytania do konferencji"}. +{"Only service administrators are allowed to send service messages","Tylko administratorzy mogą wysyłać wiadomości"}. {"Options","Opcje"}. {"Organization Name","Nazwa organizacji"}. {"Organization Unit","Dział"}. {"Outgoing s2s Connections:","Wychodzące połączenia s2s:"}. {"Outgoing s2s Connections","Wychodzące połączenia s2s"}. -{"Outgoing s2s Servers:","Serwery zewnętrzne s2s:"}. +{"Owner privileges required","Wymagane uprawnienia właściciela"}. {"Packet","Pakiet"}. {"Password ~b","Hasło ~b"}. {"Password:","Hasło:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Przechowuj na stałe dane PubSub"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Te opcje kopii zapasowych dotyczą tylko wbudowanej bazy danych typu Mnesia. Jeśli korzystasz z modułu ODBC, musisz wykonać kopie bazy we własnym zakresie."}. +{"Please, wait for a while before sending new voice request","Proszę poczekać chwile, zanim wyślesz nowe żądanie głosowe"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","PubSub"}. {"PubSub subscriber request","Żądanie subskrybcji PubSub"}. {"Purge all items when the relevant publisher goes offline","Usuń wszystkie elementy w momencie kiedy publikujący rozłączy się"}. +{"Queries to the conference members are not allowed in this room","Informacje o członkach konferencji nie są dostępne w tym pokoju"}. {"RAM and disc copy","Kopia na dysku i w pamięci RAM"}. {"RAM copy","Kopia w pamięci RAM"}. {"Raw","Żródło"}. {"Really delete message of the day?","Na pewno usunąć wiadomość dnia?"}. +{"Recipient is not in the conference room","Odbiorcy nie ma w pokoju"}. {"Register a Jabber account","Załóż konto Jabber"}. {"Registered nicknames","Zarejestrowanych nicków"}. {"Registered Users:","Użytkownicy zarejestrowani:"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Natychmiast odtwórz kopię z postaci tekstowej:"}. {"Restore","Przywróć z kopii"}. {"Room Configuration","Konfiguracja pokoju"}. +{"Room creation is denied by service policy","Zasady serwera zabraniają tworzyć nowe pokoje"}. {"Room description","Opis pokoju"}. {"Room Occupants","Lista uczestników"}. {"Room title","Tytuł pokoju"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Pokaż zwykłą tabelę"}. {"Shut Down Service","Wyłącz usługę"}. {"~s invites you to the room ~s","~s zaprasza Cię do pokoju ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Niektóre klienty Jabber mogą zapisywać Twoje hasło na komputerze. Używaj tej opcji tylko jeśli ufasz komputerowi na którym pracujesz."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Niektóre klienty Jabber mogą zapisywać Twoje hasło na komputerze. Używaj tej opcji tylko jeśli ufasz komputerowi na którym pracujesz."}. {"Specify the access model","Określ model dostępu"}. {"Specify the event message type","Określ typ wiadomości"}. {"Specify the publisher model","Określ model publikującego"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Adres subskrybenta"}. {"Subscription","Subskrypcja"}. {"Sunday","Niedziela"}. +{"That nickname is already in use by another occupant","Ta nazwa użytkownika jest używana przez kogoś innego"}. +{"That nickname is registered by another person","Ta nazwa użytkownika jest już zarejestrowana przez inną osobę"}. {"The CAPTCHA is valid.","Captcha jest poprawna."}. +{"The CAPTCHA verification has failed","Weryfikacja CAPTCHA nie powiodła się."}. {"The collections with which a node is affiliated","Grupy, do których należy węzeł"}. {"the password is","hasło to:"}. +{"The password is too weak","Hasło nie jest wystarczająco trudne"}. {"The password of your Jabber account was successfully changed.","Hasło do Twojego konta zostało zmienione."}. {"There was an error changing the password: ","Podczas próby zmiany hasła wystąpił błąd:"}. {"There was an error creating the account: ","Wystąpił błąd podczas tworzenia konta:"}. @@ -348,15 +372,18 @@ {"Time","Czas"}. {"Time delay","Opóźnienie"}. {"To","Do"}. +{"Too many CAPTCHA requests","Za dużo żądań CAPTCHA"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Zbyt wiele (~p) nieudanych prób logowanie z tego adresu IP (~s). Ten adres zostanie odblokowany o ~s UTC"}. {"Too many unacked stanzas","Zbyt wiele niepotwierdzonych pakietów"}. {"To ~s","Do ~s"}. {"Total rooms","Wszystkich pokoi"}. +{"Traffic rate limit is exceeded","Limit transferu przekroczony"}. {"Transactions Aborted:","Transakcje anulowane:"}. {"Transactions Committed:","Transakcje zakończone:"}. {"Transactions Logged:","Transakcje zalogowane:"}. {"Transactions Restarted:","Transakcje uruchomione ponownie:"}. {"Tuesday","Wtorek"}. +{"Unable to generate a CAPTCHA","Nie można wygenerować CAPTCHA"}. {"Unauthorized","Nie autoryzowano"}. {"Unregister a Jabber account","Usuń konto Jabber"}. {"Unregister","Wyrejestruj"}. @@ -371,6 +398,7 @@ {"User JID","Użytkownik "}. {"User Management","Zarządzanie użytkownikami"}. {"Username:","Nazwa użytkownika:"}. +{"Users are not allowed to register accounts so quickly","Użytkowncy nie mogą tak szybko rejestrować nowych kont"}. {"Users Last Activity","Ostatnia aktywność użytkowników"}. {"Users","Użytkownicy"}. {"User ~s","Użytkownik ~s"}. @@ -378,16 +406,23 @@ {"Validate","Potwierdź"}. {"vCard User Search","Wyszukiwanie vCard użytkowników"}. {"Virtual Hosts","Wirtualne Hosty"}. +{"Visitors are not allowed to change their nicknames in this room","Uczestnicy tego pokoju nie mogą zmieniać swoich nicków"}. +{"Visitors are not allowed to send messages to all occupants","Odwiedzający nie mogą wysyłać wiadomości do wszystkich obecnych"}. +{"Voice requests are disabled in this conference","Głosowe żądania są wyłączone w tym pokoju"}. {"Voice request","Żądanie głosowe"}. {"Wednesday","Środa"}. {"When to send the last published item","Kiedy wysłać ostatnio opublikowaną rzecz"}. {"Whether to allow subscriptions","Czy pozwolić na subskrypcje"}. {"You can later change your password using a Jabber client.","Możesz później zmienić swoje hasło za pomocą dowolnego klienta Jabber."}. +{"You have been banned from this room","Zostałeś wykluczony z tego pokoju"}. +{"You must fill in field \"Nickname\" in the form","Musisz wypełnić pole \"Nazwa użytkownika\" w formularzu"}. {"You need a client that supports x:data and CAPTCHA to register","Potrzebujesz klienta obsługującego x:data aby zarejestrować nick"}. {"You need a client that supports x:data to register the nickname","Potrzebujesz klienta obsługującego x:data aby zarejestrować nick"}. {"You need an x:data capable client to configure mod_irc settings","Potrzebujesz klienta obsługującego x:data aby skonfigurować mod_irc"}. {"You need an x:data capable client to configure room","Potrzebujesz klienta obsługującego x:data aby skonfigurować pokój"}. {"You need an x:data capable client to search","Potrzebujesz klienta obsługującego x:data aby wyszukiwać"}. +{"Your active privacy list has denied the routing of this stanza.","Aktualna lista prywatności zabrania przesyłania tej stanzy"}. +{"Your contact offline message queue is full. The message has been discarded.","Kolejka wiadomości offline adresata jest pełna. Wiadomość została odrzucona."}. {"Your Jabber account was successfully created.","Twoje konto zostało stworzone."}. {"Your Jabber account was successfully deleted.","Twoje konto zostało usunięte."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Twoje wiadomości do ~s są blokowane. Aby je odblokować, odwiedź ~s"}. diff --git a/priv/msgs/pl.po b/priv/msgs/pl.po index 900b877ee39..53273794316 100644 --- a/priv/msgs/pl.po +++ b/priv/msgs/pl.po @@ -16,49 +16,53 @@ msgstr "" "X-Additional-Translator: Mateusz Gajewski\n" "X-Generator: Poedit 1.8.4\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Wymagane jest użycie STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nie podano zasobu" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Połączenie zostało zastąpione" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "został wyrzucony" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Aktualna lista prywatności zabrania przesyłania tej stanzy" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Zbyt wiele niepotwierdzonych pakietów" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Przepisz tekst z obrazka" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Twoje wiadomości do ~s są blokowane. Aby je odblokować, odwiedź ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Jeśli nie widzisz obrazka CAPTCHA, odwiedź stronę internetową." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Strona internetowa CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Captcha jest poprawna." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Użytkownik" @@ -67,9 +71,9 @@ msgstr "Użytkownik" msgid "Server" msgstr "Serwer:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Hasło" @@ -86,275 +90,276 @@ msgstr "Nie autoryzowano" msgid "ejabberd Web Admin" msgstr "ejabberd: Panel Administracyjny" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administracja" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Lista dostępowa" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Wprowadzone" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Błędny format" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Wyślij" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Żródło" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Usuń zaznaczone" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Zasady dostępu" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s konfiguracja zasad dostępu" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Wirtualne Hosty" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Użytkownicy" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Użytkownicy zalogowani" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Ostatnia aktywność użytkowników" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Przedział czasu: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Miniony miesiąc" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Miniony rok" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Cała aktywność" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Pokaż zwykłą tabelę" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Pokaż tabelę całkowitą" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statystyki" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nie znaleziono" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Węzeł nie został znaleziony" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Dodaj nowe" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Host" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Użytkownicy zarejestrowani" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Dodaj użytkownika" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Wiadomości offline" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Ostatnia aktywność" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nigdy" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Dostępny" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Użytkownicy zarejestrowani:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Użytkownicy zalogowani:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Wychodzące połączenia s2s:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Serwery zewnętrzne s2s:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Wychodzące połączenia s2s:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Brak" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Zmień hasło" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Użytkownik ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Zasoby zalogowane:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Hasło:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Usuń użytkownika" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Brak danych" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Węzły" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Uruchomione węzły" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zatrzymane węzły" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Węzeł ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Baza danych" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Wykonaj kopie" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Porty nasłuchujące" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualizuj" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Uruchom ponownie" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Zatrzymaj" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduły" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Błąd żądania RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tabele bazy na ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Imię" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Typ bazy" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementy" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Pamięć" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Błąd" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Kopia zapasowa ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -364,146 +369,146 @@ msgstr "" "Jeśli korzystasz z modułu ODBC, musisz wykonać kopie bazy we własnym " "zakresie." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Zachowaj kopię binarną:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Natychmiast odtwórz kopię binarną:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Odtwórz kopię binarną podczas następnego uruchomienia ejabberd (wymaga mniej " "zasobów):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Zachowaj kopię w postaci tekstowej:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Natychmiast odtwórz kopię z postaci tekstowej:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importuj dane użytkowników z pliku w formacie PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Eksportuj dane wszystkich użytkowników serwera do plików w formacie PIEFXIS " "(XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Eksportuj dane użytkowników z hosta do plików w formacie PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Wyeksportuj wszystkie tabele jako zapytania SQL do pliku:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importuj dane użytkownika z pliku roboczego serwera jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importuj użytkowników z katalogu roboczego serwera jabberd14" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Porty nasłuchujące na " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Moduły na ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statystyki ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Czas pracy:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Czas CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakcje zakończone:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakcje anulowane:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakcje uruchomione ponownie:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakcje zalogowane:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Uaktualnij ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan aktualizacji" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Zmodyfikowane moduły" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Skrypt aktualizacji" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Skrypt aktualizacji niskiego poziomu" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Sprawdź skrypt" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokół" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Moduł" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opcje" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Uruchom" @@ -792,8 +797,8 @@ msgstr "Reguły dostępu" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -810,31 +815,31 @@ msgstr "Liczba zarejestrowanych użytkowników" msgid "Number of online users" msgstr "Liczba zalogowanych użytkowników" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Ostatnie logowanie" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Rozmiar listy kontaktów" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adresy IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Zasoby" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Zarządzanie " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Wykonaj na użytkowniku" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Edytuj właściwości" @@ -846,27 +851,39 @@ msgstr "" "Zbyt wiele (~p) nieudanych prób logowanie z tego adresu IP (~s). Ten adres " "zostanie odblokowany o ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Ten adres IP został zablokowany w ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Dostęp zabroniony zgodnie z zasadami usługi" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transport IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Moduł IRC ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Potrzebujesz klienta obsługującego x:data aby skonfigurować mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Rejestracja w mod_irc dla " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -874,11 +891,11 @@ msgstr "" "Wprowadź nazwę użytkownika, port i kodowanie, których chcesz używać do " "łączenia z serwerami IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nazwa użytkownika IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -890,7 +907,7 @@ msgstr "" "\"encoding\", port, \"password\"}'. Domyślne ta usługa używa kodowania \"~s" "\", portu ~p, bez hasła." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -898,35 +915,35 @@ msgstr "" "Przykład: [{\"wroclaw.irc.pl\",\"utf-8\"}, {\"warszawa.irc.pl\", " "\"iso8859-2\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parametry połączeń" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Dołącz do kanału IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Kanał IRC (nie używaj #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Serwer IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Dołącz do kanału IRC." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Dołącz do kanału IRC pod tym Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Ustawienia IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -936,48 +953,77 @@ msgstr "" "serwerami IRC. Wciśnij \"Dalej\" aby ustawić więcej parametrów połączenia. " "Wciśnij \"Zakończ\" aby zapisać ustawienia." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Nazwa użytkownika IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Hasło ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kodowanie znaków dla serwera ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Serwer ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Tylko moderatorzy mogą zmienić temat tego pokoju" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Tylko administratorzy mogą wysyłać wiadomości" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Zasady serwera zabraniają tworzyć nowe pokoje" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Pokój konferencyjny nie istnieje" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Pokoje rozmów" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Potrzebujesz klienta obsługującego x:data aby zarejestrować nick" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Rejestracja nazwy użytkownika na " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Wprowadz nazwę użytkownika którego chcesz zarejestrować" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Nazwa użytkownika" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Ta nazwa użytkownika jest już zarejestrowana przez inną osobę" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Musisz wypełnić pole \"Nazwa użytkownika\" w formularzu" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Moduł MUC" @@ -1002,353 +1048,482 @@ msgstr "Zarejestrowanych nicków" msgid "List of rooms" msgstr "Lista pokoi" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Konfiguracja pokoju zmodyfikowana" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "dołącza do pokoju" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "opuszcza pokój" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "został wykluczony" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "został wyrzucony z powodu zmiany przynależności" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "został wyrzucony z powodu zmiany pokoju na \"Tylko dla Członków\"" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "został wyrzucony z powodu wyłączenia systemu" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "jest teraz znany jako" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " zmienił temat na: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Pokój został stworzony" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Pokój został usunięty" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Pokój został uruchomiony" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Pokój został zatrzymany" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Poniedziałek" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Wtorek" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Środa" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Czwartek" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Piątek" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sobota" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Niedziela" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Styczeń" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Luty" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Marzec" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Kwiecień" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Maj" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Czerwiec" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Lipiec" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Sierpień" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Wrzesień" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Październik" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Listopad" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Grudzień" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Konfiguracja pokoju" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Lista uczestników" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Limit transferu przekroczony" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Nie wolno wysyłac prywatnych wiadomości na konferencję" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Proszę poczekać chwile, zanim wyślesz nowe żądanie głosowe" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Głosowe żądania są wyłączone w tym pokoju" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Nie udało się wydobyć JID-u z twojego żądania" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Tylko moderatorzy mogą zatwierdzać żądania głosowe" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Nieprawidłowy typ wiadomości" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Nie można wysyłać prywatnych wiadomości typu \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Odbiorcy nie ma w pokoju" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Wysyłanie prywatnych wiadomości jest zabronione" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Tylko uczestnicy mogą wysyłać wiadomości na konferencję" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Tylko uczestnicy mogą wysyłać zapytania do konferencji" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Informacje o członkach konferencji nie są dostępne w tym pokoju" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Tylko moderatorzy i uczestnicy mogą zmienić temat tego pokoju" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Tylko moderatorzy mogą zmienić temat tego pokoju" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Odwiedzający nie mogą wysyłać wiadomości do wszystkich obecnych" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Uczestnicy tego pokoju nie mogą zmieniać swoich nicków" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Ta nazwa użytkownika jest używana przez kogoś innego" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Zostałeś wykluczony z tego pokoju" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Musisz być na liście członków tego pokoju aby do niego wejść" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Aby wejść do pokoju wymagane jest hasło" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Za dużo żądań CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Nie można wygenerować CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Nieprawidłowe hasło" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Wymagane uprawnienia administratora" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Wymagane uprawnienia moderatora" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s jest niepoprawny" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Nie ma nicka ~s w tym pokoju" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Nieprawidłowa przynależność: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Nieprawidłowa rola: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Wymagane uprawnienia właściciela" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Konfiguracja pokoju ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Tytuł pokoju" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Opis pokoju" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Utwórz pokój na stałe" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Pozwól wyszukiwać pokój" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Upublicznij listę uczestników" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Pokój zabezpieczony hasłem" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maksymalna liczba uczestników" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Prawdziwe Jabber ID widoczne dla" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "tylko moderatorzy" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "wszystkich" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "tylko moderatorzy" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Pokój tylko dla członków" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Pokój moderowany" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Domyślni użytkownicy jako uczestnicy" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Pozwól użytkownikom zmieniać temat" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Pozwól użytkownikom wysyłać prywatne wiadomości" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Pozwól użytkownikom wysyłać prywatne wiadomości" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "nikt" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Pozwól użytkownikom pobierać informacje o innych użytkownikach" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Pozwól użytkownikom wysyłać zaproszenia" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Pozwól uczestnikom na wysyłanie statusów opisowych" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Pozwól uczestnikom na zmianę nicka" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Pozwól użytkownikom wysyłać zaproszenia" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimalny odstęp między żądaniami głosowymi (w sekundach)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Pokój zabezpieczony captchą" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Włącz archiwizowanie rozmów" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Pomiń Jabber ID z żądania CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Włącz logowanie" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Potrzebujesz klienta obsługującego x:data aby skonfigurować pokój" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Liczba uczestników" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "prywatny, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Żądanie głosowe" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Zatwierdź lub odrzuć żądanie głosowe" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Użytkownik " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Udzielić głosu tej osobie?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s zaprasza Cię do pokoju ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "hasło to:" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "Serwis multicast ejabbera" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Kolejka wiadomości offline adresata jest pełna. Wiadomość została odrzucona." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Kolejka wiadomości offline użytkownika ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Czas" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Od" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Do" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pakiet" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Wiadomości offline:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Usuń wszystkie wiadomości typu 'Offline'" @@ -1356,115 +1531,127 @@ msgstr "Usuń wszystkie wiadomości typu 'Offline'" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Moduł SOCKS5 Bytestreams" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "PubSub" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Moduł Publish-Subscribe" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Żądanie subskrybcji PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Wybierz, czy akceptować subskrypcję tej jednostki" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID węzła" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adres subskrybenta" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Pozwól temu Jabber ID na zapisanie się do tego węzła PubSub" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Dostarczaj zawartość publikacji wraz z powiadomieniami o zdarzeniach" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Dostarczaj powiadomienia o zdarzeniach" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Informuj subskrybentów o zmianach konfiguracji węzła" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Informuj subskrybentów o usunięciu węzła" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Informuj subskrybentów o usunięciu elementów węzła" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Przechowuj na stałe dane PubSub" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Przyjazna nazwa węzła" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maksymalna liczba przechowywanych przedmiotów" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Czy pozwolić na subskrypcje" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Określ model dostępu" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Grupy kontaktów uprawnione do subskrypcji" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Określ model publikującego" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Usuń wszystkie elementy w momencie kiedy publikujący rozłączy się" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Określ typ wiadomości" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maksymalna wielkość powiadomienia w bajtach" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kiedy wysłać ostatnio opublikowaną rzecz" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Dostarczaj powiadomienia tylko dostępnym użytkownikom" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Grupy, do których należy węzeł" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Weryfikacja CAPTCHA nie powiodła się." + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Potrzebujesz klienta obsługującego x:data aby zarejestrować nick" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Wybierz nazwę użytkownika i hasło aby zarejestrować się na tym serwerze" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Hasło nie jest wystarczająco trudne" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Użytkowncy nie mogą tak szybko rejestrować nowych kont" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Twoje konto zostało stworzone." @@ -1542,8 +1729,8 @@ msgstr "Możesz później zmienić swoje hasło za pomocą dowolnego klienta Jab #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Niektóre klienty Jabber mogą zapisywać Twoje hasło na komputerze. Używaj tej " "opcji tylko jeśli ufasz komputerowi na którym pracujesz." @@ -1581,60 +1768,60 @@ msgstr "Ta strona pozwala usunąć konto Jabber z tego serwera." msgid "Unregister" msgstr "Wyrejestruj" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Subskrypcja" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Oczekuje" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupy" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Potwierdź" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Usuń" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista kontaktów " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Dodaj Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Lista kontaktów" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Wspólne grupy kontaktów" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nazwa:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Opis:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Członkowie:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Wyświetlane grupy:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupa " @@ -1710,59 +1897,20 @@ msgstr "Wyniki wyszukiwania dla " msgid "Fill in fields to search for any matching Jabber User" msgstr "Wypełnij pola aby znaleźć pasujących użytkowników Jabbera" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Serwery zewnętrzne s2s:" + #~ msgid "Delete" #~ msgstr "Usuń" #~ msgid "This room is not anonymous" #~ msgstr "Ten pokój nie jest anonimowy" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Aktualna lista prywatności zabrania przesyłania tej stanzy" - -#~ msgid "Access denied by service policy" -#~ msgstr "Dostęp zabroniony zgodnie z zasadami usługi" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Tylko administratorzy mogą wysyłać wiadomości" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Zasady serwera zabraniają tworzyć nowe pokoje" - -#~ msgid "Conference room does not exist" -#~ msgstr "Pokój konferencyjny nie istnieje" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Ta nazwa użytkownika jest już zarejestrowana przez inną osobę" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Musisz wypełnić pole \"Nazwa użytkownika\" w formularzu" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Limit transferu przekroczony" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Ten uczestnik został wyrzucony z pokoju ponieważ wysłał komunikat błędu" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Nie wolno wysyłac prywatnych wiadomości na konferencję" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Proszę poczekać chwile, zanim wyślesz nowe żądanie głosowe" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Głosowe żądania są wyłączone w tym pokoju" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Nie udało się wydobyć JID-u z twojego żądania" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Tylko moderatorzy mogą zatwierdzać żądania głosowe" - -#~ msgid "Improper message type" -#~ msgstr "Nieprawidłowy typ wiadomości" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1770,82 +1918,12 @@ msgstr "Wypełnij pola aby znaleźć pasujących użytkowników Jabbera" #~ "Ten uczestnik został wyrzucony z pokoju ponieważ wysłał komunikat błędu " #~ "do innego uczestnika" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Nie można wysyłać prywatnych wiadomości typu \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Odbiorcy nie ma w pokoju" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Wysyłanie prywatnych wiadomości jest zabronione" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Tylko uczestnicy mogą wysyłać wiadomości na konferencję" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Tylko uczestnicy mogą wysyłać zapytania do konferencji" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Informacje o członkach konferencji nie są dostępne w tym pokoju" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Odwiedzający nie mogą wysyłać wiadomości do wszystkich obecnych" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Ten uczestnik został wyrzucony z pokoju ponieważ jego informacja o " #~ "statusie zawierała błędy" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Uczestnicy tego pokoju nie mogą zmieniać swoich nicków" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Ta nazwa użytkownika jest używana przez kogoś innego" - -#~ msgid "You have been banned from this room" -#~ msgstr "Zostałeś wykluczony z tego pokoju" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Musisz być na liście członków tego pokoju aby do niego wejść" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Aby wejść do pokoju wymagane jest hasło" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Za dużo żądań CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Nie można wygenerować CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Nieprawidłowe hasło" - -#~ msgid "Administrator privileges required" -#~ msgstr "Wymagane uprawnienia administratora" - -#~ msgid "Moderator privileges required" -#~ msgstr "Wymagane uprawnienia moderatora" - -#~ msgid "Owner privileges required" -#~ msgstr "Wymagane uprawnienia właściciela" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Kolejka wiadomości offline adresata jest pełna. Wiadomość została " -#~ "odrzucona." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Weryfikacja CAPTCHA nie powiodła się." - -#~ msgid "The password is too weak" -#~ msgstr "Hasło nie jest wystarczająco trudne" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Użytkowncy nie mogą tak szybko rejestrować nowych kont" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Captcha jest poprawna." diff --git a/priv/msgs/pt-br.msg b/priv/msgs/pt-br.msg index 62cb4978733..a18227f66a6 100644 --- a/priv/msgs/pt-br.msg +++ b/priv/msgs/pt-br.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Configuração da Lista de Controle de Acesso"}. {"Access control lists","Listas de Controle de Acesso"}. {"Access Control Lists","Listas de Controle de Acesso"}. +{"Access denied by service policy","Aceso denegado por la política do serviço"}. {"Access rules","Regras de acesso"}. {"Access Rules","Regras de Acesso"}. {"Action on user","Ação no usuário"}. @@ -11,6 +12,7 @@ {"Add User","Adicionar usuário"}. {"Administration","Administração"}. {"Administration of ","Administração de "}. +{"Administrator privileges required","Se necessita privilégios de administrador"}. {"A friendly name for the node","Um nome familiar para o nó"}. {"All activity","Todas atividades"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Autorizar este Jabber ID para a inscrição neste tópico pubsub?"}. @@ -25,6 +27,7 @@ {"All Users","Todos os usuários"}. {"Announcements","Anúncios"}. {"anyone","qualquer um"}. +{"A password is required to enter this room","Se necessita senha para entrar em esta sala"}. {"April","Abril"}. {"August","Agosto"}. {"Backup Management","Gestão de Backup"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Aprovar esta assinatura."}. {"City","Cidade"}. {"Commands","Comandos"}. +{"Conference room does not exist","La sala de conferencias não existe"}. {"Configuration","Configuração"}. {"Configuration of room ~s","Configuração para ~s"}. {"Connected Resources:","Recursos conectados:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Exportar todas as tabelas como SQL para um arquivo:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportar todos os dados de todos os usuários no servidor, para arquivos formato PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportar dados dos usuários em um host, para arquivos PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Não foi possível extrair o JID (Jabber ID) da requisição de voz"}. {"Family Name","Sobrenome"}. {"February","Fevereiro"}. {"Fill in fields to search for any matching Jabber User","Preencha campos para buscar usuários Jabber que concordem"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Importar dados dos usuários de um diretório-fila jabberd14:"}. {"Import Users from Dir at ","Importar usuários a partir do diretório em "}. {"Import Users From jabberd14 Spool Files","Importar usuários de arquivos jabberd14 (spool files)"}. +{"Improper message type","Tipo de mensagem incorreto"}. +{"Incorrect password","Senha incorreta"}. {"Invalid affiliation: ~s","Afiliação não válida: ~s"}. {"Invalid role: ~s","Cargo (role) é não válido: ~s"}. {"IP addresses","Endereços IP"}. @@ -147,6 +154,9 @@ {"IRC username","Usuário IRC"}. {"IRC Username","Usuário IRC"}. {"is now known as","é agora conhecido como"}. +{"It is not allowed to send private messages","Não é permitido enviar mensagens privadas"}. +{"It is not allowed to send private messages of type \"groupchat\"","No está permitido enviar mensagens privados do tipo \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Impedir o envio de mensagens privadas para a sala"}. {"Jabber Account Registration","Registros de Contas Jabber"}. {"Jabber ID","ID Jabber"}. {"Jabber ID ~s is invalid","O Jabber ID ~s não es válido"}. @@ -179,12 +189,14 @@ {"Max # of items to persist","Máximo # de elementos que persistem"}. {"Max payload size in bytes","Máximo tamanho do payload em bytes"}. {"May","Maio"}. +{"Membership is required to enter this room","Necessitas ser membro de esta sala para poder entrar"}. {"Members:","Membros:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memorize a sua senha, ou escreva-a em um papel e guarde-o em um lugar seguro. Jabber não é uma maneira automatizada para recuperar a sua senha, se você a esquecer eventualmente."}. {"Memory","Memória"}. {"Message body","Corpo da mensagem"}. {"Middle Name","Nome do meio"}. {"Minimum interval between voice requests (in seconds)","O intervalo mínimo entre requisições de voz (em segundos)"}. +{"Moderator privileges required","Se necessita privilégios de moderador"}. {"moderators only","apenas moderadores"}. {"Modified modules","Módulos atualizados"}. {"Module","Módulo"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Solo enviar notificações aos usuários disponíveis"}. {"Only moderators and participants are allowed to change the subject in this room","Somente os moderadores e os participamentes podem alterar o assunto desta sala"}. {"Only moderators are allowed to change the subject in this room","Somente os moderadores podem alterar o assunto desta sala"}. +{"Only moderators can approve voice requests","Somente moderadores podem aprovar requisições de voz"}. +{"Only occupants are allowed to send messages to the conference","Solo os ocupantes podem enviar mensagens a la sala"}. +{"Only occupants are allowed to send queries to the conference","Solo os ocupantes podem enviar consultas a la sala"}. +{"Only service administrators are allowed to send service messages","Apenas administradores possuem permissão para enviar mensagens de serviço"}. {"Options","Opções"}. {"Organization Name","Nome da organização"}. {"Organization Unit","Departamento/Unidade"}. {"Outgoing s2s Connections","Conexões que partam de s2s"}. {"Outgoing s2s Connections:","Conexões que partem de s2s"}. -{"Outgoing s2s Servers:","Servidores que partem de s2s"}. +{"Owner privileges required","Se requere privilégios de proprietário da sala"}. {"Packet","Pacote"}. {"Password ~b","Senha ~b"}. {"Password:","Senha:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Persistir elementos ao armazenar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Observe que tais opções farão backup apenas da base de dados Mnesia. Caso você esteja utilizando o modulo ODBC, você precisará fazer backup de sua base de dados SQL separadamente."}. +{"Please, wait for a while before sending new voice request","Por favor, espere antes de enviar uma nova requisição de voz"}. {"Pong","Pong"}. {"Port ~b","Porta ~b"}. {"Port","Porta"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Publicação de Tópico"}. {"PubSub subscriber request","PubSub requisição de assinante"}. {"Purge all items when the relevant publisher goes offline","Descartar todos os itens quando o publicante principal estiver offline"}. +{"Queries to the conference members are not allowed in this room","Nesta sala não se permite consultas aos membros da sala"}. {"RAM and disc copy","Copias na RAM e disco rígido"}. {"RAM copy","Copia em RAM"}. {"Raw","Intocado"}. {"Really delete message of the day?","Deletar realmente a mensagem do dia?"}. +{"Recipient is not in the conference room","O receptor não está em la sala de conferencia"}. {"Register a Jabber account","Registrar uma conta Jabber"}. {"Registered nicknames","Usuários registrados"}. {"Registered Users:","Usuários registrados"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Restaurar backup formato texto imediatamente:"}. {"Restore","Restaurar"}. {"Room Configuration","Configuração de salas"}. +{"Room creation is denied by service policy","Se te a denegado criar la sala por política do serviço"}. {"Room description","Descrição da Sala"}. {"Room Occupants","Número de participantes"}. {"Room title","Título da sala"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Mostrar Tabela Ordinária"}. {"Shut Down Service","Parar Serviço"}. {"~s invites you to the room ~s","~s convidou você para a sala ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Alguns clientes jabber podem salvar a sua senha no seu computador. Use recurso somente se você considera este computador seguro o suficiente."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clientes jabber podem salvar a sua senha no seu computador. Use recurso somente se você considera este computador seguro o suficiente."}. {"Specify the access model","Especificar os modelos de acesso"}. {"Specify the event message type","Especificar o tipo de mensagem para o evento"}. {"Specify the publisher model","Especificar o modelo do publicante"}. @@ -333,9 +353,13 @@ {"Subscriber Address","Endereço dos Assinantes"}. {"Subscription","Subscrição"}. {"Sunday","Domingo"}. +{"That nickname is already in use by another occupant","O apelido (nick) já está sendo utilizado"}. +{"That nickname is registered by another person","O nick já está registrado por outra pessoa"}. {"The CAPTCHA is valid.","O CAPTCHA é inválido."}. +{"The CAPTCHA verification has failed","A verificação do CAPTCHA falhou"}. {"The collections with which a node is affiliated","As coleções com as quais o nó está relacionado"}. {"the password is","a senha é"}. +{"The password is too weak","Senha considerada fraca'"}. {"The password of your Jabber account was successfully changed.","A senha da sua conta Jabber foi mudada com sucesso."}. {"There was an error changing the password: ","Houveram erros ao mudar a senha: "}. {"There was an error creating the account: ","Houveram erras ao criar esta conta: "}. @@ -347,16 +371,19 @@ {"Thursday","Quinta"}. {"Time delay","Intervalo (Tempo)"}. {"Time","Tempo"}. +{"Too many CAPTCHA requests","Número excessivo de requisições para o CAPTCHA"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço serádesbloqueado as ~s UTC"}. {"Too many unacked stanzas","número excessivo de instâncias sem confirmação"}. {"To","Para"}. {"To ~s","Para ~s"}. {"Total rooms","Salas no total"}. +{"Traffic rate limit is exceeded","Limite de banda excedido"}. {"Transactions Aborted:","Transações abortadas:"}. {"Transactions Committed:","Transações salvas:"}. {"Transactions Logged:","Transações de log:"}. {"Transactions Restarted:","Transações reiniciadas:"}. {"Tuesday","Terça"}. +{"Unable to generate a CAPTCHA","Impossível gerar um CAPTCHA"}. {"Unauthorized","Não Autorizado"}. {"Unregister a Jabber account","Deletar conta Jabber"}. {"Unregister","Deletar registro"}. @@ -371,6 +398,7 @@ {"User JID","Usuário JID"}. {"User Management","Gerenciamento de Usuários"}. {"Username:","Usuário:"}. +{"Users are not allowed to register accounts so quickly","Usuários não estão autorizados a registrar contas imediatamente"}. {"Users Last Activity","Ultimas atividades dos usuários"}. {"User ~s","Usuário ~s"}. {"Users","Usuários"}. @@ -378,16 +406,23 @@ {"Validate","Validar"}. {"vCard User Search","Busca de Usuário vCard"}. {"Virtual Hosts","Hosts virtuais"}. +{"Visitors are not allowed to change their nicknames in this room","Nesta sala, os visitantes não pode mudar seus apelidos"}. +{"Visitors are not allowed to send messages to all occupants","Os visitantes não podem enviar mensagens a todos os ocupantes"}. {"Voice request","Requisição de voz"}. +{"Voice requests are disabled in this conference","Requisições de voz estào desabilitadas nesta conferência"}. {"Wednesday","Quarta"}. {"When to send the last published item","Quando enviar o último tópico publicado"}. {"Whether to allow subscriptions","Permitir subscrições"}. {"You can later change your password using a Jabber client.","Mais tarde você pode alterar a sua senha usando um cliente Jabber."}. +{"You have been banned from this room","As sido bloqueado em esta sala"}. +{"You must fill in field \"Nickname\" in the form","Você deve completar o campo \"Apelido\" no formulário"}. {"You need a client that supports x:data and CAPTCHA to register","Você precisa de um cliente com suporte de x:data para poder registrar o nick"}. {"You need a client that supports x:data to register the nickname","Você precisa de um cliente com suporte a x:data para registrar o seu apelido"}. {"You need an x:data capable client to configure mod_irc settings","Necessitas um cliente com suporte de x:data para configurar las opções de mod_irc"}. {"You need an x:data capable client to configure room","Necessitas um cliente com suporte de x:data para configurar la sala"}. {"You need an x:data capable client to search","Necessitas um cliente com suporte de x:data para poder buscar"}. +{"Your active privacy list has denied the routing of this stanza.","Sua lista de privacidade ativa negou o roteamento deste."}. +{"Your contact offline message queue is full. The message has been discarded.","Sua fila de mensagens offline esta cheia. Sua mensagem foi descartada"}. {"Your Jabber account was successfully created.","Sua conta jabber foi criada corretamente."}. {"Your Jabber account was successfully deleted.","Sua conta Jabber foi deletada com sucesso."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Suas mensagens para ~s estão bloqueadas. Para desbloqueá-las, visite: ~s"}. diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index 42c521e931c..9cdfe114f3b 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -11,50 +11,54 @@ msgstr "" "X-Additional-Translator: Felipe Brito Vasconcellos\n" "X-Additional-Translator: Victor Hugo dos Santos\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "É obrigatório uso de STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nenhum recurso foi informado" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Substituído por nova conexão" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "foi removido" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Sua lista de privacidade ativa negou o roteamento deste." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "número excessivo de instâncias sem confirmação" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Insira o texto que você vê" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Suas mensagens para ~s estão bloqueadas. Para desbloqueá-las, visite: ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Se você não conseguir ver o CAPTCHA aqui, visite a web page." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA web page" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "O CAPTCHA é inválido." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Usuário" @@ -63,9 +67,9 @@ msgstr "Usuário" msgid "Server" msgstr "Servidor:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Senha" @@ -82,275 +86,276 @@ msgstr "Não Autorizado" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administração" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Controle de Acesso" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Submetido" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Formato incorreto" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Intocado" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Remover os selecionados" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Regras de Acesso" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configuração da Regra de Acesso ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Hosts virtuais" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Usuários" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Usuários conectados" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Ultimas atividades dos usuários" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Período: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Último mês" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Último ano" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Todas atividades" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrar Tabela Ordinária" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrar Tabela Integral" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Não encontrado" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nó não encontrado" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Adicionar novo" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Máquina" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Usuários Registrados" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Adicionar usuário" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Mensagens offline" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última atividade" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Conectado" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Usuários registrados" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Usuários online" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Conexões que partem de s2s" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Servidores que partem de s2s" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Conexões que partem de s2s" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nenhum" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Mudar senha" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Usuário ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Senha:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Remover usuário" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Nenhum dado" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nós" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nos em execução" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nos parados" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Nó ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Base de dados" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Salvar cópia de segurança" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Portas escutadas" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Atualizar" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Parar" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Erro de chamada RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Tabelas do bancod de dados em ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de armazenamento" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementos" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memória" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Erro" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Backup de ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -360,146 +365,146 @@ msgstr "" "você esteja utilizando o modulo ODBC, você precisará fazer backup de sua " "base de dados SQL separadamente." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Armazenar backup binário:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Restaurar backup binário imediatamente" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar backup binário após reinicialização do ejabberd (requer menos " "memória):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Armazenar backup em texto:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Restaurar backup formato texto imediatamente:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importar usuários de um arquivo PIEFXIS (XEP-0227): " -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportar todos os dados de todos os usuários no servidor, para arquivos " "formato PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportar dados dos usuários em um host, para arquivos PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Exportar todas as tabelas como SQL para um arquivo:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importar dados dos usuários de uma fila jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importar dados dos usuários de um diretório-fila jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Portas abertas em " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Módulos em ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Estatísticas de ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tempo de CPU" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transações salvas:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transações abortadas:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transações reiniciadas:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transações de log:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Atualizar ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plano de Atualização" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Módulos atualizados" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Script de atualização" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Script de atualização low level" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Verificação de Script" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porta" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Porta" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opções" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Iniciar" @@ -785,8 +790,8 @@ msgstr "Regras de acesso" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" @@ -803,31 +808,31 @@ msgstr "Número de usuários registrados" msgid "Number of online users" msgstr "Número de usuários online" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Último login" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Tamanho da Lista" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Endereços IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administração de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Ação no usuário" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propriedades" @@ -839,29 +844,41 @@ msgstr "" "Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço " "serádesbloqueado as ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Este endereço IP está bloqueado em ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Aceso denegado por la política do serviço" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transporte IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Módulo de IRC para ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Necessitas um cliente com suporte de x:data para configurar las opções de " "mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registro em mod_irc para " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -869,11 +886,11 @@ msgstr "" "Insira o nome de usuário, codificações, portas e senhas que vocêdeseja para " "usar nos servidores IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Usuário IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -885,7 +902,7 @@ msgstr "" "'{\"servidor IRC\", \"codificação\", porta, \"senha\"}'. Por padrão, este " "serviço usa a codificação \"~s\", porta \"~p\", e senha em branco (vazia)" -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -893,35 +910,35 @@ msgstr "" "Exemplo: [{\"irc.teste.net\", \"koi8-r\"}, 6667, \"senha\"}, {\"dominio.foo." "net\", \"iso8859-1\", 7000}, {\"irc.servidordeteste.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parâmetros para as Conexões" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Juntar-se ao canal IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Canal IRC (não coloque o #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Servidor IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Aqui! Juntar-se ao canal IRC." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Entrar no canal IRC, neste ID Jabber: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Configurações do IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -932,49 +949,79 @@ msgstr "" "mais campos que devem ser preenchidos. Ao final, pressione " "'Complete' ('Completar') para salvar a configuração." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Usuário IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Senha ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Porta ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Codificação para o servidor ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Servidor ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Somente os moderadores podem alterar o assunto desta sala" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Apenas administradores possuem permissão para enviar mensagens de serviço" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Se te a denegado criar la sala por política do serviço" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "La sala de conferencias não existe" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Salas de Chat" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Você precisa de um cliente com suporte a x:data para registrar o seu apelido" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registro do apelido em " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Introduza o apelido que quer registrar" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Apelido" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "O nick já está registrado por outra pessoa" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Você deve completar o campo \"Apelido\" no formulário" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" @@ -999,144 +1046,202 @@ msgstr "Usuários registrados" msgid "List of rooms" msgstr "Lista de salas" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Configuração da sala de bate-papo modificada" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "Entrar na sala" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "Sair da sala" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "foi banido" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "foi desconectado porque por afiliação inválida" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" "foi desconectado porque a política da sala mudou, só membros são permitidos" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "foi desconectado porque o sistema foi desligado" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "é agora conhecido como" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " a posto o assunto: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "A sala de chat está criada" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "A sala de chat está destruída" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "A sala de chat está inciada" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "A sala de chat está parada" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Segunda" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Terça" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Quarta" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Quinta" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Sexta" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sábado" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Domingo" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Janeiro" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Fevereiro" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Março" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Maio" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Junho" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Julho" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Setembro" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Outubro" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Dezembro" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Configuração de salas" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Limite de banda excedido" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Impedir o envio de mensagens privadas para a sala" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Por favor, espere antes de enviar uma nova requisição de voz" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Requisições de voz estào desabilitadas nesta conferência" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Não foi possível extrair o JID (Jabber ID) da requisição de voz" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Somente moderadores podem aprovar requisições de voz" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Tipo de mensagem incorreto" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "No está permitido enviar mensagens privados do tipo \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "O receptor não está em la sala de conferencia" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Não é permitido enviar mensagens privadas" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Solo os ocupantes podem enviar mensagens a la sala" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Solo os ocupantes podem enviar consultas a la sala" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Nesta sala não se permite consultas aos membros da sala" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1144,211 +1249,281 @@ msgstr "" "Somente os moderadores e os participamentes podem alterar o assunto desta " "sala" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Somente os moderadores podem alterar o assunto desta sala" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Os visitantes não podem enviar mensagens a todos os ocupantes" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Nesta sala, os visitantes não pode mudar seus apelidos" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "O apelido (nick) já está sendo utilizado" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "As sido bloqueado em esta sala" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Necessitas ser membro de esta sala para poder entrar" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Se necessita senha para entrar em esta sala" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Número excessivo de requisições para o CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Impossível gerar um CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Senha incorreta" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Se necessita privilégios de administrador" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Se necessita privilégios de moderador" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s não es válido" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "O nick ~s não existe em la sala" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliação não válida: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Cargo (role) é não válido: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Se requere privilégios de proprietário da sala" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Configuração para ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Descrição da Sala" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Tornar sala persistente" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Tornar sala pública possível de ser encontrada" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Tornar pública a lista de participantes" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Tornar protegida a senha da sala" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Número máximo de participantes" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ilimitado" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Tornar o Jabber ID real visível por" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "apenas moderadores" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "qualquer um" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "apenas moderadores" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Tornar sala apenas para membros" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Tornar a sala moderada" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Usuários padrões como participantes" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Permitir a usuários modificar o assunto" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Permitir a usuários enviarem mensagens privadas" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Permitir visitantes enviar mensagem privada para" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "ninguém" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Permitir a usuários pesquisar informações sobre os demais" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Permitir a usuários envio de convites" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Permitir atualizações de status aos visitantes" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Permitir mudança de apelido aos visitantes" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Permitir aos visitantes o envio de convites" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "O intervalo mínimo entre requisições de voz (em segundos)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Tornar protegida a senha da sala" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Habilitar arquivamento de mensagens" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Excluir IDs Jabber de serem submetidos ao CAPTCHA" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Permitir criação de logs" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Necessitas um cliente com suporte de x:data para configurar la sala" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privado, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Requisição de voz" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Você deve aprovar/desaprovar a requisição de voz." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Usuário JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Dar 'voice' a esta usuário?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s convidou você para a sala ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "a senha é" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Multicast" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast service" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "Sua fila de mensagens offline esta cheia. Sua mensagem foi descartada" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s's Fila de Mensagens Offline" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Tempo" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Para" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pacote" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Mensagens offline" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Remover Todas as Mensagens Offline" @@ -1356,115 +1531,127 @@ msgstr "Remover Todas as Mensagens Offline" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Modulo ejabberd SOCKS5 Bytestreams" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publicação de Tópico" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Módulo para Publicar Tópicos do ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub requisição de assinante" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Aprovar esta assinatura." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID do Tópico" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Endereço dos Assinantes" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Autorizar este Jabber ID para a inscrição neste tópico pubsub?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Enviar payloads junto com as notificações de eventos" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Entregar as notificações de evento" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notificar subscritores quando cambia la configuração do nodo" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notificar subscritores quando o nodo se elimine" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Notificar subscritores quando os elementos se eliminem do nodo" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Persistir elementos ao armazenar" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Um nome familiar para o nó" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Máximo # de elementos que persistem" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Permitir subscrições" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Especificar os modelos de acesso" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Listar grupos autorizados" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Especificar o modelo do publicante" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Descartar todos os itens quando o publicante principal estiver offline" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Especificar o tipo de mensagem para o evento" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Máximo tamanho do payload em bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Quando enviar o último tópico publicado" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Solo enviar notificações aos usuários disponíveis" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "As coleções com as quais o nó está relacionado" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "A verificação do CAPTCHA falhou" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Você precisa de um cliente com suporte de x:data para poder registrar o nick" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Escolha um nome de usuário e senha para registrar-se neste servidor" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Senha considerada fraca'" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Usuários não estão autorizados a registrar contas imediatamente" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Sua conta jabber foi criada corretamente." @@ -1543,8 +1730,8 @@ msgstr "Mais tarde você pode alterar a sua senha usando um cliente Jabber." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Alguns clientes jabber podem salvar a sua senha no seu computador. Use " "recurso somente se você considera este computador seguro o suficiente." @@ -1583,60 +1770,60 @@ msgstr "Esta página aceita para deletar uma conta Jabber neste servidor." msgid "Unregister" msgstr "Deletar registro" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscrição" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validar" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Remover" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contatos de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Adicionar ID jabber" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contatos" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Grupos Shared Roster" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Nome:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Descrição:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Membros:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Grupos Exibidos:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupo " @@ -1712,61 +1899,21 @@ msgstr "Resultados de pesquisa para " msgid "Fill in fields to search for any matching Jabber User" msgstr "Preencha campos para buscar usuários Jabber que concordem" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Servidores que partem de s2s" + #~ msgid "Delete" #~ msgstr "Eliminar" #~ msgid "This room is not anonymous" #~ msgstr "Essa sala não é anônima" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Sua lista de privacidade ativa negou o roteamento deste." - -#~ msgid "Access denied by service policy" -#~ msgstr "Aceso denegado por la política do serviço" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Apenas administradores possuem permissão para enviar mensagens de serviço" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Se te a denegado criar la sala por política do serviço" - -#~ msgid "Conference room does not exist" -#~ msgstr "La sala de conferencias não existe" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "O nick já está registrado por outra pessoa" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Você deve completar o campo \"Apelido\" no formulário" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Limite de banda excedido" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Este participante foi desconectado da sala de chat por ter enviado uma " #~ "mensagem de erro." -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Impedir o envio de mensagens privadas para a sala" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Por favor, espere antes de enviar uma nova requisição de voz" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Requisições de voz estào desabilitadas nesta conferência" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Não foi possível extrair o JID (Jabber ID) da requisição de voz" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Somente moderadores podem aprovar requisições de voz" - -#~ msgid "Improper message type" -#~ msgstr "Tipo de mensagem incorreto" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1774,80 +1921,11 @@ msgstr "Preencha campos para buscar usuários Jabber que concordem" #~ "Este participante foi desconectado da sala de chat por ter enviado uma " #~ "mensagem de erro para outro usuário." -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "No está permitido enviar mensagens privados do tipo \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "O receptor não está em la sala de conferencia" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Não é permitido enviar mensagens privadas" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Solo os ocupantes podem enviar mensagens a la sala" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Solo os ocupantes podem enviar consultas a la sala" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Nesta sala não se permite consultas aos membros da sala" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Os visitantes não podem enviar mensagens a todos os ocupantes" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Este participante foi desconectado da sala de chat por ter enviado uma " #~ "notificação errônea de presença." -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Nesta sala, os visitantes não pode mudar seus apelidos" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "O apelido (nick) já está sendo utilizado" - -#~ msgid "You have been banned from this room" -#~ msgstr "As sido bloqueado em esta sala" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Necessitas ser membro de esta sala para poder entrar" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Se necessita senha para entrar em esta sala" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Número excessivo de requisições para o CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Impossível gerar um CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Senha incorreta" - -#~ msgid "Administrator privileges required" -#~ msgstr "Se necessita privilégios de administrador" - -#~ msgid "Moderator privileges required" -#~ msgstr "Se necessita privilégios de moderador" - -#~ msgid "Owner privileges required" -#~ msgstr "Se requere privilégios de proprietário da sala" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Sua fila de mensagens offline esta cheia. Sua mensagem foi descartada" - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "A verificação do CAPTCHA falhou" - -#~ msgid "The password is too weak" -#~ msgstr "Senha considerada fraca'" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Usuários não estão autorizados a registrar contas imediatamente" - #~ msgid "Captcha test failed" #~ msgstr "O CAPTCHA é inválido." diff --git a/priv/msgs/pt.msg b/priv/msgs/pt.msg index fe2b45fcdcc..f8be5a5d93e 100644 --- a/priv/msgs/pt.msg +++ b/priv/msgs/pt.msg @@ -3,12 +3,14 @@ {"Access Control List Configuration","Configuração da Lista de Controlo de Acesso"}. {"Access control lists","Listas de Controlo de Acesso"}. {"Access Control Lists","Listas de Controlo de Acesso"}. +{"Access denied by service policy","Acesso negado pela política de serviço"}. {"Access rules","Regras de acesso"}. {"Access Rules","Regras de Acesso"}. {"Action on user","Acção no utilizador"}. {"Add New","Adicionar novo"}. {"Add User","Adicionar utilizador"}. {"Administration of ","Administração de "}. +{"Administrator privileges required","São necessários privilégios de administrador"}. {"All Users","Todos os utilizadores"}. {"Backup","Guardar cópia de segurança"}. {"Backup Management","Gestão de cópias de segurança"}. @@ -19,6 +21,7 @@ {"Choose modules to stop","Seleccione os módulos a parar"}. {"Choose storage type of tables","Seleccione o tipo de armazenagem das tabelas"}. {"City","Cidade"}. +{"Conference room does not exist","A sala não existe"}. {"Configuration","Configuração"}. {"Connected Resources:","Recursos conectados:"}. {"Country","País"}. @@ -48,9 +51,13 @@ {"Import File","Importar ficheiro"}. {"Import User from File at ","Importar utilizador a partir do ficheiro em "}. {"Import Users from Dir at ","Importar utilizadores a partir do directório em "}. +{"Improper message type","Tipo de mensagem incorrecto"}. +{"Incorrect password","Palavra-chave incorrecta"}. {"Invalid affiliation: ~s","Afiliação inválida: ~s"}. {"Invalid role: ~s","Papel inválido: ~s"}. {"IRC Username","Nome do utilizador de IRC"}. +{"It is not allowed to send private messages of type \"groupchat\"","Não é permitido enviar mensagens privadas do tipo \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Impedir o envio de mensagens privadas para a sala"}. {"Jabber ID ~s is invalid","O Jabber ID ~s não é válido"}. {"Last Activity","Última actividade"}. {"Listened Ports at ","Portas em escuta em "}. @@ -58,6 +65,7 @@ {"Make room moderated","Tornar a sala moderada"}. {"Memory","Memória"}. {"Middle Name","Segundo nome"}. +{"Moderator privileges required","São necessários privilégios de moderador"}. {"Module","Módulo"}. {"Modules","Módulos"}. {"Name","Nome"}. @@ -72,9 +80,13 @@ {"OK","OK"}. {"Online","Ligado"}. {"Online Users","Utilizadores ligados"}. +{"Only occupants are allowed to send messages to the conference","Só os ocupantes podem enviar mensagens para a sala"}. +{"Only occupants are allowed to send queries to the conference","Só os ocupantes podem enviar consultas para a sala"}. +{"Only service administrators are allowed to send service messages","Só os administradores do serviço têm permissão para enviar mensagens de serviço"}. {"Options","Opções"}. {"Organization Name","Nome da organização"}. {"Organization Unit","Unidade da organização"}. +{"Owner privileges required","São necessários privilégios de dono"}. {"Packet","Pacote"}. {"Password:","Palavra-chave:"}. {"Password","Palavra-chave"}. @@ -83,8 +95,10 @@ {"Pending","Pendente"}. {"Port","Porta"}. {"private, ","privado"}. +{"Queries to the conference members are not allowed in this room","Nesta sala não são permitidas consultas aos seus membros"}. {"RAM and disc copy","Cópia em RAM e em disco"}. {"RAM copy","Cópia em RAM"}. +{"Recipient is not in the conference room","O destinatário não está na sala"}. {"Registration in mod_irc for ","Registo no mod_irc para"}. {"Remote copy","Cópia remota"}. {"Remove","Remover"}. @@ -114,6 +128,8 @@ {"Update","Actualizar"}. {"Users","Utilizadores"}. {"User","Utilizador"}. +{"Visitors are not allowed to send messages to all occupants","Os visitantes não podem enviar mensagens para todos os ocupantes"}. +{"You have been banned from this room","Foi banido desta sala"}. {"You need an x:data capable client to configure mod_irc settings","É necessário um cliente com suporte de x:data para configurar as opções do mod_irc"}. {"You need an x:data capable client to configure room","É necessário um cliente com suporte de x:data para configurar a sala"}. {"You need an x:data capable client to search","É necessário um cliente com suporte de x:data para poder procurar"}. diff --git a/priv/msgs/pt.po b/priv/msgs/pt.po index 3620b28c98e..7e239615b76 100644 --- a/priv/msgs/pt.po +++ b/priv/msgs/pt.po @@ -7,50 +7,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Portuguese (português)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Não foi passado nenhum recurso" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 #, fuzzy msgid "Enter the text you see" msgstr "Introduza caminho para o ficheiro de texto" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Utilizador" @@ -59,9 +63,9 @@ msgstr "Utilizador" msgid "Server" msgstr "Nunca" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Palavra-chave" @@ -79,455 +83,455 @@ msgstr "" msgid "ejabberd Web Admin" msgstr "Administração do ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 #, fuzzy msgid "Administration" msgstr "Administração de " -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Listas de Controlo de Acesso" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 #, fuzzy msgid "Submitted" msgstr "enviado" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 #, fuzzy msgid "Bad format" msgstr "formato inválido" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Enviar" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 #, fuzzy msgid "Raw" msgstr "modo texto" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Eliminar os seleccionados" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Regras de Acesso" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Configuração das Regra de Acesso ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 #, fuzzy msgid "Virtual Hosts" msgstr "Servidores virtuales" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Utilizadores" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Utilizadores ligados" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 #, fuzzy msgid "Users Last Activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 #, fuzzy msgid "All activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "Nodo não encontrado" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nodo não encontrado" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Adicionar novo" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 #, fuzzy msgid "Host" msgstr "Nome do servidor" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 #, fuzzy msgid "Registered Users" msgstr "Utilizadores registados" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Adicionar utilizador" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 #, fuzzy msgid "Offline Messages" msgstr "Mensagens diferidas" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Última actividade" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nunca" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Ligado" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 #, fuzzy msgid "Registered Users:" msgstr "Utilizadores registados" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 #, fuzzy msgid "Online Users:" msgstr "Utilizadores ligados" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 #, fuzzy msgid "Outgoing s2s Connections:" msgstr "Conexões S2S para fora" -#: ejabberd_web_admin.erl:1496 +#: ejabberd_web_admin.erl:1559 #, fuzzy -msgid "Outgoing s2s Servers:" -msgstr "Servidores S2S de saída" +msgid "Incoming s2s Connections:" +msgstr "Conexões S2S para fora" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nenhum" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Mudar palavra-chave" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Utilizador" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Recursos conectados:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Palavra-chave:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Eliminar utilizador" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nodos" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nodos a correr" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nodos parados" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nodo" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Guardar cópia de segurança" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 #, fuzzy msgid "Listened Ports" msgstr "Portas em escuta em " -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Actualizar" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reiniciar" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Parar" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Módulos" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 #, fuzzy msgid "RPC Call Error" msgstr "Erro na chamada RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tabelas da BD em " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Nome" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Tipo de armazenagem" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memória" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Guardar cópia de segurança" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " "separately." msgstr "" -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 #, fuzzy msgid "Store binary backup:" msgstr "Armazenar uma cópia de segurança no ficheiro" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 #, fuzzy msgid "Restore binary backup immediately:" msgstr "Recuperar uma cópia de segurança a partir de ficheiro" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 #, fuzzy msgid "Restore plain text backup immediately:" msgstr "Recuperar uma cópia de segurança a partir de ficheiro" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "Importar utilizadores a partir de ficheiros da spool do jabberd14" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Importar utilizadores a partir de ficheiros da spool do jabberd14" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Portas em escuta em " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Parar módulos em " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 #, fuzzy msgid "Statistics of ~p" msgstr "Estatísticas" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 #, fuzzy msgid "Uptime:" msgstr "Tempo de funcionamento" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 #, fuzzy msgid "CPU Time:" msgstr "Tempo de processador consumido" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 #, fuzzy msgid "Transactions Committed:" msgstr "Transacções realizadas" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 #, fuzzy msgid "Transactions Aborted:" msgstr "Transacções abortadas" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 #, fuzzy msgid "Transactions Restarted:" msgstr "Transacções reiniciadas" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 #, fuzzy msgid "Transactions Logged:" msgstr "Transacções armazenadas" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 #, fuzzy msgid "Update plan" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "Iniciar módulos" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 #, fuzzy msgid "Update script" msgstr "Actualizar" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Porta" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "Porta" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Módulo" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Opções" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 #, fuzzy msgid "Start" msgstr "Reiniciar" @@ -827,8 +831,8 @@ msgstr "Regras de acesso" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "" @@ -847,33 +851,33 @@ msgstr "Utilizadores registados" msgid "Number of online users" msgstr "Utilizadores ligados" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 #, fuzzy msgid "Roster size" msgstr "Lista de contactos" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 #, fuzzy msgid "Resources" msgstr "Restaurar" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administração de " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Acção no utilizador" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editar propriedades" @@ -883,29 +887,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Acesso negado pela política de serviço" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Módulo de IRC ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "É necessário um cliente com suporte de x:data para configurar as opções do " "mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registo no mod_irc para" -#: mod_irc.erl:651 +#: mod_irc.erl:659 #, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " @@ -914,11 +930,11 @@ msgstr "" "Introduza o nome de utilizador e codificações de caracteres que quer usar ao " "conectar-se aos servidores de IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Nome do utilizador de IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 #, fuzzy msgid "" "If you want to specify different ports, passwords, encodings for IRC " @@ -930,42 +946,42 @@ msgstr "" "servidor IRC preencha esta lista con valores no formato '{\"servidor irc\", " "\"codificação\"}'. Este serviço usa por omissão a codificação \"~s\"." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" -#: mod_irc.erl:891 +#: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "Nome do utilizador de IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 #, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " @@ -975,53 +991,87 @@ msgstr "" "Introduza o nome de utilizador e codificações de caracteres que quer usar ao " "conectar-se aos servidores de IRC" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "Nome do utilizador de IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "Palavra-chave" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "Porta" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Só os moderadores podem mudar o tópico desta sala" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Só os administradores do serviço têm permissão para enviar mensagens de " +"serviço" + +#: mod_muc.erl:622 +#, fuzzy +msgid "Room creation is denied by service policy" +msgstr "Acesso negado pela política de serviço" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "A sala não existe" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "É necessário um cliente com suporte de x:data para poder registar a alcunha" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registo da alcunha em " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Introduza a alcunha que quer registar" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Alcunha" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#, fuzzy +msgid "That nickname is registered by another person" +msgstr "A alcunha já está registada por outra pessoa" + +#: mod_muc.erl:1088 +#, fuzzy +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Deve preencher o campo \"alcunha\" no formulário" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Módulo MUC de ejabberd" @@ -1047,382 +1097,515 @@ msgstr "Utilizadores registados" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 #, fuzzy msgid "Chatroom configuration modified" msgstr "Configuração para " -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " colocou o tópico: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "Configuração para " -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 #, fuzzy msgid "November" msgstr "Nunca" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 #, fuzzy msgid "Room Configuration" msgstr "Configuração" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Impedir o envio de mensagens privadas para a sala" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Permitir que os utilizadores enviem convites?" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Tipo de mensagem incorrecto" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Não é permitido enviar mensagens privadas do tipo \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "O destinatário não está na sala" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +#, fuzzy +msgid "It is not allowed to send private messages" +msgstr "Impedir o envio de mensagens privadas para a sala" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Só os ocupantes podem enviar mensagens para a sala" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Só os ocupantes podem enviar consultas para a sala" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Nesta sala não são permitidas consultas aos seus membros" + +#: mod_muc_room.erl:961 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Só os moderadores e os participantes podem mudar o tópico desta sala" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Só os moderadores podem mudar o tópico desta sala" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Os visitantes não podem enviar mensagens para todos os ocupantes" + +#: mod_muc_room.erl:1080 +#, fuzzy +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Só os moderadores podem mudar o tópico desta sala" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +#, fuzzy +msgid "That nickname is already in use by another occupant" +msgstr "A alcunha já está a ser usado por outro ocupante" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Foi banido desta sala" + +#: mod_muc_room.erl:1826 +#, fuzzy +msgid "Membership is required to enter this room" +msgstr "É necessário ser membro desta sala para poder entrar" + +#: mod_muc_room.erl:1872 +#, fuzzy +msgid "A password is required to enter this room" +msgstr "É necessária a palavra-chave para poder entrar nesta sala" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Palavra-chave incorrecta" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "São necessários privilégios de administrador" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "São necessários privilégios de moderador" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "O Jabber ID ~s não é válido" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "A alcunha ~s não existe na sala" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiliação inválida: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Papel inválido: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "São necessários privilégios de dono" + +#: mod_muc_room.erl:3348 #, fuzzy msgid "Configuration of room ~s" msgstr "Configuração para " -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Subscrição" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 #, fuzzy msgid "Make room persistent" msgstr "Tornar a sala permanente?" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 #, fuzzy msgid "Make room public searchable" msgstr "Tornar a sala publicamente visível?" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 #, fuzzy msgid "Make participants list public" msgstr "Tornar pública a lista de participantes?" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 #, fuzzy msgid "Make room password protected" msgstr "Proteger a sala com palavra-chave?" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 #, fuzzy msgid "anyone" msgstr "Nenhum" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +msgid "Moderator" +msgstr "" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 #, fuzzy msgid "Make room members-only" msgstr "Tornar a sala exclusiva a membros?" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Tornar a sala moderada" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 #, fuzzy msgid "Default users as participants" msgstr "Os utilizadores são membros por omissão?" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 #, fuzzy msgid "Allow users to change the subject" msgstr "Permitir aos utilizadores mudar o tópico?" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 #, fuzzy msgid "Allow users to send private messages" msgstr "Permitir que os utilizadores enviem mensagens privadas?" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Permitir que os utilizadores enviem mensagens privadas?" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 #, fuzzy msgid "Allow users to query other users" msgstr "Permitir aos utilizadores consultar outros utilizadores?" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 #, fuzzy msgid "Allow users to send invites" msgstr "Permitir que os utilizadores enviem convites?" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Permitir aos utilizadores mudar o tópico?" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Permitir que os utilizadores enviem convites?" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Proteger a sala com palavra-chave?" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 #, fuzzy msgid "Enable logging" msgstr "Guardar históricos?" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "É necessário um cliente com suporte de x:data para configurar a sala" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Utilizador" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 #, fuzzy msgid "the password is" msgstr "Mudar palavra-chave" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 #, fuzzy msgid "ejabberd Multicast service" msgstr "Utilizadores do ejabberd" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" + +#: mod_offline.erl:798 #, fuzzy msgid "~s's Offline Messages Queue" msgstr "~s fila de mensagens diferidas" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Data" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "De" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Para" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Pacote" -#: mod_offline.erl:977 +#: mod_offline.erl:992 #, fuzzy msgid "Offline Messages:" msgstr "Mensagens diferidas:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Mensagens diferidas" @@ -1432,119 +1615,133 @@ msgstr "Mensagens diferidas" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Módulo vCard de ejabberd" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 #, fuzzy msgid "ejabberd Publish-Subscribe module" msgstr "Módulo pub/sub de ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 #, fuzzy msgid "Node ID" msgstr "Nodo" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "" + +#: mod_register.erl:253 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "É necessário um cliente com suporte de x:data para poder registar a alcunha" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Escolha um nome de utilizador e palavra-chave para se registar neste servidor" +#: mod_register.erl:373 mod_register.erl:421 +#, fuzzy +msgid "The password is too weak" +msgstr "Mudar palavra-chave" + +#: mod_register.erl:426 +#, fuzzy +msgid "Users are not allowed to register accounts so quickly" +msgstr "Os visitantes não podem enviar mensagens para todos os ocupantes" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1619,8 +1816,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1657,64 +1854,64 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Subscrição" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Pendente" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupos" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Remover" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Lista de contactos de " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 #, fuzzy msgid "Add Jabber ID" msgstr "Adicionar Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Lista de contactos" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 #, fuzzy msgid "Shared Roster Groups" msgstr "Lista de contactos partilhada" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 #, fuzzy msgid "Name:" msgstr "Nome" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 #, fuzzy msgid "Description:" msgstr "Subscrição" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 #, fuzzy msgid "Group " msgstr "Grupos" @@ -1792,6 +1989,10 @@ msgstr "Procurar utilizadores em " msgid "Fill in fields to search for any matching Jabber User" msgstr "Preencha os campos para procurar utilizadores Jabber coincidentes" +#, fuzzy +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Servidores S2S de saída" + #~ msgid "Delete" #~ msgstr "Eliminar" @@ -1799,96 +2000,6 @@ msgstr "Preencha os campos para procurar utilizadores Jabber coincidentes" #~ msgid "This room is not anonymous" #~ msgstr "Tornar a sala anónima?" -#~ msgid "Access denied by service policy" -#~ msgstr "Acesso negado pela política de serviço" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Só os administradores do serviço têm permissão para enviar mensagens de " -#~ "serviço" - -#, fuzzy -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Acesso negado pela política de serviço" - -#~ msgid "Conference room does not exist" -#~ msgstr "A sala não existe" - -#, fuzzy -#~ msgid "That nickname is registered by another person" -#~ msgstr "A alcunha já está registada por outra pessoa" - -#, fuzzy -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Deve preencher o campo \"alcunha\" no formulário" - -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Impedir o envio de mensagens privadas para a sala" - -#~ msgid "Improper message type" -#~ msgstr "Tipo de mensagem incorrecto" - -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Não é permitido enviar mensagens privadas do tipo \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "O destinatário não está na sala" - -#, fuzzy -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Impedir o envio de mensagens privadas para a sala" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Só os ocupantes podem enviar mensagens para a sala" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Só os ocupantes podem enviar consultas para a sala" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Nesta sala não são permitidas consultas aos seus membros" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Os visitantes não podem enviar mensagens para todos os ocupantes" - -#, fuzzy -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Só os moderadores podem mudar o tópico desta sala" - -#, fuzzy -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "A alcunha já está a ser usado por outro ocupante" - -#~ msgid "You have been banned from this room" -#~ msgstr "Foi banido desta sala" - -#, fuzzy -#~ msgid "Membership is required to enter this room" -#~ msgstr "É necessário ser membro desta sala para poder entrar" - -#, fuzzy -#~ msgid "A password is required to enter this room" -#~ msgstr "É necessária a palavra-chave para poder entrar nesta sala" - -#~ msgid "Incorrect password" -#~ msgstr "Palavra-chave incorrecta" - -#~ msgid "Administrator privileges required" -#~ msgstr "São necessários privilégios de administrador" - -#~ msgid "Moderator privileges required" -#~ msgstr "São necessários privilégios de moderador" - -#~ msgid "Owner privileges required" -#~ msgstr "São necessários privilégios de dono" - -#, fuzzy -#~ msgid "The password is too weak" -#~ msgstr "Mudar palavra-chave" - -#, fuzzy -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Os visitantes não podem enviar mensagens para todos os ocupantes" - #~ msgid "Encodings" #~ msgstr "Codificações" diff --git a/priv/msgs/ru.msg b/priv/msgs/ru.msg index 2589a2c0e94..7acab78f91b 100644 --- a/priv/msgs/ru.msg +++ b/priv/msgs/ru.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Конфигурация списков управления доступом"}. {"Access control lists","Списки управления доступом"}. {"Access Control Lists","Списки управления доступом"}. +{"Access denied by service policy","Доступ запрещён политикой службы"}. {"Access rules","Правила доступа"}. {"Access Rules","Правила доступа"}. {"Action on user","Действие над пользователем"}. @@ -11,6 +12,7 @@ {"Add User","Добавить пользователя"}. {"Administration of ","Администрирование "}. {"Administration","Администрирование"}. +{"Administrator privileges required","Требуются права администратора"}. {"A friendly name for the node","Легко запоминаемое имя для узла"}. {"All activity","Вся статистика"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Разрешить этому Jabber ID подписаться на данный узел?"}. @@ -25,6 +27,7 @@ {"All Users","Все пользователи"}. {"Announcements","Объявления"}. {"anyone","всем участникам"}. +{"A password is required to enter this room","Чтобы войти в эту конференцию, нужен пароль"}. {"April","апреля"}. {"August","августа"}. {"Backup Management","Управление резервным копированием"}. @@ -49,6 +52,7 @@ {"Choose whether to approve this entity's subscription.","Решите: предоставить ли подписку этому объекту."}. {"City","Город"}. {"Commands","Команды"}. +{"Conference room does not exist","Конференция не существует"}. {"Configuration of room ~s","Конфигурация комнаты ~s"}. {"Configuration","Конфигурация"}. {"Connected Resources:","Подключённые ресурсы:"}. @@ -103,6 +107,7 @@ {"Export all tables as SQL queries to a file:","Экспортировать все таблицы в виде SQL запросов в файл:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Ошибка обработки JID из вашего запроса на право голоса"}. {"Family Name","Фамилия"}. {"February","февраля"}. {"Fill in fields to search for any matching Jabber User","Заполните форму для поиска пользователя Jabber"}. @@ -136,6 +141,8 @@ {"Import users data from jabberd14 spool directory:","Импорт пользовательских данных из буферной директории jabberd14:"}. {"Import Users from Dir at ","Импорт пользователей из директории на "}. {"Import Users From jabberd14 Spool Files","Импорт пользователей из спула jabberd14"}. +{"Improper message type","Неправильный тип сообщения"}. +{"Incorrect password","Неправильный пароль"}. {"Invalid affiliation: ~s","Недопустимый ранг: ~s"}. {"Invalid role: ~s","Недопустимая роль: ~s"}. {"IP addresses","IP адреса"}. @@ -147,6 +154,9 @@ {"IRC username","Имя пользователя IRC"}. {"IRC Username","Имя пользователя IRC"}. {"is now known as","изменил(а) имя на"}. +{"It is not allowed to send private messages of type \"groupchat\"","Нельзя посылать частные сообщения типа \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Не разрешается посылать частные сообщения прямо в конференцию"}. +{"It is not allowed to send private messages","Запрещено посылать приватные сообщения"}. {"Jabber Account Registration","Регистрация Jabber-аккаунта"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s недопустимый"}. @@ -179,12 +189,14 @@ {"Max # of items to persist","Максимальное число сохраняемых публикаций"}. {"Max payload size in bytes","Максимальный размер полезной нагрузки в байтах"}. {"May","мая"}. +{"Membership is required to enter this room","В эту конференцию могут входить только её члены"}. {"Members:","Члены:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Запомните пароль или запишите его на бумаге, которую сохраните в безопасном месте. В Jabber'е нет автоматизированного средства восстановления пароля в том случае, если Вы его забудете."}. {"Memory","Память"}. {"Message body","Тело сообщения"}. {"Middle Name","Отчество"}. {"Minimum interval between voice requests (in seconds)","Минимальный интервал между запросами на право голоса"}. +{"Moderator privileges required","Требуются права модератора"}. {"moderators only","только модераторам"}. {"Modified modules","Изменённые модули"}. {"Modules at ~p","Модули на ~p"}. @@ -229,12 +241,16 @@ {"Only deliver notifications to available users","Доставлять уведомления только доступным пользователям"}. {"Only moderators and participants are allowed to change the subject in this room","Только модераторы и участники могут изменять тему в этой комнате"}. {"Only moderators are allowed to change the subject in this room","Только модераторы могут изменять тему в этой комнате"}. +{"Only moderators can approve voice requests","Только модераторы могут утверждать запросы на право голоса"}. +{"Only occupants are allowed to send messages to the conference","Только присутствующим разрешается посылать сообщения в конференцию"}. +{"Only occupants are allowed to send queries to the conference","Только присутствующим разрешается посылать запросы в конференцию"}. +{"Only service administrators are allowed to send service messages","Только администратор службы может посылать служебные сообщения"}. {"Options","Параметры"}. {"Organization Name","Название организации"}. {"Organization Unit","Отдел организации"}. {"Outgoing s2s Connections:","Исходящие s2s-серверы:"}. {"Outgoing s2s Connections","Исходящие s2s-соединения"}. -{"Outgoing s2s Servers:","Исходящие s2s-серверы:"}. +{"Owner privileges required","Требуются права владельца"}. {"Packet","Пакет"}. {"Password ~b","Пароль ~b"}. {"Password Verification:","Проверка пароля:"}. @@ -249,6 +265,7 @@ {"Persist items to storage","Сохранять публикации в хранилище"}. {"Ping","Пинг"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Заметьте, что здесь производится резервное копирование только встроенной базы данных Mnesia. Если Вы также используете другое хранилище данных (например с помощью модуля ODBC), то его резервное копирование следует осуществлять отдельно."}. +{"Please, wait for a while before sending new voice request","Пожалуйста, подождите перед тем как подать новый запрос на право голоса"}. {"Pong","Понг"}. {"Port ~b","Порт ~b"}. {"Port","Порт"}. @@ -258,10 +275,12 @@ {"Publish-Subscribe","Публикация-Подписка"}. {"PubSub subscriber request","Запрос подписчика PubSub"}. {"Purge all items when the relevant publisher goes offline","Очищать все записи автора публикации когда он отключается"}. +{"Queries to the conference members are not allowed in this room","Запросы к пользователям в этой конференции запрещены"}. {"RAM and disc copy","ОЗУ и диск"}. {"RAM copy","ОЗУ"}. {"Raw","Необработанный формат"}. {"Really delete message of the day?","Действительно удалить сообщение дня?"}. +{"Recipient is not in the conference room","Адресата нет в конференции"}. {"Register a Jabber account","Зарегистрировать Jabber-аккаунт"}. {"Registered nicknames","Зарегистрированные псевдонимы"}. {"Registered Users:","Зарегистрированные пользователи:"}. @@ -282,6 +301,7 @@ {"Restore plain text backup immediately:","Восстановить из текстовой резервной копии немедленно:"}. {"Restore","Восстановление из резервной копии"}. {"Room Configuration","Конфигурация комнаты"}. +{"Room creation is denied by service policy","Cоздавать конференцию запрещено политикой службы"}. {"Room description","Описание комнаты"}. {"Room Occupants","Участники комнаты"}. {"Room title","Название комнаты"}. @@ -310,7 +330,7 @@ {"Show Ordinary Table","Показать обычную таблицу"}. {"Shut Down Service","Остановить службу"}. {"~s invites you to the room ~s","~s приглашает вас в комнату ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Некоторые Jabber-клиенты могут сохранять пароль на Вашем компьютере. Используйте эту функцию только в том случае, если считаете это безопасным."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Некоторые Jabber-клиенты могут сохранять пароль на Вашем компьютере. Используйте эту функцию только в том случае, если считаете это безопасным."}. {"Specify the access model","Укажите механизм управления доступом"}. {"Specify the event message type","Укажите тип сообщения о событии"}. {"Specify the publisher model","Условия публикации"}. @@ -333,8 +353,12 @@ {"Subscriber Address","Адрес подписчика"}. {"Subscription","Подписка"}. {"Sunday","Воскресенье"}. +{"That nickname is already in use by another occupant","Этот псевдоним уже занят другим участником"}. +{"That nickname is registered by another person","Этот псевдоним зарегистрирован кем-то другим"}. {"The CAPTCHA is valid.","Проверка капчи прошла успешно."}. +{"The CAPTCHA verification has failed","Проверка капчи не пройдена"}. {"The collections with which a node is affiliated","Имя коллекции, в которую входит узел"}. +{"The password is too weak","Слишком слабый пароль"}. {"the password is","пароль:"}. {"The password of your Jabber account was successfully changed.","Пароль Вашего Jabber-аккаунта был успешно изменен."}. {"There was an error changing the password: ","Ошибка при смене пароля:"}. @@ -347,16 +371,19 @@ {"Thursday","Четверг"}. {"Time delay","По истечение"}. {"Time","Время"}. +{"Too many CAPTCHA requests","Слишком много запросов капчи"}. {"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Слишком много (~p) неудачных попыток аутентификации с этого IP-адреса (~s). Адрес будет разблокирован в ~s UTC"}. {"Too many unacked stanzas","Слишком много неподтверждённых пакетов"}. {"To ~s","К ~s"}. {"Total rooms","Все комнаты"}. {"To","Кому"}. +{"Traffic rate limit is exceeded","Превышен лимит скорости посылки информации"}. {"Transactions Aborted:","Транзакции отмененные:"}. {"Transactions Committed:","Транзакции завершенные:"}. {"Transactions Logged:","Транзакции запротоколированные:"}. {"Transactions Restarted:","Транзакции перезапущенные:"}. {"Tuesday","Вторник"}. +{"Unable to generate a CAPTCHA","Не получилось создать капчу"}. {"Unauthorized","Не авторизован"}. {"Unregister a Jabber account","Удалить Jabber-аккаунт"}. {"Unregister","Удалить"}. @@ -371,6 +398,7 @@ {"User JID","JID пользователя"}. {"User Management","Управление пользователями"}. {"Username:","Имя пользователя:"}. +{"Users are not allowed to register accounts so quickly","Пользователи не могут регистрировать учётные записи так быстро"}. {"Users Last Activity","Статистика последнего подключения пользователей"}. {"Users","Пользователи"}. {"User ~s","Пользователь ~s"}. @@ -378,16 +406,23 @@ {"Validate","Утвердить"}. {"vCard User Search","Поиск пользователей по vCard"}. {"Virtual Hosts","Виртуальные хосты"}. +{"Visitors are not allowed to change their nicknames in this room","Посетителям запрещено изменять свои псевдонимы в этой комнате"}. +{"Visitors are not allowed to send messages to all occupants","Посетителям не разрешается посылать сообщения всем присутствующим"}. +{"Voice requests are disabled in this conference","Запросы на право голоса отключены в этой конференции"}. {"Voice request","Запрос на право голоса"}. {"Wednesday","Среда"}. {"When to send the last published item","Когда посылать последний опубликованный элемент"}. {"Whether to allow subscriptions","Разрешить подписку"}. {"You can later change your password using a Jabber client.","Позже Вы можете изменить пароль через Jabber-клиент."}. +{"You have been banned from this room","Вам запрещено входить в эту конференцию"}. +{"You must fill in field \"Nickname\" in the form","Вы должны заполнить поле \"Псевдоним\" в форме"}. {"You need a client that supports x:data and CAPTCHA to register","Чтобы зарегистрироваться, требуется x:data-совместимый клиент"}. {"You need a client that supports x:data to register the nickname","Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент"}. {"You need an x:data capable client to configure mod_irc settings","Чтобы настроить параметры mod_irc, требуется x:data-совместимый клиент"}. {"You need an x:data capable client to configure room","Чтобы сконфигурировать комнату, требуется x:data-совместимый клиент"}. {"You need an x:data capable client to search","Чтобы воспользоваться поиском, требуется x:data-совместимый клиент"}. +{"Your active privacy list has denied the routing of this stanza.","Маршрутизация этой строфы запрещена вашим активным списком приватности."}. +{"Your contact offline message queue is full. The message has been discarded.","Очередь недоставленных сообщений Вашего адресата переполнена. Сообщение не было сохранено."}. {"Your Jabber account was successfully created.","Ваш Jabber-аккаунт был успешно создан."}. {"Your Jabber account was successfully deleted.","Ваш Jabber-аккаунт был успешно удален."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ваши сообщения к ~s блокируются. Для снятия блокировки перейдите по ссылке ~s"}. diff --git a/priv/msgs/ru.po b/priv/msgs/ru.po index b1219472070..d75f381ac6c 100644 --- a/priv/msgs/ru.po +++ b/priv/msgs/ru.po @@ -17,50 +17,55 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Вы обязаны использовать STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Не указан ресурс" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Заменено новым соединением" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "выгнали из комнаты" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" +"Маршрутизация этой строфы запрещена вашим активным списком приватности." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "Слишком много неподтверждённых пакетов" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Введите увиденный текст" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Ваши сообщения к ~s блокируются. Для снятия блокировки перейдите по ссылке ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Если вы не видите изображение капчи, перейдите по ссылке." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Ссылка на капчу" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Проверка капчи прошла успешно." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Пользователь" @@ -69,9 +74,9 @@ msgstr "Пользователь" msgid "Server" msgstr "Сервер:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Пароль" @@ -88,275 +93,276 @@ msgstr "Не авторизован" msgid "ejabberd Web Admin" msgstr "Web-интерфейс администрирования ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Администрирование" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Списки управления доступом" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Отправлено" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Неправильный формат" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Отправить" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Необработанный формат" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Удалить выделенные" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Правила доступа" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Конфигурация правила доступа ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Виртуальные хосты" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Пользователи" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Подключённые пользователи" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Статистика последнего подключения пользователей" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Период" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "За последний месяц" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "За последний год" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Вся статистика" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Показать обычную таблицу" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Показать интегральную таблицу" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Статистика" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Не Найдено" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Узел не найден" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Добавить" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Хост" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Зарегистрированные пользователи" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Добавить пользователя" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Офлайновые сообщения" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Последнее подключение" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Никогда" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Подключён" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Зарегистрированные пользователи:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Подключённые пользователи:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Исходящие s2s-серверы:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" msgstr "Исходящие s2s-серверы:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Нет" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Сменить пароль" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 msgid "User ~s" msgstr "Пользователь ~s" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Подключённые ресурсы:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Пароль:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Удалить пользователя" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Нет данных" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Узлы" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Работающие узлы" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Остановленные узлы" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" msgstr "Узел ~p" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "База данных" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Резервное копирование" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Прослушиваемые порты" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Обновить" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Перезапустить" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Остановить" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Модули" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Ошибка вызова RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" msgstr "Таблицы базы данных на ~p" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Название" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Тип таблицы" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Элементы" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Память" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Ошибка" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 msgid "Backup of ~p" msgstr "Резервное копирование ~p" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -367,145 +373,145 @@ msgstr "" "(например с помощью модуля ODBC), то его резервное копирование следует " "осуществлять отдельно." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Сохранить бинарную резервную копию:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Продолжить" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Восстановить из бинарной резервной копии немедленно:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Восстановить из бинарной резервной копии при следующем запуске (требует " "меньше памяти):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Сохранить текстовую резервную копию:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Восстановить из текстовой резервной копии немедленно:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Импорт пользовательских данных из файла формата PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Экспорт данных всех пользователей сервера в файлы формата PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Экспорт пользовательских данных домена в файлы формата PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "Экспортировать все таблицы в виде SQL запросов в файл:" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Импорт пользовательских данных из буферного файла jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Импорт пользовательских данных из буферной директории jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Прослушиваемые порты на " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" msgstr "Модули на ~p" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "статистика узла ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Время работы:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Процессорное время:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Транзакции завершенные:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Транзакции отмененные:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Транзакции перезапущенные:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Транзакции запротоколированные:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 msgid "Update ~p" msgstr "Обновление ~p" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "План обновления" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Изменённые модули" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Сценарий обновления" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Низкоуровневый сценарий обновления" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Проверка сценария" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Порт" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Протокол" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Модуль" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Параметры" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Запустить" @@ -794,8 +800,8 @@ msgstr "Правила доступа" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -812,31 +818,31 @@ msgstr "Количество зарегистрированных пользов msgid "Number of online users" msgstr "Количество подключённых пользователей" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Время последнего подключения" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Размер списка контактов" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP адреса" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Ресурсы" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Администрирование " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Действие над пользователем" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Изменить параметры" @@ -848,27 +854,39 @@ msgstr "" "Слишком много (~p) неудачных попыток аутентификации с этого IP-адреса (~s). " "Адрес будет разблокирован в ~s UTC" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Этот IP адрес находится в чёрном списке ~s" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Доступ запрещён политикой службы" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Транспорт" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC модуль" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Чтобы настроить параметры mod_irc, требуется x:data-совместимый клиент" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Регистрация в mod_irc для " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -876,11 +894,11 @@ msgstr "" "Введите имя пользователя, кодировки, порты и пароли, которые будут " "использоваться при подключении к IRC-серверам" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Имя пользователя IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -892,7 +910,7 @@ msgstr "" "\"пароль\"}'. По умолчанию сервис использует кодировку \"~s\", порт ~p, " "пустой пароль." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -900,35 +918,35 @@ msgstr "" "Пример: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Параметры соединения" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Присоединиться к каналу IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Канал IRC (без символа #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "Сервер IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Присоединяйтесь к каналу IRC" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Присоединиться к каналу IRC с Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Настройки IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -938,48 +956,77 @@ msgstr "" "подключении к IRC-серверам. Нажмите 'Далее' для получения дополнительных " "полей для заполнения. Нажмите 'Завершить' для сохранения настроек." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Имя пользователя IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Пароль ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Порт ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Кодировка сервера ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Сервер ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Только модераторы могут изменять тему в этой комнате" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Только администратор службы может посылать служебные сообщения" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Cоздавать конференцию запрещено политикой службы" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Конференция не существует" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Комнаты" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Регистрация псевдонима на " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Введите псевдоним, который Вы хотели бы зарегистрировать" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдоним" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Этот псевдоним зарегистрирован кем-то другим" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Вы должны заполнить поле \"Псевдоним\" в форме" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" @@ -1004,354 +1051,485 @@ msgstr "Зарегистрированные псевдонимы" msgid "List of rooms" msgstr "Список комнат" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Конфигурация комнаты изменилась" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "вошёл(а) в комнату" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "вышел(а) из комнаты" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "запретили входить в комнату" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "выгнали из комнаты вследствие смены ранга" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "выгнали из комнаты потому что она стала только для членов" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "выгнали из комнаты из-за останова системы" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "изменил(а) имя на" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " установил(а) тему: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Комната создана" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Комната уничтожена" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Комната запущена" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Комната остановлена" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Понедельник" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Вторник" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Среда" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Четверг" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Пятница" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Суббота" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Воскресенье" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "января" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "февраля" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "марта" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "апреля" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "мая" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "июня" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "июля" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "августа" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "сентября" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "октября" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "ноября" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "декабря" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Конфигурация комнаты" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Участники комнаты" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Превышен лимит скорости посылки информации" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Не разрешается посылать частные сообщения прямо в конференцию" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" +"Пожалуйста, подождите перед тем как подать новый запрос на право голоса" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Запросы на право голоса отключены в этой конференции" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Ошибка обработки JID из вашего запроса на право голоса" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Только модераторы могут утверждать запросы на право голоса" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Неправильный тип сообщения" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Нельзя посылать частные сообщения типа \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Адресата нет в конференции" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Запрещено посылать приватные сообщения" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Только присутствующим разрешается посылать сообщения в конференцию" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Только присутствующим разрешается посылать запросы в конференцию" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Запросы к пользователям в этой конференции запрещены" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Только модераторы и участники могут изменять тему в этой комнате" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Только модераторы могут изменять тему в этой комнате" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Посетителям не разрешается посылать сообщения всем присутствующим" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Посетителям запрещено изменять свои псевдонимы в этой комнате" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Этот псевдоним уже занят другим участником" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Вам запрещено входить в эту конференцию" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "В эту конференцию могут входить только её члены" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Чтобы войти в эту конференцию, нужен пароль" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Слишком много запросов капчи" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Не получилось создать капчу" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Неправильный пароль" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Требуются права администратора" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Требуются права модератора" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s недопустимый" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Псевдоним ~s в комнате отсутствует" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Недопустимый ранг: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Недопустимая роль: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Требуются права владельца" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Конфигурация комнаты ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Название комнаты" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Описание комнаты" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Сделать комнату постоянной" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Сделать комнату видимой всем" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Сделать список участников видимым всем" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Сделать комнату защищённой паролем" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Максимальное количество участников" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Не ограничено" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Сделать реальные Jabber ID участников видимыми" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "только модераторам" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "всем участникам" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "только модераторам" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Комната только для зарегистрированных участников" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Сделать комнату модерируемой" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Сделать пользователей участниками по умолчанию" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Разрешить пользователям изменять тему" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Разрешить приватные сообщения" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Разрешить посетителям посылать приватные сообщения" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "никто" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Разрешить iq-запросы к пользователям" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Разрешить пользователям посылать приглашения" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Разрешить посетителям вставлять текcт статуса в сообщения о присутствии" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Разрешить посетителям изменять псевдоним" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Разрешить посетителям запрашивать право голоса" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Минимальный интервал между запросами на право голоса" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Сделать комнату защищённой капчей" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "Включить хранение сообщений" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Исключить показ капчи для списка Jabber ID" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Включить журналирование" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Чтобы сконфигурировать комнату, требуется x:data-совместимый клиент" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Число присутствующих" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "приватная, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Запрос на право голоса" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Подтвердите или отклоните право голоса." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "JID пользователя" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Предоставить голос?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s приглашает вас в комнату ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "пароль:" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "Мультикаст" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "ejabberd Multicast сервис" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Очередь недоставленных сообщений Вашего адресата переполнена. Сообщение не " +"было сохранено." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Oчередь офлайновых сообщений ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Время" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "От кого" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Кому" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Пакет" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Офлайновые сообщения:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Удалить все офлайновые сообщения" @@ -1359,114 +1537,126 @@ msgstr "Удалить все офлайновые сообщения" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams модуль" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Публикация-Подписка" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Модуль ejabberd Публикации-Подписки" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Запрос подписчика PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Решите: предоставить ли подписку этому объекту." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID узла" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Адрес подписчика" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Разрешить этому Jabber ID подписаться на данный узел?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Доставлять вместе с уведомлениями o публикациях сами публикации" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Доставлять уведомления о событиях" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Уведомлять подписчиков об изменении конфигурации сборника" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Уведомлять подписчиков об удалении сборника" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Уведомлять подписчиков об удалении публикаций из сборника" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Сохранять публикации в хранилище" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Легко запоминаемое имя для узла" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Максимальное число сохраняемых публикаций" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Разрешить подписку" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Укажите механизм управления доступом" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Группы списка контактов, которым разрешена подписка" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Условия публикации" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "Очищать все записи автора публикации когда он отключается" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Укажите тип сообщения о событии" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Максимальный размер полезной нагрузки в байтах" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Когда посылать последний опубликованный элемент" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Доставлять уведомления только доступным пользователям" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Имя коллекции, в которую входит узел" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Проверка капчи не пройдена" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Чтобы зарегистрироваться, требуется x:data-совместимый клиент" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Выберите имя пользователя и пароль для регистрации на этом сервере" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Слишком слабый пароль" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Пользователи не могут регистрировать учётные записи так быстро" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Ваш Jabber-аккаунт был успешно создан." @@ -1543,8 +1733,8 @@ msgstr "Позже Вы можете изменить пароль через Ja #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Некоторые Jabber-клиенты могут сохранять пароль на Вашем компьютере. " "Используйте эту функцию только в том случае, если считаете это безопасным." @@ -1583,60 +1773,60 @@ msgstr "Здесь Вы можете удалить Jabber-аккаунт с э msgid "Unregister" msgstr "Удалить" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Подписка" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Ожидание" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Группы" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Утвердить" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Удалить" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Ростер пользователя " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Добавить Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Ростер" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Группы общих контактов" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Название:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Описание:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Члены:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Видимые группы:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Группа " @@ -1712,62 +1902,21 @@ msgstr "Результаты поиска в " msgid "Fill in fields to search for any matching Jabber User" msgstr "Заполните форму для поиска пользователя Jabber" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Исходящие s2s-серверы:" + #~ msgid "Delete" #~ msgstr "Удалить" #~ msgid "This room is not anonymous" #~ msgstr "Эта комната не анонимная" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "Маршрутизация этой строфы запрещена вашим активным списком приватности." - -#~ msgid "Access denied by service policy" -#~ msgstr "Доступ запрещён политикой службы" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Только администратор службы может посылать служебные сообщения" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Cоздавать конференцию запрещено политикой службы" - -#~ msgid "Conference room does not exist" -#~ msgstr "Конференция не существует" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Этот псевдоним зарегистрирован кем-то другим" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Вы должны заполнить поле \"Псевдоним\" в форме" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Превышен лимит скорости посылки информации" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Этого участника выгнали из комнаты за то, что он послал сообщение об " #~ "ошибке" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Не разрешается посылать частные сообщения прямо в конференцию" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "" -#~ "Пожалуйста, подождите перед тем как подать новый запрос на право голоса" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Запросы на право голоса отключены в этой конференции" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Ошибка обработки JID из вашего запроса на право голоса" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Только модераторы могут утверждать запросы на право голоса" - -#~ msgid "Improper message type" -#~ msgstr "Неправильный тип сообщения" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1775,82 +1924,12 @@ msgstr "Заполните форму для поиска пользовател #~ "Этого участника выгнали из комнаты за то, что он послал сообщение об " #~ "ошибке другому участнику" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Нельзя посылать частные сообщения типа \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Адресата нет в конференции" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Запрещено посылать приватные сообщения" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Только присутствующим разрешается посылать сообщения в конференцию" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Только присутствующим разрешается посылать запросы в конференцию" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Запросы к пользователям в этой конференции запрещены" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Посетителям не разрешается посылать сообщения всем присутствующим" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Этого участника выгнали из комнаты за то, что он послал присутствие с " #~ "ошибкой" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Посетителям запрещено изменять свои псевдонимы в этой комнате" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Этот псевдоним уже занят другим участником" - -#~ msgid "You have been banned from this room" -#~ msgstr "Вам запрещено входить в эту конференцию" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "В эту конференцию могут входить только её члены" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Чтобы войти в эту конференцию, нужен пароль" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Слишком много запросов капчи" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Не получилось создать капчу" - -#~ msgid "Incorrect password" -#~ msgstr "Неправильный пароль" - -#~ msgid "Administrator privileges required" -#~ msgstr "Требуются права администратора" - -#~ msgid "Moderator privileges required" -#~ msgstr "Требуются права модератора" - -#~ msgid "Owner privileges required" -#~ msgstr "Требуются права владельца" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Очередь недоставленных сообщений Вашего адресата переполнена. Сообщение " -#~ "не было сохранено." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Проверка капчи не пройдена" - -#~ msgid "The password is too weak" -#~ msgstr "Слишком слабый пароль" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Пользователи не могут регистрировать учётные записи так быстро" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Проверка капчи прошла успешно." diff --git a/priv/msgs/sk.msg b/priv/msgs/sk.msg index ef10413126a..1be739281ce 100644 --- a/priv/msgs/sk.msg +++ b/priv/msgs/sk.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfigurácia zoznamu prístupových oprávnení (ACL)"}. {"Access control lists","Zoznamy prístupových oprávnení (ACL)"}. {"Access Control Lists","Zoznamy prístupových oprávnení (ACL)"}. +{"Access denied by service policy","Prístup bol zamietnutý nastavením služby"}. {"Access rules","Prístupové pravidlá"}. {"Access Rules","Prístupové pravidlá"}. {"Action on user","Operácia aplikovaná na užívateľa"}. @@ -11,6 +12,7 @@ {"Add User","Pridať používateľa"}. {"Administration","Administrácia"}. {"Administration of ","Administrácia "}. +{"Administrator privileges required","Sú potrebné práva administrátora"}. {"A friendly name for the node","Prístupný názov pre uzol"}. {"All activity","Všetky aktivity"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Dovoliť tomuto Jabber ID odoberať PubSub uzol?"}. @@ -25,6 +27,7 @@ {"All Users","Všetci užívatelia"}. {"Announcements","Oznámenia"}. {"anyone","všetkým"}. +{"A password is required to enter this room","Pre vstup do miestnosti je potrebné heslo"}. {"April","Apríl"}. {"August","August"}. {"Backup Management","Správa zálohovania"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","Zvolte, či chcete povoliť toto odoberanie"}. {"City","Mesto"}. {"Commands","Príkazy"}. +{"Conference room does not exist","Diskusná miestnosť neexistuje"}. {"Configuration","Konfigurácia"}. {"Configuration of room ~s","Konfigurácia miestnosti ~s"}. {"Connected Resources:","Pripojené zdroje:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","Nepoužívať CAPTCHA pre nasledujúce Jabber ID"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportovať dáta všetkých uživateľov na serveri do súborov PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportovať dáta uživateľov na hostitelovi do súborov PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Nepodarilo sa nájsť JID v súhlase o Voice."}. {"Family Name","Priezvisko"}. {"February","Február"}. {"Fill in fields to search for any matching Jabber User","Vyplnte políčka pre vyhľadávanie Jabber užívateľa"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","Importovať dáta užívateľov z jabberd14 spool adresára:"}. {"Import Users from Dir at ","Importovať užívateľov z adresára na "}. {"Import Users From jabberd14 Spool Files","Importovať užívateľov z jabberd14 spool súborov"}. +{"Improper message type","Nesprávny typ správy"}. +{"Incorrect password","Nesprávne heslo"}. {"Invalid affiliation: ~s","Neplatné priradenie: ~s"}. {"Invalid role: ~s","Neplatná rola: ~s"}. {"IP addresses","IP adresa"}. @@ -142,6 +149,9 @@ {"IRC username","IRC prezývka"}. {"IRC Username","IRC prezývka"}. {"is now known as","sa premenoval(a) na"}. +{"It is not allowed to send private messages","Nieje povolené posielať súkromné správy"}. +{"It is not allowed to send private messages of type \"groupchat\"","Nie je dovolené odoslanie súkromnej správy typu \"Skupinová správa\" "}. +{"It is not allowed to send private messages to the conference","Nie je povolené odosielať súkromné správy do konferencie"}. {"Jabber Account Registration","Registrácia jabber účtu"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s je neplatné"}. @@ -174,11 +184,13 @@ {"Max payload size in bytes","Maximálny náklad v bajtoch"}. {"May","Máj"}. {"Members:","Členovia:"}. +{"Membership is required to enter this room","Pre vstup do miestnosti je potrebné byť členom"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Zapamätajte si heslo alebo si ho zapíšte na papier. Jabber neposkytuje automatickú funkciu ako zistiť zabudnuté heslo. "}. {"Memory","Pamäť"}. {"Message body","Telo správy"}. {"Middle Name","Prostredné meno: "}. {"Minimum interval between voice requests (in seconds)","Minimum interval between voice requests (in seconds)"}. +{"Moderator privileges required","Sú potrebné práva moderátora"}. {"moderators only","moderátorom"}. {"Modified modules","Modifikované moduly"}. {"Module","Modul"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","Doručovať upozornenia len aktuálne prihláseným používateľom"}. {"Only moderators and participants are allowed to change the subject in this room","Len moderátori a zúčastnený majú povolené meniť tému tejto miestnosti"}. {"Only moderators are allowed to change the subject in this room","Len moderátori majú povolené meniť tému miestnosti"}. +{"Only moderators can approve voice requests","Len moderátori môžu schváliť žiadosť o Voice"}. +{"Only occupants are allowed to send messages to the conference","Len členovia majú povolené zasielať správy do konferencie"}. +{"Only occupants are allowed to send queries to the conference","Len členovia majú povolené dotazovať sa o konferencii"}. +{"Only service administrators are allowed to send service messages","Iba správcovia služby majú povolené odosielanie servisných správ"}. {"Options","Nastavenia"}. {"Organization Name","Meno organizácie: "}. {"Organization Unit","Organizačná jednotka: "}. {"Outgoing s2s Connections:","Odchádzajúce s2s spojenia:"}. {"Outgoing s2s Connections","Odchádzajúce s2s spojenia"}. -{"Outgoing s2s Servers:","Odchádzajúce s2s servery:"}. +{"Owner privileges required","Sú vyžadované práva vlastníka"}. {"Packet","Paket"}. {"Password ~b","Heslo ~b"}. {"Password:","Heslo:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","Uložiť položky natrvalo do úložiska"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Prosím, berte na vedomie, že tieto nastavenia zázálohujú iba zabudovnú Mnesia databázu. Ak používate ODBC modul, musíte zálohovať vašu SQL databázu separátne."}. +{"Please, wait for a while before sending new voice request","Prosím počkate, predtým než pošlete novú žiadosť o Voice"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. {"Port","Port"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","Publish-Subscribe"}. {"PubSub subscriber request","Žiadosť odberateľa PubSub"}. {"Purge all items when the relevant publisher goes offline","Odstrániť všetky relevantné položky, keď užívateľ prejde do módu offline"}. +{"Queries to the conference members are not allowed in this room","Dotazovať sa o členoch nie je v tejto miestnosti povolené"}. {"RAM and disc copy","Kópia RAM a disku"}. {"RAM copy","Kópia RAM"}. {"Raw","Surové dáta"}. {"Really delete message of the day?","Skutočne zmazať správu dňa?"}. +{"Recipient is not in the conference room","Príjemca sa nenachádza v konferenčnej miestnosti"}. {"Register a Jabber account","Zaregistrovať Jabber účet"}. {"Registered Users:","Registrovaní používatelia:"}. {"Registered Users","Registrovaní používatelia"}. @@ -270,6 +289,7 @@ {"Restore","Obnoviť"}. {"Restore plain text backup immediately:","Okamžite obnoviť zálohu z textového súboru:"}. {"Room Configuration","Nastavenia miestnosti"}. +{"Room creation is denied by service policy","Vytváranie miestnosti nie je povolené"}. {"Room description","Popis miestnosti"}. {"Room Occupants","Ľudí v miestnosti"}. {"Room title","Názov miestnosti"}. @@ -297,7 +317,7 @@ {"Show Ordinary Table","Zobraziť bežnú tabuľku"}. {"Shut Down Service","Vypnúť službu"}. {"~s invites you to the room ~s","~s Vás pozýva do miestnosti ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Niektorí Jabber klenti môžu ukladať heslá v počítači. Používajte túto funkciu len ak veríte, že sú tam v bezpečí. "}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Niektorí Jabber klenti môžu ukladať heslá v počítači. Používajte túto funkciu len ak veríte, že sú tam v bezpečí. "}. {"Specify the access model","Uveďte model prístupu"}. {"Specify the event message type","Uveďte typ pre správu o udalosti"}. {"Specify the publisher model","Špecifikovať model publikovania"}. @@ -320,9 +340,13 @@ {"Subscriber Address","Adresa odberateľa"}. {"Subscription","Prihlásenie"}. {"Sunday","Nedeľa"}. +{"That nickname is already in use by another occupant","Prezývka je už používaná iným členom"}. +{"That nickname is registered by another person","Prezývka je už zaregistrovaná inou osobou"}. {"The CAPTCHA is valid.","Platná CAPTCHA."}. +{"The CAPTCHA verification has failed","Overenie pomocou CAPTCHA zlihalo"}. {"The collections with which a node is affiliated","Kolekcie asociované s uzlom"}. {"the password is","heslo je"}. +{"The password is too weak","heslo je"}. {"The password of your Jabber account was successfully changed.","Heslo k Jabber účtu bolo úspešne zmenené."}. {"There was an error changing the password: ","Pri zmene hesla nastala chyba: "}. {"There was an error creating the account: ","Pri vytváraní účtu nastala chyba: "}. @@ -333,13 +357,16 @@ {"Thursday","Štvrtok"}. {"Time","Čas"}. {"Time delay","Časový posun"}. +{"Too many CAPTCHA requests","Príliš veľa žiadostí o CAPTCHA"}. {"To","Pre"}. {"To ~s","Pre ~s"}. +{"Traffic rate limit is exceeded","Bol prekročený prenosový limit"}. {"Transactions Aborted:","Transakcie zrušená"}. {"Transactions Committed:","Transakcie potvrdená"}. {"Transactions Logged:","Transakcie zaznamenaná"}. {"Transactions Restarted:","Transakcie reštartovaná"}. {"Tuesday","Utorok"}. +{"Unable to generate a CAPTCHA","Nepodarilo sa vygenerovat CAPTCHA"}. {"Unauthorized","Neautorizovaný"}. {"Unregister a Jabber account","Zrušiť Jabber účet"}. {"Unregister","Zrušiť účet"}. @@ -353,22 +380,30 @@ {"User JID","Používateľ "}. {"User Management","Správa užívateľov"}. {"Username:","IRC prezývka"}. +{"Users are not allowed to register accounts so quickly","Nieje dovolené vytvárať účty tak rýchlo po sebe"}. {"Users Last Activity","Posledná aktivita používateľa"}. {"Users","Používatelia"}. {"User","Užívateľ"}. {"Validate","Overiť"}. {"vCard User Search","Hľadať užívateľov vo vCard"}. {"Virtual Hosts","Virtuálne servery"}. +{"Visitors are not allowed to change their nicknames in this room","V tejto miestnosti nieje povolené meniť prezývky"}. +{"Visitors are not allowed to send messages to all occupants","Návštevníci nemajú povolené zasielať správy všetkým prihláseným do konferencie"}. +{"Voice requests are disabled in this conference","Žiadosti o Voice nie sú povolené v tejto konferencii"}. {"Voice request","Žiadosť o Voice"}. {"Wednesday","Streda"}. {"When to send the last published item","Kedy odoslať posledne publikovanú položku"}. {"Whether to allow subscriptions","Povoliť prihlasovanie"}. {"You can later change your password using a Jabber client.","Neskôr si heslo môžete zmeniť pomocou Jabber klienta."}. +{"You have been banned from this room","Boli ste vylúčený z tejto miestnosti"}. +{"You must fill in field \"Nickname\" in the form","Musíte vyplniť políčko \"Prezývka\" vo formulári"}. {"You need a client that supports x:data and CAPTCHA to register","Na registráciu prezývky potrebujete klienta podporujúceho z x:data"}. {"You need a client that supports x:data to register the nickname","Na registráciu prezývky potrebujete klienta podporujúceho z x:data"}. {"You need an x:data capable client to configure mod_irc settings","Pre konfiguráciu mod_irc potrebujete klienta podporujúceho x:data"}. {"You need an x:data capable client to configure room","Na konfiguráciu miestnosti potrebujete klienta podporujúceho x:data"}. {"You need an x:data capable client to search","Na vyhľadávanie potrebujete klienta podporujúceho x:data"}. +{"Your active privacy list has denied the routing of this stanza.","Aktívny list súkromia zbránil v smerovaní tejto stanzy."}. +{"Your contact offline message queue is full. The message has been discarded.","Fronta offline správ tohoto kontaktu je plná. Správa bola zahodená."}. {"Your Jabber account was successfully created.","Jabber účet bol úspešne vytvorený."}. {"Your Jabber account was successfully deleted.","Váš Jabber účet bol úspešne odstránený."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Správa určená pre ~s bola zablokovaná. Oblokovať ju môžete na ~s"}. diff --git a/priv/msgs/sk.po b/priv/msgs/sk.po index 03ce8f3b5cb..a8ae9991c1e 100644 --- a/priv/msgs/sk.po +++ b/priv/msgs/sk.po @@ -12,49 +12,53 @@ msgstr "" "X-Additional-Translator: Juraj Michalek\n" "X-Additional-Translator: SkLUG\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Je vyžadované použitie STARTTLS " -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nebol poskytnutý žiadny zdroj" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Nahradené novým spojením" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "bol(a) vyhodený(á) z miestnosti" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Aktívny list súkromia zbránil v smerovaní tejto stanzy." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Zadajte zobrazený text" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Správa určená pre ~s bola zablokovaná. Oblokovať ju môžete na ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Pokiaľ nevidíte obrázok CAPTCHA, navštívte webovú stránku." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Webová stránka CAPTCHA" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Platná CAPTCHA." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Užívateľ" @@ -63,9 +67,9 @@ msgstr "Užívateľ" msgid "Server" msgstr "Server ~b" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Heslo" @@ -82,279 +86,280 @@ msgstr "Neautorizovaný" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administrácia" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Zoznamy prístupových oprávnení (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Odoslané" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Zlý formát" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Odoslať" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Surové dáta" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Zmazať vybrané" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Prístupové pravidlá" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s konfigurácia prístupového pravidla" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuálne servery" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Používatelia" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Online užívatelia" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Posledná aktivita používateľa" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Čas:" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Posledný mesiac" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Posledný rok" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Všetky aktivity" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Zobraziť bežnú tabuľku" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Zobraziť kompletnú tabuľku" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Štatistiky" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Nebol nájdený" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Uzol nenájdený" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Pridať nový" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Server" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrovaní používatelia" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Pridať používateľa" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Offline správy" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Posledná aktivita" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Nikdy" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Online" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrovaní používatelia:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Online používatelia:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Odchádzajúce s2s spojenia:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Odchádzajúce s2s servery:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Odchádzajúce s2s spojenia:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nič" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Zmeniť heslo" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Používateľ " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Pripojené zdroje:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Heslo:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Odstrániť užívateľa" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Žiadne dáta" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Uzly" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Bežiace uzly" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Zastavené uzly" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Uzol" -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databáza" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Zálohovať" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Otvorené portov" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Aktualizovať" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Reštart" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Zastaviť" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduly" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Chyba RPC volania" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Databázové tabuľky na " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Meno" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Typ úložiska" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Prvky" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Pamäť" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Chyba" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Záloha " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -364,147 +369,147 @@ msgstr "" "Mnesia databázu. Ak používate ODBC modul, musíte zálohovať vašu SQL databázu " "separátne." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Uložiť binárnu zálohu:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Okamžite obnoviť binárnu zálohu:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Obnoviť binárnu zálohu pri nasledujúcom reštarte ejabberd (vyžaduje menej " "pamäte)" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Uložiť zálohu do textového súboru:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Okamžite obnoviť zálohu z textového súboru:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importovat dáta užívateľov zo súboru PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportovať dáta všetkých uživateľov na serveri do súborov PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Exportovať dáta uživateľov na hostitelovi do súborov PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importovať dáta užívateľov z jabberd14 spool súboru:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importovať dáta užívateľov z jabberd14 spool adresára:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Otvorené porty na " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduly na " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Štatistiky ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Uptime:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Čas procesoru" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transakcie potvrdená" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transakcie zrušená" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transakcie reštartovaná" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transakcie zaznamenaná" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Aktualizovať " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Aktualizovať plán" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Modifikované moduly" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Aktualizované skripty" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Nízkoúrovňový aktualizačný skript" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Kontrola skriptu" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Nastavenia" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Štart" @@ -790,8 +795,8 @@ msgstr "Prístupové pravidlá" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -808,31 +813,31 @@ msgstr "Počet registrovaných užívateľov" msgid "Number of online users" msgstr "Počet online užívateľov" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Posledné prihlásenie" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Počet kontaktov v zozname" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresa" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Zdroje" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administrácia " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Operácia aplikovaná na užívateľa" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Editovať vlastnosti" @@ -842,27 +847,39 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Prístup bol zamietnutý nastavením služby" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modul" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Pre konfiguráciu mod_irc potrebujete klienta podporujúceho x:data" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Registrácia do mod_irc na" -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -870,11 +887,11 @@ msgstr "" "Vložte meno používateľa, kódovanie, porty a heslo ktoré chcete používať pri " "pripojení na IRC server" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC prezývka" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -886,7 +903,7 @@ msgstr "" "\"}'. Predvolenéi hodnoty pre túto službu sú: kódovanie \"~s\", port ~p a " "žiadne heslo." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -894,35 +911,35 @@ msgstr "" "Príklad: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Parametre spojenia" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Pripojit IRC kanál" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanál (bez počiatočnej #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC server" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Propojiť IRC kanál sem." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Pripojit IRC kanál k tomuto Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Nastavania IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -932,48 +949,77 @@ msgstr "" "IRC servery. Kliknutím na tlačítko 'Ďalej' môžete zadať niektoré ďalšie " "hodnoty. Pomocou 'Ukončiť ' uložíte nastavenia." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC prezývka" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Heslo ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Kódovanie pre server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Len moderátori majú povolené meniť tému miestnosti" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Iba správcovia služby majú povolené odosielanie servisných správ" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Vytváranie miestnosti nie je povolené" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Diskusná miestnosť neexistuje" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Diskusné miestnosti" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "Na registráciu prezývky potrebujete klienta podporujúceho z x:data" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registrácia prezývky na " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Zadajte prezývku, ktorú chcete registrovať" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Prezývka" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Prezývka je už zaregistrovaná inou osobou" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Musíte vyplniť políčko \"Prezývka\" vo formulári" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -1001,353 +1047,483 @@ msgstr "Registrovaní používatelia" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Nastavenie diskusnej miestnosti bolo zmenené" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "vstúpil(a) do miestnosti" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "odišiel(a) z miestnosti" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "bol(a) zablokovaný(á)" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "bol vyhodený(á) kvôli zmene priradenia" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "bol vyhodený(á), pretože miestnosť bola vyhradená len pre členov" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "bol vyhodený(á) kvôli reštartu systému" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "sa premenoval(a) na" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr "zmenil(a) tému na: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Diskusná miestnosť je vytvorená" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Diskusná miestnosť je zrušená" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Diskusná miestnosť je obnovená" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Diskusná miestnosť je pozastavená" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Pondelok" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Utorok" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Streda" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Štvrtok" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Piatok" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Sobota" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Nedeľa" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Január" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Február" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Marec" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Apríl" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Máj" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Jún" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Júl" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "August" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "September" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Október" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "November" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "December" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Nastavenia miestnosti" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Ľudí v miestnosti" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Bol prekročený prenosový limit" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Nie je povolené odosielať súkromné správy do konferencie" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Prosím počkate, predtým než pošlete novú žiadosť o Voice" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Žiadosti o Voice nie sú povolené v tejto konferencii" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Nepodarilo sa nájsť JID v súhlase o Voice." + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Len moderátori môžu schváliť žiadosť o Voice" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Nesprávny typ správy" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Nie je dovolené odoslanie súkromnej správy typu \"Skupinová správa\" " + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Príjemca sa nenachádza v konferenčnej miestnosti" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Nieje povolené posielať súkromné správy" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Len členovia majú povolené zasielať správy do konferencie" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Len členovia majú povolené dotazovať sa o konferencii" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Dotazovať sa o členoch nie je v tejto miestnosti povolené" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Len moderátori a zúčastnený majú povolené meniť tému tejto miestnosti" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Len moderátori majú povolené meniť tému miestnosti" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "" +"Návštevníci nemajú povolené zasielať správy všetkým prihláseným do " +"konferencie" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "V tejto miestnosti nieje povolené meniť prezývky" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Prezývka je už používaná iným členom" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Boli ste vylúčený z tejto miestnosti" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Pre vstup do miestnosti je potrebné byť členom" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Pre vstup do miestnosti je potrebné heslo" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Príliš veľa žiadostí o CAPTCHA" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Nepodarilo sa vygenerovat CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Nesprávne heslo" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Sú potrebné práva administrátora" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Sú potrebné práva moderátora" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s je neplatné" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Prezývka ~s v miestnosti neexistuje" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Neplatné priradenie: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Neplatná rola: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Sú vyžadované práva vlastníka" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Konfigurácia miestnosti ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Názov miestnosti" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Popis miestnosti" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Nastaviť miestnosť ako trvalú" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Nastaviť miestnosť ako verejne prehľadávateľnú" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Nastaviť zoznam zúčastnených ako verejný" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Chrániť miestnosť heslom" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Počet účastníkov" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Bez limitu" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Zobrazovať skutočné Jabber ID" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "moderátorom" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "všetkým" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "moderátorom" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Nastaviť miestnosť len pre členov" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Nastaviť miestnosť ako moderovanú" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Užívatelia sú implicitne členmi" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Povoliť užívateľom meniť tému" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Povoliť užívateľom odosielať súkromné správy" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Povoliť užívateľom odosielať súkromné správy" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "nikto" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Povoliť užívateľom dotazovať sa informácie o iných užívateľoch" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Povoliť používateľom posielanie pozvánok" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Návštevníci môžu posielať textové informácie v stavových správach" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Návštevníci môžu meniť prezývky" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Povoliť používateľom posielanie pozvánok" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Minimum interval between voice requests (in seconds)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Chrániť miestnosť systémom CAPTCHA" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Nepoužívať CAPTCHA pre nasledujúce Jabber ID" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Zapnúť zaznamenávanie histórie" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Na konfiguráciu miestnosti potrebujete klienta podporujúceho x:data" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Počet zúčastnených" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "súkromná, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Žiadosť o Voice" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Povolte alebo zamietnite žiadosť o Voice." -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Používateľ " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Prideltiť Voice tejto osobe?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s Vás pozýva do miestnosti ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "heslo je" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "Fronta offline správ tohoto kontaktu je plná. Správa bola zahodená." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s Offline správy" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Čas" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Od" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Pre" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline správy" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Odstrániť všetky offline správy" @@ -1355,115 +1531,127 @@ msgstr "Odstrániť všetky offline správy" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modul" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publish-Subscribe" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modul" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Žiadosť odberateľa PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Zvolte, či chcete povoliť toto odoberanie" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID uzlu" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresa odberateľa" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Dovoliť tomuto Jabber ID odoberať PubSub uzol?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Doručiť náklad s upozornením na udalosť" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Doručiť oznamy o udalosti" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Upozorniť prihlásených používateľov na zmenu nastavenia uzlu" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Upozorniť prihlásených používateľov na zmazanie uzlu" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Upozorniť prihlásených používateľov na odstránenie položiek z uzlu" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Uložiť položky natrvalo do úložiska" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Prístupný názov pre uzol" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Maximálny počet položiek, ktoré je možné natrvalo uložiť" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Povoliť prihlasovanie" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Uveďte model prístupu" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Skupiny kontaktov, ktoré môžu odoberať" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Špecifikovať model publikovania" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Odstrániť všetky relevantné položky, keď užívateľ prejde do módu offline" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Uveďte typ pre správu o udalosti" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Maximálny náklad v bajtoch" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Kedy odoslať posledne publikovanú položku" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Doručovať upozornenia len aktuálne prihláseným používateľom" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Kolekcie asociované s uzlom" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Overenie pomocou CAPTCHA zlihalo" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Na registráciu prezývky potrebujete klienta podporujúceho z x:data" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Zvolte meno užívateľa a heslo pre registráciu na tomto servere" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "heslo je" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Nieje dovolené vytvárať účty tak rýchlo po sebe" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Jabber účet bol úspešne vytvorený." @@ -1541,8 +1729,8 @@ msgstr "Neskôr si heslo môžete zmeniť pomocou Jabber klienta." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Niektorí Jabber klenti môžu ukladať heslá v počítači. Používajte túto " "funkciu len ak veríte, že sú tam v bezpečí. " @@ -1581,60 +1769,60 @@ msgstr "" msgid "Unregister" msgstr "Zrušiť účet" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Prihlásenie" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Čakajúce" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Skupiny" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Overiť" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Odstrániť" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Zoznam kontaktov " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Pridať Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Zoznam kontaktov" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Skupiny pre zdieľaný zoznam kontaktov" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Meno:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Popis:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Členovia:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Zobrazené skupiny:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Skupina " @@ -1710,58 +1898,19 @@ msgstr "Hľadať výsledky pre " msgid "Fill in fields to search for any matching Jabber User" msgstr "Vyplnte políčka pre vyhľadávanie Jabber užívateľa" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Odchádzajúce s2s servery:" + #~ msgid "Delete" #~ msgstr "Zmazať" #~ msgid "This room is not anonymous" #~ msgstr "Táto miestnosť nie je anonymná" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Aktívny list súkromia zbránil v smerovaní tejto stanzy." - -#~ msgid "Access denied by service policy" -#~ msgstr "Prístup bol zamietnutý nastavením služby" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Iba správcovia služby majú povolené odosielanie servisných správ" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Vytváranie miestnosti nie je povolené" - -#~ msgid "Conference room does not exist" -#~ msgstr "Diskusná miestnosť neexistuje" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Prezývka je už zaregistrovaná inou osobou" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Musíte vyplniť políčko \"Prezývka\" vo formulári" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Bol prekročený prenosový limit" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "Účastník bol vyhodený z miestnosti, pretože poslal chybovú správu" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Nie je povolené odosielať súkromné správy do konferencie" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Prosím počkate, predtým než pošlete novú žiadosť o Voice" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Žiadosti o Voice nie sú povolené v tejto konferencii" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Nepodarilo sa nájsť JID v súhlase o Voice." - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Len moderátori môžu schváliť žiadosť o Voice" - -#~ msgid "Improper message type" -#~ msgstr "Nesprávny typ správy" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1769,82 +1918,11 @@ msgstr "Vyplnte políčka pre vyhľadávanie Jabber užívateľa" #~ "Účastník bol vyhodený z miestnosti, pretože poslal chybovú správu inému " #~ "účastníkovi" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Nie je dovolené odoslanie súkromnej správy typu \"Skupinová správa\" " - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Príjemca sa nenachádza v konferenčnej miestnosti" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Nieje povolené posielať súkromné správy" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Len členovia majú povolené zasielať správy do konferencie" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Len členovia majú povolené dotazovať sa o konferencii" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Dotazovať sa o členoch nie je v tejto miestnosti povolené" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "" -#~ "Návštevníci nemajú povolené zasielať správy všetkým prihláseným do " -#~ "konferencie" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Účastník bol vyhodený z miestnosti, pretože poslal chybovú správu o stave" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "V tejto miestnosti nieje povolené meniť prezývky" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Prezývka je už používaná iným členom" - -#~ msgid "You have been banned from this room" -#~ msgstr "Boli ste vylúčený z tejto miestnosti" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Pre vstup do miestnosti je potrebné byť členom" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Pre vstup do miestnosti je potrebné heslo" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Príliš veľa žiadostí o CAPTCHA" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Nepodarilo sa vygenerovat CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Nesprávne heslo" - -#~ msgid "Administrator privileges required" -#~ msgstr "Sú potrebné práva administrátora" - -#~ msgid "Moderator privileges required" -#~ msgstr "Sú potrebné práva moderátora" - -#~ msgid "Owner privileges required" -#~ msgstr "Sú vyžadované práva vlastníka" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "Fronta offline správ tohoto kontaktu je plná. Správa bola zahodená." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Overenie pomocou CAPTCHA zlihalo" - -#~ msgid "The password is too weak" -#~ msgstr "heslo je" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Nieje dovolené vytvárať účty tak rýchlo po sebe" - #~ msgid "Captcha test failed" #~ msgstr "Platná CAPTCHA." diff --git a/priv/msgs/sv.msg b/priv/msgs/sv.msg index 2eb56b41679..b992bce068d 100644 --- a/priv/msgs/sv.msg +++ b/priv/msgs/sv.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Konfiguera ACL"}. {"Access control lists","ACL"}. {"Access Control Lists","ACL"}. +{"Access denied by service policy","Åtkomst nekad enligt lokal policy"}. {"Access rules","Åtkomstregler"}. {"Access Rules","Åtkomstregler"}. {"Action on user","Handling mot användare"}. @@ -11,6 +12,7 @@ {"Add User","Lägg till användare"}. {"Administration","Administration"}. {"Administration of ","Administration av "}. +{"Administrator privileges required","Administrationsprivilegier krävs"}. {"A friendly name for the node","Ett vänligt namn for noden"}. {"All activity","All aktivitet"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Tillåt denna Jabber ID att prenumerera på denna pubsub node"}. @@ -40,6 +42,7 @@ {"Choose whether to approve this entity's subscription.","Välj om du vill godkänna hela denna prenumertion."}. {"City","Stad"}. {"Commands","Kommandon"}. +{"Conference room does not exist","Rummet finns inte"}. {"Configuration","Konfiguration"}. {"Configuration of room ~s","Konfiguration för ~s"}. {"Connected Resources:","Anslutna resurser:"}. @@ -117,6 +120,8 @@ {"Import users data from jabberd14 spool directory:","Importera användare från jabberd14 Spool directory:"}. {"Import Users from Dir at ","Importera användare från katalog på "}. {"Import Users From jabberd14 Spool Files","Importera användare från jabberd14 Spool filer"}. +{"Improper message type","Felaktig medelandetyp"}. +{"Incorrect password","Fel lösenord"}. {"Invalid affiliation: ~s","Ogiltlig rang: ~s"}. {"Invalid role: ~s","Ogiltlig roll: ~s"}. {"IP addresses","IP adresser"}. @@ -128,6 +133,9 @@ {"IRC username","IRC-användarnamn"}. {"IRC Username","IRC-användarnamn"}. {"is now known as","är känd som"}. +{"It is not allowed to send private messages","Det ar inte tillåtet att skicka privata meddelanden"}. +{"It is not allowed to send private messages of type \"groupchat\"","Det är inte tillåtet att skicka privata medelanden med typen \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Det är inte tillåtet att skicka privata medelanden till den här konferensen"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Otillåtet Jabber ID ~s"}. {"January","Januari"}. @@ -157,10 +165,12 @@ {"Max # of items to persist","Högsta antal dataposter som sparas"}. {"Max payload size in bytes","Högsta innehållsstorlek i bytes"}. {"May","Maj"}. +{"Membership is required to enter this room","Du måste vara medlem för att komma in i det här rummet"}. {"Members:","Medlemmar:"}. {"Memory","Minne"}. {"Message body","Meddelande kropp"}. {"Middle Name","Mellannamn"}. +{"Moderator privileges required","Moderatorprivilegier krävs"}. {"moderators only","endast moderatorer"}. {"Modified modules","Uppdaterade moduler"}. {"Module","Modul"}. @@ -197,12 +207,15 @@ {"Online Users:","Inloggade användare"}. {"Only deliver notifications to available users","Skicka notifikationer bara till uppkopplade användare"}. {"Only moderators and participants are allowed to change the subject in this room","Endast moderatorer och deltagare har tillåtelse att ändra ämnet i det här rummet"}. +{"Only occupants are allowed to send messages to the conference","Utomstående får inte skicka medelanden till den här konferensen"}. +{"Only occupants are allowed to send queries to the conference","Utomstående får inte skicka iq-queries till den här konferensen"}. +{"Only service administrators are allowed to send service messages","Endast administratörer får skicka tjänstmeddelanden"}. {"Options","Parametrar"}. {"Organization Name","Organisationsnamn"}. {"Organization Unit","Organisationsenhet"}. {"Outgoing s2s Connections","Utgaende s2s anslutning"}. {"Outgoing s2s Connections:","Utgående s2s anslutning"}. -{"Outgoing s2s Servers:","Utgående s2s server"}. +{"Owner privileges required","Ägarprivilegier krävs"}. {"Packet","Paket"}. {"Password ~b","Lösenord ~b"}. {"Password:","Lösenord:"}. @@ -223,10 +236,12 @@ {"Protocol","Protocol"}. {"Publish-Subscribe","Publikprenumeration"}. {"PubSub subscriber request","Pubsub prenumerationsforfrågan"}. +{"Queries to the conference members are not allowed in this room","Det är förbjudet att skicka iq-queries till konferensdeltagare"}. {"RAM and disc copy","RAM- och diskkopia"}. {"RAM copy","RAM-kopia"}. {"Raw","Ra"}. {"Really delete message of the day?","Verkligen ta bort dagens meddelanden?"}. +{"Recipient is not in the conference room","Mottagaren finns inte i rummet"}. {"Registered Users:","Registrerade användare"}. {"Registered Users","Registrerade användare"}. {"Registration in mod_irc for ","mod_irc-registrering för "}. @@ -243,6 +258,7 @@ {"Restore binary backup immediately:","återställ den binära backupen omedelbart"}. {"Restore plain text backup immediately:","återställ textbackup omedelbart"}. {"Room Configuration","Rumkonfiguration"}. +{"Room creation is denied by service policy","Skapandet av rum är förbjudet enligt lokal policy"}. {"Room Occupants","Antal besökare"}. {"Room title","Rumstitel"}. {"Roster groups allowed to subscribe","Rostergrupper tillåts att prenumerera"}. @@ -290,6 +306,7 @@ {"Subscriber Address","Prenumerationsadress"}. {"Subscription","Prenumeration"}. {"Sunday","Söndag"}. +{"That nickname is registered by another person","Smeknamnet är reserverat"}. {"The CAPTCHA is valid.","Din CAPTCHA är godkänd."}. {"the password is","Lösenordet är"}. {"Thursday","Torsdag"}. @@ -297,6 +314,7 @@ {"Time","Tid"}. {"To ~s","Till ~s"}. {"To","Till"}. +{"Traffic rate limit is exceeded","Trafikgränsen har överstigits"}. {"Transactions Aborted:","Transaktioner borttagna"}. {"Transactions Committed:","Transaktioner kommittade"}. {"Transactions Logged:","Transaktioner loggade "}. @@ -313,14 +331,20 @@ {"User","Användarnamn"}. {"User Management","Användarmanagement"}. {"Users","Användare"}. +{"Users are not allowed to register accounts so quickly","Det är inte tillåtet för användare att skapa konton så fort"}. {"Users Last Activity","Användarens senaste aktivitet"}. {"Validate","Validera"}. {"vCard User Search","vCard användare sök"}. {"Virtual Hosts","Virtuella servrar"}. +{"Visitors are not allowed to change their nicknames in this room","Det är inte tillåtet for gäster att ändra sina smeknamn i detta rummet"}. +{"Visitors are not allowed to send messages to all occupants","Besökare får inte skicka medelande till alla"}. {"Wednesday","Onsdag"}. {"When to send the last published item","När att skicka senast publicerade ämne"}. {"Whether to allow subscriptions","Tillåta prenumerationer?"}. +{"You have been banned from this room","Du har blivit bannlyst från det här rummet"}. +{"You must fill in field \"Nickname\" in the form","Du måste fylla i fält \"smeknamn\" i formen"}. {"You need an x:data capable client to configure mod_irc settings","Du behöer en klient som stöjer x:data för att konfigurera mod_irc"}. {"You need an x:data capable client to configure room","Du behöver en klient som stödjer x:data för att konfiguera detta rum"}. {"You need an x:data capable client to search","Du behöver en klient som stödjer x:data, för att kunna söka"}. +{"Your contact offline message queue is full. The message has been discarded.","Din kontaktkö for offlinekontakter ar full"}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Dina meddelanden till ~s är blockerade. För att avblockera dem, gå till ~s"}. diff --git a/priv/msgs/sv.po b/priv/msgs/sv.po index cfb28dab4ce..631fdb707d8 100644 --- a/priv/msgs/sv.po +++ b/priv/msgs/sv.po @@ -11,50 +11,54 @@ msgstr "" "X-Additional-Translator: Magnus Henoch\n" "X-Additional-Translator: Jonas Ådahl\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Du måste använda STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Ingen resurs angiven" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Ersatt av ny anslutning" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "har blivit kickad" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Skriv in sökväg till textfil" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "Dina meddelanden till ~s är blockerade. För att avblockera dem, gå till ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Din CAPTCHA är godkänd." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Användarnamn" @@ -63,9 +67,9 @@ msgstr "Användarnamn" msgid "Server" msgstr "Server ~b" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Lösenord" @@ -82,279 +86,280 @@ msgstr "Ej auktoriserad" msgid "ejabberd Web Admin" msgstr "ejabberd Web Admin" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Administration" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "ACL" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Skicka in" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Dåligt format" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Skicka" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ra" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Tabort valda" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Åtkomstregler" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Åtkomstregelkonfiguration för ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Virtuella servrar" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Användare" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Anslutna användare" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Användarens senaste aktivitet" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Period: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Senaste månaden" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Senaste året" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "All aktivitet" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Visa normal tabell" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Visa kumulativ tabell" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Statistik" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Noden finns inte" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Noden finns inte" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Lägg till ny" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Server" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Registrerade användare" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Lägg till användare" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Offline meddelanden" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Senast aktivitet" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Aldrig" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Ansluten" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Registrerade användare" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Inloggade användare" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Utgående s2s anslutning" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Utgående s2s server" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Utgående s2s anslutning" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Inga" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Ändra lösenord" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Användare " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Anslutna resurser:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Lösenord:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Ta bort användare" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Ingen data" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Noder" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Körande noder" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Stannade noder" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nod " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Databas" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Säkerhetskopiera" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Lyssnarport" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Uppdatera" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Omstart" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Stoppa" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Moduler" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC Uppringningserror" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Databas tabell pa" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Namn" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Lagringstyp" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elements" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Minne" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Fel" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Backup av" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -364,144 +369,144 @@ msgstr "" "databas. Om du använder ODBC modul så måste du ta backup på SQLs databas " "enskilt" -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Lagra den binära backupen" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "återställ den binära backupen omedelbart" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "återställ den binära backupen efter nästa ejabberd omstart" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Lagra textbackup" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "återställ textbackup omedelbart" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Importera användardata från en PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Exportera data av alla användare i servern till en PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Exportera data av användare i en host till PIEFXIS fil (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Importera användare från jabberd14 Spool filer" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Importera användare från jabberd14 Spool directory:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Lyssnande portar på " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Moduler på" -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Statistik på ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tid upp" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU tid" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaktioner kommittade" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaktioner borttagna" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaktioner omstartade" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaktioner loggade " -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Uppdatera" -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Uppdateringsplan" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Uppdaterade moduler" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Uppdatera skript" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Uppdaterade laglevel skript" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Skript kollat" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Port" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protocol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modul" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Parametrar" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Starta" @@ -787,8 +792,8 @@ msgstr "Åtkomstregler" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -805,31 +810,31 @@ msgstr "Antal registrerade användare" msgid "Number of online users" msgstr "Antal inloggade användare" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Senaste login" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Roster storlek" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresser" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Resurser" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Administration av " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Handling mot användare" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Redigera egenskaper" @@ -839,27 +844,39 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Åtkomst nekad enligt lokal policy" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC transport" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC-modul" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "Du behöer en klient som stöjer x:data för att konfigurera mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "mod_irc-registrering för " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -867,11 +884,11 @@ msgstr "" "Skriv in användarnamn och textkodning du vill använda för att ansluta till " "IRC-servrar" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC-användarnamn" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -882,7 +899,7 @@ msgstr "" "i formatet '{\"irc server\", \"encoding\", port, \"password\"}'. Som " "standard används \"~s\", port ~p, no password." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -890,35 +907,35 @@ msgstr "" "Exempel: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Uppkopplingsparametrar" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Lägg till IRC kanal" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanal (skriv inte första #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-användarnamn" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Lägg till IRC kanal här." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Lägg till IRC kanal till detta Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC Inställningar" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 #, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " @@ -928,49 +945,78 @@ msgstr "" "Skriv in användarnamn och textkodning du vill använda för att ansluta till " "IRC-servrar" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC-användarnamn" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Lösenord ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Port ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Encoding för server ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Server ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Endast moderatorer får ändra ämnet i det här rummet" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Endast administratörer får skicka tjänstmeddelanden" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Skapandet av rum är förbjudet enligt lokal policy" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Rummet finns inte" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Chattrum" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "Du behöver en klient som stödjer x:data för att registrera smeknamn" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Registrera smeknamn på " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Skriv in smeknamnet du vill registrera" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Smeknamn" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Smeknamnet är reserverat" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Du måste fylla i fält \"smeknamn\" i formen" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -998,147 +1044,208 @@ msgstr "Registrerade användare" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Chattrum konfiguration modifierad" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "joinar rummet" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "lämnar rummet" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "har blivit bannad" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "har blivit kickad p.g.a en ändring av tillhörighet" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "har blivit kickad p.g.a att rummet har ändrats till endast användare" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "har blivit kickad p.g.a en systemnerstängning" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "är känd som" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " har satt ämnet till: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "Chattrum" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Chattrum" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Chattrum" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Chattrum" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Måndag" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Tisdag" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Onsdag" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Torsdag" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Fredag" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Lördag" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Söndag" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Januari" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Februari" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Mars" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "April" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Maj" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Juni" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Juli" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Augusti" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "September" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Oktober" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "November" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "December" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Rumkonfiguration" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Trafikgränsen har överstigits" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "" +"Det är inte tillåtet att skicka privata medelanden till den här konferensen" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Tillåt användare att skicka inbjudningar" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Felaktig medelandetyp" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "" +"Det är inte tillåtet att skicka privata medelanden med typen \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Mottagaren finns inte i rummet" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Det ar inte tillåtet att skicka privata meddelanden" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Utomstående får inte skicka medelanden till den här konferensen" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Utomstående får inte skicka iq-queries till den här konferensen" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Det är förbjudet att skicka iq-queries till konferensdeltagare" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1146,217 +1253,290 @@ msgstr "" "Endast moderatorer och deltagare har tillåtelse att ändra ämnet i det här " "rummet" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Endast moderatorer får ändra ämnet i det här rummet" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Besökare får inte skicka medelande till alla" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Det är inte tillåtet for gäster att ändra sina smeknamn i detta rummet" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +#, fuzzy +msgid "That nickname is already in use by another occupant" +msgstr "Smeknamnet används redan" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Du har blivit bannlyst från det här rummet" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Du måste vara medlem för att komma in i det här rummet" + +#: mod_muc_room.erl:1872 +#, fuzzy +msgid "A password is required to enter this room" +msgstr "Lösenord erfordras" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +#, fuzzy +msgid "Unable to generate a CAPTCHA" +msgstr "Kunde inte generera ett CAPTCHA" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Fel lösenord" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Administrationsprivilegier krävs" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Moderatorprivilegier krävs" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Otillåtet Jabber ID ~s" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Smeknamnet ~s existerar inte i det här rummet" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Ogiltlig rang: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Ogiltlig roll: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Ägarprivilegier krävs" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Konfiguration för ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Rumstitel" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Beskrivning:" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Gör rummet permanent" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Gör rummet publikt sökbart" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Gör deltagarlistan publik" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Gör losenorden i rummet publika" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Maximalt antal av användare" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Ingen gräns" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Nuvarande äkta Jabber IDs till" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "endast moderatorer" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "Vemsomhelst" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "endast moderatorer" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Gör om rummet till endast medlemmar" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Gör rummet modererat" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Gör om användare till deltagare" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Tillåt användare att byta ämne" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Tillåt användare att skicka privata meddelanden" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Tillåt användare att skicka privata meddelanden" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Tillåt användare att söka efter andra användare" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Tillåt användare att skicka inbjudningar" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "Tillåt gäster att skicka statustext som uppdatering" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Tillåt gäster att kunna ändra smeknamn" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Tillåt användare att skicka inbjudningar" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Gör losenorden i rummet publika" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Möjliggör login" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "Du behöver en klient som stödjer x:data för att konfiguera detta rum" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Användare " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s bjöd in dig till rummet ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "Lösenordet är" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "Din kontaktkö for offlinekontakter ar full" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s's offline meddelandekö" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Tid" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Från" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Till" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Offline meddelanden:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Offline meddelanden" @@ -1365,116 +1545,130 @@ msgstr "Offline meddelanden" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestrem modul" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Publikprenumeration" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd publikprenumerations modul" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Pubsub prenumerationsforfrågan" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Välj om du vill godkänna hela denna prenumertion." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Node ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Prenumerationsadress" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Tillåt denna Jabber ID att prenumerera på denna pubsub node" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Skicka innehåll tillsammans med notifikationer" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Skicka eventnotifikation" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Meddela prenumeranter när nodens konfiguration ändras" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Meddela prenumeranter när noden tas bort" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Meddela prenumeranter när dataposter tas bort från noden" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Spara dataposter permanent" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Ett vänligt namn for noden" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Högsta antal dataposter som sparas" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Tillåta prenumerationer?" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Specificera accessmodellen" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Rostergrupper tillåts att prenumerera" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Ange publiceringsmodell" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Specificera accessmodellen" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Högsta innehållsstorlek i bytes" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "När att skicka senast publicerade ämne" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Skicka notifikationer bara till uppkopplade användare" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:250 +#: mod_register.erl:209 +#, fuzzy +msgid "The CAPTCHA verification has failed" +msgstr "Din CAPTCHA är godkänd." + +#: mod_register.erl:253 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "Du behöver en klient som stödjer x:data för att registrera smeknamn" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Välj ett användarnamn och lösenord för att registrera mot denna server" +#: mod_register.erl:373 mod_register.erl:421 +#, fuzzy +msgid "The password is too weak" +msgstr "Lösenordet är" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Det är inte tillåtet för användare att skapa konton så fort" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1548,8 +1742,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1587,60 +1781,60 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Prenumeration" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Ännu inte godkända" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Grupper" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Validera" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Ta bort" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontaktlista för " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Lägg till Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Kontaktlista" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Delade Rostergrupper" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Namn:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Beskrivning:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Medlemmar:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Visade grupper:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Grupp " @@ -1716,47 +1910,21 @@ msgstr "Sökresultat för" msgid "Fill in fields to search for any matching Jabber User" msgstr "Fyll i fält för att söka efter jabberanvändare" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Utgående s2s server" + #~ msgid "Delete" #~ msgstr "Ta bort" #~ msgid "This room is not anonymous" #~ msgstr "Detta rum är inte anonymt" -#~ msgid "Access denied by service policy" -#~ msgstr "Åtkomst nekad enligt lokal policy" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Endast administratörer får skicka tjänstmeddelanden" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Skapandet av rum är förbjudet enligt lokal policy" - -#~ msgid "Conference room does not exist" -#~ msgstr "Rummet finns inte" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Smeknamnet är reserverat" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Du måste fylla i fält \"smeknamn\" i formen" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Trafikgränsen har överstigits" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Deltagaren har blivit kickad fran rummet p.g.a att han skickade ett " #~ "errormeddelande" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "" -#~ "Det är inte tillåtet att skicka privata medelanden till den här " -#~ "konferensen" - -#~ msgid "Improper message type" -#~ msgstr "Felaktig medelandetyp" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1764,80 +1932,12 @@ msgstr "Fyll i fält för att söka efter jabberanvändare" #~ "Deltagaren har blivit kickad från rummet p.g.a att han skickade ett " #~ "errormeddelande till en annan deltagare" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "Det är inte tillåtet att skicka privata medelanden med typen \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Mottagaren finns inte i rummet" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Det ar inte tillåtet att skicka privata meddelanden" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Utomstående får inte skicka medelanden till den här konferensen" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Utomstående får inte skicka iq-queries till den här konferensen" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Det är förbjudet att skicka iq-queries till konferensdeltagare" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Besökare får inte skicka medelande till alla" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Denna deltagaren är kickad från rummet p.g.a att han skickade en " #~ "errorstatus" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Det är inte tillåtet for gäster att ändra sina smeknamn i detta rummet" - -#, fuzzy -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Smeknamnet används redan" - -#~ msgid "You have been banned from this room" -#~ msgstr "Du har blivit bannlyst från det här rummet" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Du måste vara medlem för att komma in i det här rummet" - -#, fuzzy -#~ msgid "A password is required to enter this room" -#~ msgstr "Lösenord erfordras" - -#, fuzzy -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Kunde inte generera ett CAPTCHA" - -#~ msgid "Incorrect password" -#~ msgstr "Fel lösenord" - -#~ msgid "Administrator privileges required" -#~ msgstr "Administrationsprivilegier krävs" - -#~ msgid "Moderator privileges required" -#~ msgstr "Moderatorprivilegier krävs" - -#~ msgid "Owner privileges required" -#~ msgstr "Ägarprivilegier krävs" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "Din kontaktkö for offlinekontakter ar full" - -#, fuzzy -#~ msgid "The password is too weak" -#~ msgstr "Lösenordet är" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Det är inte tillåtet för användare att skapa konton så fort" - #, fuzzy #~ msgid "Captcha test failed" #~ msgstr "Din CAPTCHA är godkänd." diff --git a/priv/msgs/th.msg b/priv/msgs/th.msg index 18acbef4acb..4730123e064 100644 --- a/priv/msgs/th.msg +++ b/priv/msgs/th.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","การกำหนดค่ารายการควบคุมการเข้าถึง"}. {"Access control lists","รายการควบคุมการเข้าถึง"}. {"Access Control Lists","รายการควบคุมการเข้าถึง"}. +{"Access denied by service policy","การเข้าถึงถูกปฏิเสธโดยนโยบายการบริการ"}. {"Access rules","กฎการเข้าถึง"}. {"Access Rules","กฎการเข้าถึง"}. {"Action on user","การดำเนินการกับผู้ใช้"}. @@ -11,6 +12,7 @@ {"Add User","เพิ่มผู้ใช้"}. {"Administration","การดูแล"}. {"Administration of ","การดูแล "}. +{"Administrator privileges required","ต้องมีสิทธิพิเศษของผู้ดูแลระบบ"}. {"All activity","กิจกรรมทั้งหมด"}. {"Allow this Jabber ID to subscribe to this pubsub node?","อนุญาตให้ Jabber ID นี้เข้าร่วมเป็นสมาชิกของโหนด pubsub หรือไม่"}. {"Allow users to query other users","อนุญาตให้ผู้ใช้ถามคำถามกับผู้ใช้คนอื่นๆ ได้"}. @@ -36,6 +38,7 @@ {"Choose whether to approve this entity's subscription.","เลือกว่าจะอนุมัติการสมัครเข้าใช้งานของเอนทิตี้นี้หรือไม่"}. {"City","เมือง"}. {"Commands","คำสั่ง"}. +{"Conference room does not exist","ไม่มีห้องประชุม"}. {"Configuration","การกำหนดค่า"}. {"Connected Resources:","ทรัพยากรที่เชื่อมต่อ:"}. {"Country","ประเทศ"}. @@ -95,12 +98,16 @@ {"Import User from File at ","อิมพอร์ตผู้ใช้จากไฟล์ที่"}. {"Import Users from Dir at ","อิมพอร์ตผู้ใช้จาก Dir ที่"}. {"Import Users From jabberd14 Spool Files","อิมพอร์ตผู้ใช้จากไฟล์เก็บพักข้อมูล jabberd14"}. +{"Improper message type","ประเภทข้อความไม่เหมาะสม"}. +{"Incorrect password","รหัสผ่านไม่ถูกต้อง"}. {"Invalid affiliation: ~s","การเข้าร่วมที่ไม่ถูกต้อง: ~s"}. {"Invalid role: ~s","บทบาทไม่ถูกต้อง: ~s"}. {"IP addresses","ที่อยู่ IP"}. {"IRC Transport","การส่ง IRC"}. {"IRC Username","ชื่อผู้ใช้ IRC"}. {"is now known as","ซึ่งรู้จักกันในชื่อ"}. +{"It is not allowed to send private messages of type \"groupchat\"","ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยัง \"กลุ่มสนทนา\""}. +{"It is not allowed to send private messages to the conference","ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยังห้องประชุม"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s ไม่ถูกต้อง"}. {"January","มกราคม"}. @@ -130,6 +137,7 @@ {"Memory","หน่วยความจำ"}. {"Message body","เนื้อหาของข้อความ"}. {"Middle Name","ชื่อกลาง"}. +{"Moderator privileges required","ต้องมีสิทธิพิเศษของผู้ดูแลการสนทนา"}. {"moderators only","สำหรับผู้ดูแลการสนทนาเท่านั้น"}. {"Module","โมดูล"}. {"Modules","โมดูล"}. @@ -163,12 +171,15 @@ {"Online Users:","ผู้ใช้ออนไลน์:"}. {"Online Users","ผู้ใช้ออนไลน์"}. {"Only deliver notifications to available users","ส่งการแจ้งเตือนถึงผู้ใช้ที่สามารถติดต่อได้เท่านั้น"}. +{"Only occupants are allowed to send messages to the conference","ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความไปยังห้องประชุม"}. +{"Only occupants are allowed to send queries to the conference","ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งกระทู้ถามไปยังห้องประชุม"}. +{"Only service administrators are allowed to send service messages","ผู้ดูแลด้านการบริการเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความการบริการ"}. {"Options","ตัวเลือก"}. {"Organization Name","ชื่อองค์กร"}. {"Organization Unit","หน่วยขององค์กร"}. {"Outgoing s2s Connections:","การเชื่อมต่อ s2s ขาออก:"}. {"Outgoing s2s Connections","การเชื่อมต่อ s2s ขาออก"}. -{"Outgoing s2s Servers:","เซิร์ฟเวอร์ s2s ขาออก:"}. +{"Owner privileges required","ต้องมีสิทธิพิเศษของเจ้าของ"}. {"Packet","แพ็กเก็ต"}. {"Password:","รหัสผ่าน:"}. {"Password","รหัสผ่าน"}. @@ -185,10 +196,12 @@ {"private, ","ส่วนตัว, "}. {"Publish-Subscribe","เผยแพร่-สมัครเข้าใช้งาน"}. {"PubSub subscriber request","คำร้องขอของผู้สมัครเข้าใช้งาน PubSub"}. +{"Queries to the conference members are not allowed in this room","ห้องนี้ไม่อนุญาตให้ส่งกระทู้ถามถึงสมาชิกในห้องประชุม"}. {"RAM and disc copy","คัดลอก RAM และดิสก์"}. {"RAM copy","คัดลอก RAM"}. {"Raw","ข้อมูลดิบ"}. {"Really delete message of the day?","แน่ใจว่าต้องการลบข้อความของวันหรือไม่"}. +{"Recipient is not in the conference room","ผู้รับไม่ได้อยู่ในห้องประชุม"}. {"Registered Users:","ผู้ใช้ที่ลงทะเบียน:"}. {"Registered Users","ผู้ใช้ที่ลงทะเบียน"}. {"Registration in mod_irc for ","การลงทะเบียนใน mod_irc สำหรับ"}. @@ -205,6 +218,7 @@ {"Restore binary backup immediately:","คืนค่าข้อมูลสำรองแบบไบนารีโดยทันที:"}. {"Restore plain text backup immediately:","คืนค่าข้อมูลสำรองที่เป็นข้อความธรรมดาโดยทันที:"}. {"Room Configuration","การกำหนดค่าห้องสนทนา"}. +{"Room creation is denied by service policy","การสร้างห้องสนทนาถูกปฏิเสธโดยนโยบายการบริการ"}. {"Room title","ชื่อห้อง"}. {"Roster","บัญชีรายชื่อ"}. {"Roster of ","บัญชีรายชื่อของ "}. @@ -255,6 +269,7 @@ {"Time delay","การหน่วงเวลา"}. {"To","ถึง"}. {"To ~s","ถึง ~s"}. +{"Traffic rate limit is exceeded","อัตราของปริมาณการเข้าใช้เกินขีดจำกัด"}. {"Transactions Aborted:","ทรานแซกชันที่ถูกยกเลิก:"}. {"Transactions Committed:","ทรานแซกชันที่ได้รับมอบหมาย:"}. {"Transactions Logged:","ทรานแซกชันที่บันทึก:"}. @@ -274,9 +289,13 @@ {"Validate","ตรวจสอบ"}. {"vCard User Search","ค้นหาผู้ใช้ vCard "}. {"Virtual Hosts","โฮสต์เสมือน"}. +{"Visitors are not allowed to send messages to all occupants","ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด"}. {"Wednesday","วันพุธ"}. {"When to send the last published item","เวลาที่ส่งรายการที่เผยแพร่ครั้งล่าสุด"}. {"Whether to allow subscriptions","อนุญาตให้เข้าร่วมเป็นสมาชิกหรือไม่"}. +{"You have been banned from this room","คุณถูกสั่งห้ามไมให้เข้าห้องนี้"}. +{"You must fill in field \"Nickname\" in the form","คุณต้องกรอกฟิลด์ \"Nickname\" ในแบบฟอร์ม"}. {"You need an x:data capable client to configure mod_irc settings","คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดการตั้งค่า mod_irc"}. {"You need an x:data capable client to configure room","คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดค่าห้องสนทนา "}. {"You need an x:data capable client to search","คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อค้นหา"}. +{"Your contact offline message queue is full. The message has been discarded.","ลำดับข้อความออฟไลน์ของผู้ที่ติดต่อของคุณเต็มแล้ว ข้อความถูกลบทิ้งแล้ว"}. diff --git a/priv/msgs/th.po b/priv/msgs/th.po index d988554c482..c2fca4a23d4 100644 --- a/priv/msgs/th.po +++ b/priv/msgs/th.po @@ -7,50 +7,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Thai (ภาษาไทย)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "ต้องใช้ STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "ไม่ได้ระบุข้อมูล" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "แทนที่ด้วยการเชื่อมต่อใหม่" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "ถูกไล่ออก" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 #, fuzzy msgid "Enter the text you see" msgstr "ป้อนพาธของไฟล์ข้อความ" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "ผู้ใช้" @@ -59,9 +63,9 @@ msgstr "ผู้ใช้" msgid "Server" msgstr "ไม่เคย" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "รหัสผ่าน" @@ -79,280 +83,281 @@ msgstr "" msgid "ejabberd Web Admin" msgstr "เว็บอินเทอร์เฟซของ ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "การดูแล" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "รายการควบคุมการเข้าถึง" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "ส่งแล้ว" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "รูปแบบที่ไม่ถูกต้อง" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "ส่ง" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "ข้อมูลดิบ" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "ลบข้อความที่เลือก" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "กฎการเข้าถึง" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s การกำหนดค่ากฎการเข้าถึง" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "โฮสต์เสมือน" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "ผู้ใช้" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "ผู้ใช้ออนไลน์" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "กิจกรรมล่าสุดของผู้ใช้" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "ระยะเวลา:" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "เดือนที่แล้ว" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "ปีที่แล้ว" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "กิจกรรมทั้งหมด" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "แสดงตารางทั่วไป" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "แสดงตารางรวม" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "สถิติ" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "ไม่พบโหนด" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "ไม่พบโหนด" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "เพิ่มผู้ใช้ใหม่" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "โฮสต์" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "ผู้ใช้ที่ลงทะเบียน" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "เพิ่มผู้ใช้" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "ข้อความออฟไลน์" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "กิจกรรมล่าสุด" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "ไม่เคย" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "ออนไลน์" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "ผู้ใช้ที่ลงทะเบียน:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "ผู้ใช้ออนไลน์:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "การเชื่อมต่อ s2s ขาออก:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "เซิร์ฟเวอร์ s2s ขาออก:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "การเชื่อมต่อ s2s ขาออก:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "ไม่มี" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "เปลี่ยนรหัสผ่าน" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "ผู้ใช้" -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "ทรัพยากรที่เชื่อมต่อ:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "รหัสผ่าน:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "ลบผู้ใช้" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "ไม่มีข้อมูล" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "โหนด" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "โหนดที่ทำงาน" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "โหนดที่หยุด" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "โหนด " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "ฐานข้อมูล" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "การสำรองข้อมูล " -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "พอร์ทฟัง" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "อัพเดต" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "เริ่มต้นใหม่" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "หยุด" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "โมดูล" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "ข้อผิดพลาดจากการเรียกใช้ RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "ตารางฐานข้อมูลที่" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "ชื่อ" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "ชนิดที่เก็บข้อมูล" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "หน่วยความจำ" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "การสำรองข้อมูล" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 #, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " @@ -362,148 +367,148 @@ msgstr "" "โปรดทราบว่าตัวเลือกเหล่านี้จะสำรองข้อมูลในฐานข้อมูล builtin Mnesia เท่านั้น หากคุณใช้โมดูล " "ODBC คุณต้องสำรองข้อมูลของฐานข้อมูล SQL แยกต่างหากด้วย" -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "จัดเก็บข้อมูลสำรองแบบไบนารี:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "ตกลง" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "คืนค่าข้อมูลสำรองแบบไบนารีโดยทันที:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "คืนค่าข้อมูลสำรองแบบไบนารีหลังจากที่ ejabberd ถัดไปเริ่มการทำงานใหม่ (ใช้หน่วยความจำน้อยลง):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "จัดเก็บข้อมูลสำรองที่เป็นข้อความธรรมดา:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "คืนค่าข้อมูลสำรองที่เป็นข้อความธรรมดาโดยทันที:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "อิมพอร์ตผู้ใช้จากไฟล์เก็บพักข้อมูล jabberd14" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "อิมพอร์ตผู้ใช้จากไฟล์เก็บพักข้อมูล jabberd14" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "พอร์ทฟังที่" -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "โมดูลที่ " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "สถิติของ ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "เวลาการทำงานต่อเนื่อง:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "เวลาการทำงานของ CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "ทรานแซกชันที่ได้รับมอบหมาย:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "ทรานแซกชันที่ถูกยกเลิก:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "ทรานแซกชันที่เริ่มทำงานใหม่อีกครั้ง:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "ทรานแซกชันที่บันทึก:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "อัพเดต " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "แผนการอัพเดต" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "โมดูลที่อัพเดต" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "อัพเดตสคริปต์" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "อัพเดตสคริปต์ระดับต่ำ" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "ตรวจสอบคริปต์" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "พอร์ท" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "พอร์ท" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "โมดูล" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "ตัวเลือก" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "เริ่ม" @@ -788,8 +793,8 @@ msgstr "กฎการเข้าถึง" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -806,31 +811,31 @@ msgstr "จำนวนผู้ใช้ที่ลงทะเบียน" msgid "Number of online users" msgstr "จำนวนผู้ใช้ออนไลน์" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "การเข้าสู่ระบบครั้งล่าสุด" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "ขนาดของบัญชีรายชื่อ" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "ที่อยู่ IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "ทรัพยากร" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "การดูแล " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "การดำเนินการกับผู้ใช้" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "แก้ไขคุณสมบัติ" @@ -840,38 +845,50 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "การเข้าถึงถูกปฏิเสธโดยนโยบายการบริการ" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "การส่ง IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC module" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดการตั้งค่า mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "การลงทะเบียนใน mod_irc สำหรับ" -#: mod_irc.erl:651 +#: mod_irc.erl:659 #, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "ป้อนชื่อผู้ใช้และการเข้ารหัสที่คุณต้องการใช้สำหรับเชื่อมต่อกับเซิร์ฟเวอร์ IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "ชื่อผู้ใช้ IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 #, fuzzy msgid "" "If you want to specify different ports, passwords, encodings for IRC " @@ -883,7 +900,7 @@ msgstr "" "server\", \"encoding\"}' ลงในรายการ การบริการนี้ใช้การเข้ารหัสในรูปแบบ \"~s\" " "โดยค่าดีฟอลต์ " -#: mod_irc.erl:696 +#: mod_irc.erl:704 #, fuzzy msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." @@ -892,36 +909,36 @@ msgstr "" "ตัวอย่าง: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", " "\"iso8859-1\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" -#: mod_irc.erl:891 +#: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "ชื่อผู้ใช้ IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 #, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " @@ -929,52 +946,82 @@ msgid "" "settings." msgstr "ป้อนชื่อผู้ใช้และการเข้ารหัสที่คุณต้องการใช้สำหรับเชื่อมต่อกับเซิร์ฟเวอร์ IRC" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "ชื่อผู้ใช้ IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "รหัสผ่าน" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "พอร์ท" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "ผู้ดูแลด้านการบริการเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความการบริการ" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "การสร้างห้องสนทนาถูกปฏิเสธโดยนโยบายการบริการ" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "ไม่มีห้องประชุม" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "ห้องสนทนา" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อลงทะเบียนชื่อเล่น" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "การลงทะเบียนชื่อเล่นที่ " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "ป้อนชื่อเล่นที่คุณต้องการลงทะเบียน" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "ชื่อเล่น" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#, fuzzy +msgid "That nickname is registered by another person" +msgstr "ชื่อเล่นถูกลงทะเบียนใช้งานโดยบุคคลอื่น" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "คุณต้องกรอกฟิลด์ \"Nickname\" ในแบบฟอร์ม" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC module" @@ -1002,370 +1049,504 @@ msgstr "ผู้ใช้ที่ลงทะเบียน" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "มีการปรับเปลี่ยนการกำหนดค่าของห้องสนทนา" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "เข้าห้องสนทนานี้" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "ออกจากห้อง" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "ถูกสั่งห้าม" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "ซึ่งรู้จักกันในชื่อ" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " ตั้งหัวข้อว่า: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "ห้องสนทนา" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "วันจันทร์" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "วันอังคาร" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "วันพุธ" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "วันพฤหัสบดี" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "วันศุกร์" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "วันเสาร์" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "วันอาทิตย์" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "มกราคม" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "กุมภาพันธ์" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "มีนาคม" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "เมษายน" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "พฤษภาคม" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "มิถุนายน" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "กรกฎาคม" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "สิงหาคม" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "กันยายน" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "ตุลาคม" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "พฤศจิกายน" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "ธันวาคม" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "การกำหนดค่าห้องสนทนา" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 #, fuzzy msgid "Room Occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "อัตราของปริมาณการเข้าใช้เกินขีดจำกัด" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยังห้องประชุม" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "ประเภทข้อความไม่เหมาะสม" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยัง \"กลุ่มสนทนา\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "ผู้รับไม่ได้อยู่ในห้องประชุม" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +#, fuzzy +msgid "It is not allowed to send private messages" +msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยังห้องประชุม" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความไปยังห้องประชุม" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งกระทู้ถามไปยังห้องประชุม" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "ห้องนี้ไม่อนุญาตให้ส่งกระทู้ถามถึงสมาชิกในห้องประชุม" + +#: mod_muc_room.erl:961 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "ผู้ดูแลการสนทนาและผู้เข้าร่วมเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด" + +#: mod_muc_room.erl:1080 +#, fuzzy +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +#, fuzzy +msgid "That nickname is already in use by another occupant" +msgstr "ชื่อเล่นถูกใช้งานอยู่โดยผู้ครอบครองห้อง" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "คุณถูกสั่งห้ามไมให้เข้าห้องนี้" + +#: mod_muc_room.erl:1826 +#, fuzzy +msgid "Membership is required to enter this room" +msgstr "ต้องเป็นสมาชิกจึงจะสามารถเข้าห้องนี้ได้" + +#: mod_muc_room.erl:1872 +#, fuzzy +msgid "A password is required to enter this room" +msgstr "ต้องใส่รหัสผ่านเพื่อเข้าห้องนี้" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "รหัสผ่านไม่ถูกต้อง" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "ต้องมีสิทธิพิเศษของผู้ดูแลระบบ" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "ต้องมีสิทธิพิเศษของผู้ดูแลการสนทนา" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s ไม่ถูกต้อง" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "ไม่มีชื่อเล่น ~s อยู่ในห้องนี้" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "การเข้าร่วมที่ไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "บทบาทไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "ต้องมีสิทธิพิเศษของเจ้าของ" + +#: mod_muc_room.erl:3348 #, fuzzy msgid "Configuration of room ~s" msgstr "การกำหนดค่าสำหรับ " -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "ชื่อห้อง" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "รายละเอียด:" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "สร้างเป็นห้องถาวร" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "สร้างเป็นห้องที่บุคคลทั่วไปสามารถค้นหาได้" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "สร้างรายการผู้เข้าร่วมสำหรับใช้งานโดยบุคคลทั่วไป" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "สร้างห้องที่มีการป้องกันด้วยรหัสผ่าน" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "จำนวนผู้ครอบครองห้องสูงสุด" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "ไม่จำกัด" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "แสดง Jabber IDs ที่ถูกต้องแก่" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "สำหรับผู้ดูแลการสนทนาเท่านั้น" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "ทุกคน" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "สำหรับผู้ดูแลการสนทนาเท่านั้น" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "สร้างห้องสำหรับสมาชิกเท่านั้น" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 #, fuzzy msgid "Make room moderated" msgstr "สร้างเป็นห้องถาวร" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "ผู้ใช้เริ่มต้นเป็นผู้เข้าร่วม" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 #, fuzzy msgid "Allow users to change the subject" msgstr "อนุญาตให้ผู้ใช้เปลี่ยนหัวข้อได้" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "อนุญาตให้ผู้ใช้ถามคำถามกับผู้ใช้คนอื่นๆ ได้" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "อนุญาตให้ผู้ใช้ส่งข้อความส่วนตัว" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 #, fuzzy msgid "Allow visitors to change nickname" msgstr "อนุญาตให้ผู้ใช้เปลี่ยนหัวข้อได้" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "อนุญาตให้ผู้ใช้ส่งคำเชิญถึงกันได้" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "สร้างห้องที่มีการป้องกันด้วยรหัสผ่าน" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "เปิดใช้งานการบันทึก" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดค่าห้องสนทนา " -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "ส่วนตัว, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "ผู้ใช้" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s เชิญคุณเข้าร่วมสนทนาในห้อง ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "รหัสผ่านคือ" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "ลำดับข้อความออฟไลน์ของผู้ที่ติดต่อของคุณเต็มแล้ว ข้อความถูกลบทิ้งแล้ว" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s's ลำดับข้อความออฟไลน์" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "เวลา" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "จาก" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "ถึง" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "แพ็กเก็ต" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "ข้อความออฟไลน์:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "ข้อความออฟไลน์" @@ -1374,116 +1555,130 @@ msgstr "ข้อความออฟไลน์" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams module" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "เผยแพร่-สมัครเข้าใช้งาน" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe module" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "คำร้องขอของผู้สมัครเข้าใช้งาน PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "เลือกว่าจะอนุมัติการสมัครเข้าใช้งานของเอนทิตี้นี้หรือไม่" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID โหนด" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "ที่อยู่ของผู้สมัคร" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "อนุญาตให้ Jabber ID นี้เข้าร่วมเป็นสมาชิกของโหนด pubsub หรือไม่" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "ส่งส่วนของข้อมูล (payload) พร้อมกับการแจ้งเตือนเหตุการณ์" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "ส่งการแจ้งเตือนเหตุการณ์" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "แจ้งเตือนผู้สมัครสมาชิกเมื่อการกำหนดค่าโหนดเปลี่ยนแปลง" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "แจ้งเตือนผู้สมัครสมาชิกเมื่อโหนดถูกลบ" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "แจ้งเตือนผู้สมัครสมาชิกเมื่อรายการถูกลบออกจากโหนด" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "ยืนยันรายการที่จะจัดเก็บ" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "จำนวนสูงสุดของรายการที่ยืนยัน" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "อนุญาตให้เข้าร่วมเป็นสมาชิกหรือไม่" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "ระบุโมเดลการเข้าถึง" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "ระบุโมเดลผู้เผยแพร่" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "ระบุโมเดลการเข้าถึง" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "ขนาดสูงสุดของส่วนของข้อมูล (payload) มีหน่วยเป็นไบต์" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "เวลาที่ส่งรายการที่เผยแพร่ครั้งล่าสุด" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "ส่งการแจ้งเตือนถึงผู้ใช้ที่สามารถติดต่อได้เท่านั้น" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "" + +#: mod_register.erl:253 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อลงทะเบียนชื่อเล่น" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "เลือกชื่อผู้ใช้และรหัสผ่านเพื่อลงทะเบียนกับเซิร์ฟเวอร์นี้" +#: mod_register.erl:373 mod_register.erl:421 +#, fuzzy +msgid "The password is too weak" +msgstr "รหัสผ่านคือ" + +#: mod_register.erl:426 +#, fuzzy +msgid "Users are not allowed to register accounts so quickly" +msgstr "ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1557,8 +1752,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1596,60 +1791,60 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "การสมัครสมาชิก" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "ค้างอยู่" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "กลุ่ม" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "ตรวจสอบ" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "ลบ" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "บัญชีรายชื่อของ " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "เพิ่ม Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "บัญชีรายชื่อ" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "กลุ่มบัญชีรายชื่อที่ใช้งานร่วมกัน" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "ชื่อ:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "รายละเอียด:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "สมาชิก:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "กลุ่มที่แสดง:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "กลุ่ม" @@ -1725,106 +1920,15 @@ msgstr "ผลการค้นหาสำหรับ " msgid "Fill in fields to search for any matching Jabber User" msgstr "กรอกข้อมูลลงในฟิลด์เพื่อค้นหาผู้ใช้ Jabber ที่ตรงกัน" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "เซิร์ฟเวอร์ s2s ขาออก:" + #~ msgid "Delete" #~ msgstr "ลบ" #~ msgid "This room is not anonymous" #~ msgstr "ห้องนี้ไม่ปิดบังชื่อ" -#~ msgid "Access denied by service policy" -#~ msgstr "การเข้าถึงถูกปฏิเสธโดยนโยบายการบริการ" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "ผู้ดูแลด้านการบริการเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความการบริการ" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "การสร้างห้องสนทนาถูกปฏิเสธโดยนโยบายการบริการ" - -#~ msgid "Conference room does not exist" -#~ msgstr "ไม่มีห้องประชุม" - -#, fuzzy -#~ msgid "That nickname is registered by another person" -#~ msgstr "ชื่อเล่นถูกลงทะเบียนใช้งานโดยบุคคลอื่น" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "คุณต้องกรอกฟิลด์ \"Nickname\" ในแบบฟอร์ม" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "อัตราของปริมาณการเข้าใช้เกินขีดจำกัด" - -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยังห้องประชุม" - -#~ msgid "Improper message type" -#~ msgstr "ประเภทข้อความไม่เหมาะสม" - -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยัง \"กลุ่มสนทนา\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "ผู้รับไม่ได้อยู่ในห้องประชุม" - -#, fuzzy -#~ msgid "It is not allowed to send private messages" -#~ msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยังห้องประชุม" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความไปยังห้องประชุม" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งกระทู้ถามไปยังห้องประชุม" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "ห้องนี้ไม่อนุญาตให้ส่งกระทู้ถามถึงสมาชิกในห้องประชุม" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด" - -#, fuzzy -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" - -#, fuzzy -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "ชื่อเล่นถูกใช้งานอยู่โดยผู้ครอบครองห้อง" - -#~ msgid "You have been banned from this room" -#~ msgstr "คุณถูกสั่งห้ามไมให้เข้าห้องนี้" - -#, fuzzy -#~ msgid "Membership is required to enter this room" -#~ msgstr "ต้องเป็นสมาชิกจึงจะสามารถเข้าห้องนี้ได้" - -#, fuzzy -#~ msgid "A password is required to enter this room" -#~ msgstr "ต้องใส่รหัสผ่านเพื่อเข้าห้องนี้" - -#~ msgid "Incorrect password" -#~ msgstr "รหัสผ่านไม่ถูกต้อง" - -#~ msgid "Administrator privileges required" -#~ msgstr "ต้องมีสิทธิพิเศษของผู้ดูแลระบบ" - -#~ msgid "Moderator privileges required" -#~ msgstr "ต้องมีสิทธิพิเศษของผู้ดูแลการสนทนา" - -#~ msgid "Owner privileges required" -#~ msgstr "ต้องมีสิทธิพิเศษของเจ้าของ" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "ลำดับข้อความออฟไลน์ของผู้ที่ติดต่อของคุณเต็มแล้ว ข้อความถูกลบทิ้งแล้ว" - -#, fuzzy -#~ msgid "The password is too weak" -#~ msgstr "รหัสผ่านคือ" - -#, fuzzy -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "ผู้เยี่ยมเยือนไม่ได้รับอนุญาตให้ส่งข้อความถึงผู้ครอบครองห้องทั้งหมด" - #~ msgid "Encodings" #~ msgstr "การเข้ารหัส" diff --git a/priv/msgs/tr.msg b/priv/msgs/tr.msg index dd4927eec31..356d245e3d8 100644 --- a/priv/msgs/tr.msg +++ b/priv/msgs/tr.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Erişim Kontrol Listelerinin Ayarlanması (ACL)"}. {"Access control lists","Erişim kontrol listeleri (ACL)"}. {"Access Control Lists","Erişim Kontrol Listeleri (ACL)"}. +{"Access denied by service policy","Servis politikası gereği erişim engellendi"}. {"Access rules","Erişim kuralları"}. {"Access Rules","Erişim Kuralları"}. {"Action on user","Kullanıcıya uygulanacak eylem"}. @@ -11,6 +12,7 @@ {"Add User","Kullanıcı Ekle"}. {"Administration of ","Yönetim : "}. {"Administration","Yönetim"}. +{"Administrator privileges required","Yönetim yetkileri gerekli"}. {"A friendly name for the node","Düğüm için dostane bir isim"}. {"All activity","Tüm aktivite"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Bu Jabber ID bu pubsub düğümüne üye olmasına izin verilsin mi?"}. @@ -25,6 +27,7 @@ {"All Users","Tüm Kullanıcılar"}. {"Announcements","Duyurular"}. {"anyone","herkes"}. +{"A password is required to enter this room","Bu odaya girmek için parola gerekiyor"}. {"April","Nisan"}. {"August","Ağustos"}. {"Backup Management","Yedek Yönetimi"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","Bu varlığın üyeliğini onaylayıp onaylamamayı seçiniz."}. {"City","İl"}. {"Commands","Komutlar"}. +{"Conference room does not exist","Konferans odası bulunamadı"}. {"Configuration","Ayarlar"}. {"Configuration of room ~s","~s odasının ayarları"}. {"Connected Resources:","Bağlı Kaynaklar:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","CAPTCHA doğrulamasını şu Jabber ID'ler için yapma"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Sunucudaki tüm kullanıcıların verisini PIEFXIS dosyalarına (XEP-0227) dışa aktar:"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Bir sunucudaki kullanıcıların verisini PIEFXIS dosyalarına (XEP-0227) dışa aktar:"}. +{"Failed to extract JID from your voice request approval","Ses isteği onayınızdan JID bilginize ulaşılamadı"}. {"Family Name","Soyisim"}. {"February","Şubat"}. {"Fill in fields to search for any matching Jabber User","Eşleşen jabber kullanıcılarını aramak için alanları doldurunuz"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","Jabberd 1.4 Spool Dizininden Kullanıcıları İçe Aktar:"}. {"Import Users from Dir at ","Dizinden Kullanıcıları İçe Aktar : "}. {"Import Users From jabberd14 Spool Files","Jabberd 1.4 Spool Dosyalarından Kullanıcıları İçeri Aktar"}. +{"Improper message type","Uygunsuz mesaj tipi"}. +{"Incorrect password","Yanlış parola"}. {"Invalid affiliation: ~s","Geçersiz ilişki: ~s"}. {"Invalid role: ~s","Geçersiz rol: ~s"}. {"IP addresses","IP adresleri"}. @@ -142,6 +149,9 @@ {"IRC username","IRC kullanıcı ismi"}. {"IRC Username","IRC Kullanıcı İsmi"}. {"is now known as","isim değiştirdi :"}. +{"It is not allowed to send private messages of type \"groupchat\"","\"groupchat\" tipinde özel mesajlar gönderilmesine izin verilmiyor"}. +{"It is not allowed to send private messages","Özel mesaj gönderilmesine izin verilmiyor"}. +{"It is not allowed to send private messages to the conference","Konferansa özel mesajlar gönderilmesine izin verilmiyor"}. {"Jabber Account Registration","Jabber Hesap Kaydı"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s geçersiz"}. @@ -173,12 +183,14 @@ {"Max # of items to persist","Kalıcı hale getirilecek en fazla öğe sayısı"}. {"Max payload size in bytes","En fazla yük (payload) boyutu (bayt olarak)"}. {"May","Mayıs"}. +{"Membership is required to enter this room","Bu odaya girmek için üyelik gerekiyor"}. {"Members:","Üyeler:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Parolanızı ezberleyin ya da bir kağıda yazarak güvenli bir yerde saklayın. Jabber'da parolanızı unutursanız, otomatik kurtarmak için bir yöntem bulunmuyor."}. {"Memory","Bellek"}. {"Message body","Mesajın gövdesi"}. {"Middle Name","Ortanca İsim"}. {"Minimum interval between voice requests (in seconds)","Ses istekleri arasında olabilecek en az aralık (saniye olarak)"}. +{"Moderator privileges required","Moderatör yetkileri gerekli"}. {"moderators only","sadece moderatörler"}. {"Modified modules","Değişen modüller"}. {"Module","Modül"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","Uyarıları sadece durumu uygun kullanıcılara ulaştır"}. {"Only moderators and participants are allowed to change the subject in this room","Sadece moderatörlerin ve katılımcıların bu odanın konusunu değiştirmesine izin veriliyor"}. {"Only moderators are allowed to change the subject in this room","Sadece moderatörlerin bu odanın konusunu değiştirmesine izin veriliyor"}. +{"Only moderators can approve voice requests","Yalnız moderatörler ses isteklerini onaylayabilir"}. +{"Only occupants are allowed to send messages to the conference","Sadece oda sakinlerinin konferansa mesaj göndermesine izin veriliyor"}. +{"Only occupants are allowed to send queries to the conference","Sadece oda sakinlerinin konferansa sorgu göndermesine izin veriliyor"}. +{"Only service administrators are allowed to send service messages","Sadece servis yöneticileri servis mesajı gönderebilirler"}. {"Options","Seçenekler"}. {"Organization Name","Kurum İsmi"}. {"Organization Unit","Kurumun İlgili Birimi"}. {"Outgoing s2s Connections:","Giden s2s Bağlantıları:"}. {"Outgoing s2s Connections","Giden s2s Bağlantıları"}. -{"Outgoing s2s Servers:","Giden s2s Sunucuları"}. +{"Owner privileges required","Sahip yetkileri gerekli"}. {"Packet","Paket"}. {"Password ~b","Parola ~b"}. {"Password:","Parola:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","Öğeleri depoda kalıcı hale getir"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Bu seçeneklerin sadece gömülü Mnesia veritabanını yedekleyeceğine dikkat edin. Eğer ODBC modülünü kullanıyorsanız, SQL veritabanınızı da ayrıca yedeklemeniz gerekiyor."}. +{"Please, wait for a while before sending new voice request","Lütfen yeni bir ses isteği göndermeden önce biraz bekleyin"}. {"Pong","Pong"}. {"Port ~b","Kapı (Port) ~b"}. {"Port","Kapı (Port)"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","Yayınla-Üye Ol"}. {"PubSub subscriber request","PubSub üye isteği"}. {"Purge all items when the relevant publisher goes offline","İlgili yayıncı çevirimdışı olunca tüm onunla ilgili olanları sil"}. +{"Queries to the conference members are not allowed in this room","Bu odada konferans üyelerine sorgu yapılmasına izin verilmiyor"}. {"RAM and disc copy","RAM ve disk kopyala"}. {"RAM copy","RAM kopyala"}. {"Raw","Ham"}. {"Really delete message of the day?","Günün mesajını silmek istediğinize emin misiniz?"}. +{"Recipient is not in the conference room","Alıcı konferans odasında değil"}. {"Register a Jabber account","Bir Jabber hesabı kaydet"}. {"Registered Users:","Kayıtlı Kullanıcılar:"}. {"Registered Users","Kayıtlı Kullanıcılar"}. @@ -270,6 +289,7 @@ {"Restore plain text backup immediately:","Hemen düz metin yedekten geri al"}. {"Restore","Yedekten Geri Al"}. {"Room Configuration","Oda Ayarları"}. +{"Room creation is denied by service policy","Odanın oluşturulması servis politikası gereği reddedildi"}. {"Room description","Oda tanımı"}. {"Room Occupants","Oda Sakini Sayısı"}. {"Room title","Oda başlığı"}. @@ -298,7 +318,7 @@ {"Show Ordinary Table","Sıradan Tabloyu Göster"}. {"Shut Down Service","Servisi Kapat"}. {"~s invites you to the room ~s","~s sizi ~s odasına davet ediyor"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Bazı Jabber istemcileri parolanızı bilgisayarınızda saklayabilir. Bu özelliği ancak bilgisayarın güvenli olduğuna güveniyorsanız kullanın."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Bazı Jabber istemcileri parolanızı bilgisayarınızda saklayabilir. Bu özelliği ancak bilgisayarın güvenli olduğuna güveniyorsanız kullanın."}. {"Specify the access model","Erişim modelini belirtiniz"}. {"Specify the event message type","Olay mesaj tipini belirtiniz"}. {"Specify the publisher model","Yayıncı modelini belirtiniz"}. @@ -321,9 +341,13 @@ {"Subscriber Address","Üye Olanın Adresi"}. {"Subscription","Üyelik"}. {"Sunday","Pazar"}. +{"That nickname is already in use by another occupant","Takma isim odanın başka bir sakini tarafından halihazırda kullanımda"}. +{"That nickname is registered by another person","O takma isim başka biri tarafından kaydettirilmiş"}. {"The CAPTCHA is valid.","İnsan doğrulaması (captcha) geçerli."}. +{"The CAPTCHA verification has failed","CAPTCHA doğrulaması başarısız oldu"}. {"The collections with which a node is affiliated","Bir düğüm ile bağlantılı koleksiyonlar"}. {"the password is","parola :"}. +{"The password is too weak","Parola çok zayıf"}. {"The password of your Jabber account was successfully changed.","Jabber hesabınızın parolası başarıyla değiştirildi."}. {"There was an error changing the password: ","Parolanın değiştirilmesi sırasında bir hata oluştu:"}. {"There was an error creating the account: ","Hesap oluşturulurken bir hata oluştu:"}. @@ -335,12 +359,15 @@ {"Time delay","Zaman gecikmesi"}. {"Time","Zaman"}. {"To","Kime"}. +{"Too many CAPTCHA requests","Çok fazla CAPTCHA isteği"}. {"To ~s","Kime ~s"}. +{"Traffic rate limit is exceeded","Trafik oran sınırı aşıldı"}. {"Transactions Aborted:","İptal Edilen Hareketler (Transactions):"}. {"Transactions Committed:","Tamamlanan Hareketler (Transactions Committed):"}. {"Transactions Logged:","Kaydı Tutulan Hareketler (Transactions):"}. {"Transactions Restarted:","Tekrar Başlatılan Hareketler (Transactions):"}. {"Tuesday","Salı"}. +{"Unable to generate a CAPTCHA","İnsan doğrulaması (CAPTCHA) oluşturulamadı"}. {"Unauthorized","Yetkisiz"}. {"Unregister a Jabber account","Bir Jabber hesabı kaydı sil"}. {"Unregister","Kaydı Sil"}. @@ -355,21 +382,29 @@ {"User","Kullanıcı"}. {"User Management","Kullanıcı Yönetimi"}. {"Username:","Kullanıcı adı:"}. +{"Users are not allowed to register accounts so quickly","Kullanıcıların bu kadar hızlı hesap açmalarına izin verilmiyor"}. {"Users","Kullanıcılar"}. {"Users Last Activity","Kullanıcıların Son Aktiviteleri"}. {"Validate","Geçerli"}. {"vCard User Search","vCard Kullanıcı Araması"}. {"Virtual Hosts","Sanal Sunucuları"}. +{"Visitors are not allowed to change their nicknames in this room","Bu odada ziyaretçilerin takma isimlerini değiştirmesine izin verilmiyor"}. +{"Visitors are not allowed to send messages to all occupants","Ziyaretçilerin odadaki tüm sakinlere mesaj göndermesine izin verilmiyor"}. +{"Voice requests are disabled in this conference","Bu konferansta ses istekleri etkisizleştirilmiş durumda."}. {"Voice request","Ses isteği"}. {"Wednesday","Çarşamba"}. {"When to send the last published item","Son yayınlanan öğe ne zaman gönderilsin"}. {"Whether to allow subscriptions","Üyeliklere izin verilsin mi"}. {"You can later change your password using a Jabber client.","Parolanızı daha sonra bir Jabber istemci kullanarak değiştirebilirsiniz."}. +{"You have been banned from this room","Bu odaya girmeniz yasaklandı"}. +{"You must fill in field \"Nickname\" in the form","Formda \"Takma isim\" alanını doldurmanız gerekiyor"}. {"You need a client that supports x:data and CAPTCHA to register","Takma isminizi kaydettirmek için x:data ve CAPTCHA destekleyen bir istemciye gereksinimiz var"}. {"You need a client that supports x:data to register the nickname","Takma isminizi kaydettirmek için x:data destekleyen bir istemciye gereksinimiz var"}. {"You need an x:data capable client to configure mod_irc settings","mod_irc ayarlarını düzenlemek için x:data becerisine sahip bir istemciye gereksinimiz var"}. {"You need an x:data capable client to configure room","Odayı ayarlamak için x:data becerisine sahip bir istemciye gereksinimiz var"}. {"You need an x:data capable client to search","Arama yapabilmek için x:data becerisine sahip bir istemciye gereksinimiz var"}. +{"Your active privacy list has denied the routing of this stanza.","Etkin mahremiyet listeniz bu bölümün yönlendirilmesini engelledi."}. +{"Your contact offline message queue is full. The message has been discarded.","Çevirim-dışı mesaj kuyruğunuz dolu. Mesajını dikkate alınmadı."}. {"Your Jabber account was successfully created.","Jabber hesabınız başarıyla oluşturuldu."}. {"Your Jabber account was successfully deleted.","Jabber hesabınız başarıyla silindi."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","~s kullanıcısına mesajlarınız engelleniyor. Durumu düzeltmek için ~s adresini ziyaret ediniz."}. diff --git a/priv/msgs/tr.po b/priv/msgs/tr.po index 1c976864a13..52ae45c1822 100644 --- a/priv/msgs/tr.po +++ b/priv/msgs/tr.po @@ -13,52 +13,56 @@ msgstr "" "X-Language: Turkish (türkçe)\n" "X-Generator: KBabel 1.11.4\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "STARTTLS kullanımı gereklidir" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Hiç kaynak sağlanmadı" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Eski bağlantı yenisi ile değiştirildi" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "odadan atıldı" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Etkin mahremiyet listeniz bu bölümün yönlendirilmesini engelledi." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Gördüğünüz metni giriniz" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" "~s kullanıcısına mesajlarınız engelleniyor. Durumu düzeltmek için ~s " "adresini ziyaret ediniz." -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" "Eğer burada CAPTCHA resmini göremiyorsanız, web sayfasını ziyaret edin." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "CAPTCHA web sayfası" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "İnsan doğrulaması (captcha) geçerli." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Kullanıcı" @@ -67,9 +71,9 @@ msgstr "Kullanıcı" msgid "Server" msgstr "Sunucu:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Parola" @@ -86,279 +90,280 @@ msgstr "Yetkisiz" msgid "ejabberd Web Admin" msgstr "ejabberd Web Yöneticisi" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Yönetim" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Erişim Kontrol Listeleri (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Gönderilenler" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Kötü biçem" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Gönder" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Ham" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Seçilenleri Sil" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Erişim Kuralları" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s erişim kuralları ayarları" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Sanal Sunucuları" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Kullanıcılar" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Bağlı Kullanıcılar" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Kullanıcıların Son Aktiviteleri" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Periyot:" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Geçen ay" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Geçen yıl" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tüm aktivite" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Sıradan Tabloyu Göster" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Önemli Tabloyu Göster" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "İstatistikler" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "Bulunamadı" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Düğüm bulunamadı" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Yeni Ekle" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Sunucu" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Kayıtlı Kullanıcılar" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Kullanıcı Ekle" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Çevirim-dışı Mesajlar" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Son Aktivite" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Asla" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Bağlı" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Kayıtlı Kullanıcılar:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Bağlı Kullanıcılar:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Giden s2s Bağlantıları:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Giden s2s Sunucuları" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Giden s2s Bağlantıları:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Hiçbiri" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Parola Değiştir" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Kullanıcı " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Bağlı Kaynaklar:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Parola:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Kullanıcıyı Kaldır" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Veri Yok" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Düğümler" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Çalışan Düğümler" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Durdurulmuş Düğümler" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Düğüm " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Veritabanı" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Yedekle" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Dinlenen Kapılar (Portlar)" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "GÜncelle" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Tekrar Başlat" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Durdur" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modüller" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC Çağrı Hatası" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Veritabanı Tabloları : " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "İsim" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Depolama Tipi" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Elementler" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Bellek" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Hata" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Yedek : " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -368,149 +373,149 @@ msgstr "" "edin. Eğer ODBC modülünü kullanıyorsanız, SQL veritabanınızı da ayrıca " "yedeklemeniz gerekiyor." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "İkili yedeği sakla:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Tamam" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Hemen ikili yedekten geri al:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "ejabberd'nin bir sonraki tekrar başlatılışında ikili yedekten geri al (daha " "az bellek gerektirir)" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Düz metin yedeği sakla:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Hemen düz metin yedekten geri al" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Kullanıcıları bir PIEFXIS dosyasından (XEP-0227) içe aktar:" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" "Sunucudaki tüm kullanıcıların verisini PIEFXIS dosyalarına (XEP-0227) dışa " "aktar:" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" "Bir sunucudaki kullanıcıların verisini PIEFXIS dosyalarına (XEP-0227) dışa " "aktar:" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Jabberd 1.4 Spool Dosyalarından Kullanıcıları İçe Aktar:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Jabberd 1.4 Spool Dizininden Kullanıcıları İçe Aktar:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Dinlenen Kapılar (Portlar) : " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Modüller : " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "~p istatistikleri" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Hizmet Süresi:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "İşlemci Zamanı:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Tamamlanan Hareketler (Transactions Committed):" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "İptal Edilen Hareketler (Transactions):" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Tekrar Başlatılan Hareketler (Transactions):" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Kaydı Tutulan Hareketler (Transactions):" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Güncelle " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Planı güncelle" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Değişen modüller" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Betiği Güncelle" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Düşük seviye güncelleme betiği" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Betik kontrolü" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Kapı (Port)" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Protokol" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Modül" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Seçenekler" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Başlat" @@ -796,8 +801,8 @@ msgstr "Erişim kuralları" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -814,31 +819,31 @@ msgstr "Kayıtlı kullanıcı sayısı" msgid "Number of online users" msgstr "Bağlı kullanıcı sayısı" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Son giriş" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "İsim listesi boyutu" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP adresleri" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Kaynaklar" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Yönetim : " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Kullanıcıya uygulanacak eylem" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Özellikleri Düzenle" @@ -848,29 +853,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Servis politikası gereği erişim engellendi" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Nakli (Transport)" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC modülü" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "mod_irc ayarlarını düzenlemek için x:data becerisine sahip bir istemciye " "gereksinimiz var" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "mod_irc'ye kayıt : " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -878,11 +895,11 @@ msgstr "" "IRC sunuculara bağlanmak için kullanmak istediğiniz kullanıcı ismi, " "kodlamalar, kapılar (portlar) ve parolaları giriniz" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC Kullanıcı İsmi" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -894,7 +911,7 @@ msgstr "" "\"}' biçeminde değerlerle bu listeyi doldurunuz. Öntanımlı olarak bu servis " "\"~s\" kodlamasını, ~p \"kapısını\", \"boş\" parolasını kullanıyor." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -902,35 +919,35 @@ msgstr "" "Örnek: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"gizli\"}, {\"vendetta.fef.net" "\", \"iso8859-1\", 7000}], {\"irc.sometestserver.net\", \"utf-8\"}]" -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Bağlantı parametreleri" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "IRC kanalına katıl" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC kanalı (ilk # işaretini koymayın)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC sunucusu" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Buradaki IRC kanalına katıl." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "IRC kanalına bu Jabber ID'si ile katıl: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC ayarları" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -940,50 +957,79 @@ msgstr "" "kodlamaları giriniz. 'İleri' tuşuna basınca karşınıza dolduracak daha fazla " "alan çıkacak. 'Tamamla' tuşuna basarak ayarları kaydedin." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC kullanıcı ismi" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Parola ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Kapı (Port) ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Sunucu için kodlama ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Sunucu ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Sadece moderatörlerin bu odanın konusunu değiştirmesine izin veriliyor" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Sadece servis yöneticileri servis mesajı gönderebilirler" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Odanın oluşturulması servis politikası gereği reddedildi" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Konferans odası bulunamadı" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Sohbet Odaları" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Takma isminizi kaydettirmek için x:data destekleyen bir istemciye " "gereksinimiz var" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Takma İsim Kaydı : " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Kaydettirmek istediğiniz takma ismi giriniz" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Takma isim" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "O takma isim başka biri tarafından kaydettirilmiş" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Formda \"Takma isim\" alanını doldurmanız gerekiyor" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC modülü" @@ -1011,143 +1057,201 @@ msgstr "Kayıtlı Kullanıcılar" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Sohbet odası ayarı değiştirildi" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "odaya katıldı" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "odadan ayrıldı" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "odaya girmesi yasaklandı" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "ilişki değişikliğinden dolayı atıldı" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "oda üyelere-özel hale getirildiğinden dolayı atıldı" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "sistem kapandığından dolayı atıldı" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "isim değiştirdi :" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " konuyu değiştirdi: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Sohbet odası oluşturuldu" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Sohbet odası kaldırıldı" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Sohbet odası başlatıldı" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Sohbet odası durduruldu" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Pazartesi" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Salı" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Çarşamba" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Perşembe" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Cuma" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Cumartesi" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Pazar" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Ocak" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Şubat" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Mart" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Nisan" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Mayıs" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Haziran" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Temmuz" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Ağustos" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Eylül" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Ekim" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Kasım" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Aralık" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Oda Ayarları" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Oda Sakini Sayısı" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Trafik oran sınırı aşıldı" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Konferansa özel mesajlar gönderilmesine izin verilmiyor" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "Lütfen yeni bir ses isteği göndermeden önce biraz bekleyin" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "Bu konferansta ses istekleri etkisizleştirilmiş durumda." + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "Ses isteği onayınızdan JID bilginize ulaşılamadı" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "Yalnız moderatörler ses isteklerini onaylayabilir" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Uygunsuz mesaj tipi" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "\"groupchat\" tipinde özel mesajlar gönderilmesine izin verilmiyor" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Alıcı konferans odasında değil" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Özel mesaj gönderilmesine izin verilmiyor" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Sadece oda sakinlerinin konferansa mesaj göndermesine izin veriliyor" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Sadece oda sakinlerinin konferansa sorgu göndermesine izin veriliyor" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Bu odada konferans üyelerine sorgu yapılmasına izin verilmiyor" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1155,214 +1259,286 @@ msgstr "" "Sadece moderatörlerin ve katılımcıların bu odanın konusunu değiştirmesine " "izin veriliyor" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Sadece moderatörlerin bu odanın konusunu değiştirmesine izin veriliyor" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "" +"Ziyaretçilerin odadaki tüm sakinlere mesaj göndermesine izin verilmiyor" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "" +"Bu odada ziyaretçilerin takma isimlerini değiştirmesine izin verilmiyor" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Takma isim odanın başka bir sakini tarafından halihazırda kullanımda" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Bu odaya girmeniz yasaklandı" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "Bu odaya girmek için üyelik gerekiyor" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Bu odaya girmek için parola gerekiyor" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Çok fazla CAPTCHA isteği" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "İnsan doğrulaması (CAPTCHA) oluşturulamadı" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Yanlış parola" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Yönetim yetkileri gerekli" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Moderatör yetkileri gerekli" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s geçersiz" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "~s takma ismi odada yok" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Geçersiz ilişki: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Geçersiz rol: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Sahip yetkileri gerekli" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "~s odasının ayarları" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Oda başlığı" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Oda tanımı" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Odayı kalıcı hale getir" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Odayı herkes tarafından aranabilir hale getir" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Katılımcı listesini herkese açık hale getir" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Odayı parola korumalı hale getir" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Odada En Fazla Bulunabilecek Kişi Sayısı" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Sınırsız" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Gerçek Jabber ID'lerini göster :" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "sadece moderatörler" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "herkes" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "sadece moderatörler" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Odayı sadece üyelere açık hale getir" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Odayı moderasyonlu hale getir" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Kullanıcılar öntanımlı olarak katılımcı olsun" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Kullanıcıların konu değiştirmesine izin ver" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Kullanıcıların özel mesaj göndermelerine izin ver" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "Ziyaretçilerin özel mesaj göndermelerine izin ver" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "hiç kimse" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Kullanıcıların diğer kullanıcıları sorgulamalarına izin ver" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Kullanıcıların davetiye göndermelerine izin ver" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Ziyaretçilerin varlık (presence) güncellemelerinde durum metni " "göndermelerine izin ver" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Ziyaretçilerin takma isim değiştirmelerine izin ver" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "Ziyaretçilerin ses isteğine göndermelerine izin ver" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "Ses istekleri arasında olabilecek en az aralık (saniye olarak)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Odayı insan doğrulaması (captcha) korumalı hale getir" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "CAPTCHA doğrulamasını şu Jabber ID'ler için yapma" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Kayıt tutma özelliğini aç" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Odayı ayarlamak için x:data becerisine sahip bir istemciye gereksinimiz var" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Oda sakini sayısı" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "özel" -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "Ses isteği" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "Ses isteğini kabul edin ya da reddedin" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "Kullanıcı JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "Bu kişiye ses verelim mi?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s sizi ~s odasına davet ediyor" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "parola :" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "Çevirim-dışı mesaj kuyruğunuz dolu. Mesajını dikkate alınmadı." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s Kullanıcısının Mesaj Kuyruğu" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Zaman" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Kimden" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Kime" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Çevirim-dışı Mesajlar:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Tüm Çevirim-dışı Mesajları Kaldır" @@ -1370,116 +1546,128 @@ msgstr "Tüm Çevirim-dışı Mesajları Kaldır" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams modülü" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Yayınla-Üye Ol" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd Publish-Subscribe modülü" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub üye isteği" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Bu varlığın üyeliğini onaylayıp onaylamamayı seçiniz." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "Düğüm ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Üye Olanın Adresi" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Bu Jabber ID bu pubsub düğümüne üye olmasına izin verilsin mi?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Yükleri (payload) olay uyarıları ile beraber gönder" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Olay uyarıları gönderilsin" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Düğüm ayarları değiştiğinde üyeleri uyar" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Bir düğüm silindiğinde üyeleri uyar" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Düğümden öğeler kaldırıldığında üyeleri uyar" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Öğeleri depoda kalıcı hale getir" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Düğüm için dostane bir isim" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Kalıcı hale getirilecek en fazla öğe sayısı" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Üyeliklere izin verilsin mi" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Erişim modelini belirtiniz" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Üye olunmasına izin verilen kontak listesi grupları" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Yayıncı modelini belirtiniz" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "İlgili yayıncı çevirimdışı olunca tüm onunla ilgili olanları sil" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Olay mesaj tipini belirtiniz" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "En fazla yük (payload) boyutu (bayt olarak)" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Son yayınlanan öğe ne zaman gönderilsin" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Uyarıları sadece durumu uygun kullanıcılara ulaştır" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Bir düğüm ile bağlantılı koleksiyonlar" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "CAPTCHA doğrulaması başarısız oldu" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Takma isminizi kaydettirmek için x:data ve CAPTCHA destekleyen bir istemciye " "gereksinimiz var" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Bu sunucuya kayıt olmak için bir kullanıcı ismi ve parola seçiniz" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Parola çok zayıf" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Kullanıcıların bu kadar hızlı hesap açmalarına izin verilmiyor" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Jabber hesabınız başarıyla oluşturuldu." @@ -1557,8 +1745,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Bazı Jabber istemcileri parolanızı bilgisayarınızda saklayabilir. Bu " "özelliği ancak bilgisayarın güvenli olduğuna güveniyorsanız kullanın." @@ -1599,60 +1787,60 @@ msgstr "" msgid "Unregister" msgstr "Kaydı Sil" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Üyelik" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Sıra Bekleyen" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Gruplar" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Geçerli" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Kaldır" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Kontak Listesi : " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Jabber ID'si Ekle" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Kontak Listesi" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Paylaşımlı Kontak Listesi Grupları" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "İsim:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Tanım:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Üyeler:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Gösterilen Gruplar:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Group " @@ -1729,58 +1917,19 @@ msgstr "Arama sonuçları : " msgid "Fill in fields to search for any matching Jabber User" msgstr "Eşleşen jabber kullanıcılarını aramak için alanları doldurunuz" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Giden s2s Sunucuları" + #~ msgid "Delete" #~ msgstr "Sil" #~ msgid "This room is not anonymous" #~ msgstr "Bu oda anonim değil" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "Etkin mahremiyet listeniz bu bölümün yönlendirilmesini engelledi." - -#~ msgid "Access denied by service policy" -#~ msgstr "Servis politikası gereği erişim engellendi" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Sadece servis yöneticileri servis mesajı gönderebilirler" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Odanın oluşturulması servis politikası gereği reddedildi" - -#~ msgid "Conference room does not exist" -#~ msgstr "Konferans odası bulunamadı" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "O takma isim başka biri tarafından kaydettirilmiş" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Formda \"Takma isim\" alanını doldurmanız gerekiyor" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Trafik oran sınırı aşıldı" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "Bu katılımcı bir hata mesajı gönderdiği için odadan atıldı" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Konferansa özel mesajlar gönderilmesine izin verilmiyor" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "Lütfen yeni bir ses isteği göndermeden önce biraz bekleyin" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "Bu konferansta ses istekleri etkisizleştirilmiş durumda." - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "Ses isteği onayınızdan JID bilginize ulaşılamadı" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "Yalnız moderatörler ses isteklerini onaylayabilir" - -#~ msgid "Improper message type" -#~ msgstr "Uygunsuz mesaj tipi" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1788,80 +1937,7 @@ msgstr "Eşleşen jabber kullanıcılarını aramak için alanları doldurunuz" #~ "Bu katılımcı başka bir katılımcıya bir hata mesajı gönderdiği için odadan " #~ "atıldı" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "\"groupchat\" tipinde özel mesajlar gönderilmesine izin verilmiyor" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Alıcı konferans odasında değil" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Özel mesaj gönderilmesine izin verilmiyor" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "" -#~ "Sadece oda sakinlerinin konferansa mesaj göndermesine izin veriliyor" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "" -#~ "Sadece oda sakinlerinin konferansa sorgu göndermesine izin veriliyor" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Bu odada konferans üyelerine sorgu yapılmasına izin verilmiyor" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "" -#~ "Ziyaretçilerin odadaki tüm sakinlere mesaj göndermesine izin verilmiyor" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Bu katılımcı bir hata varlığı (presence) gönderdiği için odadan atıldı" - -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Bu odada ziyaretçilerin takma isimlerini değiştirmesine izin verilmiyor" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "" -#~ "Takma isim odanın başka bir sakini tarafından halihazırda kullanımda" - -#~ msgid "You have been banned from this room" -#~ msgstr "Bu odaya girmeniz yasaklandı" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "Bu odaya girmek için üyelik gerekiyor" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Bu odaya girmek için parola gerekiyor" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Çok fazla CAPTCHA isteği" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "İnsan doğrulaması (CAPTCHA) oluşturulamadı" - -#~ msgid "Incorrect password" -#~ msgstr "Yanlış parola" - -#~ msgid "Administrator privileges required" -#~ msgstr "Yönetim yetkileri gerekli" - -#~ msgid "Moderator privileges required" -#~ msgstr "Moderatör yetkileri gerekli" - -#~ msgid "Owner privileges required" -#~ msgstr "Sahip yetkileri gerekli" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "Çevirim-dışı mesaj kuyruğunuz dolu. Mesajını dikkate alınmadı." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "CAPTCHA doğrulaması başarısız oldu" - -#~ msgid "The password is too weak" -#~ msgstr "Parola çok zayıf" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Kullanıcıların bu kadar hızlı hesap açmalarına izin verilmiyor" diff --git a/priv/msgs/uk.msg b/priv/msgs/uk.msg index 48abe548073..985796ca05a 100644 --- a/priv/msgs/uk.msg +++ b/priv/msgs/uk.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Конфігурація списків керування доступом"}. {"Access control lists","Списки керування доступом"}. {"Access Control Lists","Списки керування доступом"}. +{"Access denied by service policy","Доступ заборонений політикою служби"}. {"Access rules","Правила доступу"}. {"Access Rules","Правила доступу"}. {"Action on user","Дія над користувачем"}. @@ -11,6 +12,7 @@ {"Add User","Додати користувача"}. {"Administration of ","Адміністрування "}. {"Administration","Адміністрування"}. +{"Administrator privileges required","Необхідні права адміністратора"}. {"A friendly name for the node","Псевдонім для вузла"}. {"All activity","Вся статистика"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Чи дозволити цьому Jabber ID підписатись новини наданого вузла"}. @@ -23,6 +25,7 @@ {"All Users","Всі користувачі"}. {"Announcements","Сповіщення"}. {"anyone","всім учасникам"}. +{"A password is required to enter this room","Щоб зайти в цю конференцію, необхідно ввести пароль"}. {"April","квітня"}. {"August","серпня"}. {"Backup Management","Керування резервним копіюванням"}. @@ -46,6 +49,7 @@ {"Choose whether to approve this entity's subscription.","Вирішіть, чи задовольнити запит цього об'єкту на підписку"}. {"City","Місто"}. {"Commands","Команди"}. +{"Conference room does not exist","Конференція не існує"}. {"Configuration of room ~s","Конфігурація кімнати ~s"}. {"Configuration","Конфігурація"}. {"Connected Resources:","Підключені ресурси:"}. @@ -127,6 +131,8 @@ {"Import users data from jabberd14 spool directory:","Імпорт користувачів з діректорії спула jabberd14:"}. {"Import Users from Dir at ","Імпортування користувача з директорії на "}. {"Import Users From jabberd14 Spool Files","Імпорт користувачів зі спулу jabberd14"}. +{"Improper message type","Неправильний тип повідомлення"}. +{"Incorrect password","Неправильний пароль"}. {"Invalid affiliation: ~s","Недопустимий ранг: ~s"}. {"Invalid role: ~s","Недопустима роль: ~s"}. {"IP addresses","IP адреси"}. @@ -138,6 +144,9 @@ {"IRC username","Ім'я користувача IRC"}. {"IRC Username","Ім'я користувача IRC"}. {"is now known as","змінив(ла) псевдонім на"}. +{"It is not allowed to send private messages of type \"groupchat\"","Не дозволяється надсилати приватні повідомлення типу \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Не дозволяється надсилати приватні повідомлення в конференцію"}. +{"It is not allowed to send private messages","Приватні повідомлення не дозволені"}. {"Jabber Account Registration","Реєстрація Jabber-акаунту"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s недопустимий"}. @@ -169,11 +178,13 @@ {"Max # of items to persist","Максимальне число збережених публікацій"}. {"Max payload size in bytes","Максимальний розмір корисного навантаження в байтах"}. {"May","травня"}. +{"Membership is required to enter this room","В цю конференцію можуть входити тільки її члени"}. {"Members:","Члени:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Запам'ятайте пароль, або запишіть його на папері, який треба зберегти у безпечному місці. У Jabber'і немає автоматизованих засобів відновлення пароля на той випадок, якщо ви його забудете."}. {"Memory","Пам'ять"}. {"Message body","Тіло повідомлення"}. {"Middle Name","По-батькові"}. +{"Moderator privileges required","Необхідні права модератора"}. {"moderators only","тільки модераторам"}. {"Modified modules","Змінені модулі"}. {"Modules","Модулі"}. @@ -213,12 +224,15 @@ {"Only deliver notifications to available users","Доставляти повідомленнями тільки доступним користувачам"}. {"Only moderators and participants are allowed to change the subject in this room","Тільки модератори та учасники можуть змінювати тему в цій кімнаті"}. {"Only moderators are allowed to change the subject in this room","Тільки модератори можуть змінювати тему в цій кімнаті"}. +{"Only occupants are allowed to send messages to the conference","Тільки присутнім дозволяється надсилати повідомленняя в конференцію"}. +{"Only occupants are allowed to send queries to the conference","Тільки присутнім дозволяється відправляти запити в конференцію"}. +{"Only service administrators are allowed to send service messages","Тільки адміністратор сервісу може надсилати службові повідомлення"}. {"Options","Параметри"}. {"Organization Name","Назва організації"}. {"Organization Unit","Відділ організації"}. {"Outgoing s2s Connections:","Вихідні s2s-з'єднання:"}. {"Outgoing s2s Connections","Вихідні s2s-з'єднання"}. -{"Outgoing s2s Servers:","Вихідні s2s-сервери:"}. +{"Owner privileges required","Необхідні права власника"}. {"Packet","Пакет"}. {"Password ~b","Пароль ~b"}. {"Password Verification:","Перевірка Пароля:"}. @@ -241,10 +255,12 @@ {"Publish-Subscribe","Публікація-Підписка"}. {"PubSub subscriber request","Запит на підписку PubSub"}. {"Purge all items when the relevant publisher goes offline","Видалити всі елементи, коли особа, що їх опублікувала, вимикається від мережі"}. +{"Queries to the conference members are not allowed in this room","Запити до користувачів в цій конференції заборонені"}. {"RAM and disc copy","ОЗП та диск"}. {"RAM copy","ОЗП"}. {"Raw","необроблений формат"}. {"Really delete message of the day?","Насправді видалити повідомлення дня?"}. +{"Recipient is not in the conference room","Адресата немає в конференції"}. {"Register a Jabber account","Зареєструвати Jabber-акаунт"}. {"Registered Users:","Зареєстровані користувачі:"}. {"Registered Users","Зареєстровані користувачі"}. @@ -264,6 +280,7 @@ {"Restore plain text backup immediately:","Відновити з текстової резервної копії негайно:"}. {"Restore","Відновлення з резервної копії"}. {"Room Configuration","Конфігурація кімнати"}. +{"Room creation is denied by service policy","Створювати конференцію заборонено політикою служби"}. {"Room description","Опис кімнати"}. {"Room Occupants","Учасники кімнати"}. {"Room title","Назва кімнати"}. @@ -292,7 +309,7 @@ {"Show Ordinary Table","Показати звичайну таблицю"}. {"Shut Down Service","Вимкнути Сервіс"}. {"~s invites you to the room ~s","~s запрошує вас до кімнати ~s"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","Деякі Jabber-клієнти можуть зберігати пароль на вашому комп'ютері. Користуйтесь цією функцією тільки у тому випадку, якщо вважаєте її безпечною."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Деякі Jabber-клієнти можуть зберігати пароль на вашому комп'ютері. Користуйтесь цією функцією тільки у тому випадку, якщо вважаєте її безпечною."}. {"Specify the access model","Визначити модель доступу"}. {"Specify the event message type","Вкажіть тип повідомлень зі сповіщеннями про події"}. {"Specify the publisher model","Умови публікації"}. @@ -315,8 +332,12 @@ {"Subscriber Address","Адреса абонента"}. {"Subscription","Підписка"}. {"Sunday","Неділя"}. +{"That nickname is already in use by another occupant","Псевдонім зайнято кимось з присутніх"}. +{"That nickname is registered by another person","Псевдонім зареєстровано кимось іншим"}. {"The CAPTCHA is valid.","Перевірку капчею закінчено успішно"}. +{"The CAPTCHA verification has failed","Перевірку капчею не пройдено"}. {"The collections with which a node is affiliated","Колекція, до якої входить вузол"}. +{"The password is too weak","Пароль надто простий"}. {"the password is","пароль:"}. {"The password of your Jabber account was successfully changed.","Пароль вашого Jabber-акаунту був успішно змінений."}. {"There was an error changing the password: ","Помилка при зміні пароля: "}. @@ -328,13 +349,16 @@ {"Thursday","Четвер"}. {"Time delay","Час затримки"}. {"Time","Час"}. +{"Too many CAPTCHA requests","Надто багато CAPTCHA-запитів"}. {"To ~s","До ~s"}. {"To","Кому"}. +{"Traffic rate limit is exceeded","Швидкість передачі інформації було перевищено"}. {"Transactions Aborted:","Транзакції відмінені:"}. {"Transactions Committed:","Транзакції завершені:"}. {"Transactions Logged:","Транзакції запротокольовані:"}. {"Transactions Restarted:","Транзакції перезапущені:"}. {"Tuesday","Вівторок"}. +{"Unable to generate a CAPTCHA","Нема можливості згенерувати капчу"}. {"Unauthorized","Не авторизовано"}. {"Unregister a Jabber account","Видалити Jabber-акаунт"}. {"Unregister","Видалити"}. @@ -347,21 +371,28 @@ {"Use of STARTTLS required","Ви мусите використовувати STARTTLS"}. {"User Management","Управління Користувачами"}. {"Username:","Ім'я користувача:"}. +{"Users are not allowed to register accounts so quickly","Користувачам не дозволено так часто реєструвати облікові записи"}. {"Users Last Activity","Статистика останнього підключення користувачів"}. {"Users","Користувачі"}. {"User","Користувач"}. {"Validate","Затвердити"}. {"vCard User Search","Пошук користувачів по vCard"}. {"Virtual Hosts","віртуальні хости"}. +{"Visitors are not allowed to change their nicknames in this room","Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті"}. +{"Visitors are not allowed to send messages to all occupants","Відвідувачам не дозволяється надсилати повідомлення всім присутнім"}. {"Wednesday","Середа"}. {"When to send the last published item","Коли надсилати останній опублікований елемент"}. {"Whether to allow subscriptions","Дозволяти підписку"}. {"You can later change your password using a Jabber client.","Пізніше можна змінити пароль через Jabber-клієнт."}. +{"You have been banned from this room","Вам заборонено входити в цю конференцію"}. +{"You must fill in field \"Nickname\" in the form","Вам необхідно заповнити поле \"Псевдонім\" у формі"}. {"You need a client that supports x:data and CAPTCHA to register","Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:data"}. {"You need a client that supports x:data to register the nickname","Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:data"}. {"You need an x:data capable client to configure mod_irc settings","Для налагодження параметрів mod_irc необхідно використовувати клієнт, що має підтримку x:data"}. {"You need an x:data capable client to configure room","Для конфігурування кімнати потрібно використовувати клієнт з підтримкою x:data"}. {"You need an x:data capable client to search","Для пошуку необхідний клієнт із підтримкою x:data"}. +{"Your active privacy list has denied the routing of this stanza.","Маршрутизація цієї строфи була відмінена активним списком приватності."}. +{"Your contact offline message queue is full. The message has been discarded.","Черга повідомлень, що не були доставлені, переповнена. Повідомлення не було збережено."}. {"Your Jabber account was successfully created.","Ваш Jabber-акаунт було успішно створено."}. {"Your Jabber account was successfully deleted.","Ваш Jabber-акаунт було успішно видалено."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s"}. diff --git a/priv/msgs/uk.po b/priv/msgs/uk.po index 8b39ac64a61..4f6b2a0ead9 100644 --- a/priv/msgs/uk.po +++ b/priv/msgs/uk.po @@ -14,49 +14,53 @@ msgstr "" "X-Additional-Translator: Stoune\n" "X-Additional-Translator: Sergei Golovan\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Ви мусите використовувати STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Не вказаний ресурс" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Замінено новим з'єднанням" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "вигнали з кімнати" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "Маршрутизація цієї строфи була відмінена активним списком приватності." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "Введіть текст, що ви бачите" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "Ваші повідомлення до ~s блокуються. Для розблокування відвідайте ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "Якщо ви не бачите зображення капчі, перейдіть за за цією адресою." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "Адреса капчі" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "Перевірку капчею закінчено успішно" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Користувач" @@ -65,9 +69,9 @@ msgstr "Користувач" msgid "Server" msgstr "Сервер:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Пароль" @@ -84,279 +88,280 @@ msgstr "Не авторизовано" msgid "ejabberd Web Admin" msgstr "Веб-інтерфейс Адміністрування ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Адміністрування" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Списки керування доступом" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Відправлено" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Неправильний формат" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Відправити" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "необроблений формат" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Видалити виділені" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Правила доступу" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Конфігурація правила доступу ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "віртуальні хости" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Користувачі" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Підключені користувачі" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Статистика останнього підключення користувачів" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Період" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "За останній місяць" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "За останній рік" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Вся статистика" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Показати звичайну таблицю" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Показати інтегральну таблицю" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Статистика" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "не знайдено" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Вузол не знайдено" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Додати" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Хост" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Зареєстровані користувачі" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Додати користувача" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Офлайнові повідомлення" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Останнє підключення" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Ніколи" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Підключений" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Зареєстровані користувачі:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Підключені користувачі:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Вихідні s2s-з'єднання:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Вихідні s2s-сервери:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Вихідні s2s-з'єднання:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Немає" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Змінити пароль" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Користувач " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Підключені ресурси:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Пароль:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Видалити користувача" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Немає даних" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Вузли" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Працюючі вузли" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Зупинені вузли" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Вузол " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "База даних" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Резервне копіювання" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Відкриті порти" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Обновити" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Перезапустити" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Зупинити" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Модулі" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Помилка виклику RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Таблиці бази даних на " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Назва" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Тип таблиці" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "Елементи" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Пам'ять" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "Помилка" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Резервне копіювання " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -367,145 +372,145 @@ msgstr "" "(наприклад за допомогою модуля ODBC), то його резервне копіювання потрібно " "робити окремо." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Зберегти бінарну резервну копію:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "Продовжити" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Відновити з бінарної резервної копії негайно:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Відновити з бінарної резервної копії при наступному запуску (потребує менше " "пам'яті):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Зберегти текстову резервну копію:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Відновити з текстової резервної копії негайно:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "Імпорт даних користовучів з файлу PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "Експорт даних всіх користувачів сервера до файлу PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "Експорт даних користувачів домена до файлу PIEFXIS (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "Імпорт користувачів з файла спула jabberd14:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "Імпорт користувачів з діректорії спула jabberd14:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Відкриті порти на " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Модулі на " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Статистика вузла ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Час роботи:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Процесорний час:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Транзакції завершені:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Транзакції відмінені:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Транзакції перезапущені:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Транзакції запротокольовані:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Поновлення " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "План поновлення" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "Змінені модулі" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Сценарій поновлення" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Низькорівневий сценарій поновлення" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Перевірка сценарію" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Порт" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "Протокол" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Модуль" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Параметри" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Запустити" @@ -794,8 +799,8 @@ msgstr "Правила доступу" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -812,31 +817,31 @@ msgstr "Кількість зареєстрованих користувачів msgid "Number of online users" msgstr "Кількість підключених користувачів" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Останнє підключення" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Кількість контактів" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP адреси" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Ресурси" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Адміністрування " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Дія над користувачем" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Змінити параметри" @@ -846,29 +851,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Доступ заборонений політикою служби" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC Транспорт" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC модуль" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Для налагодження параметрів mod_irc необхідно використовувати клієнт, що має " "підтримку x:data" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Реєстрація в mod_irc для " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" @@ -876,11 +893,11 @@ msgstr "" "Введіть ім'я користувача, кодування, порти та паролі, що будуть " "використовуватися при підключенні до IRC-серверів" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Ім'я користувача IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -892,7 +909,7 @@ msgstr "" "\"password\"}'. За замовчуванням ця служба використовує \"~s\" кодування, " "порт ~p, пустий пароль." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -900,35 +917,35 @@ msgstr "" "Приклад: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta." "fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "Параметри з'єднання" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "Приєднатися до каналу IRC" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "Канал IRC (не включаючи #)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC-сервер" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "Приєднатися до каналу IRC" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "Приєднатися до каналу IRC з Jabber ID: ~s" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "Парметри IRC" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -938,50 +955,79 @@ msgstr "" "підключенні до IRC-серверів Натисніть 'Далі' для заповнення додаткових " "полів. Натисніть 'Завершити' для збереження параметрів." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "Ім'я користувача IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "Пароль ~b" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "Порт ~b" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "Кодування для сервера ~b" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "Сервер ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Тільки адміністратор сервісу може надсилати службові повідомлення" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Створювати конференцію заборонено політикою служби" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Конференція не існує" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Кімнати" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:" "data" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Реєстрація псевдоніма на " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Введіть псевдонім, який ви хочете зареєструвати" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдонім" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "Псевдонім зареєстровано кимось іншим" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Вам необхідно заповнити поле \"Псевдонім\" у формі" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" @@ -1009,359 +1055,490 @@ msgstr "Зареєстровані користувачі" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Конфігурація кімнати змінилась" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "увійшов(ла) в кімнату" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "вийшов(ла) з кімнати" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "заборонили вхід в кімнату" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "вигнано з кімнати внаслідок зміни рангу" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "вигнано з кімнати тому, що вона стала тільки для учасників" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "вигнано з кімнати внаслідок зупинки системи" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "змінив(ла) псевдонім на" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " встановив(ла) тему: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "Створено кімнату" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "Знищено кімнату" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "Запущено кімнату" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "Зупинено кімнату" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Понеділок" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Вівторок" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Середа" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Четвер" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "П'ятниця" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Субота" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Неділя" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "січня" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "лютого" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "березня" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "квітня" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "травня" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "червня" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "липня" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "серпня" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "вересня" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "грудня" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "листопада" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "грудня" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Конфігурація кімнати" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "Учасники кімнати" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Швидкість передачі інформації було перевищено" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Не дозволяється надсилати приватні повідомлення в конференцію" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Дозволити користувачам надсилати запрошення" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Неправильний тип повідомлення" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Не дозволяється надсилати приватні повідомлення типу \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Адресата немає в конференції" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Приватні повідомлення не дозволені" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Тільки присутнім дозволяється надсилати повідомленняя в конференцію" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Тільки присутнім дозволяється відправляти запити в конференцію" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "Запити до користувачів в цій конференції заборонені" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "Тільки модератори та учасники можуть змінювати тему в цій кімнаті" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Відвідувачам не дозволяється надсилати повідомлення всім присутнім" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "Псевдонім зайнято кимось з присутніх" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Вам заборонено входити в цю конференцію" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "В цю конференцію можуть входити тільки її члени" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "Щоб зайти в цю конференцію, необхідно ввести пароль" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "Надто багато CAPTCHA-запитів" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "Нема можливості згенерувати капчу" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Неправильний пароль" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Необхідні права адміністратора" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Необхідні права модератора" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s недопустимий" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Псевдонім ~s в кімнаті відсутній" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Недопустимий ранг: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Недопустима роль: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Необхідні права власника" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "Конфігурація кімнати ~s" -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Назва кімнати" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "Опис кімнати" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Зробити кімнату постійною" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Зробити кімнату видимою всім" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Зробити список учасників видимим всім" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Зробити кімнату захищеною паролем" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Максимальна кількість учасників" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Без обмежень" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Зробити реальні Jabber ID учасників видимими" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "тільки модераторам" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "всім учасникам" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "тільки модераторам" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Кімната тільки для зареєтрованых учасників" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Зробити кімнату модерованою" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Зробити користувачів учасниками за замовчуванням" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "Дозволити користувачам змінювати тему" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Дозволити приватні повідомлення" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Дозволити приватні повідомлення" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Дозволити iq-запити до користувачів" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Дозволити користувачам надсилати запрошення" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Дозволити відвідувачам відсилати текст статусу в оновленнях присутності" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Дозволити відвідувачам змінювати псевдонім" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Дозволити користувачам надсилати запрошення" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "Зробити кімнату захищеною капчею" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "Пропускати ці Jabber ID без CAPTCHA-запиту" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Включити журнал роботи" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Для конфігурування кімнати потрібно використовувати клієнт з підтримкою x:" "data" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Кількість присутніх" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "приватна, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Користувач " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s запрошує вас до кімнати ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "пароль:" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Черга повідомлень, що не були доставлені, переповнена. Повідомлення не було " +"збережено." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "Черга офлайнових повідомлень ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Час" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Від кого" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Кому" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Пакет" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Офлайнові повідомлення:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "Видалити всі офлайнові повідомлення" @@ -1369,117 +1546,129 @@ msgstr "Видалити всі офлайнові повідомлення" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 Bytestreams модуль" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Публікація-Підписка" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Модуль ejabberd Публікації-Підписки" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Запит на підписку PubSub" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Вирішіть, чи задовольнити запит цього об'єкту на підписку" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID вузла" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Адреса абонента" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Чи дозволити цьому Jabber ID підписатись новини наданого вузла" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Доставляти разом з повідомленнями про публікації самі публікації" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Доставляти сповіщення про події" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Повідомляти абонентів про зміни в конфігурації збірника" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Повідомляти абонентів про видалення збірника" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Повідомляти абонентів про видалення публікацій із збірника" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Зберегати публікації до сховища" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "Псевдонім для вузла" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Максимальне число збережених публікацій" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Дозволяти підписку" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Визначити модель доступу" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Дозволені для підписки групи ростера" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Умови публікації" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" "Видалити всі елементи, коли особа, що їх опублікувала, вимикається від мережі" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "Вкажіть тип повідомлень зі сповіщеннями про події" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Максимальний розмір корисного навантаження в байтах" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Коли надсилати останній опублікований елемент" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Доставляти повідомленнями тільки доступним користувачам" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "Колекція, до якої входить вузол" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "Перевірку капчею не пройдено" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:" "data" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Виберіть назву користувача та пароль для реєстрації на цьому сервері" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "Пароль надто простий" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "Користувачам не дозволено так часто реєструвати облікові записи" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "Ваш Jabber-акаунт було успішно створено." @@ -1556,8 +1745,8 @@ msgstr "Пізніше можна змінити пароль через Jabber- #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "Деякі Jabber-клієнти можуть зберігати пароль на вашому комп'ютері. " "Користуйтесь цією функцією тільки у тому випадку, якщо вважаєте її безпечною." @@ -1596,60 +1785,60 @@ msgstr "Ця сторінка дозволяє видалити свій ака msgid "Unregister" msgstr "Видалити" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Підписка" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Очікування" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Групи" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Затвердити" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Видалити" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Ростер користувача " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Додати Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Ростер" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Спільні групи контактів" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Назва:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Опис:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Члени:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Видимі групи:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Група " @@ -1725,49 +1914,21 @@ msgstr "Результати пошуку в " msgid "Fill in fields to search for any matching Jabber User" msgstr "Заповніть поля для пошуку користувача Jabber" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Вихідні s2s-сервери:" + #~ msgid "Delete" #~ msgstr "Видалити" #~ msgid "This room is not anonymous" #~ msgstr "Ця кімната не анонімна" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "" -#~ "Маршрутизація цієї строфи була відмінена активним списком приватності." - -#~ msgid "Access denied by service policy" -#~ msgstr "Доступ заборонений політикою служби" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Тільки адміністратор сервісу може надсилати службові повідомлення" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Створювати конференцію заборонено політикою служби" - -#~ msgid "Conference room does not exist" -#~ msgstr "Конференція не існує" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "Псевдонім зареєстровано кимось іншим" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Вам необхідно заповнити поле \"Псевдонім\" у формі" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Швидкість передачі інформації було перевищено" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Цього учасника було відключено від кімнати через те, що він надіслав " #~ "помилкове повідомлення" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Не дозволяється надсилати приватні повідомлення в конференцію" - -#~ msgid "Improper message type" -#~ msgstr "Неправильний тип повідомлення" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1775,81 +1936,11 @@ msgstr "Заповніть поля для пошуку користувача J #~ "Цього учасника було відключено від кімнати через те, що він надіслав " #~ "помилкове повідомлення іншому учаснику" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Не дозволяється надсилати приватні повідомлення типу \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Адресата немає в конференції" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Приватні повідомлення не дозволені" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Тільки присутнім дозволяється надсилати повідомленняя в конференцію" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Тільки присутнім дозволяється відправляти запити в конференцію" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "Запити до користувачів в цій конференції заборонені" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Відвідувачам не дозволяється надсилати повідомлення всім присутнім" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Цього учасника було відключено від кімнати через те, що він надіслав " #~ "помилковий статус присутності" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Псевдонім зайнято кимось з присутніх" - -#~ msgid "You have been banned from this room" -#~ msgstr "Вам заборонено входити в цю конференцію" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "В цю конференцію можуть входити тільки її члени" - -#~ msgid "A password is required to enter this room" -#~ msgstr "Щоб зайти в цю конференцію, необхідно ввести пароль" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "Надто багато CAPTCHA-запитів" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "Нема можливості згенерувати капчу" - -#~ msgid "Incorrect password" -#~ msgstr "Неправильний пароль" - -#~ msgid "Administrator privileges required" -#~ msgstr "Необхідні права адміністратора" - -#~ msgid "Moderator privileges required" -#~ msgstr "Необхідні права модератора" - -#~ msgid "Owner privileges required" -#~ msgstr "Необхідні права власника" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Черга повідомлень, що не були доставлені, переповнена. Повідомлення не " -#~ "було збережено." - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "Перевірку капчею не пройдено" - -#~ msgid "The password is too weak" -#~ msgstr "Пароль надто простий" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Користувачам не дозволено так часто реєструвати облікові записи" - #~ msgid "Captcha test failed" #~ msgstr "Перевірка капчею закінчилась невдало" diff --git a/priv/msgs/vi.msg b/priv/msgs/vi.msg index 4edeb1baf60..3e5fdf5f108 100644 --- a/priv/msgs/vi.msg +++ b/priv/msgs/vi.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Cấu Hình Danh Sách Kiểm Soát Truy Cập"}. {"Access control lists","Danh sách kiểm soát truy cập"}. {"Access Control Lists","Danh Sách Kiểm Soát Truy Cập"}. +{"Access denied by service policy","Sự truy cập bị chặn theo chính sách phục vụ"}. {"Access rules","Quy tắc Truy Cập"}. {"Access Rules","Quy Tắc Truy Cập"}. {"Action on user","Hành động đối với người sử dụng"}. @@ -11,6 +12,7 @@ {"Add User","Thêm Người Sử Dụng"}. {"Administration of ","Quản trị về "}. {"Administration","Quản trị"}. +{"Administrator privileges required","Yêu cầu đặc quyền của nhà quản trị"}. {"All activity","Tất cả hoạt động"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Cho phép Jabber ID đăng ký nút môđun xuất bản đăng ký này không?"}. {"Allow users to query other users","Cho phép người sử dụng hỏi người sử dụng khác"}. @@ -36,6 +38,7 @@ {"Choose whether to approve this entity's subscription.","Chọn có nên chấp nhận sự đăng ký của đối tượng này không"}. {"City","Thành phố"}. {"Commands","Lệnh"}. +{"Conference room does not exist","Phòng họp không tồn tại"}. {"Configuration","Cấu hình"}. {"Connected Resources:","Tài Nguyên Được Kết Nối:"}. {"Country","Quốc gia"}. @@ -95,12 +98,16 @@ {"Import User from File at ","Nhập Người Sử Dụng từ Tập Tin tại"}. {"Import Users from Dir at ","Nhập Người Sử Dụng từ Thư Mục tại"}. {"Import Users From jabberd14 Spool Files","Nhập Người Sử Dụng Từ Các Tập Tin Spool jabberd14"}. +{"Improper message type","Loại thư không phù hợp"}. +{"Incorrect password","Mật khẩu sai"}. {"Invalid affiliation: ~s","Tư cách không hợp lệ: ~s"}. {"Invalid role: ~s","Vai trò không hợp lệ: ~s"}. {"IP addresses","Địa chỉ IP"}. {"IRC Transport","Truyền tải IRC"}. {"IRC Username","Tên truy cập IRC"}. {"is now known as","bây giờ được biết như"}. +{"It is not allowed to send private messages of type \"groupchat\"","Không được phép gửi những thư riêng loại \"groupchat\""}. +{"It is not allowed to send private messages to the conference","Không được phép gửi những thư riêng đến phòng họp"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s không hợp lệ"}. {"January","Tháng Một"}. @@ -130,6 +137,7 @@ {"Memory","Bộ Nhớ"}. {"Message body","Thân thư"}. {"Middle Name","Họ Đệm"}. +{"Moderator privileges required","Yêu cầu đặc quyền của nhà điều phối"}. {"moderators only","nhà điều phối duy nhất"}. {"Module","Môđun"}. {"Modules","Môđun"}. @@ -163,12 +171,15 @@ {"Online Users:","Người Sử Dụng Trực Tuyến:"}. {"Online Users","Người Sử Dụng Trực Tuyến"}. {"Only deliver notifications to available users","Chỉ gửi thông báo đến những người sử dụng hiện có"}. +{"Only occupants are allowed to send messages to the conference","Chỉ có những đối tượng tham gia mới được phép gửi thư đến phòng họp"}. +{"Only occupants are allowed to send queries to the conference","Chỉ có những đối tượng tham gia mới được phép gửi yêu cầu đến phòng họp"}. +{"Only service administrators are allowed to send service messages","Chỉ có người quản trị dịch vụ mới được phép gửi những thư dịch vụ"}. {"Options","Tùy chọn"}. {"Organization Name","Tên Tổ Chức"}. {"Organization Unit","Bộ Phận"}. {"Outgoing s2s Connections:","Kết Nối Bên Ngoài s2s:"}. {"Outgoing s2s Connections","Kết Nối Bên Ngoài s2s"}. -{"Outgoing s2s Servers:","Máy chủ Bên Ngoài s2s:"}. +{"Owner privileges required","Yêu cầu đặc quyền của người sở hữu"}. {"Packet","Gói thông tin"}. {"Password:","Mật Khẩu:"}. {"Password","Mật Khẩu"}. @@ -185,10 +196,12 @@ {"private, ","riêng,"}. {"Publish-Subscribe","Xuất Bản-Đăng Ký"}. {"PubSub subscriber request","Yêu cầu người đăng ký môđun Xuất Bản Đăng Ký"}. +{"Queries to the conference members are not allowed in this room","Không được phép gửi các yêu cầu gửi đến các thành viên trong phòng họp này"}. {"RAM and disc copy","Sao chép vào RAM và đĩa"}. {"RAM copy","Sao chép vào RAM"}. {"Raw","Thô"}. {"Really delete message of the day?","Có thực sự xóa thư trong ngày này không?"}. +{"Recipient is not in the conference room","Người nhận không có trong phòng họp"}. {"Registered Users:","Người Sử Dụng Đã Đăng Ký:"}. {"Registered Users","Người Sử Dụng Đã Đăng Ký"}. {"Registration in mod_irc for ","Đăng ký trong mod_irc cho "}. @@ -205,6 +218,7 @@ {"Restore","Khôi phục"}. {"Restore plain text backup immediately:","Khôi phục bản sao lưu dự phòng thuần văn bản ngay lập tức:"}. {"Room Configuration","Cấu Hình Phòng"}. +{"Room creation is denied by service policy","Việc tạo phòng bị ngăn lại theo chính sách dịch vụ"}. {"Room title","Tên phòng"}. {"Roster","Bảng phân công"}. {"Roster of ","Bảng phân công của "}. @@ -255,6 +269,7 @@ {"Time","Thời Gian"}. {"To","Đến"}. {"To ~s","Gửi đến ~s"}. +{"Traffic rate limit is exceeded","Quá giới hạn tỷ lệ lưu lượng truyền tải"}. {"Transactions Aborted:","Giao Dịch Hủy Bỏ:"}. {"Transactions Committed:","Giao Dịch Được Cam Kết:"}. {"Transactions Logged:","Giao Dịch Được Ghi Nhận:"}. @@ -274,9 +289,13 @@ {"Validate","Xác nhận hợp lệ"}. {"vCard User Search","Tìm Kiếm Người Sử Dụng vCard"}. {"Virtual Hosts","Máy Chủ Ảo"}. +{"Visitors are not allowed to send messages to all occupants","Người ghé thăm không được phép gửi thư đến tất cả các người tham dự"}. {"Wednesday","Thứ Tư"}. {"When to send the last published item","Khi cần gửi mục được xuất bản cuối cùng"}. {"Whether to allow subscriptions","Xác định nên cho phép đăng ký không"}. +{"You have been banned from this room","Bạn bị cấm tham gia phòng này"}. +{"You must fill in field \"Nickname\" in the form","Bạn phải điền thông tin vào ô \"Nickname\" trong biểu mẫu này"}. {"You need an x:data capable client to configure mod_irc settings","Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định các thiết lập mod_irc"}. {"You need an x:data capable client to configure room","Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định cấu hình phòng họp"}. {"You need an x:data capable client to search","Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để tìm kiếm"}. +{"Your contact offline message queue is full. The message has been discarded.","Danh sách chờ thư liên lạc ngoại tuyến của bạn đã đầy. Thư này đã bị loại bỏ."}. diff --git a/priv/msgs/vi.po b/priv/msgs/vi.po index e8101eac9c7..4302750d58b 100644 --- a/priv/msgs/vi.po +++ b/priv/msgs/vi.po @@ -7,50 +7,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Vietnamese (tiếng việt)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "Yêu cầu sử dụng STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Không có nguồn lực cung cấp" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Được thay thế bởi kết nối mới" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "đã bị đẩy ra khỏi" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 #, fuzzy msgid "Enter the text you see" msgstr "Nhập đường dẫn đến tập tin văn bản" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Người sử dụng" @@ -59,9 +63,9 @@ msgstr "Người sử dụng" msgid "Server" msgstr "Không bao giờ" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Mật Khẩu" @@ -79,280 +83,281 @@ msgstr "" msgid "ejabberd Web Admin" msgstr "Giao diện Web ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Quản trị" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Danh Sách Kiểm Soát Truy Cập" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Đã gửi" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Định dạng hỏng" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Gửi" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Thô" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Tùy chọn Xóa được Chọn" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Quy Tắc Truy Cập" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s cấu hình quy tắc truy cập" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Máy Chủ Ảo" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Người sử dụng" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Người Sử Dụng Trực Tuyến" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Hoạt Động Cuối Cùng Của Người Sử Dụng" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Giai đoạn: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Tháng trước" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Năm trước" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Tất cả hoạt động" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Hiển Thị Bảng Thường" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Hiển Thị Bảng Đầy Đủ" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Số liệu thống kê" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "Nút không tìm thấy" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nút không tìm thấy" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Thêm Mới" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Máy chủ" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Người Sử Dụng Đã Đăng Ký" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Thêm Người Sử Dụng" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Thư Ngoại Tuyến" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Hoạt Động Cuối Cùng" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Không bao giờ" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Trực tuyến" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Người Sử Dụng Đã Đăng Ký:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Người Sử Dụng Trực Tuyến:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Kết Nối Bên Ngoài s2s:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Máy chủ Bên Ngoài s2s:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Kết Nối Bên Ngoài s2s:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Không có" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Thay Đổi Mật Khẩu" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Người sử dụng " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Tài Nguyên Được Kết Nối:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Mật Khẩu:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Gỡ Bỏ Người Sử Dụng" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Không Dữ Liệu" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nút" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nút Hoạt Động" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nút Dừng" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nút " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Cơ sở dữ liệu" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Sao lưu dự phòng" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Cổng Kết Nối" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Cập Nhật" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Khởi động lại" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Dừng" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Môđun" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Lỗi Gọi RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Bảng Cơ Sở Dữ Liệu tại" -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "Tên" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Loại Lưu Trữ" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Bộ Nhớ" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Sao lưu dự phòng về" -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 #, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " @@ -363,149 +368,149 @@ msgstr "" "Mnesia. Nếu bạn đang sử dụng môđun ODBC, bạn cũng cần sao lưu cơ sở dữ liệu " "SQL của bạn riêng biệt." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Lưu dữ liệu sao lưu dạng nhị phân:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "OK" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Khôi phục bản sao lưu dự phòng dạng nhị phận ngay lập tức:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Khôi phục bản sao lưu dự phòng dạng nhị phân sau lần khởi động ejabberd kế " "tiếp (yêu cầu ít bộ nhớ hơn):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Khôi phục bản sao lưu dự phòng thuần văn bản" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Khôi phục bản sao lưu dự phòng thuần văn bản ngay lập tức:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "Nhập Người Sử Dụng Từ Các Tập Tin Spool jabberd14" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Nhập Người Sử Dụng Từ Các Tập Tin Spool jabberd14" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Cổng Liên Lạc tại" -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Môđun tại " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Thống kê về ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Thời gian tải lên:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Thời Gian CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Giao Dịch Được Cam Kết:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Giao Dịch Hủy Bỏ:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Giao Dịch Khởi Động Lại:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Giao Dịch Được Ghi Nhận:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Cập Nhật " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Kế hoạch cập nhật" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "Môđun cập nhật" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Cập nhận lệnh" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Lệnh cập nhật mức độ thấp" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Lệnh kiểm tra" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Cổng" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "Cổng" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Môđun" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Tùy chọn" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Khởi động" @@ -793,8 +798,8 @@ msgstr "Quy tắc Truy Cập" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -811,31 +816,31 @@ msgstr "Số người sử dụng đã đăng ký" msgid "Number of online users" msgstr "Số người sử dụng trực tuyến" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Đăng nhập lần cuối" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Kích thước bảng phân công" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Địa chỉ IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Nguồn tài nguyên" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Quản trị về " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Hành động đối với người sử dụng" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Chỉnh Sửa Thuộc Tính" @@ -845,29 +850,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "Sự truy cập bị chặn theo chính sách phục vụ" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Truyền tải IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Môdun ejabberd IRC Bản quyền" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định " "các thiết lập mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Đăng ký trong mod_irc cho " -#: mod_irc.erl:651 +#: mod_irc.erl:659 #, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " @@ -876,11 +893,11 @@ msgstr "" "Nhập tên truy cập và mã hóa mà bạn muốn sử dụng khi kết nối với các máy chủ " "IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "Tên truy cập IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 #, fuzzy msgid "" "If you want to specify different ports, passwords, encodings for IRC " @@ -892,7 +909,7 @@ msgstr "" "hãy điền vào danh sách này những giá trị theo định dạng '{\"máy chủ irc\", " "\"mã hóa\"}'. Dịch vụ này mặc định sử dụng định dạng mã hóa \"~s\"." -#: mod_irc.erl:696 +#: mod_irc.erl:704 #, fuzzy msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." @@ -901,36 +918,36 @@ msgstr "" "Ví dụ: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", " "\"iso8859-1\"}]" -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" -#: mod_irc.erl:891 +#: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "Tên truy cập IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 #, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " @@ -940,54 +957,84 @@ msgstr "" "Nhập tên truy cập và mã hóa mà bạn muốn sử dụng khi kết nối với các máy chủ " "IRC" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "Tên truy cập IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "Mật Khẩu" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "Cổng" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "Chỉ có người quản trị dịch vụ mới được phép gửi những thư dịch vụ" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "Việc tạo phòng bị ngăn lại theo chính sách dịch vụ" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Phòng họp không tồn tại" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Phòng trò chuyện" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để đăng ký " "bí danh" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Đăng Ký Bí Danh tại" -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Nhập bí danh bạn muốn đăng ký" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Bí danh" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#, fuzzy +msgid "That nickname is registered by another person" +msgstr "Một người khác đã đăng ký bí danh này rồi" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Bạn phải điền thông tin vào ô \"Nickname\" trong biểu mẫu này" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Môdun ejabberd MUC Bản quyền" @@ -1015,148 +1062,210 @@ msgstr "Người Sử Dụng Đã Đăng Ký" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "Cấu hình phòng trò chuyện được chỉnh sửa" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "tham gia phòng này" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "rời khỏi phòng này" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "đã bị cấm" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "bây giờ được biết như" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " đã đặt chủ đề thành: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Phòng trò chuyện" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "Thứ Hai" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "Thứ Ba" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "Thứ Tư" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "Thứ Năm" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "Thứ Sáu" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "Thứ Bảy" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "Chủ Nhật" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "Tháng Một" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "Tháng Hai" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "Tháng Ba" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "Tháng Tư" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "Tháng Năm" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "Tháng Sáu" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "Tháng Bảy" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "Tháng Tám" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "Tháng Chín" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "Tháng Mười" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "Tháng Mười Một" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "Tháng Mười Hai" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Cấu Hình Phòng" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 #, fuzzy msgid "Room Occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Quá giới hạn tỷ lệ lưu lượng truyền tải" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "Không được phép gửi những thư riêng đến phòng họp" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Cho phép người sử dụng gửi lời mời" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Loại thư không phù hợp" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "Không được phép gửi những thư riêng loại \"groupchat\"" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Người nhận không có trong phòng họp" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +#, fuzzy +msgid "It is not allowed to send private messages" +msgstr "Không được phép gửi những thư riêng đến phòng họp" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Chỉ có những đối tượng tham gia mới được phép gửi thư đến phòng họp" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "" +"Chỉ có những đối tượng tham gia mới được phép gửi yêu cầu đến phòng họp" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Không được phép gửi các yêu cầu gửi đến các thành viên trong phòng họp này" + +#: mod_muc_room.erl:961 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " @@ -1165,224 +1274,299 @@ msgstr "" "Chỉ có những người điều phối và những người tham gia được phép thay đổi chủ " "đề trong phòng này" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Người ghé thăm không được phép gửi thư đến tất cả các người tham dự" + +#: mod_muc_room.erl:1080 +#, fuzzy +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +#, fuzzy +msgid "That nickname is already in use by another occupant" +msgstr "Bí danh đang do một người tham dự khác sử dụng" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Bạn bị cấm tham gia phòng này" + +#: mod_muc_room.erl:1826 +#, fuzzy +msgid "Membership is required to enter this room" +msgstr "Yêu cầu tư cách thành viên khi tham gia vào phòng này" + +#: mod_muc_room.erl:1872 +#, fuzzy +msgid "A password is required to enter this room" +msgstr "Yêu cầu nhập mật khẩu để vào phòng này" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Mật khẩu sai" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "Yêu cầu đặc quyền của nhà quản trị" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "Yêu cầu đặc quyền của nhà điều phối" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s không hợp lệ" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Bí danh ~s không tồn tại trong phòng này" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Tư cách không hợp lệ: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Vai trò không hợp lệ: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "Yêu cầu đặc quyền của người sở hữu" + +#: mod_muc_room.erl:3348 #, fuzzy msgid "Configuration of room ~s" msgstr "Cấu hình cho " -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Tên phòng" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Miêu tả:" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Tạo phòng bền vững" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Tạo phòng có thể tìm kiếm công khai" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Tạo danh sách người tham dự công khai" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Tạo phòng được bảo vệ bằng mật khẩu" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Số Lượng Người Tham Dự Tối Đa" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Không giới hạn" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Jabber ID thực tế hiện hành đến" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "nhà điều phối duy nhất" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "bất kỳ ai" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "nhà điều phối duy nhất" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Tạo phòng chỉ cho phép tư cách thành viên tham gia" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 #, fuzzy msgid "Make room moderated" msgstr "Tạo phòng bền vững" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Người sử dụng mặc định là người tham dự" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 #, fuzzy msgid "Allow users to change the subject" msgstr "Cho phép người sử dụng thay đổi chủ đề" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Cho phép người sử dụng hỏi người sử dụng khác" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Cho phép người sử dụng gửi lời mời" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 #, fuzzy msgid "Allow visitors to send status text in presence updates" msgstr "Cho phép người sử dụng gửi thư riêng" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 #, fuzzy msgid "Allow visitors to change nickname" msgstr "Cho phép người sử dụng thay đổi chủ đề" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Cho phép người sử dụng gửi lời mời" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Tạo phòng được bảo vệ bằng mật khẩu" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Cho phép ghi nhật ký" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định " "cấu hình phòng họp" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "riêng," -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Người sử dụng " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s mời bạn vào phòng ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "mật khẩu là" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Danh sách chờ thư liên lạc ngoại tuyến của bạn đã đầy. Thư này đã bị loại bỏ." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s's Danh Sách Chờ Thư Ngoại Tuyến" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Thời Gian" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Từ" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Đến" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Gói thông tin" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Thư Ngoại Tuyến:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Thư Ngoại Tuyến" @@ -1391,118 +1575,132 @@ msgstr "Thư Ngoại Tuyến" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Môdun SOCKS5 Bytestreams Bản quyền" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Xuất Bản-Đăng Ký" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Môdun ejabberd Xuất Bản-Đăng Ký Bản quyền" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Yêu cầu người đăng ký môđun Xuất Bản Đăng Ký" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Chọn có nên chấp nhận sự đăng ký của đối tượng này không" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID Nút" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Địa Chỉ Người Đăng Ký" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "Cho phép Jabber ID đăng ký nút môđun xuất bản đăng ký này không?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Đưa ra thông tin dung lượng với các thông báo sự kiện" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Đưa ra các thông báo sự kiện" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Thông báo cho người đăng ký khi nào cấu hình nút thay đổi" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Thông báo cho người đăng ký khi nào nút bị xóa bỏ" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Thông báo cho người đăng ký khi nào các mục chọn bị gỡ bỏ khỏi nút" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Những mục cần để lưu trữ" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Số mục tối đa để lưu trữ" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Xác định nên cho phép đăng ký không" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Xác định mô hình truy cập" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Xác định mô hình nhà xuất bản" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Xác định mô hình truy cập" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Kích thước dung lượng byte tối đa" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Khi cần gửi mục được xuất bản cuối cùng" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Chỉ gửi thông báo đến những người sử dụng hiện có" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "" + +#: mod_register.erl:253 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để đăng ký " "bí danh" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "Chọn một tên truy cập và mật khẩu để đăng ký với máy chủ này" +#: mod_register.erl:373 mod_register.erl:421 +#, fuzzy +msgid "The password is too weak" +msgstr "mật khẩu là" + +#: mod_register.erl:426 +#, fuzzy +msgid "Users are not allowed to register accounts so quickly" +msgstr "Người ghé thăm không được phép gửi thư đến tất cả các người tham dự" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1576,8 +1774,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1615,60 +1813,60 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Đăng ký" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Chờ" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Nhóm" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Xác nhận hợp lệ" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Gỡ bỏ" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Bảng phân công của " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Thêm Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Bảng phân công" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Nhóm Phân Công Chia Sẻ" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Tên:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Miêu tả:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Thành viên:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Nhóm được hiển thị:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Nhóm " @@ -1747,111 +1945,15 @@ msgstr "" "Điền vào các ô để tìm kiếm bất kỳ các thông tin nào khớp với Người sử dụng " "Jabber" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Máy chủ Bên Ngoài s2s:" + #~ msgid "Delete" #~ msgstr "Xóa" #~ msgid "This room is not anonymous" #~ msgstr "Phòng này không nặc danh" -#~ msgid "Access denied by service policy" -#~ msgstr "Sự truy cập bị chặn theo chính sách phục vụ" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "Chỉ có người quản trị dịch vụ mới được phép gửi những thư dịch vụ" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "Việc tạo phòng bị ngăn lại theo chính sách dịch vụ" - -#~ msgid "Conference room does not exist" -#~ msgstr "Phòng họp không tồn tại" - -#, fuzzy -#~ msgid "That nickname is registered by another person" -#~ msgstr "Một người khác đã đăng ký bí danh này rồi" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Bạn phải điền thông tin vào ô \"Nickname\" trong biểu mẫu này" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Quá giới hạn tỷ lệ lưu lượng truyền tải" - -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "Không được phép gửi những thư riêng đến phòng họp" - -#~ msgid "Improper message type" -#~ msgstr "Loại thư không phù hợp" - -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "Không được phép gửi những thư riêng loại \"groupchat\"" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Người nhận không có trong phòng họp" - -#, fuzzy -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Không được phép gửi những thư riêng đến phòng họp" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Chỉ có những đối tượng tham gia mới được phép gửi thư đến phòng họp" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "" -#~ "Chỉ có những đối tượng tham gia mới được phép gửi yêu cầu đến phòng họp" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Không được phép gửi các yêu cầu gửi đến các thành viên trong phòng họp này" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Người ghé thăm không được phép gửi thư đến tất cả các người tham dự" - -#, fuzzy -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "" -#~ "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" - -#, fuzzy -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Bí danh đang do một người tham dự khác sử dụng" - -#~ msgid "You have been banned from this room" -#~ msgstr "Bạn bị cấm tham gia phòng này" - -#, fuzzy -#~ msgid "Membership is required to enter this room" -#~ msgstr "Yêu cầu tư cách thành viên khi tham gia vào phòng này" - -#, fuzzy -#~ msgid "A password is required to enter this room" -#~ msgstr "Yêu cầu nhập mật khẩu để vào phòng này" - -#~ msgid "Incorrect password" -#~ msgstr "Mật khẩu sai" - -#~ msgid "Administrator privileges required" -#~ msgstr "Yêu cầu đặc quyền của nhà quản trị" - -#~ msgid "Moderator privileges required" -#~ msgstr "Yêu cầu đặc quyền của nhà điều phối" - -#~ msgid "Owner privileges required" -#~ msgstr "Yêu cầu đặc quyền của người sở hữu" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Danh sách chờ thư liên lạc ngoại tuyến của bạn đã đầy. Thư này đã bị loại " -#~ "bỏ." - -#, fuzzy -#~ msgid "The password is too weak" -#~ msgstr "mật khẩu là" - -#, fuzzy -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Người ghé thăm không được phép gửi thư đến tất cả các người tham dự" - #~ msgid "Encodings" #~ msgstr "Mã hóa" diff --git a/priv/msgs/wa.msg b/priv/msgs/wa.msg index 8fee456c687..9c79a6f7d30 100644 --- a/priv/msgs/wa.msg +++ b/priv/msgs/wa.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","Apontiaedje des droets (ACL)"}. {"Access control lists","Droets (ACL)"}. {"Access Control Lists","Droets (ACL)"}. +{"Access denied by service policy","L' accès a stî rfuzé pal politike do siervice"}. {"Access rules","Rîles d' accès"}. {"Access Rules","Rîles d' accès"}. {"Action on user","Accion so l' uzeu"}. @@ -11,6 +12,7 @@ {"Add User","Radjouter èn uzeu"}. {"Administration","Manaedjaedje"}. {"Administration of ","Manaedjaedje di "}. +{"Administrator privileges required","I fåt des priviledjes di manaedjeu"}. {"A friendly name for the node","On no uzeu-ahessåve pol nuk"}. {"All activity","Dispoy todi"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Permete ki ci Jabber ID ci si poye abouner a ç' nuk eplaidaedje-abounmint ci?"}. @@ -39,6 +41,7 @@ {"Choose whether to approve this entity's subscription.","Tchoezi s' i fåt aprover ou nén l' abounmint di ciste intité."}. {"City","Veye"}. {"Commands","Comandes"}. +{"Conference room does not exist","Li såle di conferince n' egzistêye nén"}. {"Configuration","Apontiaedjes"}. {"Connected Resources:","Raloyî avou les rsoûces:"}. {"Country","Payis"}. @@ -102,12 +105,17 @@ {"Import User from File at ","Sititchî uzeu d' on fitchî so "}. {"Import Users from Dir at ","Sitichî des uzeus d' on ridant so "}. {"Import Users From jabberd14 Spool Files","Sititchî des uzeus Jabberd 1.4"}. +{"Improper message type","Sôre di messaedje nén valide"}. +{"Incorrect password","Sicret nén corek"}. {"Invalid affiliation: ~s","Afiyaedje nén valide: ~s"}. {"Invalid role: ~s","Role nén valide: ~s"}. {"IP addresses","Adresses IP"}. {"IRC Transport","Transpoirt IRC"}. {"IRC Username","No d' uzeu IRC"}. {"is now known as","est asteure kinoxhou come"}. +{"It is not allowed to send private messages","Ci n' est nén permetou d' evoyî des messaedjes privés"}. +{"It is not allowed to send private messages of type \"groupchat\"","C' est nén possibe d' evoyî des messaedjes privés del sôre «groupchat»"}. +{"It is not allowed to send private messages to the conference","On n' pout nén evoyî des messaedjes privés dins cisse conferince ci"}. {"Jabber ID","ID Jabber"}. {"Jabber ID ~s is invalid","Li Jabber ID ~s n' est nén valide"}. {"January","djanvî"}. @@ -138,6 +146,7 @@ {"Memory","Memwere"}. {"Message body","Coir do messaedje"}. {"Middle Name","No do mitan"}. +{"Moderator privileges required","I fåt des priviledjes di moderateu"}. {"moderators only","les moderateus seulmint"}. {"Module","Module"}. {"Modules","Modules"}. @@ -171,12 +180,15 @@ {"Online Users:","Uzeus raloyîs:"}. {"Online Users","Uzeus raloyîs"}. {"Only deliver notifications to available users","Seulmint evoyî des notifiaedje åzès uzeus disponibes"}. +{"Only occupants are allowed to send messages to the conference","Seulmint les prezints polèt evoyî des messaedjes al conferince"}. +{"Only occupants are allowed to send queries to the conference","Seulmint les prezints polèt evoyî des cweraedjes sol conferince"}. +{"Only service administrators are allowed to send service messages","Seulmint les manaedjeus d' siervices polèt evoyî des messaedjes di siervice"}. {"Options","Tchuzes"}. {"Organization Name","No d' l' organizåcion"}. {"Organization Unit","Unité d' l' organizåcion"}. {"Outgoing s2s Connections:","Raloyaedjes s2s e rexhowe:"}. {"Outgoing s2s Connections","Raloyaedjes s2s e rexhowe"}. -{"Outgoing s2s Servers:","Sierveus s2s e rexhowe:"}. +{"Owner privileges required","I fåt des priviledjes di prôpietaire"}. {"Packet","Paket"}. {"Password:","Sicret:"}. {"Password","Sicret"}. @@ -193,10 +205,12 @@ {"private, ","privé, "}. {"Publish-Subscribe","Eplaidaedje-abounmint"}. {"PubSub subscriber request","Dimande d' eplaidaedje-abounmint d' èn abouné"}. +{"Queries to the conference members are not allowed in this room","Les cweraedjes des mimbes del conferince ni sont nén permetous dins cisse såle ci"}. {"RAM and disc copy","Copeye e memwere (RAM) et sol deure plake"}. {"RAM copy","Copeye e memwere (RAM)"}. {"Raw","Dinêyes brutes"}. {"Really delete message of the day?","Voloz vs vormint disfacer l' messaedje do djoû?"}. +{"Recipient is not in the conference room","Li riçuveu n' est nén dins l' såle di conferince"}. {"Registered Users:","Uzeus edjistrés:"}. {"Registered Users","Uzeus edjistrés"}. {"Registration in mod_irc for ","Edjîstraedje dins mod_irc po "}. @@ -213,6 +227,7 @@ {"Restore plain text backup immediately:","Rapexhî do côp foû d' ene copeye di såvrité tecse:"}. {"Restore","Rapexhî"}. {"Room Configuration","Apontiaedje del såle"}. +{"Room creation is denied by service policy","L' ahivaedje del såle est rfuzé pal politike do siervice"}. {"Room title","Tite del såle"}. {"Roster","Djivêye des soçons"}. {"Roster groups allowed to subscribe","Pårtaedjîs groupes di soçons k' on s' î pout abouner"}. @@ -264,6 +279,7 @@ {"Time delay","Tårdjaedje"}. {"To","Po"}. {"To ~s","Viè ~s"}. +{"Traffic rate limit is exceeded","Li limite pol volume di trafik a stî passêye"}. {"Transactions Aborted:","Transaccions arestêyes:"}. {"Transactions Committed:","Transaccions evoyeyes:"}. {"Transactions Logged:","Transaccions wårdêyes e djournå:"}. @@ -283,9 +299,14 @@ {"Validate","Valider"}. {"vCard User Search","Calpin des uzeus"}. {"Virtual Hosts","Forveyous sierveus"}. +{"Visitors are not allowed to change their nicknames in this room","Les viziteus èn polèt nén candjî leus metous no po ç' såle ci"}. +{"Visitors are not allowed to send messages to all occupants","Les viziteus n' polèt nén evoyî des messaedjes a tos les prezints"}. {"Wednesday","mierkidi"}. {"When to send the last published item","Cwand evoyî l' dierin cayet eplaidî"}. {"Whether to allow subscriptions","Si on permete les abounmints"}. +{"You have been banned from this room","Vos avoz stî bani di cisse såle ci"}. +{"You must fill in field \"Nickname\" in the form","Vos dvoz rimpli l' tchamp «Metou no» dins l' formiulaire"}. {"You need an x:data capable client to configure mod_irc settings","Vos avoz mezåjhe d' on cliyint ki sopoite x:data po candjî ls apontiaedjes di mod_irc"}. {"You need an x:data capable client to configure room","I vs fåt on cliyint ki sopoite x:data por vos poleur apontyî l' såle"}. {"You need an x:data capable client to search","Vos avoz mezåjhe d' on cliyint ki sopoite x:data po fé on cweraedje"}. +{"Your contact offline message queue is full. The message has been discarded.","Li cawêye di messaedjes e môde disraloyî di vosse soçon est plinne. Li messaedje a stî tapé å diale."}. diff --git a/priv/msgs/wa.po b/priv/msgs/wa.po index ae42f0b269e..d5c7ef1899d 100644 --- a/priv/msgs/wa.po +++ b/priv/msgs/wa.po @@ -7,50 +7,54 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Walon (Walloon)\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "L' eployaedje di STARTTL est oblidjî" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "Nole rissoûce di dnêye" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "Replaecî pa on novea raloyaedje" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "a stî pité evoye" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "" + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 #, fuzzy msgid "Enter the text you see" msgstr "Dinez l' tchimin viè l' fitchî tecse" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "" -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "" -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "Uzeu" @@ -59,9 +63,9 @@ msgstr "Uzeu" msgid "Server" msgstr "Måy" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Sicret" @@ -78,280 +82,281 @@ msgstr "" msgid "ejabberd Web Admin" msgstr "Manaedjeu waibe ejabberd" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "Manaedjaedje" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "Droets (ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "Candjmints evoyîs" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "Mwais fôrmat" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "Evoyî" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "Dinêyes brutes" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "Disfacer les elemints tchoezis" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "Rîles d' accès" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "Apontiaedje des rîles d' accès a ~s" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "Forveyous sierveus" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "Uzeus" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "Uzeus raloyîs" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "Dierinne activité des uzeus" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "Termene:" -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "Dierin moes" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "Dierinne anêye" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "Dispoy todi" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "Mostrer crexhince" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "Mostrer totå" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "Sitatistikes" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 #, fuzzy msgid "Not Found" msgstr "Nuk nén trové" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "Nuk nén trové" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "Radjouter" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "Sierveu" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "Uzeus edjistrés" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "Radjouter èn uzeu" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "Messaedjes ki ratindèt" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "Dierinne activité" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "Måy" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "Raloyî" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "Uzeus edjistrés:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "Uzeus raloyîs:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "Raloyaedjes s2s e rexhowe:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "Sierveus s2s e rexhowe:" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "Raloyaedjes s2s e rexhowe:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "Nole" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "Candjî l' sicret" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "Uzeu " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "Raloyî avou les rsoûces:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "Sicret:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "Disfacer l' uzeu" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "Nole dinêye disponibe" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "Nuks" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "Nuks en alaedje" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "Nuks essoctés" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "Nuk " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "Båze di dnêyes" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "Copeye di såvrité" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "Pôrts drovous" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "Mete a djoû" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "Renonder" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "Arester" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "Modules" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "Aroke di houcaedje RPC" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "Tåves del båze di dnêyes so " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "No" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "Sôre di wårdaedje" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "Memwere" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "Copeye di såvrité po " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 #, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " @@ -363,149 +368,149 @@ msgstr "" "båze di dnêyes avou l' module ODBC, vos dvoz fé ene copeye di såvrité del " "båze SQL da vosse sepårumint." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "Copeye di såvrité binaire:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "'l est bon" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "Rapexhî do côp foû d' ene copeye di såvrité binaire:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Rapexhî l' copeye di såvrité binaire après l' renondaedje ki vént " "d' ejabberd (çoula prind moens d' memwere del fé insi):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "Copeye di såvrité tecse:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "Rapexhî do côp foû d' ene copeye di såvrité tecse:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 #, fuzzy msgid "Import user data from jabberd14 spool file:" msgstr "Sititchî des uzeus Jabberd 1.4" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 #, fuzzy msgid "Import users data from jabberd14 spool directory:" msgstr "Sititchî des uzeus Jabberd 1.4" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Pôrts drovous so " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "Modules so " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "Sitatistikes di ~p" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "Tins dispoy l' enondaedje:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "Tins CPU:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "Transaccions evoyeyes:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "Transaccions arestêyes:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "Transaccions renondêyes:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "Transaccions wårdêyes e djournå:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "Metaedje a djoû " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan d' metaedje a djoû" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 #, fuzzy msgid "Modified modules" msgstr "Modules metous a djoû" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "Sicripe di metaedje a djoû" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "Sicripe di metaedje a djoû d' bas livea" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "Acertinaedje do scripe" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Pôrt" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 #, fuzzy msgid "Protocol" msgstr "Pôrt" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "Module" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "Tchuzes" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "Enonder" @@ -791,8 +796,8 @@ msgstr "Rîles d' accès" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" @@ -809,31 +814,31 @@ msgstr "Nombe d' uzeus edjîstrés" msgid "Number of online users" msgstr "Nombe d' uzeus raloyîs" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "Dierin elodjaedje" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "Grandeu del djivêye des soçons" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "Adresses IP" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "Rissoûces" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "Manaedjaedje di " -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "Accion so l' uzeu" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "Candjî les prôpietés" @@ -843,29 +848,41 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "L' accès a stî rfuzé pal politike do siervice" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "Transpoirt IRC" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "Module IRC po ejabberd" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po candjî ls apontiaedjes " "di mod_irc" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "Edjîstraedje dins mod_irc po " -#: mod_irc.erl:651 +#: mod_irc.erl:659 #, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " @@ -874,11 +891,11 @@ msgstr "" "Dinez les nos d' uzeu et ls ecôdaedjes ki vos vloz eployî po vs raloyî åzès " "sierveus IRC" -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "No d' uzeu IRC" -#: mod_irc.erl:674 +#: mod_irc.erl:682 #, fuzzy msgid "" "If you want to specify different ports, passwords, encodings for IRC " @@ -890,7 +907,7 @@ msgstr "" "cisse djivêye ci avou des valixhances del cogne «{\"sierveu irc\", " "\"ecôdaedje\"}». Li prémetou ecôdaedje do siervice c' est «~s»." -#: mod_irc.erl:696 +#: mod_irc.erl:704 #, fuzzy msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." @@ -899,36 +916,36 @@ msgstr "" "Egzimpe: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", " "\"iso8859-1\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "" -#: mod_irc.erl:891 +#: mod_irc.erl:903 #, fuzzy msgid "IRC server" msgstr "No d' uzeu IRC" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "" -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 #, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " @@ -938,53 +955,84 @@ msgstr "" "Dinez les nos d' uzeu et ls ecôdaedjes ki vos vloz eployî po vs raloyî åzès " "sierveus IRC" -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 #, fuzzy msgid "IRC username" msgstr "No d' uzeu IRC" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 #, fuzzy msgid "Password ~b" msgstr "Sicret" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 #, fuzzy msgid "Port ~b" msgstr "Pôrt" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "" +"Seulmint les manaedjeus d' siervices polèt evoyî des messaedjes di siervice" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "L' ahivaedje del såle est rfuzé pal politike do siervice" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "Li såle di conferince n' egzistêye nén" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "Såles di berdelaedje" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "Edjîstraedje di metou no amon " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "Dinez l' metou no ki vos vloz edjîstrer" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "Metou no" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#, fuzzy +msgid "That nickname is registered by another person" +msgstr "Li metou no est ddja edjîstré pa ene ôte sakî" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "Vos dvoz rimpli l' tchamp «Metou no» dins l' formiulaire" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "Module MUC (såles di berdelaedje) po ejabberd" @@ -1012,149 +1060,210 @@ msgstr "Uzeus edjistrés" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "L' apontiaedje del såle di berdelaedje a candjî" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "arive sol såle" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "cwite li såle" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "a stî bani" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "a stî pité evoye cåze d' on candjmint d' afiyaedje" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "" "a stî pité evoye cåze ki l' såle a stî ristrindowe åzès mimbes seulmint" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "a stî pité evoye cåze d' èn arestaedje do sistinme" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "est asteure kinoxhou come" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr " a candjî l' tite a: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 #, fuzzy msgid "Chatroom is created" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 #, fuzzy msgid "Chatroom is destroyed" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 #, fuzzy msgid "Chatroom is started" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 #, fuzzy msgid "Chatroom is stopped" msgstr "Såles di berdelaedje" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "londi" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "mårdi" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "mierkidi" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "djudi" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "vénrdi" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "semdi" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "dimegne" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "djanvî" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "fevrî" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "måss" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "avri" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "may" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "djun" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "djulete" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "awousse" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "setimbe" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "octôbe" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "nôvimbe" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "decimbe" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "Apontiaedje del såle" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 #, fuzzy msgid "Room Occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "Li limite pol volume di trafik a stî passêye" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "On n' pout nén evoyî des messaedjes privés dins cisse conferince ci" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "" + +#: mod_muc_room.erl:377 +#, fuzzy +msgid "Only moderators can approve voice requests" +msgstr "Les uzeus polèt evoyî priyaedjes" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "Sôre di messaedje nén valide" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "C' est nén possibe d' evoyî des messaedjes privés del sôre «groupchat»" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "Li riçuveu n' est nén dins l' såle di conferince" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "Ci n' est nén permetou d' evoyî des messaedjes privés" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "Seulmint les prezints polèt evoyî des messaedjes al conferince" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "Seulmint les prezints polèt evoyî des cweraedjes sol conferince" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "" +"Les cweraedjes des mimbes del conferince ni sont nén permetous dins cisse " +"såle ci" + +#: mod_muc_room.erl:961 #, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " @@ -1163,221 +1272,296 @@ msgstr "" "Seulmint les moderateus et les pårticipants polèt candjî l' sudjet dins " "cisse såle ci" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 #, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "Les viziteus n' polèt nén evoyî des messaedjes a tos les prezints" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "Les viziteus èn polèt nén candjî leus metous no po ç' såle ci" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +#, fuzzy +msgid "That nickname is already in use by another occupant" +msgstr "Li metou no est ddja eployî pa ene ôte sakî sol såle" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "Vos avoz stî bani di cisse såle ci" + +#: mod_muc_room.erl:1826 +#, fuzzy +msgid "Membership is required to enter this room" +msgstr "I fåt esse mimbe po poleur intrer dins cisse såle ci" + +#: mod_muc_room.erl:1872 +#, fuzzy +msgid "A password is required to enter this room" +msgstr "I fåt dner on scret po poleur intrer dins cisse såle ci" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "Sicret nén corek" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "I fåt des priviledjes di manaedjeu" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "I fåt des priviledjes di moderateu" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Li Jabber ID ~s n' est nén valide" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "Li metou no ~s n' egzistêye nén dins l' såle" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "Afiyaedje nén valide: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "Role nén valide: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "I fåt des priviledjes di prôpietaire" + +#: mod_muc_room.erl:3348 #, fuzzy msgid "Configuration of room ~s" msgstr "Apontiaedje po " -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "Tite del såle" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 #, fuzzy msgid "Room description" msgstr "Discrijhaedje:" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "Rinde li såle permaninte" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "Rinde li såle di berdelaedje cweråve publicmint" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "Rinde publike li djivêye des pårticipants" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "Rinde li såle di berdelaedje protedjeye pa scret" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "Nombe macsimom di prezints" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "Pont d' limite" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "Mostrer les vraiys Jabber IDs a" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "les moderateus seulmint" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "tot l' minme kî" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "les moderateus seulmint" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "Rinde li såle di berdelaedje ristrindowe ås mimbes seulmint" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "Rinde li såle di berdelaedje moderêye" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "Les uzeus sont des pårticipants come prémetowe dujhance" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 #, fuzzy msgid "Allow users to change the subject" msgstr "Les uzeus polèt candjî l' tite" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "Les uzeus polèt evoyî des messaedjes privés" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 #, fuzzy msgid "Allow visitors to send private messages to" msgstr "Les uzeus polèt evoyî des messaedjes privés" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "Les uzeus polèt cweri ls ôtes uzeus" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "Les uzeus polèt evoyî priyaedjes" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "" "Permete ki les viziteus evoyexhe des tecse d' estat dins leus messaedjes di " "prezince" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "Permete ki les viziteus candjexhe leus metous nos" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 #, fuzzy msgid "Allow visitors to send voice requests" msgstr "Les uzeus polèt evoyî priyaedjes" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 #, fuzzy msgid "Make room CAPTCHA protected" msgstr "Rinde li såle di berdelaedje protedjeye pa scret" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "Mete en alaedje li djournå" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "I vs fåt on cliyint ki sopoite x:data por vos poleur apontyî l' såle" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 #, fuzzy msgid "User JID" msgstr "Uzeu " -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s vos preye sol såle ~s" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "li scret est" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "" +"Li cawêye di messaedjes e môde disraloyî di vosse soçon est plinne. Li " +"messaedje a stî tapé å diale." + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "messaedjes ki ratindèt el cawêye po ~s" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "Date" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "Di" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "Po" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "Paket" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "Messaedjes ki ratindèt:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 #, fuzzy msgid "Remove All Offline Messages" msgstr "Messaedjes ki ratindèt" @@ -1386,119 +1570,133 @@ msgstr "Messaedjes ki ratindèt" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "Module SOCKS5 Bytestreams po ejabberd" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "Eplaidaedje-abounmint" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "Module d' eplaidaedje-abounmint po ejabberd" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "Dimande d' eplaidaedje-abounmint d' èn abouné" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "Tchoezi s' i fåt aprover ou nén l' abounmint di ciste intité." -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "ID d' nuk" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "Adresse di l' abouné" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "" "Permete ki ci Jabber ID ci si poye abouner a ç' nuk eplaidaedje-abounmint ci?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "Evoyî l' contnou avou les notifiaedjes d' evenmints" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "Evoyî des notifiaedjes d' evenmints" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "Notifyî åzès abounés cwand l' apontiaedje do nuk candje" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "Notifyî åzès abounés cwand l' nuk est disfacé" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "Notifyî åzès abounés cwand des cayets sont oisté foû do nuk" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "Cayets permanints a wårder" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "On no uzeu-ahessåve pol nuk" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "Nombe macsimoms di cayets permanints" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "Si on permete les abounmints" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "Sipecifyî l' modele d' accès" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "Pårtaedjîs groupes di soçons k' on s' î pout abouner" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "Dinez l' modele d' eplaideu" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 #, fuzzy msgid "Specify the event message type" msgstr "Sipecifyî l' modele d' accès" -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "Contnou macsimom en octets" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "Cwand evoyî l' dierin cayet eplaidî" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "Seulmint evoyî des notifiaedje åzès uzeus disponibes" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "" + +#: mod_register.erl:253 #, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "" "Tchoezixhoz on no d' uzeu eyet on scret po vs edjîstrer so ç' sierveu ci" +#: mod_register.erl:373 mod_register.erl:421 +#, fuzzy +msgid "The password is too weak" +msgstr "li scret est" + +#: mod_register.erl:426 +#, fuzzy +msgid "Users are not allowed to register accounts so quickly" +msgstr "Les noveas uzeus n' si polèt nén edjîstrer si raddimint" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "" @@ -1572,8 +1770,8 @@ msgstr "" #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" #: mod_register_web.erl:256 @@ -1611,60 +1809,60 @@ msgstr "" msgid "Unregister" msgstr "" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "Abounmimnt" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "Ratindant" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "Groupes" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "Valider" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "Oister" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "Djivêye des soçons da " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "Radjouter èn ID Jabber" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "Djivêye des soçons" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "Pårtaedjîs groupes ezès djivêyes di soçons" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "Pitit no:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "Discrijhaedje:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "Mimbes:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "Groupes håynés:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "Groupe " @@ -1740,48 +1938,21 @@ msgstr "Rizultats do cweraedje po " msgid "Fill in fields to search for any matching Jabber User" msgstr "Rimplixhoz les tchamps po cweri èn uzeu Jabber" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "Sierveus s2s e rexhowe:" + #~ msgid "Delete" #~ msgstr "Disfacer" #~ msgid "This room is not anonymous" #~ msgstr "Cisse såle ci n' est nén anonime" -#~ msgid "Access denied by service policy" -#~ msgstr "L' accès a stî rfuzé pal politike do siervice" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "" -#~ "Seulmint les manaedjeus d' siervices polèt evoyî des messaedjes di " -#~ "siervice" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "L' ahivaedje del såle est rfuzé pal politike do siervice" - -#~ msgid "Conference room does not exist" -#~ msgstr "Li såle di conferince n' egzistêye nén" - -#, fuzzy -#~ msgid "That nickname is registered by another person" -#~ msgstr "Li metou no est ddja edjîstré pa ene ôte sakî" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "Vos dvoz rimpli l' tchamp «Metou no» dins l' formiulaire" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "Li limite pol volume di trafik a stî passêye" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "" #~ "Ci pårticipant ci a stî pité evoye del såle cåze k' il a-st evoyî on " #~ "messaedje d' aroke" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "On n' pout nén evoyî des messaedjes privés dins cisse conferince ci" - -#~ msgid "Improper message type" -#~ msgstr "Sôre di messaedje nén valide" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" @@ -1789,81 +1960,12 @@ msgstr "Rimplixhoz les tchamps po cweri èn uzeu Jabber" #~ "Ci pårticipant ci a stî pité evoye del såle cåze k' il a-st evoyî on " #~ "messaedje d' aroke a èn ôte pårticipant" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "" -#~ "C' est nén possibe d' evoyî des messaedjes privés del sôre «groupchat»" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "Li riçuveu n' est nén dins l' såle di conferince" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "Ci n' est nén permetou d' evoyî des messaedjes privés" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "Seulmint les prezints polèt evoyî des messaedjes al conferince" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "Seulmint les prezints polèt evoyî des cweraedjes sol conferince" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "" -#~ "Les cweraedjes des mimbes del conferince ni sont nén permetous dins cisse " -#~ "såle ci" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "Les viziteus n' polèt nén evoyî des messaedjes a tos les prezints" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "" #~ "Ci pårticipant ci a stî pité evoye del såle cåze k' il a-st evoyî ene " #~ "aroke di prezince" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "Les viziteus èn polèt nén candjî leus metous no po ç' såle ci" - -#, fuzzy -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "Li metou no est ddja eployî pa ene ôte sakî sol såle" - -#~ msgid "You have been banned from this room" -#~ msgstr "Vos avoz stî bani di cisse såle ci" - -#, fuzzy -#~ msgid "Membership is required to enter this room" -#~ msgstr "I fåt esse mimbe po poleur intrer dins cisse såle ci" - -#, fuzzy -#~ msgid "A password is required to enter this room" -#~ msgstr "I fåt dner on scret po poleur intrer dins cisse såle ci" - -#~ msgid "Incorrect password" -#~ msgstr "Sicret nén corek" - -#~ msgid "Administrator privileges required" -#~ msgstr "I fåt des priviledjes di manaedjeu" - -#~ msgid "Moderator privileges required" -#~ msgstr "I fåt des priviledjes di moderateu" - -#~ msgid "Owner privileges required" -#~ msgstr "I fåt des priviledjes di prôpietaire" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "" -#~ "Li cawêye di messaedjes e môde disraloyî di vosse soçon est plinne. Li " -#~ "messaedje a stî tapé å diale." - -#, fuzzy -#~ msgid "The password is too weak" -#~ msgstr "li scret est" - -#, fuzzy -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "Les noveas uzeus n' si polèt nén edjîstrer si raddimint" - #~ msgid "Encodings" #~ msgstr "Ecôdaedjes" diff --git a/priv/msgs/zh.msg b/priv/msgs/zh.msg index 131b84f7065..41309b16557 100644 --- a/priv/msgs/zh.msg +++ b/priv/msgs/zh.msg @@ -3,6 +3,7 @@ {"Access Control List Configuration","访问控制列表(ACL)配置"}. {"Access control lists","访问控制列表(ACL)"}. {"Access Control Lists","访问控制列表(ACL)"}. +{"Access denied by service policy","访问被服务策略拒绝"}. {"Access rules","访问规则"}. {"Access Rules","访问规则"}. {"Action on user","对用户的动作"}. @@ -11,6 +12,7 @@ {"Add User","添加用户"}. {"Administration of ","管理"}. {"Administration","管理"}. +{"Administrator privileges required","需要管理员权限"}. {"A friendly name for the node","该节点的友好名称"}. {"All activity","所有活动"}. {"Allow this Jabber ID to subscribe to this pubsub node?","允许该 Jabber ID 订阅该 pubsub 节点?"}. @@ -25,6 +27,7 @@ {"All Users","所有用户"}. {"Announcements","通知"}. {"anyone","任何人"}. +{"A password is required to enter this room","进入此房间需要密码"}. {"April","四月"}. {"August","八月"}. {"Backup Management","备份管理"}. @@ -48,6 +51,7 @@ {"Choose whether to approve this entity's subscription.","选择是否允许该实体的订阅"}. {"City","城市"}. {"Commands","命令"}. +{"Conference room does not exist","会议室不存在"}. {"Configuration of room ~s","房间 ~s 的配置 "}. {"Configuration","配置"}. {"Connected Resources:","已连接资源:"}. @@ -98,6 +102,7 @@ {"Exclude Jabber IDs from CAPTCHA challenge","从验证码挑战中排除 Jabber ID"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","将服务器上所有用户的数据导出到 PIEFXIS 文件 (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","将某主机的用户数据导出到 PIEFXIS 文件 (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","无法从你的声音请求确认信息中提取JID"}. {"Family Name","姓氏"}. {"February","二月"}. {"Fill in fields to search for any matching Jabber User","填充字段以搜索任何匹配的 Jabber 用户"}. @@ -131,6 +136,8 @@ {"Import users data from jabberd14 spool directory:","从 jabberd14 Spool 目录导入用户数据:"}. {"Import Users from Dir at ","导入用户的目录位于 "}. {"Import Users From jabberd14 Spool Files","从 jabberd14 Spool 文件导入用户"}. +{"Improper message type","不恰当的消息类型"}. +{"Incorrect password","密码不正确"}. {"Invalid affiliation: ~s","无效加入: ~s"}. {"Invalid role: ~s","无效角色: ~s"}. {"IP addresses","IP 地址"}. @@ -142,6 +149,9 @@ {"IRC username","IRC 用户名"}. {"IRC Username","IRC 用户名"}. {"is now known as","现在称呼为"}. +{"It is not allowed to send private messages of type \"groupchat\"","\"群组聊天\"类型不允许发送私聊消息"}. +{"It is not allowed to send private messages to the conference","不允许向会议发送私聊消息"}. +{"It is not allowed to send private messages","不可以发送私聊消息"}. {"Jabber Account Registration","Jabber 帐户注册"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s 无效"}. @@ -173,12 +183,14 @@ {"Max # of items to persist","允许持久化的最大内容条目数"}. {"Max payload size in bytes","最大有效负载字节数"}. {"May","五月"}. +{"Membership is required to enter this room","进入此房间需要会员身份"}. {"Members:","会员:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","记住你的密码, 或将其记到纸上并放于安全位置. 如果你忘记了密码, Jabber 也没有自动恢复密码的方式."}. {"Memory","内存"}. {"Message body","消息主体"}. {"Middle Name","中间名"}. {"Minimum interval between voice requests (in seconds)","声音请求的最小间隔(以秒为单位)"}. +{"Moderator privileges required","需要主持人权限"}. {"moderators only","仅主持人"}. {"Modified modules","被修改模块"}. {"Modules","模块"}. @@ -219,12 +231,16 @@ {"Only deliver notifications to available users","仅将通知发送给可发送的用户"}. {"Only moderators and participants are allowed to change the subject in this room","只有主持人和参与人可以在此房间里更改主题"}. {"Only moderators are allowed to change the subject in this room","只有主持人可以在此房间里更改主题"}. +{"Only moderators can approve voice requests","仅主持人能确认声音请求"}. +{"Only occupants are allowed to send messages to the conference","只有与会人可以向大会发送消息"}. +{"Only occupants are allowed to send queries to the conference","只有与会人可以向大会发出查询请求"}. +{"Only service administrators are allowed to send service messages","只有服务管理员可以发送服务消息"}. {"Options","选项"}. {"Organization Name","组织名称"}. {"Organization Unit","组织单位"}. {"Outgoing s2s Connections:","出站 s2s 连接:"}. {"Outgoing s2s Connections","出站 s2s 连接"}. -{"Outgoing s2s Servers:","出站 s2s 服务器"}. +{"Owner privileges required","需要持有人权限"}. {"Packet","数据包"}. {"Password ~b","~b 的密码"}. {"Password Verification:","密码确认:"}. @@ -238,6 +254,7 @@ {"Persist items to storage","持久化内容条目"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","注意:这些选项仅将备份内置的 Mnesia 数据库. 如果您正在使用 ODBC 模块, 您还需要分别备份您的数据库."}. +{"Please, wait for a while before sending new voice request","请稍后再发送新的声音请求"}. {"Pong","Pong"}. {"Port ~b","~b 的端口"}. {"Port","端口"}. @@ -247,10 +264,12 @@ {"Publish-Subscribe","发行-订阅"}. {"PubSub subscriber request","PubSub 订阅人请求"}. {"Purge all items when the relevant publisher goes offline","相关发布人离线后清除所有选项"}. +{"Queries to the conference members are not allowed in this room","本房间不可以查询会议成员信息"}. {"RAM and disc copy","内存与磁盘复制"}. {"RAM copy","内存(RAM)复制"}. {"Raw","原始格式"}. {"Really delete message of the day?","确实要删除每日消息吗?"}. +{"Recipient is not in the conference room","接收人不在会议室"}. {"Register a Jabber account","注册 Jabber 帐户"}. {"Registered Users:","注册用户:"}. {"Registered Users","注册用户"}. @@ -270,6 +289,7 @@ {"Restore plain text backup immediately:","立即恢复普通文本备份:"}. {"Restore","恢复"}. {"Room Configuration","房间配置"}. +{"Room creation is denied by service policy","创建房间被服务策略拒绝"}. {"Room description","房间描述"}. {"Room Occupants","房间人数"}. {"Room title","房间标题"}. @@ -298,7 +318,7 @@ {"Show Ordinary Table","显示普通列表"}. {"Shut Down Service","关闭服务"}. {"~s invites you to the room ~s","~s 邀请你到 ~s 房间"}. -{"Some Jabber clients can store your password in your computer. Use that feature only if you trust your computer is safe.","某些 Jabber 客户端可以在你的计算机里存储密码. 请仅在你确认你的计算机安全的情况下使用该功能."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","某些 Jabber 客户端可以在你的计算机里存储密码. 请仅在你确认你的计算机安全的情况下使用该功能."}. {"Specify the access model","指定访问范例"}. {"Specify the event message type","指定事件消息类型"}. {"Specify the publisher model","指定发布人范例"}. @@ -321,8 +341,12 @@ {"Subscriber Address","订阅人地址"}. {"Subscription","订阅"}. {"Sunday","星期天"}. +{"That nickname is already in use by another occupant","该昵称已被另一用户使用"}. +{"That nickname is registered by another person","该昵称已被另一个人注册了"}. {"The CAPTCHA is valid.","验证码有效."}. +{"The CAPTCHA verification has failed","验证码检查失败"}. {"The collections with which a node is affiliated","加入结点的集合"}. +{"The password is too weak","密码强度太弱"}. {"the password is","密码是"}. {"The password of your Jabber account was successfully changed.","你的 Jabber 帐户密码已成功更新."}. {"There was an error changing the password: ","修改密码出错: "}. @@ -334,13 +358,16 @@ {"Thursday","星期四"}. {"Time delay","时间延迟"}. {"Time","时间"}. +{"Too many CAPTCHA requests","验证码请求太多"}. {"To ~s","发送给~s"}. {"To","到"}. +{"Traffic rate limit is exceeded","已经超过传输率限制"}. {"Transactions Aborted:","取消的事务:"}. {"Transactions Committed:","提交的事务:"}. {"Transactions Logged:","记入日志的事务:"}. {"Transactions Restarted:","重启的事务:"}. {"Tuesday","星期二"}. +{"Unable to generate a CAPTCHA","无法生成验证码"}. {"Unauthorized","未认证的"}. {"Unregister a Jabber account","注销 Jabber 帐户"}. {"Unregister","取消注册"}. @@ -354,22 +381,30 @@ {"User JID","用户 JID"}. {"User Management","用户管理"}. {"Username:","用户名:"}. +{"Users are not allowed to register accounts so quickly","不允许用户太频繁地注册帐户"}. {"Users Last Activity","用户上次活动"}. {"Users","用户"}. {"User","用户"}. {"Validate","确认"}. {"vCard User Search","vCard 用户搜索"}. {"Virtual Hosts","虚拟主机"}. +{"Visitors are not allowed to change their nicknames in this room","此房间不允许用户更改昵称"}. +{"Visitors are not allowed to send messages to all occupants","不允许访客给所有占有者发送消息"}. +{"Voice requests are disabled in this conference","该会议的声音请求以被禁用"}. {"Voice request","声音请求"}. {"Wednesday","星期三"}. {"When to send the last published item","何时发送最新发布的内容条目"}. {"Whether to allow subscriptions","是否允许订阅"}. {"You can later change your password using a Jabber client.","你可以稍后用 Jabber 客户端修改你的密码."}. +{"You have been banned from this room","您已被禁止进入该房间"}. +{"You must fill in field \"Nickname\" in the form","您必须填充表单中\"昵称\"项"}. {"You need a client that supports x:data and CAPTCHA to register","您需要一个支持 x:data 和验证码的客户端进行注册"}. {"You need a client that supports x:data to register the nickname","您需要一个支持 x:data 的客户端来注册昵称"}. {"You need an x:data capable client to configure mod_irc settings","您需要一个兼容 x:data 的客户端来配置 mod_irc 设置"}. {"You need an x:data capable client to configure room","您需要一个兼容 x:data 的客户端来配置房间"}. {"You need an x:data capable client to search","您需要一个兼容 x:data 的客户端来搜索"}. +{"Your active privacy list has denied the routing of this stanza.","你的活跃私聊列表拒绝了在此房间进行路由分发."}. +{"Your contact offline message queue is full. The message has been discarded.","您的联系人离线消息队列已满. 消息已被丢弃"}. {"Your Jabber account was successfully created.","你的 Jabber 帐户已成功创建."}. {"Your Jabber account was successfully deleted.","你的 Jabber 帐户已成功删除."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","您发送给 ~s 的消息已被阻止. 要解除阻止, 请访问 ~s"}. diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index a1bd3d9ff88..67b8d050fc1 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -9,49 +9,53 @@ msgstr "" "X-Additional-Translator: Zhan Caibao - zhancaibao AT gmail DOT com\n" "X-Additional-Translator: Mike Wang\n" -#: ejabberd_c2s.erl:528 ejabberd_c2s.erl:875 +#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" msgstr "要求使用 STARTTLS" -#: ejabberd_c2s.erl:626 +#: ejabberd_c2s.erl:604 msgid "No resource provided" msgstr "无资源提供" -#: ejabberd_c2s.erl:1401 +#: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" msgstr "被新的连接替换" -#: ejabberd_c2s.erl:1405 mod_configure.erl:1854 mod_muc_log.erl:474 -#: mod_muc_log.erl:477 +#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 +#: mod_muc_log.erl:430 msgid "has been kicked" msgstr "已被踢出" -#: ejabberd_c2s.erl:2490 +#: ejabberd_c2s.erl:2112 +msgid "Your active privacy list has denied the routing of this stanza." +msgstr "你的活跃私聊列表拒绝了在此房间进行路由分发." + +#: ejabberd_c2s.erl:2427 msgid "Too many unacked stanzas" msgstr "" -#: ejabberd_captcha.erl:129 ejabberd_captcha.erl:252 ejabberd_captcha.erl:297 +#: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" msgstr "请输入您所看到的文本" -#: ejabberd_captcha.erl:154 +#: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" msgstr "您发送给 ~s 的消息已被阻止. 要解除阻止, 请访问 ~s" -#: ejabberd_captcha.erl:199 +#: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." msgstr "如果您在这里没有看到验证码图片, 请访问网页." -#: ejabberd_captcha.erl:234 +#: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" msgstr "验证码网页" -#: ejabberd_captcha.erl:400 +#: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." msgstr "验证码有效." -#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1338 -#: ejabberd_web_admin.erl:1393 mod_register.erl:262 mod_vcard.erl:490 +#: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 +#: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 msgid "User" msgstr "用户" @@ -60,9 +64,9 @@ msgstr "用户" msgid "Server" msgstr "服务器:" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1343 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2124 -#: mod_muc_room.erl:3377 mod_register.erl:272 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 +#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "密码" @@ -79,279 +83,280 @@ msgstr "未认证的" msgid "ejabberd Web Admin" msgstr "ejabberd 网页管理" -#: ejabberd_web_admin.erl:605 ejabberd_web_admin.erl:616 +#: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" msgstr "管理" -#: ejabberd_web_admin.erl:673 ejabberd_web_admin.erl:709 mod_configure.erl:196 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 #: mod_configure.erl:532 msgid "Access Control Lists" msgstr "访问控制列表(ACL)" -#: ejabberd_web_admin.erl:677 ejabberd_web_admin.erl:713 -#: ejabberd_web_admin.erl:779 ejabberd_web_admin.erl:812 -#: ejabberd_web_admin.erl:853 ejabberd_web_admin.erl:1329 -#: ejabberd_web_admin.erl:1614 ejabberd_web_admin.erl:1774 -#: ejabberd_web_admin.erl:1808 ejabberd_web_admin.erl:1888 -#: ejabberd_web_admin.erl:2058 ejabberd_web_admin.erl:2087 -#: ejabberd_web_admin.erl:2184 mod_offline.erl:787 mod_roster.erl:1494 -#: mod_shared_roster.erl:1171 mod_shared_roster.erl:1266 +#: ejabberd_web_admin.erl:741 ejabberd_web_admin.erl:777 +#: ejabberd_web_admin.erl:843 ejabberd_web_admin.erl:876 +#: ejabberd_web_admin.erl:917 ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1677 ejabberd_web_admin.erl:1836 +#: ejabberd_web_admin.erl:1870 ejabberd_web_admin.erl:1950 +#: ejabberd_web_admin.erl:2120 ejabberd_web_admin.erl:2149 +#: ejabberd_web_admin.erl:2246 mod_offline.erl:802 mod_roster.erl:1493 +#: mod_shared_roster.erl:1166 mod_shared_roster.erl:1261 msgid "Submitted" msgstr "已提交" -#: ejabberd_web_admin.erl:678 ejabberd_web_admin.erl:714 -#: ejabberd_web_admin.erl:780 ejabberd_web_admin.erl:813 -#: ejabberd_web_admin.erl:854 ejabberd_web_admin.erl:1330 -#: ejabberd_web_admin.erl:1615 ejabberd_web_admin.erl:1775 -#: ejabberd_web_admin.erl:2059 ejabberd_web_admin.erl:2088 mod_roster.erl:1495 -#: mod_shared_roster.erl:1172 mod_shared_roster.erl:1267 +#: ejabberd_web_admin.erl:742 ejabberd_web_admin.erl:778 +#: ejabberd_web_admin.erl:844 ejabberd_web_admin.erl:877 +#: ejabberd_web_admin.erl:918 ejabberd_web_admin.erl:1395 +#: ejabberd_web_admin.erl:1678 ejabberd_web_admin.erl:1837 +#: ejabberd_web_admin.erl:2121 ejabberd_web_admin.erl:2150 mod_roster.erl:1494 +#: mod_shared_roster.erl:1167 mod_shared_roster.erl:1262 msgid "Bad format" msgstr "格式错误" -#: ejabberd_web_admin.erl:689 ejabberd_web_admin.erl:726 -#: ejabberd_web_admin.erl:791 ejabberd_web_admin.erl:861 -#: ejabberd_web_admin.erl:1877 mod_shared_roster.erl:1274 +#: ejabberd_web_admin.erl:753 ejabberd_web_admin.erl:790 +#: ejabberd_web_admin.erl:855 ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:1939 mod_shared_roster.erl:1269 msgid "Submit" msgstr "提交" -#: ejabberd_web_admin.erl:718 ejabberd_web_admin.erl:817 +#: ejabberd_web_admin.erl:782 ejabberd_web_admin.erl:881 msgid "Raw" msgstr "原始格式" -#: ejabberd_web_admin.erl:723 ejabberd_web_admin.erl:823 mod_offline.erl:809 -#: mod_shared_roster.erl:1180 +#: ejabberd_web_admin.erl:787 ejabberd_web_admin.erl:887 mod_offline.erl:824 +#: mod_shared_roster.erl:1175 msgid "Delete Selected" msgstr "删除已选内容" -#: ejabberd_web_admin.erl:775 ejabberd_web_admin.erl:808 mod_configure.erl:198 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 #: mod_configure.erl:533 msgid "Access Rules" msgstr "访问规则" -#: ejabberd_web_admin.erl:849 +#: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" msgstr "~s 访问规则配置" -#: ejabberd_web_admin.erl:867 +#: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" msgstr "虚拟主机" -#: ejabberd_web_admin.erl:876 ejabberd_web_admin.erl:884 +#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:948 msgid "Users" msgstr "用户" -#: ejabberd_web_admin.erl:891 ejabberd_web_admin.erl:1275 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 #: mod_configure.erl:524 msgid "Online Users" msgstr "在线用户" -#: ejabberd_web_admin.erl:907 +#: ejabberd_web_admin.erl:971 msgid "Users Last Activity" msgstr "用户上次活动" -#: ejabberd_web_admin.erl:911 +#: ejabberd_web_admin.erl:975 msgid "Period: " msgstr "持续时间: " -#: ejabberd_web_admin.erl:924 +#: ejabberd_web_admin.erl:988 msgid "Last month" msgstr "上个月" -#: ejabberd_web_admin.erl:925 +#: ejabberd_web_admin.erl:989 msgid "Last year" msgstr "上一年" -#: ejabberd_web_admin.erl:927 +#: ejabberd_web_admin.erl:991 msgid "All activity" msgstr "所有活动" -#: ejabberd_web_admin.erl:930 +#: ejabberd_web_admin.erl:994 msgid "Show Ordinary Table" msgstr "显示普通列表" -#: ejabberd_web_admin.erl:933 +#: ejabberd_web_admin.erl:997 msgid "Show Integral Table" msgstr "显示完整列表" -#: ejabberd_web_admin.erl:940 ejabberd_web_admin.erl:1785 +#: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 #: mod_muc_admin.erl:247 msgid "Statistics" msgstr "统计" -#: ejabberd_web_admin.erl:950 +#: ejabberd_web_admin.erl:1014 msgid "Not Found" msgstr "没有找到" -#: ejabberd_web_admin.erl:963 +#: ejabberd_web_admin.erl:1027 msgid "Node not found" msgstr "没有找到节点" -#: ejabberd_web_admin.erl:1185 mod_shared_roster.erl:1166 +#: ejabberd_web_admin.erl:1250 mod_shared_roster.erl:1161 msgid "Add New" msgstr "添加新用户" -#: ejabberd_web_admin.erl:1273 +#: ejabberd_web_admin.erl:1338 msgid "Host" msgstr "主机" -#: ejabberd_web_admin.erl:1274 +#: ejabberd_web_admin.erl:1339 msgid "Registered Users" msgstr "注册用户" -#: ejabberd_web_admin.erl:1352 mod_configure.erl:177 mod_configure.erl:539 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 #: mod_configure.erl:1386 msgid "Add User" msgstr "添加用户" -#: ejabberd_web_admin.erl:1394 +#: ejabberd_web_admin.erl:1459 msgid "Offline Messages" msgstr "离线消息" -#: ejabberd_web_admin.erl:1395 ejabberd_web_admin.erl:1625 +#: ejabberd_web_admin.erl:1460 ejabberd_web_admin.erl:1688 msgid "Last Activity" msgstr "上次活动" -#: ejabberd_web_admin.erl:1413 ejabberd_web_admin.erl:1597 -#: mod_configure.erl:1917 +#: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 +#: mod_configure.erl:1916 msgid "Never" msgstr "从未" -#: ejabberd_web_admin.erl:1431 ejabberd_web_admin.erl:1608 -#: mod_configure.erl:1927 +#: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 +#: mod_configure.erl:1926 msgid "Online" msgstr "在线" -#: ejabberd_web_admin.erl:1487 ejabberd_web_admin.erl:1506 +#: ejabberd_web_admin.erl:1550 ejabberd_web_admin.erl:1569 msgid "Registered Users:" msgstr "注册用户:" -#: ejabberd_web_admin.erl:1490 ejabberd_web_admin.erl:1509 -#: ejabberd_web_admin.erl:2125 +#: ejabberd_web_admin.erl:1553 ejabberd_web_admin.erl:1572 +#: ejabberd_web_admin.erl:2187 msgid "Online Users:" msgstr "在线用户:" -#: ejabberd_web_admin.erl:1493 +#: ejabberd_web_admin.erl:1556 msgid "Outgoing s2s Connections:" msgstr "出站 s2s 连接:" -#: ejabberd_web_admin.erl:1496 -msgid "Outgoing s2s Servers:" -msgstr "出站 s2s 服务器" +#: ejabberd_web_admin.erl:1559 +#, fuzzy +msgid "Incoming s2s Connections:" +msgstr "出站 s2s 连接:" -#: ejabberd_web_admin.erl:1532 ejabberd_web_admin.erl:1732 -#: ejabberd_web_admin.erl:1742 ejabberd_web_admin.erl:2152 mod_roster.erl:1430 +#: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 +#: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 msgid "None" msgstr "无" -#: ejabberd_web_admin.erl:1589 mod_register_web.erl:188 +#: ejabberd_web_admin.erl:1652 mod_register_web.erl:188 #: mod_register_web.erl:347 mod_register_web.erl:355 mod_register_web.erl:379 msgid "Change Password" msgstr "更改密码" -#: ejabberd_web_admin.erl:1610 +#: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" msgstr "用户 " -#: ejabberd_web_admin.erl:1621 +#: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" msgstr "已连接资源:" -#: ejabberd_web_admin.erl:1623 mod_register_web.erl:239 +#: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" msgstr "密码:" -#: ejabberd_web_admin.erl:1630 mod_configure.erl:2118 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" msgstr "删除用户" -#: ejabberd_web_admin.erl:1678 +#: ejabberd_web_admin.erl:1740 msgid "No Data" msgstr "没有数据" -#: ejabberd_web_admin.erl:1751 +#: ejabberd_web_admin.erl:1813 msgid "Nodes" msgstr "节点" -#: ejabberd_web_admin.erl:1752 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 msgid "Running Nodes" msgstr "运行中的节点" -#: ejabberd_web_admin.erl:1753 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 msgid "Stopped Nodes" msgstr "已经停止的节点" -#: ejabberd_web_admin.erl:1771 ejabberd_web_admin.erl:1796 +#: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" msgstr "节点 " -#: ejabberd_web_admin.erl:1780 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" msgstr "数据库" -#: ejabberd_web_admin.erl:1781 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" msgstr "备份" -#: ejabberd_web_admin.erl:1783 +#: ejabberd_web_admin.erl:1845 msgid "Listened Ports" msgstr "被监听的端口" -#: ejabberd_web_admin.erl:1786 ejabberd_web_admin.erl:2199 +#: ejabberd_web_admin.erl:1848 ejabberd_web_admin.erl:2261 msgid "Update" msgstr "更新" -#: ejabberd_web_admin.erl:1790 ejabberd_web_admin.erl:2407 -#: ejabberd_web_admin.erl:2551 +#: ejabberd_web_admin.erl:1852 ejabberd_web_admin.erl:2469 +#: ejabberd_web_admin.erl:2613 msgid "Restart" msgstr "重启" -#: ejabberd_web_admin.erl:1792 ejabberd_web_admin.erl:2411 -#: ejabberd_web_admin.erl:2555 +#: ejabberd_web_admin.erl:1854 ejabberd_web_admin.erl:2473 +#: ejabberd_web_admin.erl:2617 msgid "Stop" msgstr "停止" -#: ejabberd_web_admin.erl:1799 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 msgid "Modules" msgstr "模块" -#: ejabberd_web_admin.erl:1804 +#: ejabberd_web_admin.erl:1866 msgid "RPC Call Error" msgstr "RPC 调用错误" -#: ejabberd_web_admin.erl:1855 +#: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" msgstr "数据库列表位于 " -#: ejabberd_web_admin.erl:1865 mod_vcard.erl:490 mod_vcard.erl:616 +#: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" msgstr "姓名" -#: ejabberd_web_admin.erl:1866 +#: ejabberd_web_admin.erl:1928 msgid "Storage Type" msgstr "存储类型" -#: ejabberd_web_admin.erl:1867 +#: ejabberd_web_admin.erl:1929 msgid "Elements" msgstr "元素" -#: ejabberd_web_admin.erl:1868 +#: ejabberd_web_admin.erl:1930 msgid "Memory" msgstr "内存" -#: ejabberd_web_admin.erl:1890 ejabberd_web_admin.erl:2061 +#: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" msgstr "错误" -#: ejabberd_web_admin.erl:1893 +#: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" msgstr "备份来源 " -#: ejabberd_web_admin.erl:1897 +#: ejabberd_web_admin.erl:1959 msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -360,143 +365,143 @@ msgstr "" "注意:这些选项仅将备份内置的 Mnesia 数据库. 如果您正在使用 ODBC 模块, 您还需" "要分别备份您的数据库." -#: ejabberd_web_admin.erl:1907 +#: ejabberd_web_admin.erl:1969 msgid "Store binary backup:" msgstr "存储为二进制备份:" -#: ejabberd_web_admin.erl:1914 ejabberd_web_admin.erl:1924 -#: ejabberd_web_admin.erl:1935 ejabberd_web_admin.erl:1944 -#: ejabberd_web_admin.erl:1954 ejabberd_web_admin.erl:1967 -#: ejabberd_web_admin.erl:1979 ejabberd_web_admin.erl:1995 -#: ejabberd_web_admin.erl:2011 ejabberd_web_admin.erl:2022 -#: ejabberd_web_admin.erl:2032 +#: ejabberd_web_admin.erl:1976 ejabberd_web_admin.erl:1986 +#: ejabberd_web_admin.erl:1997 ejabberd_web_admin.erl:2006 +#: ejabberd_web_admin.erl:2016 ejabberd_web_admin.erl:2029 +#: ejabberd_web_admin.erl:2041 ejabberd_web_admin.erl:2057 +#: ejabberd_web_admin.erl:2073 ejabberd_web_admin.erl:2084 +#: ejabberd_web_admin.erl:2094 msgid "OK" msgstr "确定" -#: ejabberd_web_admin.erl:1917 +#: ejabberd_web_admin.erl:1979 msgid "Restore binary backup immediately:" msgstr "立即恢复二进制备份:" -#: ejabberd_web_admin.erl:1927 +#: ejabberd_web_admin.erl:1989 msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "在下次 ejabberd 重启后恢复二进制备份(需要的内存更少):" -#: ejabberd_web_admin.erl:1937 +#: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" msgstr "存储为普通文本备份:" -#: ejabberd_web_admin.erl:1947 +#: ejabberd_web_admin.erl:2009 msgid "Restore plain text backup immediately:" msgstr "立即恢复普通文本备份:" -#: ejabberd_web_admin.erl:1957 +#: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" msgstr "从 PIEFXIS 文件 (XEP-0227) 导入用户数据:" -#: ejabberd_web_admin.erl:1970 +#: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "将服务器上所有用户的数据导出到 PIEFXIS 文件 (XEP-0227):" -#: ejabberd_web_admin.erl:1982 +#: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "将某主机的用户数据导出到 PIEFXIS 文件 (XEP-0227):" -#: ejabberd_web_admin.erl:1998 +#: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" msgstr "" -#: ejabberd_web_admin.erl:2014 +#: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" msgstr "从 jabberd14 Spool 文件导入用户数据:" -#: ejabberd_web_admin.erl:2025 +#: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" msgstr "从 jabberd14 Spool 目录导入用户数据:" -#: ejabberd_web_admin.erl:2053 +#: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "监听的端口位于 " -#: ejabberd_web_admin.erl:2082 +#: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" msgstr "模块位于 " -#: ejabberd_web_admin.erl:2113 +#: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" msgstr "~p 的统计" -#: ejabberd_web_admin.erl:2117 +#: ejabberd_web_admin.erl:2179 msgid "Uptime:" msgstr "正常运行时间:" -#: ejabberd_web_admin.erl:2121 +#: ejabberd_web_admin.erl:2183 msgid "CPU Time:" msgstr "CPU 时间:" -#: ejabberd_web_admin.erl:2129 +#: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" msgstr "提交的事务:" -#: ejabberd_web_admin.erl:2133 +#: ejabberd_web_admin.erl:2195 msgid "Transactions Aborted:" msgstr "取消的事务:" -#: ejabberd_web_admin.erl:2137 +#: ejabberd_web_admin.erl:2199 msgid "Transactions Restarted:" msgstr "重启的事务:" -#: ejabberd_web_admin.erl:2141 +#: ejabberd_web_admin.erl:2203 msgid "Transactions Logged:" msgstr "记入日志的事务:" -#: ejabberd_web_admin.erl:2181 +#: ejabberd_web_admin.erl:2243 #, fuzzy msgid "Update ~p" msgstr "更新 " -#: ejabberd_web_admin.erl:2192 +#: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "更新计划" -#: ejabberd_web_admin.erl:2193 +#: ejabberd_web_admin.erl:2255 msgid "Modified modules" msgstr "被修改模块" -#: ejabberd_web_admin.erl:2194 +#: ejabberd_web_admin.erl:2256 msgid "Update script" msgstr "更新脚本" -#: ejabberd_web_admin.erl:2195 +#: ejabberd_web_admin.erl:2257 msgid "Low level update script" msgstr "低级别更新脚本" -#: ejabberd_web_admin.erl:2196 +#: ejabberd_web_admin.erl:2258 msgid "Script check" msgstr "脚本检查" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "IP" msgstr "IP" -#: ejabberd_web_admin.erl:2376 +#: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "端口" -#: ejabberd_web_admin.erl:2377 +#: ejabberd_web_admin.erl:2439 msgid "Protocol" msgstr "协议" -#: ejabberd_web_admin.erl:2378 ejabberd_web_admin.erl:2533 +#: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" msgstr "模块" -#: ejabberd_web_admin.erl:2379 ejabberd_web_admin.erl:2534 +#: ejabberd_web_admin.erl:2441 ejabberd_web_admin.erl:2596 msgid "Options" msgstr "选项" -#: ejabberd_web_admin.erl:2431 ejabberd_web_admin.erl:2567 +#: ejabberd_web_admin.erl:2493 ejabberd_web_admin.erl:2629 msgid "Start" msgstr "开始" @@ -781,8 +786,8 @@ msgstr "访问规则" #: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 #: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1935 -#: mod_configure.erl:1962 mod_roster.erl:1435 mod_vcard.erl:613 +#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 +#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "Jabber ID" @@ -799,31 +804,31 @@ msgstr "注册用户数" msgid "Number of online users" msgstr "在线用户数" -#: mod_configure.erl:1937 +#: mod_configure.erl:1936 msgid "Last login" msgstr "上次登陆" -#: mod_configure.erl:1964 +#: mod_configure.erl:1963 msgid "Roster size" msgstr "花名册大小" -#: mod_configure.erl:1966 +#: mod_configure.erl:1965 msgid "IP addresses" msgstr "IP 地址" -#: mod_configure.erl:1968 +#: mod_configure.erl:1967 msgid "Resources" msgstr "资源" -#: mod_configure.erl:2096 +#: mod_configure.erl:2095 msgid "Administration of " msgstr "管理" -#: mod_configure.erl:2101 +#: mod_configure.erl:2100 msgid "Action on user" msgstr "对用户的动作" -#: mod_configure.erl:2109 +#: mod_configure.erl:2108 msgid "Edit Properties" msgstr "编辑属性" @@ -833,37 +838,49 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" +#: mod_http_upload.erl:593 +msgid "Please specify file size." +msgstr "" + +#: mod_http_upload.erl:597 +msgid "Please specify file name." +msgstr "" + #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "" -#: mod_irc.erl:431 +#: mod_irc.erl:220 mod_muc.erl:467 +msgid "Access denied by service policy" +msgstr "访问被服务策略拒绝" + +#: mod_irc.erl:439 msgid "IRC Transport" msgstr "IRC 传输" -#: mod_irc.erl:468 +#: mod_irc.erl:476 msgid "ejabberd IRC module" msgstr "ejabberd IRC 模块" -#: mod_irc.erl:636 +#: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "您需要一个兼容 x:data 的客户端来配置 mod_irc 设置" -#: mod_irc.erl:645 +#: mod_irc.erl:653 msgid "Registration in mod_irc for " msgstr "mod_irc 中的注册是为 " -#: mod_irc.erl:651 +#: mod_irc.erl:659 msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "请输入您想使用的用来连接到IRC服务器的用户名, 编码, 端口和密码." -#: mod_irc.erl:659 +#: mod_irc.erl:667 msgid "IRC Username" msgstr "IRC 用户名" -#: mod_irc.erl:674 +#: mod_irc.erl:682 msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" @@ -874,7 +891,7 @@ msgstr "" "码\", 端口, \"密码\"}' 格式的值填充此表单. 默认情况下此服务使用\"~s\"编码, " "~p 端口, 密码为空." -#: mod_irc.erl:696 +#: mod_irc.erl:704 msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." @@ -882,35 +899,35 @@ msgstr "" "例如: [{\"irc.lucky.net\", \"koi8-r\"}, 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." -#: mod_irc.erl:705 +#: mod_irc.erl:713 msgid "Connections parameters" msgstr "连接参数" -#: mod_irc.erl:874 +#: mod_irc.erl:886 msgid "Join IRC channel" msgstr "加入 IRC 频道" -#: mod_irc.erl:881 +#: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" msgstr "IRC 频道 (不要输入第一个#号)" -#: mod_irc.erl:891 +#: mod_irc.erl:903 msgid "IRC server" msgstr "IRC 服务器" -#: mod_irc.erl:938 mod_irc.erl:946 +#: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." msgstr "在这里加入 IRC 频道." -#: mod_irc.erl:955 +#: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" msgstr "用此 Jabber ID: ~s 加入 IRC 频道" -#: mod_irc.erl:1034 +#: mod_irc.erl:1046 msgid "IRC settings" msgstr "IRC 设置" -#: mod_irc.erl:1039 +#: mod_irc.erl:1051 msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " @@ -919,48 +936,77 @@ msgstr "" "请输入您想使用的用来连接到 IRC 服务器的用户名和编码. 按 '下一步' 获取更多待填" "字段. 按 '完成' 保存设置." -#: mod_irc.erl:1048 +#: mod_irc.erl:1060 msgid "IRC username" msgstr "IRC 用户名" -#: mod_irc.erl:1114 +#: mod_irc.erl:1126 msgid "Password ~b" msgstr "~b 的密码" -#: mod_irc.erl:1125 +#: mod_irc.erl:1137 msgid "Port ~b" msgstr "~b 的端口" -#: mod_irc.erl:1138 +#: mod_irc.erl:1150 msgid "Encoding for server ~b" msgstr "服务器 ~b 的编码" -#: mod_irc.erl:1159 +#: mod_irc.erl:1171 msgid "Server ~b" msgstr "服务器 ~b" -#: mod_muc.erl:797 mod_muc_admin.erl:321 +#: mod_mam.erl:270 +#, fuzzy +msgid "Only members are allowed to query archives of this room" +msgstr "只有主持人可以在此房间里更改主题" + +#: mod_muc.erl:585 +msgid "Only service administrators are allowed to send service messages" +msgstr "只有服务管理员可以发送服务消息" + +#: mod_muc.erl:622 +msgid "Room creation is denied by service policy" +msgstr "创建房间被服务策略拒绝" + +#: mod_muc.erl:629 +msgid "Conference room does not exist" +msgstr "会议室不存在" + +#: mod_muc.erl:740 mod_muc_admin.erl:321 msgid "Chatrooms" msgstr "聊天室" -#: mod_muc.erl:997 +#: mod_muc.erl:779 +msgid "Empty Rooms" +msgstr "" + +#: mod_muc.erl:931 msgid "You need a client that supports x:data to register the nickname" msgstr "您需要一个支持 x:data 的客户端来注册昵称" -#: mod_muc.erl:1007 +#: mod_muc.erl:941 msgid "Nickname Registration at " msgstr "昵称注册于 " -#: mod_muc.erl:1013 +#: mod_muc.erl:947 msgid "Enter nickname you want to register" msgstr "请输入您想要注册的昵称" -#: mod_muc.erl:1014 mod_muc_room.erl:4265 mod_roster.erl:1436 -#: mod_vcard.erl:490 mod_vcard.erl:621 +#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_vcard.erl:621 msgid "Nickname" msgstr "昵称" -#: mod_muc.erl:1177 +#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +msgid "That nickname is registered by another person" +msgstr "该昵称已被另一个人注册了" + +#: mod_muc.erl:1088 +msgid "You must fill in field \"Nickname\" in the form" +msgstr "您必须填充表单中\"昵称\"项" + +#: mod_muc.erl:1111 msgid "ejabberd MUC module" msgstr "ejabberd MUC 模块" @@ -988,353 +1034,481 @@ msgstr "注册用户" msgid "List of rooms" msgstr "" -#: mod_muc_log.erl:445 mod_muc_log.erl:454 +#: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" msgstr "聊天室配置已修改" -#: mod_muc_log.erl:457 +#: mod_muc_log.erl:410 msgid "joins the room" msgstr "加入房间" -#: mod_muc_log.erl:460 mod_muc_log.erl:463 +#: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" msgstr "离开房间" -#: mod_muc_log.erl:467 mod_muc_log.erl:470 +#: mod_muc_log.erl:420 mod_muc_log.erl:423 msgid "has been banned" msgstr "已被禁止" -#: mod_muc_log.erl:482 +#: mod_muc_log.erl:435 msgid "has been kicked because of an affiliation change" msgstr "因联属关系改变而被踢出" -#: mod_muc_log.erl:487 +#: mod_muc_log.erl:440 msgid "has been kicked because the room has been changed to members-only" msgstr "因该房间改为只对会员开放而被踢出" -#: mod_muc_log.erl:492 +#: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" msgstr "因系统关机而被踢出" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:450 msgid "is now known as" msgstr "现在称呼为" -#: mod_muc_log.erl:500 mod_muc_log.erl:839 +#: mod_muc_log.erl:453 mod_muc_log.erl:792 msgid " has set the subject to: " msgstr "已将标题设置为: " -#: mod_muc_log.erl:540 +#: mod_muc_log.erl:493 msgid "Chatroom is created" msgstr "聊天室已被创建" -#: mod_muc_log.erl:542 +#: mod_muc_log.erl:495 msgid "Chatroom is destroyed" msgstr "聊天室已被销毁" -#: mod_muc_log.erl:544 +#: mod_muc_log.erl:497 msgid "Chatroom is started" msgstr "聊天室已被启动" -#: mod_muc_log.erl:546 +#: mod_muc_log.erl:499 msgid "Chatroom is stopped" msgstr "聊天室已被停用" -#: mod_muc_log.erl:550 +#: mod_muc_log.erl:503 msgid "Monday" msgstr "星期一" -#: mod_muc_log.erl:551 +#: mod_muc_log.erl:504 msgid "Tuesday" msgstr "星期二" -#: mod_muc_log.erl:552 +#: mod_muc_log.erl:505 msgid "Wednesday" msgstr "星期三" -#: mod_muc_log.erl:553 +#: mod_muc_log.erl:506 msgid "Thursday" msgstr "星期四" -#: mod_muc_log.erl:554 +#: mod_muc_log.erl:507 msgid "Friday" msgstr "星期五" -#: mod_muc_log.erl:555 +#: mod_muc_log.erl:508 msgid "Saturday" msgstr "星期六" -#: mod_muc_log.erl:556 +#: mod_muc_log.erl:509 msgid "Sunday" msgstr "星期天" -#: mod_muc_log.erl:560 +#: mod_muc_log.erl:513 msgid "January" msgstr "一月" -#: mod_muc_log.erl:561 +#: mod_muc_log.erl:514 msgid "February" msgstr "二月" -#: mod_muc_log.erl:562 +#: mod_muc_log.erl:515 msgid "March" msgstr "三月" -#: mod_muc_log.erl:563 +#: mod_muc_log.erl:516 msgid "April" msgstr "四月" -#: mod_muc_log.erl:564 +#: mod_muc_log.erl:517 msgid "May" msgstr "五月" -#: mod_muc_log.erl:565 +#: mod_muc_log.erl:518 msgid "June" msgstr "六月" -#: mod_muc_log.erl:566 +#: mod_muc_log.erl:519 msgid "July" msgstr "七月" -#: mod_muc_log.erl:567 +#: mod_muc_log.erl:520 msgid "August" msgstr "八月" -#: mod_muc_log.erl:568 +#: mod_muc_log.erl:521 msgid "September" msgstr "九月" -#: mod_muc_log.erl:569 +#: mod_muc_log.erl:522 msgid "October" msgstr "十月" -#: mod_muc_log.erl:570 +#: mod_muc_log.erl:523 msgid "November" msgstr "十一月" -#: mod_muc_log.erl:571 +#: mod_muc_log.erl:524 msgid "December" msgstr "十二月" -#: mod_muc_log.erl:959 +#: mod_muc_log.erl:912 msgid "Room Configuration" msgstr "房间配置" -#: mod_muc_log.erl:979 +#: mod_muc_log.erl:932 msgid "Room Occupants" msgstr "房间人数" -#: mod_muc_room.erl:998 +#: mod_muc_room.erl:163 +msgid "Traffic rate limit is exceeded" +msgstr "已经超过传输率限制" + +#: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 +msgid "" +"It is not allowed to send error messages to the room. This participant (~s) " +"sent an error message (~s) and gets kicked from the room" +msgstr "" + +#: mod_muc_room.erl:241 +msgid "It is not allowed to send private messages to the conference" +msgstr "不允许向会议发送私聊消息" + +#: mod_muc_room.erl:316 +msgid "Please, wait for a while before sending new voice request" +msgstr "请稍后再发送新的声音请求" + +#: mod_muc_room.erl:329 +msgid "Voice requests are disabled in this conference" +msgstr "该会议的声音请求以被禁用" + +#: mod_muc_room.erl:347 +msgid "Failed to extract JID from your voice request approval" +msgstr "无法从你的声音请求确认信息中提取JID" + +#: mod_muc_room.erl:377 +msgid "Only moderators can approve voice requests" +msgstr "仅主持人能确认声音请求" + +#: mod_muc_room.erl:389 +msgid "Improper message type" +msgstr "不恰当的消息类型" + +#: mod_muc_room.erl:534 +msgid "It is not allowed to send private messages of type \"groupchat\"" +msgstr "\"群组聊天\"类型不允许发送私聊消息" + +#: mod_muc_room.erl:546 mod_muc_room.erl:621 +msgid "Recipient is not in the conference room" +msgstr "接收人不在会议室" + +#: mod_muc_room.erl:576 mod_muc_room.erl:598 +msgid "It is not allowed to send private messages" +msgstr "不可以发送私聊消息" + +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +msgid "Only occupants are allowed to send messages to the conference" +msgstr "只有与会人可以向大会发送消息" + +#: mod_muc_room.erl:644 +msgid "Only occupants are allowed to send queries to the conference" +msgstr "只有与会人可以向大会发出查询请求" + +#: mod_muc_room.erl:657 +msgid "Queries to the conference members are not allowed in this room" +msgstr "本房间不可以查询会议成员信息" + +#: mod_muc_room.erl:961 msgid "" "Only moderators and participants are allowed to change the subject in this " "room" msgstr "只有主持人和参与人可以在此房间里更改主题" -#: mod_muc_room.erl:1003 +#: mod_muc_room.erl:966 msgid "Only moderators are allowed to change the subject in this room" msgstr "只有主持人可以在此房间里更改主题" -#: mod_muc_room.erl:2752 +#: mod_muc_room.erl:974 +msgid "Visitors are not allowed to send messages to all occupants" +msgstr "不允许访客给所有占有者发送消息" + +#: mod_muc_room.erl:1080 +msgid "Visitors are not allowed to change their nicknames in this room" +msgstr "此房间不允许用户更改昵称" + +#: mod_muc_room.erl:1093 mod_muc_room.erl:1835 +msgid "That nickname is already in use by another occupant" +msgstr "该昵称已被另一用户使用" + +#: mod_muc_room.erl:1822 +msgid "You have been banned from this room" +msgstr "您已被禁止进入该房间" + +#: mod_muc_room.erl:1826 +msgid "Membership is required to enter this room" +msgstr "进入此房间需要会员身份" + +#: mod_muc_room.erl:1872 +msgid "A password is required to enter this room" +msgstr "进入此房间需要密码" + +#: mod_muc_room.erl:1898 mod_register.erl:295 +msgid "Too many CAPTCHA requests" +msgstr "验证码请求太多" + +#: mod_muc_room.erl:1908 mod_register.erl:301 +msgid "Unable to generate a CAPTCHA" +msgstr "无法生成验证码" + +#: mod_muc_room.erl:1919 +msgid "Incorrect password" +msgstr "密码不正确" + +#: mod_muc_room.erl:2573 +msgid "Administrator privileges required" +msgstr "需要管理员权限" + +#: mod_muc_room.erl:2586 +msgid "Moderator privileges required" +msgstr "需要主持人权限" + +#: mod_muc_room.erl:2758 msgid "Jabber ID ~s is invalid" msgstr "Jabber ID ~s 无效" -#: mod_muc_room.erl:2766 +#: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" msgstr "昵称 ~s 不在该房间" -#: mod_muc_room.erl:2789 mod_muc_room.erl:3169 +#: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" msgstr "无效加入: ~s" -#: mod_muc_room.erl:2840 +#: mod_muc_room.erl:2846 msgid "Invalid role: ~s" msgstr "无效角色: ~s" -#: mod_muc_room.erl:3342 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +msgid "Owner privileges required" +msgstr "需要持有人权限" + +#: mod_muc_room.erl:3348 msgid "Configuration of room ~s" msgstr "房间 ~s 的配置 " -#: mod_muc_room.erl:3353 +#: mod_muc_room.erl:3359 msgid "Room title" msgstr "房间标题" -#: mod_muc_room.erl:3355 mod_muc_room.erl:4102 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 msgid "Room description" msgstr "房间描述" -#: mod_muc_room.erl:3363 +#: mod_muc_room.erl:3369 msgid "Make room persistent" msgstr "永久保存该房间" -#: mod_muc_room.erl:3369 +#: mod_muc_room.erl:3375 msgid "Make room public searchable" msgstr "使房间可被公开搜索" -#: mod_muc_room.erl:3372 +#: mod_muc_room.erl:3378 msgid "Make participants list public" msgstr "公开参与人列表" -#: mod_muc_room.erl:3374 +#: mod_muc_room.erl:3380 msgid "Make room password protected" msgstr "进入此房间需要密码" -#: mod_muc_room.erl:3388 +#: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" msgstr "允许的与会人最大数" -#: mod_muc_room.erl:3400 +#: mod_muc_room.erl:3406 msgid "No limit" msgstr "不限" -#: mod_muc_room.erl:3430 +#: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" msgstr "将真实 Jabber ID 显示给" -#: mod_muc_room.erl:3444 mod_muc_room.erl:3507 +#: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" msgstr "仅主持人" -#: mod_muc_room.erl:3454 mod_muc_room.erl:3517 +#: mod_muc_room.erl:3460 mod_muc_room.erl:3570 msgid "anyone" msgstr "任何人" -#: mod_muc_room.erl:3460 +#: mod_muc_room.erl:3471 +msgid "Roles for which Presence is Broadcasted" +msgstr "" + +#: mod_muc_room.erl:3486 +#, fuzzy +msgid "Moderator" +msgstr "仅主持人" + +#: mod_muc_room.erl:3496 +msgid "Participant" +msgstr "" + +#: mod_muc_room.erl:3506 +msgid "Visitor" +msgstr "" + +#: mod_muc_room.erl:3513 msgid "Make room members-only" msgstr "设置房间只接收会员" -#: mod_muc_room.erl:3463 +#: mod_muc_room.erl:3516 msgid "Make room moderated" msgstr "设置房间只接收主持人" -#: mod_muc_room.erl:3466 +#: mod_muc_room.erl:3519 msgid "Default users as participants" msgstr "用户默认被视为参与人" -#: mod_muc_room.erl:3469 +#: mod_muc_room.erl:3522 msgid "Allow users to change the subject" msgstr "允许用户更改主题" -#: mod_muc_room.erl:3472 +#: mod_muc_room.erl:3525 msgid "Allow users to send private messages" msgstr "允许用户发送私聊消息" -#: mod_muc_room.erl:3480 +#: mod_muc_room.erl:3533 msgid "Allow visitors to send private messages to" msgstr "允许访客发送私聊消息至" -#: mod_muc_room.erl:3498 +#: mod_muc_room.erl:3551 msgid "nobody" msgstr "没有人" -#: mod_muc_room.erl:3523 +#: mod_muc_room.erl:3576 msgid "Allow users to query other users" msgstr "允许用户查询其它用户" -#: mod_muc_room.erl:3526 +#: mod_muc_room.erl:3579 msgid "Allow users to send invites" msgstr "允许用户发送邀请" -#: mod_muc_room.erl:3529 +#: mod_muc_room.erl:3582 msgid "Allow visitors to send status text in presence updates" msgstr "更新在线状态时允许用户发送状态文本" -#: mod_muc_room.erl:3533 +#: mod_muc_room.erl:3586 msgid "Allow visitors to change nickname" msgstr "允许用户更改昵称" -#: mod_muc_room.erl:3536 +#: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" msgstr "允许访客发送声音请求" -#: mod_muc_room.erl:3539 +#: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" msgstr "声音请求的最小间隔(以秒为单位)" -#: mod_muc_room.erl:3546 +#: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" msgstr "保护房间验证码" -#: mod_muc_room.erl:3553 +#: mod_muc_room.erl:3606 msgid "Enable message archiving" msgstr "" -#: mod_muc_room.erl:3559 +#: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" msgstr "从验证码挑战中排除 Jabber ID" -#: mod_muc_room.erl:3568 +#: mod_muc_room.erl:3621 msgid "Enable logging" msgstr "启用服务器端聊天记录" -#: mod_muc_room.erl:3578 +#: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" msgstr "您需要一个兼容 x:data 的客户端来配置房间" -#: mod_muc_room.erl:4104 +#: mod_muc_room.erl:4190 msgid "Number of occupants" msgstr "驻留人数" -#: mod_muc_room.erl:4174 +#: mod_muc_room.erl:4260 msgid "private, " msgstr "保密, " -#: mod_muc_room.erl:4238 +#: mod_muc_room.erl:4324 msgid "Voice request" msgstr "声音请求" -#: mod_muc_room.erl:4243 +#: mod_muc_room.erl:4329 msgid "Either approve or decline the voice request." msgstr "接受或拒绝声音请求" -#: mod_muc_room.erl:4263 +#: mod_muc_room.erl:4349 msgid "User JID" msgstr "用户 JID" -#: mod_muc_room.erl:4267 +#: mod_muc_room.erl:4353 msgid "Grant voice to this person?" msgstr "为此人授权声音?" -#: mod_muc_room.erl:4410 +#: mod_muc_room.erl:4496 msgid "~s invites you to the room ~s" msgstr "~s 邀请你到 ~s 房间" -#: mod_muc_room.erl:4422 +#: mod_muc_room.erl:4507 msgid "the password is" msgstr "密码是" -#: mod_multicast.erl:273 +#: mod_multicast.erl:291 msgid "Multicast" msgstr "" -#: mod_multicast.erl:288 +#: mod_multicast.erl:306 msgid "ejabberd Multicast service" msgstr "" -#: mod_offline.erl:783 +#: mod_offline.erl:647 +msgid "" +"Your contact offline message queue is full. The message has been discarded." +msgstr "您的联系人离线消息队列已满. 消息已被丢弃" + +#: mod_offline.erl:798 msgid "~s's Offline Messages Queue" msgstr "~s 的离线消息队列" -#: mod_offline.erl:796 +#: mod_offline.erl:811 msgid "Time" msgstr "时间" -#: mod_offline.erl:797 +#: mod_offline.erl:812 msgid "From" msgstr "从" -#: mod_offline.erl:798 +#: mod_offline.erl:813 msgid "To" msgstr "到" -#: mod_offline.erl:799 +#: mod_offline.erl:814 msgid "Packet" msgstr "数据包" -#: mod_offline.erl:977 +#: mod_offline.erl:992 msgid "Offline Messages:" msgstr "离线消息:" -#: mod_offline.erl:981 +#: mod_offline.erl:996 msgid "Remove All Offline Messages" msgstr "移除所有离线消息" @@ -1342,115 +1516,127 @@ msgstr "移除所有离线消息" msgid "ejabberd SOCKS5 Bytestreams module" msgstr "ejabberd SOCKS5 字节流模块" -#: mod_pubsub.erl:1103 +#: mod_pubsub.erl:1102 msgid "Publish-Subscribe" msgstr "发行-订阅" -#: mod_pubsub.erl:1223 +#: mod_pubsub.erl:1222 msgid "ejabberd Publish-Subscribe module" msgstr "ejabberd 发行-订阅模块" -#: mod_pubsub.erl:1538 +#: mod_pubsub.erl:1537 msgid "PubSub subscriber request" msgstr "PubSub 订阅人请求" -#: mod_pubsub.erl:1544 +#: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." msgstr "选择是否允许该实体的订阅" -#: mod_pubsub.erl:1560 +#: mod_pubsub.erl:1559 msgid "Node ID" msgstr "节点 ID" -#: mod_pubsub.erl:1572 +#: mod_pubsub.erl:1571 msgid "Subscriber Address" msgstr "订阅人地址" -#: mod_pubsub.erl:1585 +#: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" msgstr "允许该 Jabber ID 订阅该 pubsub 节点?" -#: mod_pubsub.erl:3702 +#: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" msgstr "用事件通告传输有效负载" -#: mod_pubsub.erl:3704 +#: mod_pubsub.erl:3747 msgid "Deliver event notifications" msgstr "传递事件通知" -#: mod_pubsub.erl:3706 +#: mod_pubsub.erl:3749 msgid "Notify subscribers when the node configuration changes" msgstr "当节点设置改变时通知订阅人" -#: mod_pubsub.erl:3708 +#: mod_pubsub.erl:3751 msgid "Notify subscribers when the node is deleted" msgstr "当节点被删除时通知订阅人" -#: mod_pubsub.erl:3710 +#: mod_pubsub.erl:3753 msgid "Notify subscribers when items are removed from the node" msgstr "当从节点删除内容条目时通知订阅人" -#: mod_pubsub.erl:3712 +#: mod_pubsub.erl:3755 msgid "Persist items to storage" msgstr "持久化内容条目" -#: mod_pubsub.erl:3714 +#: mod_pubsub.erl:3757 msgid "A friendly name for the node" msgstr "该节点的友好名称" -#: mod_pubsub.erl:3716 +#: mod_pubsub.erl:3759 msgid "Max # of items to persist" msgstr "允许持久化的最大内容条目数" -#: mod_pubsub.erl:3718 +#: mod_pubsub.erl:3761 msgid "Whether to allow subscriptions" msgstr "是否允许订阅" -#: mod_pubsub.erl:3720 +#: mod_pubsub.erl:3763 msgid "Specify the access model" msgstr "指定访问范例" -#: mod_pubsub.erl:3722 +#: mod_pubsub.erl:3765 msgid "Roster groups allowed to subscribe" msgstr "允许订阅的花名册组" -#: mod_pubsub.erl:3724 +#: mod_pubsub.erl:3767 msgid "Specify the publisher model" msgstr "指定发布人范例" -#: mod_pubsub.erl:3726 +#: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" msgstr "相关发布人离线后清除所有选项" -#: mod_pubsub.erl:3728 +#: mod_pubsub.erl:3771 msgid "Specify the event message type" msgstr "指定事件消息类型" # bytes was translated as 'bits'. It's corrected now. -#: mod_pubsub.erl:3730 +#: mod_pubsub.erl:3773 msgid "Max payload size in bytes" msgstr "最大有效负载字节数" -#: mod_pubsub.erl:3732 +#: mod_pubsub.erl:3775 msgid "When to send the last published item" msgstr "何时发送最新发布的内容条目" -#: mod_pubsub.erl:3734 +#: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" msgstr "仅将通知发送给可发送的用户" -#: mod_pubsub.erl:3736 +#: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" msgstr "加入结点的集合" -#: mod_register.erl:250 +#: mod_register.erl:209 +msgid "The CAPTCHA verification has failed" +msgstr "验证码检查失败" + +#: mod_register.erl:253 msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "您需要一个支持 x:data 和验证码的客户端进行注册" -#: mod_register.erl:256 mod_register.erl:317 +#: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" msgstr "请选择在此服务器上注册所需的用户名和密码" +#: mod_register.erl:373 mod_register.erl:421 +msgid "The password is too weak" +msgstr "密码强度太弱" + +#: mod_register.erl:426 +msgid "Users are not allowed to register accounts so quickly" +msgstr "不允许用户太频繁地注册帐户" + #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." msgstr "你的 Jabber 帐户已成功创建." @@ -1524,8 +1710,8 @@ msgstr "你可以稍后用 Jabber 客户端修改你的密码." #: mod_register_web.erl:252 msgid "" -"Some Jabber clients can store your password in your computer. Use that " -"feature only if you trust your computer is safe." +"Some Jabber clients can store your password in the computer, but you should " +"do this only in your personal computer for safety reasons." msgstr "" "某些 Jabber 客户端可以在你的计算机里存储密码. 请仅在你确认你的计算机安全的情" "况下使用该功能." @@ -1563,60 +1749,60 @@ msgstr "此页面允许在此 Jabber 服务器上注销 Jabber 帐户" msgid "Unregister" msgstr "取消注册" -#: mod_roster.erl:1437 +#: mod_roster.erl:1436 msgid "Subscription" msgstr "订阅" -#: mod_roster.erl:1438 +#: mod_roster.erl:1437 msgid "Pending" msgstr "挂起" -#: mod_roster.erl:1439 +#: mod_roster.erl:1438 msgid "Groups" msgstr "组" -#: mod_roster.erl:1477 +#: mod_roster.erl:1476 msgid "Validate" msgstr "确认" -#: mod_roster.erl:1486 +#: mod_roster.erl:1485 msgid "Remove" msgstr "移除" -#: mod_roster.erl:1491 +#: mod_roster.erl:1490 msgid "Roster of " msgstr "花名册属于 " -#: mod_roster.erl:1505 +#: mod_roster.erl:1504 msgid "Add Jabber ID" msgstr "添加 Jabber ID" -#: mod_roster.erl:1623 +#: mod_roster.erl:1622 msgid "Roster" msgstr "花名册" -#: mod_shared_roster.erl:1125 mod_shared_roster.erl:1167 -#: mod_shared_roster.erl:1261 +#: mod_shared_roster.erl:1120 mod_shared_roster.erl:1162 +#: mod_shared_roster.erl:1256 msgid "Shared Roster Groups" msgstr "共享的花名册组群" -#: mod_shared_roster.erl:1237 +#: mod_shared_roster.erl:1232 msgid "Name:" msgstr "姓名:" -#: mod_shared_roster.erl:1241 +#: mod_shared_roster.erl:1236 msgid "Description:" msgstr "描述:" -#: mod_shared_roster.erl:1248 +#: mod_shared_roster.erl:1243 msgid "Members:" msgstr "会员:" -#: mod_shared_roster.erl:1255 +#: mod_shared_roster.erl:1250 msgid "Displayed Groups:" msgstr "已显示的组:" -#: mod_shared_roster.erl:1264 +#: mod_shared_roster.erl:1259 msgid "Group " msgstr "组" @@ -1690,135 +1876,28 @@ msgstr "搜索结果属于关键词 " msgid "Fill in fields to search for any matching Jabber User" msgstr "填充字段以搜索任何匹配的 Jabber 用户" +#~ msgid "Outgoing s2s Servers:" +#~ msgstr "出站 s2s 服务器" + #~ msgid "Delete" #~ msgstr "删除" #~ msgid "This room is not anonymous" #~ msgstr "此房间不是匿名房间" -#~ msgid "Your active privacy list has denied the routing of this stanza." -#~ msgstr "你的活跃私聊列表拒绝了在此房间进行路由分发." - -#~ msgid "Access denied by service policy" -#~ msgstr "访问被服务策略拒绝" - -#~ msgid "Only service administrators are allowed to send service messages" -#~ msgstr "只有服务管理员可以发送服务消息" - -#~ msgid "Room creation is denied by service policy" -#~ msgstr "创建房间被服务策略拒绝" - -#~ msgid "Conference room does not exist" -#~ msgstr "会议室不存在" - -#~ msgid "That nickname is registered by another person" -#~ msgstr "该昵称已被另一个人注册了" - -#~ msgid "You must fill in field \"Nickname\" in the form" -#~ msgstr "您必须填充表单中\"昵称\"项" - -#~ msgid "Traffic rate limit is exceeded" -#~ msgstr "已经超过传输率限制" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" #~ msgstr "该参与人由于发送了错误消息而被踢出了聊天室" -#~ msgid "It is not allowed to send private messages to the conference" -#~ msgstr "不允许向会议发送私聊消息" - -#~ msgid "Please, wait for a while before sending new voice request" -#~ msgstr "请稍后再发送新的声音请求" - -#~ msgid "Voice requests are disabled in this conference" -#~ msgstr "该会议的声音请求以被禁用" - -#~ msgid "Failed to extract JID from your voice request approval" -#~ msgstr "无法从你的声音请求确认信息中提取JID" - -#~ msgid "Only moderators can approve voice requests" -#~ msgstr "仅主持人能确认声音请求" - -#~ msgid "Improper message type" -#~ msgstr "不恰当的消息类型" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" #~ msgstr "该参与人由于给其他人发送了出错消息而被踢出了聊天室" -#~ msgid "It is not allowed to send private messages of type \"groupchat\"" -#~ msgstr "\"群组聊天\"类型不允许发送私聊消息" - -#~ msgid "Recipient is not in the conference room" -#~ msgstr "接收人不在会议室" - -#~ msgid "It is not allowed to send private messages" -#~ msgstr "不可以发送私聊消息" - -#~ msgid "Only occupants are allowed to send messages to the conference" -#~ msgstr "只有与会人可以向大会发送消息" - -#~ msgid "Only occupants are allowed to send queries to the conference" -#~ msgstr "只有与会人可以向大会发出查询请求" - -#~ msgid "Queries to the conference members are not allowed in this room" -#~ msgstr "本房间不可以查询会议成员信息" - -#~ msgid "Visitors are not allowed to send messages to all occupants" -#~ msgstr "不允许访客给所有占有者发送消息" - #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" #~ msgstr "该用户由于发送了错误状态而被踢出了聊天室" -#~ msgid "Visitors are not allowed to change their nicknames in this room" -#~ msgstr "此房间不允许用户更改昵称" - -#~ msgid "That nickname is already in use by another occupant" -#~ msgstr "该昵称已被另一用户使用" - -#~ msgid "You have been banned from this room" -#~ msgstr "您已被禁止进入该房间" - -#~ msgid "Membership is required to enter this room" -#~ msgstr "进入此房间需要会员身份" - -#~ msgid "A password is required to enter this room" -#~ msgstr "进入此房间需要密码" - -#~ msgid "Too many CAPTCHA requests" -#~ msgstr "验证码请求太多" - -#~ msgid "Unable to generate a CAPTCHA" -#~ msgstr "无法生成验证码" - -#~ msgid "Incorrect password" -#~ msgstr "密码不正确" - -#~ msgid "Administrator privileges required" -#~ msgstr "需要管理员权限" - -#~ msgid "Moderator privileges required" -#~ msgstr "需要主持人权限" - -#~ msgid "Owner privileges required" -#~ msgstr "需要持有人权限" - -#~ msgid "" -#~ "Your contact offline message queue is full. The message has been " -#~ "discarded." -#~ msgstr "您的联系人离线消息队列已满. 消息已被丢弃" - -#~ msgid "The CAPTCHA verification has failed" -#~ msgstr "验证码检查失败" - -#~ msgid "The password is too weak" -#~ msgstr "密码强度太弱" - -#~ msgid "Users are not allowed to register accounts so quickly" -#~ msgstr "不允许用户太频繁地注册帐户" - #~ msgid "Captcha test failed" #~ msgstr "验证码检测失败." From 4cdb30d59e008fa8946851bae6ae683ee84cfbc6 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 29 Dec 2015 09:54:48 +0100 Subject: [PATCH 442/695] mod_mam: Use tags for deduplication Use elements instead of tags to check for messages resent by the stream management code. The element is preferable, as it is added by mod_mam itself. --- src/mod_mam.erl | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 7124e2c6d13..6dfff605816 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -166,7 +166,7 @@ user_receive_packet(Pkt, C2SState, JID, Peer, To) -> LUser = JID#jid.luser, LServer = JID#jid.lserver, IsBareCopy = is_bare_copy(JID, To), - case should_archive(Pkt) of + case should_archive(Pkt, LServer) of true when not IsBareCopy -> NewPkt = strip_my_archived_tag(Pkt, LServer), case store_msg(C2SState, NewPkt, LUser, LServer, Peer, recv) of @@ -191,7 +191,7 @@ user_receive_packet(Pkt, C2SState, JID, Peer, To) -> user_send_packet(Pkt, C2SState, JID, Peer) -> LUser = JID#jid.luser, LServer = JID#jid.lserver, - case should_archive(Pkt) of + case should_archive(Pkt, LServer) of true -> NewPkt = strip_my_archived_tag(Pkt, LServer), store_msg(C2SState, jlib:replace_from_to(JID, Peer, NewPkt), @@ -385,14 +385,14 @@ process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> With, RSM, IQ, MsgType) end. -should_archive(#xmlel{name = <<"message">>} = Pkt) -> +should_archive(#xmlel{name = <<"message">>} = Pkt, LServer) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of <<"error">> -> false; <<"groupchat">> -> false; _ -> - case is_resent(Pkt) of + case is_resent(Pkt, LServer) of true -> false; false -> @@ -412,7 +412,7 @@ should_archive(#xmlel{name = <<"message">>} = Pkt) -> end end end; -should_archive(#xmlel{}) -> +should_archive(#xmlel{}, _LServer) -> false. strip_my_archived_tag(Pkt, LServer) -> @@ -492,12 +492,17 @@ has_no_store_hint(Message) -> xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS) /= false. -is_resent(Pkt) -> - case xml:get_subtag_cdata(Pkt, <<"delay">>) of - <<>> -> - false; - Desc -> - binary:match(Desc, <<"Resent">>) =/= nomatch +is_resent(Pkt, LServer) -> + case xml:get_subtag_with_xmlns(Pkt, <<"stanza-id">>, ?NS_SID_0) of + #xmlel{attrs = Attrs} -> + case xml:get_attr(<<"by">>, Attrs) of + {value, LServer} -> + true; + _ -> + false + end; + false -> + false end. store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> From 1d2dc6cdc1f5353066912dfa22e8c524ee20b01c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 29 Dec 2015 11:11:50 +0100 Subject: [PATCH 443/695] mod_muc_room: Replace deprecated function call --- src/mod_muc_room.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 760bd729281..40d11bf67bf 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1314,7 +1314,7 @@ get_error_condition2(Packet) -> {condition, Condition}. make_reason(Packet, From, StateData, Reason1) -> - {ok, #user{nick = FromNick}} = (?DICT):find(jlib:jid_tolower(From), StateData#state.users), + {ok, #user{nick = FromNick}} = (?DICT):find(jid:tolower(From), StateData#state.users), Condition = get_error_condition(Packet), iolist_to_binary(io_lib:format(Reason1, [FromNick, Condition])). From 91d205715ec6ab6ff7b78ebe0c0e07e03bad671a Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 30 Dec 2015 12:53:40 +0100 Subject: [PATCH 444/695] New send_stanza command (ejabberd_contrib#142) --- src/mod_admin_extra.erl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 01478782580..c878e1fc588 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -46,7 +46,7 @@ private_get/4, private_set/3, srg_create/5, srg_delete/2, srg_list/1, srg_get_info/2, srg_get_members/2, srg_user_add/4, srg_user_del/4, - send_message/5, send_stanza_c2s/4, privacy_set/3, + send_message/5, send_stanza/3, send_stanza_c2s/4, privacy_set/3, stats/1, stats/2, mod_opt_type/1]). @@ -478,6 +478,11 @@ commands() -> module = ?MODULE, function = send_stanza_c2s, args = [{user, binary}, {host, binary}, {resource, binary}, {stanza, binary}], result = {res, rescode}}, + #ejabberd_commands{name = send_stanza, tags = [stanza], + desc = "Send a stanza; provide From JID and valid To JID", + module = ?MODULE, function = send_stanza, + args = [{from, binary}, {to, binary}, {stanza, binary}], + result = {res, rescode}}, #ejabberd_commands{name = privacy_set, tags = [stanza], desc = "Send a IQ set privacy stanza for a local account", module = ?MODULE, function = privacy_set, @@ -1327,6 +1332,12 @@ build_packet(Type, Subject, Body) -> [{xmlel, <<"body">>, [], [{xmlcdata, Body}]} | Tail] }. +send_stanza(FromString, ToString, Data) -> + Stanza = {xmlel, _, _, _} = xml_stream:parse_element(Data), + From = jlib:string_to_jid(FromString), + To = jlib:string_to_jid(ToString), + ejabberd_router:route(From, To, Stanza). + send_stanza_c2s(Username, Host, Resource, Stanza) -> C2sPid = ejabberd_sm:get_session_pid(Username, Host, Resource), XmlEl = xml_stream:parse_element(Stanza), From b73678992b4328fd1963a4a828596637080f6790 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 2 Jan 2016 20:57:01 +0100 Subject: [PATCH 445/695] mod_muc_admin: Allow for setting MAM option Fixes #890. --- src/mod_muc_admin.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 97ae3c6ec09..195cc632c9c 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -797,6 +797,7 @@ change_option(Option, Value, Config) -> captcha_protected -> Config#config{captcha_protected = Value}; description -> Config#config{description = Value}; logging -> Config#config{logging = Value}; + mam -> Config#config{mam = Value}; max_users -> Config#config{max_users = Value}; members_by_default -> Config#config{members_by_default = Value}; members_only -> Config#config{members_only = Value}; From 5deb6a91f776a24f459909768db3dacb648e3a7c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 2 Jan 2016 21:27:48 +0100 Subject: [PATCH 446/695] mod_admin_extra: Replace deprecated function calls --- src/mod_admin_extra.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index c878e1fc588..fb351d2f4c6 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -1334,8 +1334,8 @@ build_packet(Type, Subject, Body) -> send_stanza(FromString, ToString, Data) -> Stanza = {xmlel, _, _, _} = xml_stream:parse_element(Data), - From = jlib:string_to_jid(FromString), - To = jlib:string_to_jid(ToString), + From = jid:from_string(FromString), + To = jid:from_string(ToString), ejabberd_router:route(From, To, Stanza). send_stanza_c2s(Username, Host, Resource, Stanza) -> From fc013442bbce6a6d9b8f31a6747edd0d4b9a23fa Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sun, 3 Jan 2016 23:35:41 +0100 Subject: [PATCH 447/695] ejabberdctl: Call erl without -pa argument The path to ejabberd's ebin directories is now specified by setting the ERL_LIBS variable. --- ejabberdctl.template | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 5fbcf94ee17..fe6cc4c0271 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -167,7 +167,6 @@ start() $EXEC_CMD "$ERL \ $NAME $ERLANG_NODE \ -noinput -detached \ - -pa $EJABBERD_EBIN_PATH \ $MNESIA_OPTS \ $KERNEL_OPTS \ $EJABBERD_OPTS \ @@ -207,7 +206,6 @@ live() livewarning $EXEC_CMD "$ERL \ $NAME $ERLANG_NODE \ - -pa $EJABBERD_EBIN_PATH \ $MNESIA_OPTS \ $KERNEL_OPTS \ $EJABBERD_OPTS \ @@ -221,7 +219,6 @@ iexlive() livewarning $EXEC_CMD "$IEX \ $IEXNAME $ERLANG_NODE \ - -pa $EJABBERD_EBIN_PATH \ --erl \"-mnesia dir \\\"$SPOOL_DIR\\\"\" \ --erl \"$KERNEL_OPTS\" \ --erl \"$EJABBERD_OPTS\" \ @@ -236,7 +233,6 @@ foreground() $EXEC_CMD "$ERL \ $NAME $ERLANG_NODE \ -noinput \ - -pa $EJABBERD_EBIN_PATH \ $MNESIA_OPTS \ $KERNEL_OPTS \ $EJABBERD_OPTS \ @@ -306,7 +302,6 @@ ping() $EXEC_CMD "$ERL \ $NAME ping-${TTY}-${ERLANG_NODE} \ -hidden \ - -pa $EJABBERD_EBIN_PATH \ $KERNEL_OPTS $ERLANG_OPTS \ -eval 'io:format(\"~p~n\",[net_adm:ping($1)])' \ -s erlang halt -output text -noinput" @@ -417,7 +412,6 @@ ctlexec() $NAME ${CONN_NAME} \ -noinput \ -hidden \ - -pa $EJABBERD_EBIN_PATH \ $KERNEL_OPTS \ -s ejabberd_ctl -extra $ERLANG_NODE $EJABBERD_NO_TIMEOUT $COMMAND" } From 94c620cc2780fe8efa1650b732149f620c4397dd Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 4 Jan 2016 01:01:14 +0100 Subject: [PATCH 448/695] mod_http_upload: Fix logging of file size mismatch --- src/mod_http_upload.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 6d19f873f4f..66116370326 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -412,7 +412,7 @@ process([_UserDir, _RandDir, _FileName] = Slot, [Path, ?ADDR_TO_STR(IP), Host, ?FORMAT(Error)]), http_response(Host, 500) end; - {ok, Size, Path} -> + {ok, Size, Path, _FileMode, _DirMode, _GetPrefix, _Thumbnail} -> ?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B", [Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]), http_response(Host, 413); From fb8a51136519a190145265736c4243095e2516ec Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 4 Jan 2016 13:55:25 +0300 Subject: [PATCH 449/695] Use crypto:rand_uniform instead of random:uniform --- src/randoms.erl | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/randoms.erl b/src/randoms.erl index 4068fa79d7c..9d9b392f6a2 100644 --- a/src/randoms.erl +++ b/src/randoms.erl @@ -29,23 +29,12 @@ -export([get_string/0]). --export([start/0, init/0]). +-export([start/0]). start() -> - register(random_generator, spawn(randoms, init, [])). - -init() -> - random:seed(p1_time_compat:timestamp()), loop(). - -loop() -> - receive - {From, get_random, N} -> - From ! {random, random:uniform(N)}, loop(); - _ -> loop() - end. + ok. get_string() -> - random_generator ! {self(), get_random, 65536 * 65536}, - receive - {random, R} -> jlib:integer_to_binary(R) - end. + R = crypto:rand_uniform(0, 16#10000000000000000), + jlib:integer_to_binary(R). + From 98bad73d562f202c606f1aa8e51e1c2756cba15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 4 Jan 2016 12:13:18 +0100 Subject: [PATCH 450/695] Improve escaping of arguments passed to ejabberdctl This fixes issue #804 --- ejabberdctl.template | 150 +++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 69 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index fe6cc4c0271..f65c21f51ab 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # define default configuration POLL=true @@ -42,9 +42,9 @@ else fi # parse command line parameters -ARGS="" +declare -a ARGS=() while [ $# -ne 0 ] ; do - PARAM=$1 + PARAM="$1" shift case $PARAM in --) break ;; @@ -55,7 +55,7 @@ while [ $# -ne 0 ] ; do --ctl-config) EJABBERDCTL_CONFIG_PATH="$1" ; shift ;; --logs) LOGS_DIR="$1" ; shift ;; --spool) SPOOL_DIR="$1" ; shift ;; - *) ARGS="$ARGS $PARAM" ;; + *) ARGS=("${ARGS[@]}" "$PARAM") ;; esac done @@ -160,18 +160,27 @@ export CONTRIB_MODULES_PATH export CONTRIB_MODULES_CONF_DIR export ERL_LIBS +shell_escape() +{ + local RES=() + for i in "$@"; do + printf '%q ' "$i" + done +} + # start server start() { check_start - $EXEC_CMD "$ERL \ - $NAME $ERLANG_NODE \ - -noinput -detached \ - $MNESIA_OPTS \ - $KERNEL_OPTS \ - $EJABBERD_OPTS \ - -s ejabberd \ - $ERLANG_OPTS $ARGS \"$@\"" + CMD="`shell_escape \"$ERL\" \"$NAME\" \"$ERLANG_NODE\"` \ + -noinput -detached \ + $MNESIA_OPTS \ + $KERNEL_OPTS \ + $EJABBERD_OPTS \ + -s ejabberd \ + $ERLANG_OPTS \ + `shell_escape \"${ARGS[@]}\" \"$@\"`" + $EXEC_CMD "$CMD" } # attach to server @@ -179,12 +188,13 @@ debug() { debugwarning TTY=`tty | sed -e 's/.*\///g'` - $EXEC_CMD "$ERL \ - $NAME debug-${TTY}-${ERLANG_NODE} \ - -remsh $ERLANG_NODE \ - -hidden \ - $KERNEL_OPTS \ - $ERLANG_OPTS $ARGS \"$@\"" + CMD="`shell_escape \"$ERL\" \"$NAME\" \"debug-${TTY}-${ERLANG_NODE}\"` \ + -remsh $ERLANG_NODE \ + -hidden \ + $KERNEL_OPTS \ + $ERLANG_OPTS \ + `shell_escape \"${ARGS[@]}\" \"$@\"`" + $EXEC_CMD "$CMD" } # attach to server using Elixir @@ -193,51 +203,57 @@ iexdebug() debugwarning TTY=`tty | sed -e 's/.*\///g'` # Elixir shell is hidden as default - $EXEC_CMD "$IEX \ - $IEXNAME debug-${TTY}-${ERLANG_NODE} \ - --remsh $ERLANG_NODE \ - --erl \"$KERNEL_OPTS\" \ - --erl \"$ERLANG_OPTS\" --erl \"$ARGS\" --erl \"$@\"" + CMD="`shell_escape \"$IEX\" \"$IEXNAME\" \"debug-${TTY}-${ERLANG_NODE}\"` \ + -remsh $ERLANG_NODE \ + --erl \"`shell_escape \"$KERNEL_OPTS\"\" \ + --erl \"`shell_escape \"$ERLANG_OPTS\"\" \ + --erl \"`shell_escape \"${ARGS[@]}\"\" \ + --erl \"`shell_escape \"$@\"\"" + $EXEC_CMD "$CMD" } # start interactive server live() { livewarning - $EXEC_CMD "$ERL \ - $NAME $ERLANG_NODE \ - $MNESIA_OPTS \ - $KERNEL_OPTS \ - $EJABBERD_OPTS \ - -s ejabberd \ - $ERLANG_OPTS $ARGS \"$@\"" + CMD="`shell_escape \"$ERL\" \"$NAME\" \"${ERLANG_NODE}\"` \ + $MNESIA_OPTS \ + $KERNEL_OPTS \ + $EJABBERD_OPTS \ + -s ejabberd \ + $ERLANG_OPTS \ + `shell_escape \"${ARGS[@]}\" \"$@\"`" + $EXEC_CMD "$CMD" } # start interactive server with Elixir iexlive() { livewarning - $EXEC_CMD "$IEX \ - $IEXNAME $ERLANG_NODE \ - --erl \"-mnesia dir \\\"$SPOOL_DIR\\\"\" \ - --erl \"$KERNEL_OPTS\" \ - --erl \"$EJABBERD_OPTS\" \ - --app ejabberd \ - --erl \"$ERLANG_OPTS\" --erl $ARGS --erl \"$@\"" + CMD="`shell_escape \"$IEX\" \"$IEXNAME\" \"${ERLANG_NODE}\"` \ + --erl \"-mnesia dir \\\"$SPOOL_DIR\\\"\" \ + --erl \"`shell_escape \"$KERNEL_OPTS\"`\" \ + --erl \"`shell_escape \"$EJABBERD_OPTS\"`\" \ + --app ejabberd \ + --erl \"`shell_escape \"$ERLANG_OPTS\"`\" \ + --erl \"`shell_escape \"${ARGS[@]}\"`\" \ + --erl \"`shell_escape \"$@\"`\"" + $EXEC_CMD "$CMD" } # start server in the foreground foreground() { check_start - $EXEC_CMD "$ERL \ - $NAME $ERLANG_NODE \ - -noinput \ - $MNESIA_OPTS \ - $KERNEL_OPTS \ - $EJABBERD_OPTS \ - -s ejabberd \ - $ERLANG_OPTS $ARGS \"$@\"" + CMD="`shell_escape \"$ERL\" \"$NAME\" \"$ERLANG_NODE\"` \ + -noinput \ + $MNESIA_OPTS \ + $KERNEL_OPTS \ + $EJABBERD_OPTS \ + -s ejabberd \ + $ERLANG_OPTS \ + `shell_escape \"${ARGS[@]}\" \"$@\"`" + $EXEC_CMD "$CMD" } debugwarning() @@ -331,8 +347,6 @@ help() # common control function ctl() { - COMMAND=$@ - # Control number of connections identifiers # using flock if available. Expects a linux-style # flock that can lock a file descriptor. @@ -344,13 +358,13 @@ ctl() if [ ! -x "$JOT" ] ; then # no flock or jot, simply invoke ctlexec() CTL_CONN="ctl-${ERLANG_NODE}" - ctlexec $CTL_CONN $COMMAND + ctlexec $CTL_CONN "$@" result=$? else # no flock, but at least there is jot RAND=`jot -r 1 0 $MAXCONNID` CTL_CONN="ctl-${RAND}-${ERLANG_NODE}" - ctlexec $CTL_CONN $COMMAND + ctlexec $CTL_CONN "$@" result=$? fi else @@ -365,7 +379,7 @@ ctl() ( exec 8>"$CTL_LOCKFILE" if flock --nb 8; then - ctlexec $CTL_CONN $COMMAND + ctlexec $CTL_CONN "$@" ssresult=$? # segregate from possible flock exit(1) ssresult=`expr $ssresult \* 10` @@ -407,13 +421,11 @@ ctl() ctlexec() { CONN_NAME=$1; shift - COMMAND=$(echo $@ | sed 's/["&$;\|<>()]/\\&/g') - $EXEC_CMD "$ERL \ - $NAME ${CONN_NAME} \ - -noinput \ - -hidden \ - $KERNEL_OPTS \ - -s ejabberd_ctl -extra $ERLANG_NODE $EJABBERD_NO_TIMEOUT $COMMAND" + CMD="`shell_escape \"$ERL\" \"$NAME\" \"$CONN_NAME\"` \ + -noinput -hidden $KERNEL_OPTS -s ejabberd_ctl \ + -extra `shell_escape \"$ERLANG_NODE\"` $EJABBERD_NO_TIMEOUT \ + `shell_escape \"$@\"`" + $EXEC_CMD "$CMD" } # stop epmd if there is no other running node @@ -463,16 +475,16 @@ wait_for_status() } # main handler -case $ARGS in - ' start') start;; - ' debug') debug;; - ' iexdebug') iexdebug;; - ' live') live;; - ' iexlive') iexlive;; - ' foreground') foreground;; - ' ping'*) ping ${ARGS# ping};; - ' etop') etop;; - ' started') wait_for_status 0 30 2;; # wait 30x2s before timeout - ' stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout - *) ctl $ARGS;; +case "${ARGS[0]}" in + 'start') start;; + 'debug') debug;; + 'iexdebug') iexdebug;; + 'live') live;; + 'iexlive') iexlive;; + 'foreground') foreground;; + 'ping'*) ping ${ARGS# ping};; + 'etop') etop;; + 'started') wait_for_status 0 30 2;; # wait 30x2s before timeout + 'stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout + *) ctl "${ARGS[@]}";; esac From da45a064a8a2e70ce35163182d9eaf8000b56f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 4 Jan 2016 22:06:19 +0100 Subject: [PATCH 451/695] Fix handling of some options in old style configs This fixes issue #893. --- src/ejabberd_config.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 75d56509ec4..6e2cabb5770 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -425,7 +425,6 @@ merge_configs(Terms, ResMap) -> maps:put(Name, Val, Map) end, ResMap, Terms). - %% @doc Include additional configuration files in the list of terms. %% @spec ([term()]) -> [term()] include_config_files(Terms) -> @@ -443,8 +442,8 @@ include_config_files(Terms) -> include_config_file(File, Opts) end, lists:flatten(FileOpts)), - M1 = merge_configs(Terms1, #{}), - M2 = merge_configs(Terms2, M1), + M1 = merge_configs(transform_terms(Terms1), #{}), + M2 = merge_configs(transform_terms(Terms2), M1), maps_to_lists(M2). transform_include_option({include_config_file, File}) when is_list(File) -> From c01e3f24a5e7153805524068e0365a0ee623710e Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 5 Jan 2016 12:29:13 +0100 Subject: [PATCH 452/695] Error converting times in mod_fail2ban (#889) --- src/mod_fail2ban.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 523cbb3f94f..394a7186f87 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -83,7 +83,7 @@ check_bl_c2s(_Acc, Addr, Lang) -> true -> IP = jlib:ip_to_list(Addr), UnbanDate = format_date( - calendar:now_to_universal_time(TS)), + calendar:now_to_universal_time(seconds_to_now(TS))), LogReason = io_lib:fwrite( "Too many (~p) failed authentications " "from this IP address (~s). The address " @@ -179,6 +179,9 @@ is_loaded_at_other_hosts(Host) -> gen_mod:is_loaded(VHost, ?MODULE) end, ?MYHOSTS). +seconds_to_now(Secs) -> + {Secs div 1000000, Secs rem 1000000, 0}. + format_date({{Year, Month, Day}, {Hour, Minute, Second}}) -> io_lib:format("~2..0w:~2..0w:~2..0w ~2..0w.~2..0w.~4..0w", [Hour, Minute, Second, Day, Month, Year]). From efda70e73aa80399377613b05d93ac208ca687fd Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 5 Jan 2016 16:00:47 +0100 Subject: [PATCH 453/695] Update dependencies --- rebar.config | 47 ++++++++++----------- tools/set-dep-versions | 92 ------------------------------------------ 2 files changed, 24 insertions(+), 115 deletions(-) delete mode 100755 tools/set-dep-versions diff --git a/rebar.config b/rebar.config index 62b44d13ab1..4036dc221c1 100644 --- a/rebar.config +++ b/rebar.config @@ -7,30 +7,31 @@ %%% Created : 1 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -{deps, [{if_var_true, lager, {lager, ".*", {git, "git://github.com/basho/lager"}}}, - {if_var_false, lager, {p1_logger, ".*", {git, "git://github.com/processone/p1_logger"}}}, - {cache_tab, ".*", {git, "git://github.com/processone/cache_tab", {tag, "1.0.1"}}}, - {p1_tls, ".*", {git, "https://github.com/processone/tls"}}, - {p1_stringprep, ".*", {git, "git://github.com/processone/stringprep"}}, - {p1_xml, ".*", {git, "https://github.com/processone/xml"}}, - {esip, ".*", {git, "git://github.com/processone/p1_sip"}}, - {p1_stun, ".*", {git, "git://github.com/processone/stun"}}, - {p1_yaml, ".*", {git, "git://github.com/processone/p1_yaml"}}, - {p1_utils, ".*", {git, "git://github.com/processone/p1_utils"}}, - {jiffy, ".*", {git, "git://github.com/davisp/jiffy"}}, - {oauth2, ".*", {git, "https://github.com/prefiks/oauth2.git"}}, - {xmlrpc, ".*", {git, "git://github.com/rds13/xmlrpc"}}, - {if_var_true, mysql, {p1_mysql, ".*", {git, "git://github.com/processone/mysql"}}}, - {if_var_true, pgsql, {p1_pgsql, ".*", {git, "git://github.com/processone/pgsql"}}}, - {if_var_true, sqlite, {sqlite3, ".*", {git, "git://github.com/alexeyr/erlang-sqlite3"}}}, - {if_var_true, pam, {p1_pam, ".*", {git, "git://github.com/processone/epam"}}}, - {if_var_true, zlib, {p1_zlib, ".*", {git, "git://github.com/processone/zlib"}}}, - {if_var_true, riak, {riakc, ".*", {git, "git://github.com/basho/riak-erlang-client"}}}, - {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "git@github.com:processone/rebar_elixir_plugin.git"}}}, - {if_var_true, elixir, {elixir, ".*", {git, "git://github.com/elixir-lang/elixir", {branch, "v1.0"}}}}, - {if_var_true, iconv, {p1_iconv, ".*", {git, "git://github.com/processone/eiconv"}}}, +{deps, [{if_var_true, lager, {lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.0.2"}}}}, + {if_var_false, lager, {p1_logger, ".*", {git, "https://github.com/processone/p1_logger", {tag, "1.0.0"}}}}, + {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.2"}}}, + {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.1"}}}, + {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, + {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.0"}}}, + {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.1"}}}, + {p1_stun, ".*", {git, "https://github.com/processone/stun", "0.9.0"}}, + {esip, ".*", {git, "https://github.com/processone/p1_sip", "1.0.0"}}, + {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", {tag, "1.0.0"}}}, + {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.5"}}}, + {oauth2, ".*", {git, "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}}, + {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc", {tag, "1.15"}}}, + {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/mysql", {tag, "1.0.0"}}}}, + {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", {tag, "1.0.0"}}}}, + {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}}}, + {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.0"}}}}, + {if_var_true, zlib, {p1_zlib, ".*", {git, "https://github.com/processone/zlib", {tag, "1.0.0"}}}}, + {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 + {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, + {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, + {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.1.0"}}}}, + {if_var_true, iconv, {p1_iconv, ".*", {git, "https://github.com/processone/eiconv", {tag, "0.9.0"}}}}, {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, - {if_var_true, redis, {eredis, ".*", {git, "git://github.com/wooga/eredis"}}}]}. + {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}}]}. {if_var_true, latest_deps, {floating_deps, [p1_logger, diff --git a/tools/set-dep-versions b/tools/set-dep-versions deleted file mode 100755 index 3681def2277..00000000000 --- a/tools/set-dep-versions +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh - -set -e -set -u - -export PATH="/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:$PATH" - -deps_dir='deps' -rebar_script='rebar.config' -temp_file=$(mktemp "$rebar_script.XXXXXX") - -trap 'rm -f $temp_file' EXIT INT TERM - -die() -{ - echo >&2 "FATAL: $@." - exit 1 -} - -get_dep_list() -{ - sed -n ' - /.*{ *\([^,]*\),[^,]*, *{ *git, *"\([^"]*\)" *} *}.*/ { - s//\1,\2,master/ - p - } - /.*{ *\([^,]*\),[^,]*, *{ *git, *"\([^"]*\)" *, *{ *branch, *"\([^"]*\)".*/ { - s//\1,\2,\3/ - p - }' "$rebar_script" -} - -get_dep_name() -{ - printf '%s' "${1%%,*}" -} - -get_dep_url() -{ - dep_url=${1#*,} - dep_url=${dep_url%,*} - - printf '%s' "$dep_url" -} - -get_dep_branch() -{ - printf '%s' "${1##*,}" -} - -get_dep_rev() -{ - dep_name=$(get_dep_name "$1") - dep_dir="$deps_dir/$dep_name" - - test -d "$dep_dir" || clone_repo "$dep" - cd "$dep_dir" - printf '%s' "$(git rev-parse --verify HEAD)" - cd "$OLDPWD" -} - -clone_repo() -{ - dep_name=$(get_dep_name "$1") - dep_url=$(get_dep_url "$1") - dep_branch=$(get_dep_branch "$1") - - cd "$deps_dir" - git clone -q -b "$dep_branch" "$dep_url" "$dep_name" - cd "$OLDPWD" -} - -edit_rebar_script() -{ - dep_name=$(get_dep_name "$1") - dep_url=$(get_dep_url "$1") - dep_rev=$(get_dep_rev "$1") - - echo "Using revision $dep_rev of $dep_name" - sed -e "s|\"$dep_url\".*{ *branch[^}]*} *}|\"$dep_url\", \"$dep_rev\"}|" \ - -e "s|\"$dep_url\"[^}]*}|\"$dep_url\", \"$dep_rev\"}|" \ - "$rebar_script" >"$temp_file" - mv "$temp_file" "$rebar_script" -} - -test -e "$rebar_script" || die 'Please change to ejabberd source directory' -test -d "$deps_dir" || mkdir -p "$deps_dir" - -for dep in $(get_dep_list) -do - edit_rebar_script "$dep" -done From 3f5a20c90a2317dfa2d1aecb4e8443a1bd100c23 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 5 Jan 2016 22:06:34 +0100 Subject: [PATCH 454/695] mod_http_upload: Rename variable for clarity --- src/mod_http_upload.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 66116370326..0abce21246a 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -775,14 +775,14 @@ iq_disco_info(Lang, Name) -> binary(), slot(), boolean()) -> ok | {ok, [{binary(), binary()}], binary()} | {error, term()}. -store_file(Path, Data, FileMode, DirMode, GetPrefix, LocalPath, Thumbnail) -> +store_file(Path, Data, FileMode, DirMode, GetPrefix, Slot, Thumbnail) -> case do_store_file(Path, Data, FileMode, DirMode) of ok when Thumbnail -> case identify(Path) of {ok, MediaInfo} -> case convert(Path, MediaInfo) of {ok, OutPath} -> - [UserDir, RandDir | _] = LocalPath, + [UserDir, RandDir | _] = Slot, FileName = filename:basename(OutPath), URL = str:join([GetPrefix, UserDir, RandDir, FileName], <<$/>>), From e1539a11be95f94bc7ebcb05327c8df802a84b01 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 6 Jan 2016 00:12:36 +0100 Subject: [PATCH 455/695] mod_http_upload: Use full PUT URL for process name Don't just use the "put_url" domain name, but also any path components of the specified URL, to generate a mod_http_upload process name. This way, a single domain name can be used for multiple virtual hosts by specifying a "put_url" such as "https://example.com/@HOST@/". --- src/mod_http_upload.erl | 53 +++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 0abce21246a..7aa28b6e136 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -393,9 +393,17 @@ code_change(_OldVsn, #state{server_host = ServerHost} = State, _Extra) -> -spec process([binary()], #request{}) -> {pos_integer(), [{binary(), binary()}], binary()}. -process([_UserDir, _RandDir, _FileName] = Slot, - #request{method = 'PUT', host = Host, ip = IP, data = Data}) -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME), +process(LocalPath, #request{method = Method, host = Host, ip = IP}) + when length(LocalPath) < 3, + Method == 'PUT' orelse + Method == 'GET' orelse + Method == 'HEAD' -> + ?DEBUG("Rejecting ~s request from ~s for ~s: Too few path components", + [Method, ?ADDR_TO_STR(IP), Host]), + http_response(Host, 404); +process(_LocalPath, #request{method = 'PUT', host = Host, ip = IP, + data = Data} = Request) -> + {Proc, Slot} = parse_http_request(Request), case catch gen_server:call(Proc, {use_slot, Slot}) of {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail} when byte_size(Data) == Size -> @@ -425,11 +433,10 @@ process([_UserDir, _RandDir, _FileName] = Slot, [?ADDR_TO_STR(IP), Host, Error]), http_response(Host, 500) end; -process([_UserDir, _RandDir, FileName] = Slot, - #request{method = Method, host = Host, ip = IP}) +process(_LocalPath, #request{method = Method, host = Host, ip = IP} = Request) when Method == 'GET'; Method == 'HEAD' -> - Proc = gen_mod:get_module_proc(Host, ?PROCNAME), + {Proc, [_UserDir, _RandDir, FileName] = Slot} = parse_http_request(Request), case catch gen_server:call(Proc, get_docroot) of {ok, DocRoot} -> Path = str:join([DocRoot | Slot], <<$/>>), @@ -469,19 +476,6 @@ process([_UserDir, _RandDir, FileName] = Slot, [Method, ?ADDR_TO_STR(IP), Host, Error]), http_response(Host, 500) end; -process(LocalPath, #request{method = 'PUT', host = Host, ip = IP}) - when length(LocalPath) > 3 -> - ?INFO_MSG("Rejecting PUT request from ~s for ~s: Too many path components", - [?ADDR_TO_STR(IP), Host]), - ?INFO_MSG("Check whether 'request_handlers' path matches 'put_url'", []), - http_response(Host, 404); -process(_LocalPath, #request{method = Method, host = Host, ip = IP}) - when Method == 'PUT'; - Method == 'GET'; - Method == 'HEAD' -> - ?DEBUG("Rejecting ~s request from ~s for ~s: Too few/many path components", - [Method, ?ADDR_TO_STR(IP), Host]), - http_response(Host, 404); process(_LocalPath, #request{method = 'OPTIONS', host = Host, ip = IP}) -> ?DEBUG("Responding to OPTIONS request from ~s for ~s", [?ADDR_TO_STR(IP), Host]), @@ -504,10 +498,10 @@ get_proc_name(ServerHost, ModuleName) -> (_) -> <<"http://@HOST@">> end, <<"http://@HOST@">>), - [_, ProcHost | _] = binary:split(expand_host(PutURL, ServerHost), - [<<"http://">>, <<"https://">>, - <<":">>, <<"/">>], [global]), - gen_mod:get_module_proc(ProcHost, ModuleName). + {ok, {_Scheme, _UserInfo, Host, _Port, Path, _Query}} = + http_uri:parse(binary_to_list(expand_host(PutURL, ServerHost))), + ProcPrefix = list_to_binary(string:strip(Host ++ Path, right, $/)), + gen_mod:get_module_proc(ProcPrefix, ModuleName). -spec expand_home(binary()) -> binary(). @@ -769,6 +763,19 @@ iq_disco_info(Lang, Name) -> %% HTTP request handling. +-spec parse_http_request(#request{}) -> {atom(), slot()}. + +parse_http_request(#request{host = Host, path = Path}) -> + PrefixLength = length(Path) - 3, + {ProcURL, Slot} = if PrefixLength > 0 -> + Prefix = lists:sublist(Path, PrefixLength), + {str:join([Host | Prefix], $/), + lists:nthtail(PrefixLength, Path)}; + true -> + {Host, Path} + end, + {gen_mod:get_module_proc(ProcURL, ?PROCNAME), Slot}. + -spec store_file(binary(), binary(), integer() | undefined, integer() | undefined, From bbd428a0e1251758a97c742a779067b64fb282f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 6 Jan 2016 12:06:28 +0100 Subject: [PATCH 456/695] Update deps in reltool.config.scripts --- rel/reltool.config.script | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/rel/reltool.config.script b/rel/reltool.config.script index 09dd8365765..6ebb3b3e831 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -28,21 +28,27 @@ ConfiguredOTPApps = lists:flatmap( OTPApps = RequiredOTPApps ++ ConfiguredOTPApps, -DepRequiredApps = [p1_cache_tab, p1_tls, p1_stringprep, p1_xml, p1_yaml, p1_utils], +DepRequiredApps = [cache_tab, p1_tls, p1_stringprep, p1_xml, esip, p1_stun, + p1_yaml, p1_utils, jiffy, oauth2, xmlrpc], -DepConfiguredApps = lists:flatmap( + +DepConfiguredApp0 = lists:flatmap( fun({mysql, true}) -> [p1_mysql]; ({pgsql, true}) -> [p1_pgsql]; + ({sqlite, true}) -> [sqlite3]; ({pam, true}) -> [p1_pam]; ({zlib, true}) -> [p1_zlib]; - ({stun, true}) -> [p1_stun]; - ({json, true}) -> [jiffy]; + ({riak, true}) -> [riakc, riak_pb, protobuffs, hamcrest, meck]; + ({elixir, true}) -> [elixir, rebar_elixir_plugin]; ({iconv, true}) -> [p1_iconv]; + ({tools, true}) -> [meck]; + ({redis, true}) -> [eredis]; ({lager, true}) -> [lager, goldrush]; ({lager, false}) -> [p1_logger]; (_) -> [] end, Vars), +DepConfiguredApps = lists:usort(fun(A, B) -> A >= B end, DepConfiguredApp0), DepApps = DepRequiredApps ++ DepConfiguredApps, Sys = [{lib_dirs, []}, From 14815b9a45aab12c5e8ddc66b7c0b11e26a365d6 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 6 Jan 2016 12:27:43 +0100 Subject: [PATCH 457/695] Update mix deps --- mix.exs | 49 ++++++++++++++++++++++++++----------------------- mix.lock | 30 +++++++----------------------- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/mix.exs b/mix.exs index e8e34c47e57..b002e36b760 100644 --- a/mix.exs +++ b/mix.exs @@ -3,8 +3,8 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "15.11.0", - elixir: "~> 1.0", + version: "16.01.0", + elixir: "~> 1.1", elixirc_paths: ["lib"], compile_path: ".", compilers: [:asn1] ++ Mix.compilers, @@ -16,11 +16,12 @@ defmodule Ejabberd.Mixfile do def application do [mod: {:ejabberd_app, []}, - applications: [:ssl], - included_applications: [:p1_logger, :p1_yaml, :p1_tls, :p1_xml, - :p1_stringprep, :p1_zlib, :cache_tab, - :mnesia, :p1_utils, :p1_iconv, :esip, :p1_stun, - :p1_mysql, :p1_pgsql, :eredis, :oauth2, :xmlrpc]] + applications: [:ssl, :mnesia], + included_applications: [:lager, :p1_utils, :cache_tab, + :p1_tls, :p1_stringprep, :p1_xml, + :p1_stun, :p1_yaml, :p1_zlib, :p1_iconv, + :esip, :jiffy, :oauth2, :xmlrpc, :eredis, + :p1_mysql, :p1_pgsql, :sqlite3]] end defp erlc_options do @@ -30,23 +31,25 @@ defmodule Ejabberd.Mixfile do end defp deps do - [{:p1_xml, git: "https://github.com/processone/xml"}, - {:p1_logger, git: "https://github.com/processone/p1_logger"}, - {:p1_yaml, git: "https://github.com/processone/p1_yaml"}, - {:p1_tls, git: "https://github.com/processone/tls"}, - {:p1_stringprep, git: "https://github.com/processone/stringprep"}, - {:p1_zlib, git: "https://github.com/processone/zlib"}, + [{:lager, git: "https://github.com/basho/lager", tag: "3.0.2"}, + {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.2"}, {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.1"}, - {:p1_utils, git: "https://github.com/processone/p1_utils"}, - {:p1_iconv, git: "https://github.com/processone/eiconv"}, - {:esip, git: "https://github.com/processone/p1_sip"}, - {:p1_stun, git: "https://github.com/processone/stun"}, - {:p1_mysql, git: "https://github.com/processone/mysql"}, - {:p1_pgsql, git: "https://github.com/processone/pgsql"}, - {:eredis, git: "https://github.com/wooga/eredis"}, - {:oauth2, git: "https://github.com/prefiks/oauth2.git"}, - {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git"}, - {:exrm, "~> 0.19.2"}] + {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, + {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.0"}, + {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.1"}, + {:p1_stun, git: "https://github.com/processone/stun", tag: "0.9.0"}, + {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.0"}, + {:p1_yaml, git: "https://github.com/processone/p1_yaml", tag: "1.0.0"}, + {:jiffy, git: "https://github.com/davisp/jiffy", tag: "0.14.5"}, + {:oauth2, git: "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}, + {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git", tag: "1.15"}, + {:p1_mysql, git: "https://github.com/processone/mysql", tag: "1.0.0"}, + {:p1_pgsql, git: "https://github.com/processone/pgsql", tag: "1.0.0"}, + {:sqlite3, git: "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}, + {:p1_zlib, git: "https://github.com/processone/zlib", tag: "1.0.0"}, + {:p1_iconv, git: "https://github.com/processone/eiconv", tag: "0.9.0"}, + {:eredis, git: "https://github.com/wooga/eredis", tag: "v1.0.8"}, + {:exrm, "0.19.9"}] end defp package do diff --git a/mix.lock b/mix.lock index 001e00624cb..5f4955115bd 100644 --- a/mix.lock +++ b/mix.lock @@ -1,24 +1,8 @@ -%{"bbmustache": {:hex, :bbmustache, "1.0.3"}, - "conform": {:hex, :conform, "0.17.0"}, - "eredis": {:git, "https://github.com/wooga/eredis", "bf12ecb30253c84a2331f4f0d93fd68856fcb9f4", []}, - "erlware_commons": {:hex, :erlware_commons, "0.15.0"}, - "esip": {:git, "https://github.com/processone/p1_sip", "d662d3fe7f6288b444ea321d854de0bd6d40e022", []}, - "exrm": {:hex, :exrm, "0.19.9"}, +%{"bbmustache": {:hex, :bbmustache, "1.0.4"}, + "erlware_commons": {:hex, :erlware_commons, "0.18.0"}, "getopt": {:hex, :getopt, "0.8.2"}, - "neotoma": {:hex, :neotoma, "1.7.3"}, - "oauth2": {:git, "https://github.com/prefiks/oauth2.git", "e6da9912e5d8f658e7e868f41a102d085bdbef59", []}, - "p1_cache_tab": {:git, "https://github.com/processone/cache_tab", "f7ea12b0ba962a3d2f9a406d2954cf7de4e27230", []}, - "p1_iconv": {:git, "https://github.com/processone/eiconv", "8b7542b1aaf0a851f335e464956956985af6d9a2", []}, - "p1_logger": {:git, "https://github.com/processone/p1_logger", "3e19507fd5606a73694917158767ecb3f5704e3f", []}, - "p1_mysql": {:git, "https://github.com/processone/mysql", "dfa87da95f8fdb92e270741c2a53f796b682f918", []}, - "p1_pgsql": {:git, "https://github.com/processone/pgsql", "e72c03c60bfcb56bbb5d259342021d9cb3581dac", []}, - "p1_stringprep": {:git, "https://github.com/processone/stringprep", "3c640237a3a7831dc39de6a6d329d3a9af25c579", []}, - "p1_stun": {:git, "https://github.com/processone/stun", "061bdae484268cbf0457ad4797e74b8516df3ad1", []}, - "p1_tls": {:git, "https://github.com/processone/tls", "e56321afd974e9da33da913cd31beebc8e73e75f", []}, - "p1_utils": {:git, "https://github.com/processone/p1_utils", "7aa022f995e3be006224a25405cd431483e7d026", []}, - "p1_xml": {:git, "https://github.com/processone/xml", "403066ea5e0b2cd89e65c3ed1a329789c02c3588", []}, - "p1_yaml": {:git, "https://github.com/processone/p1_yaml", "79f756ba73a235c4d3836ec07b5f7f2b55f49638", []}, - "p1_zlib": {:git, "https://github.com/processone/zlib", "e3d4222b7aae616d7ef2e7e2fa0bbf451516c602", []}, - "providers": {:hex, :providers, "1.4.1"}, - "relx": {:hex, :relx, "3.5.0"}, - "xmlrpc": {:git, "https://github.com/rds13/xmlrpc.git", "42e6e96a0fe7106830274feed915125feb1056f3", []}} + "providers": {:hex, :providers, "1.6.0"}, + "cf": {:hex, :cf, "0.2.1"}, + "relx": {:hex, :relx, "3.11.0"}, + "conform": {:hex, :conform, "0.17.0"}, + "neotoma": {:hex, :neotoma, "1.7.3"}} From 006e96612c2b111726530961882d9ade55cd3374 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Wed, 6 Jan 2016 16:03:10 +0100 Subject: [PATCH 458/695] We need to checkout elixir first when elixir enabled --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 4036dc221c1..30c03609e6c 100644 --- a/rebar.config +++ b/rebar.config @@ -27,8 +27,8 @@ {if_var_true, zlib, {p1_zlib, ".*", {git, "https://github.com/processone/zlib", {tag, "1.0.0"}}}}, {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, - {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.1.0"}}}}, + {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, {if_var_true, iconv, {p1_iconv, ".*", {git, "https://github.com/processone/eiconv", {tag, "0.9.0"}}}}, {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}}]}. From 6d8263df15a8e6da6dda61117c4f3c0fadca77d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 7 Jan 2016 14:10:54 +0100 Subject: [PATCH 459/695] Extract deps from rebar.config to use in reltool.config.script --- rebar.config.script | 2 +- rel/reltool.config.script | 48 ++++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/rebar.config.script b/rebar.config.script index fdba3a91a4e..ab6a69999c3 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -7,7 +7,7 @@ %%% Created : 1 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -Cfg = case file:consult("vars.config") of +Cfg = case file:consult(filename:join(filename:dirname(SCRIPT), "vars.config")) of {ok, Terms} -> Terms; _Err -> diff --git a/rel/reltool.config.script b/rel/reltool.config.script index 6ebb3b3e831..bb664b67c0b 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -6,7 +6,30 @@ %%% @end %%% Created : 8 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -Vars = case file:consult(filename:join(["..", "vars.config"])) of + +TopDir = filename:join(filename:dirname(SCRIPT), ".."), + +GetDeps = fun(Config, GetDepsFun) -> + case catch rebar_config:consult_file(Config) of + {ok, Data} -> + case lists:keyfind(deps, 1, Data) of + {deps, Deps} -> + lists:map(fun({Dep, _, _}) -> + [Dep, GetDepsFun(filename:join([TopDir, + "deps", + Dep, + "rebar.config"]), + GetDepsFun)] + end, Deps); + _ -> + [] + end; + _ -> + [] + end + end, + +Vars = case file:consult(filename:join([TopDir, "vars.config"])) of {ok, Terms} -> Terms; _Err -> @@ -28,28 +51,7 @@ ConfiguredOTPApps = lists:flatmap( OTPApps = RequiredOTPApps ++ ConfiguredOTPApps, -DepRequiredApps = [cache_tab, p1_tls, p1_stringprep, p1_xml, esip, p1_stun, - p1_yaml, p1_utils, jiffy, oauth2, xmlrpc], - - -DepConfiguredApp0 = lists:flatmap( - fun({mysql, true}) -> [p1_mysql]; - ({pgsql, true}) -> [p1_pgsql]; - ({sqlite, true}) -> [sqlite3]; - ({pam, true}) -> [p1_pam]; - ({zlib, true}) -> [p1_zlib]; - ({riak, true}) -> [riakc, riak_pb, protobuffs, hamcrest, meck]; - ({elixir, true}) -> [elixir, rebar_elixir_plugin]; - ({iconv, true}) -> [p1_iconv]; - ({tools, true}) -> [meck]; - ({redis, true}) -> [eredis]; - ({lager, true}) -> [lager, goldrush]; - ({lager, false}) -> [p1_logger]; - (_) -> [] - end, Vars), - -DepConfiguredApps = lists:usort(fun(A, B) -> A >= B end, DepConfiguredApp0), -DepApps = DepRequiredApps ++ DepConfiguredApps, +DepApps = lists:usort(lists:flatten(GetDeps(filename:join(TopDir, "rebar.config"), GetDeps))), Sys = [{lib_dirs, []}, {erts, [{mod_cond, derived}, {app_file, strip}]}, From 0d750ff169c46cc4e54c4dd9a379cb675d2802a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 7 Jan 2016 18:49:55 +0100 Subject: [PATCH 460/695] Add version sufixes to application locations in 'make install' --- Makefile.in | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/Makefile.in b/Makefile.in index 6f5b1c78c52..a5cd94b83c3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -114,21 +114,34 @@ spec: JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1)) +VERSIONED_DEP=$(if $(DEP_$(1)_VERSION),$(DEP_$(1)_VERSION),$(1)) + ELIXIR_TO_DEST=$(LIBDIR) $(wordlist 2,2,$(1)) $(wordlist 5,1000,$(1)) -DEPS_TO_DEST=$(LIBDIR) $(wordlist 2,1000,$(1)) -MAIN_TO_DEST=$(LIBDIR) ejabberd $(1) +DEPS_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 3,1000,$(1)) +MAIN_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,ejabberd) $(1) TO_DEST_SINGLE=$(if $(subst XdepsX,,X$(word 1,$(1))X),$(call MAIN_TO_DEST,$(1)),$(if $(subst XlibX,,X$(word 3,$(1))X),$(call DEPS_TO_DEST,$(1)),$(call ELIXIR_TO_DEST,$(1)))) TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(call TO_DEST_SINGLE,$(subst /, ,$(path))))) FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path))) FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w)))) -DEPS_FILES=$(call FILES_WILDCARD,deps/*/ebin/*.beam deps/*/ebin/*.app deps/*/priv/* deps/*/priv/lib/* deps/*/priv/bin/* deps/*/include/*.hrl deps/*/lib/*/ebin/*.beam deps/*/lib/*/ebin/*.app) +ifeq ($(MAKECMDGOALS),copy-files-sub) + +DEPS:=$(sort $(shell $(REBAR) list-deps|$(SED) -e 's/^\([a-z_0-9-]\+\).*/\1/;t;d')) + +DEPS_FILES=$(call FILES_WILDCARD,$(foreach DEP,$(DEPS),deps/$(DEP)/ebin/*.beam deps/$(DEP)/ebin/*.app deps/$(DEP)/priv/* deps/$(DEP)/priv/lib/* deps/$(DEP)/priv/bin/* deps/$(DEP)/include/*.hrl deps/$(DEP)/lib/*/ebin/*.beam deps/$(DEP)/lib/*/ebin/*.app)) DEPS_FILES_FILTERED=$(filter-out %/epam deps/elixir/ebin/elixir.app,$(DEPS_FILES)) -DEPS_DIRS=$(sort deps/ $(wildcard deps/*) $(dir $(DEPS_FILES))) +DEPS_DIRS=$(sort deps/ $(foreach DEP,$(DEPS),deps/$(DEP)/) $(dir $(DEPS_FILES))) MAIN_FILES=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/*.app priv/msgs/*.msg priv/lib/* include/*.hrl)) -MAIN_DIRS=$(sort $(dir $(MAIN_FILES))) +MAIN_DIRS=$(sort $(dir $(MAIN_FILES)) priv/bin priv/sql) + +define DEP_VERSION_template +DEP_$(1)_VERSION:=$(shell sed -ne 's/.*{vsn\s*,\s*"\([^"]\+\)".*/$(1)-\1/;T;p;Q' $(2) 2>/dev/null) +endef + +$(foreach DEP,$(DEPS),$(eval $(call DEP_VERSION_template,$(DEP),deps/$(DEP)/ebin/$(DEP).app))) +$(eval $(call DEP_VERSION_template,ejabberd,ebin/ejabberd.app)) define COPY_template $(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; $$(INSTALL) -m 644 $(1) $(call TO_DEST,$(1)) @@ -139,13 +152,23 @@ $(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template, $(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))): $(INSTALL) -d $@ -$(call TO_DEST,deps/p1_pam/priv/bin/epam): $(LIBDIR)/%: deps/% $(call TO_DEST,deps/p1_pam/priv/bin/) +$(call TO_DEST,deps/p1_pam/priv/bin/epam): $(LIBDIR)/%: deps/p1_pam/priv/bin/epam $(call TO_DEST,deps/p1_pam/priv/bin/) + $(INSTALL) -m 750 $(O_USER) $< $@ + +$(call TO_DEST,priv/sql/lite.sql): sql/lite.sql $(call TO_DEST,priv/sql) + $(INSTALL) -m 644 $< $@ + +$(call TO_DEST,priv/bin/captcha.sh): tools/captcha.sh $(call TO_DEST,priv/bin) $(INSTALL) -m 750 $(O_USER) $< $@ +copy-files-sub2: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES) priv/bin/captcha.sh priv/sql/lite.sql) + +endif + copy-files: $(MAKE) copy-files-sub -copy-files-sub: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES)) +copy-files-sub: copy-files-sub2 install: all copy-files # @@ -183,14 +206,6 @@ install: all copy-files > ejabberd.init chmod 755 ejabberd.init # - # Binary C programs - $(INSTALL) -d $(PBINDIR) - $(INSTALL) -m 750 $(O_USER) tools/captcha.sh $(PBINDIR) - # - # Copy lite.sql - [ -d deps/sqlite3 ] && $(INSTALL) -d $(SQLDIR) || true - [ -d deps/sqlite3 ] && $(INSTALL) -m 644 sql/lite.sql $(SQLDIR) || true - # # Spool directory $(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR) $(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT) From 00f502f6e99727e2cf370d3955715995d5f80a28 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 8 Jan 2016 11:22:59 +0100 Subject: [PATCH 461/695] Fix 'make install' to work on osx --- Makefile.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index a5cd94b83c3..08cd83791fe 100644 --- a/Makefile.in +++ b/Makefile.in @@ -116,7 +116,7 @@ JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wo VERSIONED_DEP=$(if $(DEP_$(1)_VERSION),$(DEP_$(1)_VERSION),$(1)) -ELIXIR_TO_DEST=$(LIBDIR) $(wordlist 2,2,$(1)) $(wordlist 5,1000,$(1)) +ELIXIR_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 5,1000,$(1)) DEPS_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 3,1000,$(1)) MAIN_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,ejabberd) $(1) TO_DEST_SINGLE=$(if $(subst XdepsX,,X$(word 1,$(1))X),$(call MAIN_TO_DEST,$(1)),$(if $(subst XlibX,,X$(word 3,$(1))X),$(call DEPS_TO_DEST,$(1)),$(call ELIXIR_TO_DEST,$(1)))) @@ -127,7 +127,7 @@ FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w)))) ifeq ($(MAKECMDGOALS),copy-files-sub) -DEPS:=$(sort $(shell $(REBAR) list-deps|$(SED) -e 's/^\([a-z_0-9-]\+\).*/\1/;t;d')) +DEPS:=$(sort $(shell $(REBAR) list-deps|$(SED) -e '/^=/d;s/ .*//')) DEPS_FILES=$(call FILES_WILDCARD,$(foreach DEP,$(DEPS),deps/$(DEP)/ebin/*.beam deps/$(DEP)/ebin/*.app deps/$(DEP)/priv/* deps/$(DEP)/priv/lib/* deps/$(DEP)/priv/bin/* deps/$(DEP)/include/*.hrl deps/$(DEP)/lib/*/ebin/*.beam deps/$(DEP)/lib/*/ebin/*.app)) DEPS_FILES_FILTERED=$(filter-out %/epam deps/elixir/ebin/elixir.app,$(DEPS_FILES)) @@ -137,7 +137,7 @@ MAIN_FILES=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/ MAIN_DIRS=$(sort $(dir $(MAIN_FILES)) priv/bin priv/sql) define DEP_VERSION_template -DEP_$(1)_VERSION:=$(shell sed -ne 's/.*{vsn\s*,\s*"\([^"]\+\)".*/$(1)-\1/;T;p;Q' $(2) 2>/dev/null) +DEP_$(1)_VERSION:=$(shell $(SED) -e '/vsn/!d;s/.*,"/$(1)-/;s/".*//' $(2) 2>/dev/null) endef $(foreach DEP,$(DEPS),$(eval $(call DEP_VERSION_template,$(DEP),deps/$(DEP)/ebin/$(DEP).app))) From c7b67ff00b4c1055b0dca789d94f53c85893d42c Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 8 Jan 2016 13:13:30 +0100 Subject: [PATCH 462/695] Clarify a little more room error string (thanks to Genghis Khan) --- src/mod_muc_room.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 40d11bf67bf..6dfda260f2a 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -228,8 +228,8 @@ normal_state({route, From, <<"">>, case is_user_online(From, StateData) of true -> ErrorText = <<"It is not allowed to send error messages to the" - " room. This participant (~s) sent an error " - "message (~s) and gets kicked from the room">>, + " room. The participant (~s) has sent an error " + "message (~s) and got kicked from the room">>, NewState = expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)), @@ -516,8 +516,8 @@ normal_state({route, From, ToNick, {expulse_sender, Reason} -> ?DEBUG(Reason, []), ErrorText = <<"It is not allowed to send error messages to the" - " room. This participant (~s) sent an error " - "message (~s) and gets kicked from the room">>, + " room. The participant (~s) has sent an error " + "message (~s) and got kicked from the room">>, NewState = expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)), {next_state, normal_state, NewState}; @@ -1057,8 +1057,8 @@ process_presence(From, Nick, remove_online_user(From, NewState, Reason); <<"error">> -> ErrorText = <<"It is not allowed to send error messages to the" - " room. This participant (~s) sent an error " - "message (~s) and gets kicked from the room">>, + " room. The participant (~s) has sent an error " + "message (~s) and got kicked from the room">>, expulse_participant(Packet, From, StateData, translate:translate(Lang, ErrorText)); From 15245e9ec42989ea8689080993add3b9d661c076 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 8 Jan 2016 13:14:10 +0100 Subject: [PATCH 463/695] Update Hebrew translation (thanks to Genghis Khan) --- priv/msgs/he.po | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 0b9fefe5537..1390d15dd7c 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -248,9 +248,8 @@ msgid "Outgoing s2s Connections:" msgstr "חיבורי s2s יוצאים:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "חיבורי s2s יוצאים:" +msgstr "חיבורי s2s נכנסים:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -853,13 +852,13 @@ msgstr "" "יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה " "בשעה ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:587 msgid "Please specify file size." -msgstr "" +msgstr "אנא ציין גודל קובץ." -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:591 msgid "Please specify file name." -msgstr "" +msgstr "אנא ציין שם קובץ." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" @@ -976,9 +975,8 @@ msgid "Server ~b" msgstr "שרת ~b" #: mod_mam.erl:270 -#, fuzzy msgid "Only members are allowed to query archives of this room" -msgstr "רק אחראים רשאים לשנות את הנושא בחדר זה" +msgstr "רק חברים רשאים לתשאל ארכיונים של חדר זה" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -997,9 +995,8 @@ msgid "Chatrooms" msgstr "חדרי שיחה" #: mod_muc.erl:779 -#, fuzzy msgid "Empty Rooms" -msgstr "חדרים" +msgstr "חדרים ריקים" # to register nickname #: mod_muc.erl:931 @@ -1196,13 +1193,16 @@ msgstr "מגבלת שיעור תעבורה נחצתה" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" +"אין זה מותר לשלוח הודעות שגיאה לחדר. משתתף זה (~s) שלח הודעת שגיאה (~s) " +"ונבעט מתוך החדר" +# חל איסור #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" -msgstr "אין זה מותר לשלוח הודעות פרטיות אל הועידה" +msgstr "אין זה מותר לשלוח הודעות פרטיות לועידה" #: mod_muc_room.erl:316 msgid "Please, wait for a while before sending new voice request" @@ -1233,7 +1233,6 @@ msgstr "אין זה מותר לשלוח הודעות פרטיות מן טיפו msgid "Recipient is not in the conference room" msgstr "מקבל אינו מצוי בחדר הועידה" -# אסור #: mod_muc_room.erl:576 mod_muc_room.erl:598 msgid "It is not allowed to send private messages" msgstr "אין זה מותר לשלוח הודעות פרטיות" @@ -1377,20 +1376,19 @@ msgstr "לכל אחד" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "תפקידים להם נוכחות הינה משודרת" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "לאחראים בלבד" +msgstr "אחראי" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "משתתף" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "מבקר" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1739,13 +1737,15 @@ msgstr "אל תגלה את הסיסמה שלך לאף אחד, אפילו לא ל msgid "You can later change your password using a Jabber client." msgstr "באפשרותך לשנות את הסיסמה שלך מאוחר יותר באמצעות לקוח Jabber." +# בוטח +# trust that your #: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in the computer, but you should " "do this only in your personal computer for safety reasons." msgstr "" -"לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה " -"זו רק אם אתה סמוך כי המחשב שלך הינו מוגן." +"ישנם לקוחות Jabber אשר מסוגלים לאחסן את הסיסמה שלך בתוך המחשב, אולם עליך " +"לעשות זאת רק בתוך המחשב האישי שלך מסיבות ביטחוניות." # תישכח #: mod_register_web.erl:256 From 0ad0fd2187b9d9eb144c772fee6f1bc7a7382a00 Mon Sep 17 00:00:00 2001 From: Matthias Rieber Date: Mon, 11 Jan 2016 12:11:24 +0100 Subject: [PATCH 464/695] mod_http_upload: Use application/octet-stream instead of text/html for security reasons --- src/mod_http_upload.erl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 7aa28b6e136..077ca0f4969 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -43,7 +43,6 @@ {<<".bz2">>, <<"application/x-bzip2">>}, {<<".gif">>, <<"image/gif">>}, {<<".gz">>, <<"application/x-gzip">>}, - {<<".html">>, <<"text/html">>}, {<<".jpeg">>, <<"image/jpeg">>}, {<<".jpg">>, <<"image/jpeg">>}, {<<".mp3">>, <<"audio/mpeg">>}, From c7931b4a4f35022325feaa58bb555bb688c90bd2 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 11 Jan 2016 14:22:17 +0300 Subject: [PATCH 465/695] CVE-2016-1232: Add Dialback Key Generation and Validation support (XEP-0185) --- src/ejabberd_s2s.erl | 61 ++++++++++++++++------------------------ src/ejabberd_s2s_in.erl | 6 ++-- src/ejabberd_s2s_out.erl | 32 +++++++++++---------- 3 files changed, 44 insertions(+), 55 deletions(-) diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 0e51ec0448d..24694f3f0e8 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -35,8 +35,8 @@ %% API -export([start_link/0, route/3, have_connection/1, - has_key/2, get_connections_pids/1, try_register/1, - remove_connection/3, find_connection/2, + make_key/2, get_connections_pids/1, try_register/1, + remove_connection/2, find_connection/2, dirty_get_connections/0, allow_host/2, incoming_s2s_number/0, outgoing_s2s_number/0, clean_temporarily_blocked_table/0, @@ -75,8 +75,7 @@ %% once a server is temporarly blocked, it stay blocked for 60 seconds -record(s2s, {fromto = {<<"">>, <<"">>} :: {binary(), binary()} | '_', - pid = self() :: pid() | '_' | '$1', - key = <<"">> :: binary() | '_'}). + pid = self() :: pid() | '_' | '$1'}). -record(state, {}). @@ -134,19 +133,15 @@ is_temporarly_blocked(Host) -> end. -spec remove_connection({binary(), binary()}, - pid(), binary()) -> {atomic, ok} | - ok | - {aborted, any()}. + pid()) -> {atomic, ok} | ok | {aborted, any()}. -remove_connection(FromTo, Pid, Key) -> +remove_connection(FromTo, Pid) -> case catch mnesia:dirty_match_object(s2s, - #s2s{fromto = FromTo, pid = Pid, - _ = '_'}) + #s2s{fromto = FromTo, pid = Pid}) of - [#s2s{pid = Pid, key = Key}] -> + [#s2s{pid = Pid}] -> F = fun () -> - mnesia:delete_object(#s2s{fromto = FromTo, pid = Pid, - key = Key}) + mnesia:delete_object(#s2s{fromto = FromTo, pid = Pid}) end, mnesia:transaction(F); _ -> ok @@ -162,19 +157,6 @@ have_connection(FromTo) -> false end. --spec has_key({binary(), binary()}, binary()) -> boolean(). - -has_key(FromTo, Key) -> - case mnesia:dirty_select(s2s, - [{#s2s{fromto = FromTo, key = Key, _ = '_'}, - [], - ['$_']}]) of - [] -> - false; - _ -> - true - end. - -spec get_connections_pids({binary(), binary()}) -> [pid()]. get_connections_pids(FromTo) -> @@ -185,10 +167,9 @@ get_connections_pids(FromTo) -> [] end. --spec try_register({binary(), binary()}) -> {key, binary()} | false. +-spec try_register({binary(), binary()}) -> boolean(). try_register(FromTo) -> - Key = randoms:get_string(), MaxS2SConnectionsNumber = max_s2s_connections_number(FromTo), MaxS2SConnectionsNumberPerNode = max_s2s_connections_number_per_node(FromTo), @@ -198,9 +179,8 @@ try_register(FromTo) -> MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode), if NeededConnections > 0 -> - mnesia:write(#s2s{fromto = FromTo, pid = self(), - key = Key}), - {key, Key}; + mnesia:write(#s2s{fromto = FromTo, pid = self()}), + true; true -> false end end, @@ -241,6 +221,12 @@ check_peer_certificate(SockMod, Sock, Peer) -> {error, <<"Cannot get peer certificate">>} end. +make_key({From, To}, StreamID) -> + Secret = ejabberd_config:get_option(shared_key, fun(V) -> V end), + p1_sha:to_hexlist( + crypto:hmac(sha256, p1_sha:to_hexlist(crypto:hash(sha256, Secret)), + [To, " ", From, " ", StreamID])). + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -407,17 +393,15 @@ open_several_connections(N, MyServer, Server, From, new_connection(MyServer, Server, From, FromTo, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode) -> - Key = randoms:get_string(), {ok, Pid} = ejabberd_s2s_out:start( - MyServer, Server, {new, Key}), + MyServer, Server, new), F = fun() -> L = mnesia:read({s2s, FromTo}), NeededConnections = needed_connections_number(L, MaxS2SConnectionsNumber, MaxS2SConnectionsNumberPerNode), if NeededConnections > 0 -> - mnesia:write(#s2s{fromto = FromTo, pid = Pid, - key = Key}), + mnesia:write(#s2s{fromto = FromTo, pid = Pid}), ?INFO_MSG("New s2s connection started ~p", [Pid]), Pid; true -> choose_connection(From, L) @@ -520,9 +504,12 @@ update_tables() -> end, case catch mnesia:table_info(s2s, attributes) of [fromto, node, key] -> - mnesia:transform_table(s2s, ignore, [fromto, pid, key]), + mnesia:transform_table(s2s, ignore, [fromto, pid]), + mnesia:clear_table(s2s); + [fromto, pid, key] -> + mnesia:transform_table(s2s, ignore, [fromto, pid]), mnesia:clear_table(s2s); - [fromto, pid, key] -> ok; + [fromto, pid] -> ok; {'EXIT', _} -> ok end, case lists:member(local_s2s, mnesia:system_info(tables)) of diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 1b184a274df..4159dee4ab6 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -432,9 +432,9 @@ stream_established({xmlstreamelement, El}, StateData) -> ?DEBUG("VERIFY KEY: ~p", [{To, From, Id, Key}]), LTo = jid:nameprep(To), LFrom = jid:nameprep(From), - Type = case ejabberd_s2s:has_key({LTo, LFrom}, Key) of - true -> <<"valid">>; - _ -> <<"invalid">> + Type = case ejabberd_s2s:make_key({LTo, LFrom}, Id) of + Key -> <<"valid">>; + _ -> <<"invalid">> end, send_element(StateData, #xmlel{name = <<"db:verify">>, diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index a5f7280555d..331f5443658 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -56,6 +56,7 @@ -record(state, {socket :: ejabberd_socket:socket_state(), streamid = <<"">> :: binary(), + remote_streamid = <<"">> :: binary(), use_v10 = true :: boolean(), tls = false :: boolean(), tls_required = false :: boolean(), @@ -69,7 +70,7 @@ server = <<"">> :: binary(), queue = queue:new() :: ?TQUEUE, delay_to_retry = undefined_delay :: undefined_delay | non_neg_integer(), - new = false :: false | binary(), + new = false :: boolean(), verify = false :: false | {pid(), binary(), binary()}, bridge :: {atom(), atom()}, timer = make_ref() :: reference()}). @@ -196,7 +197,7 @@ init([From, Server, Type]) -> true -> TLSOpts4 end, {New, Verify} = case Type of - {new, Key} -> {Key, false}; + new -> {true, false}; {verify, Pid, Key, SID} -> start_connection(self()), {false, {Pid, Key, SID}} end, @@ -310,7 +311,7 @@ open_socket2(Type, Addr, Port) -> wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> - {CertCheckRes, CertCheckMsg, NewStateData} = + {CertCheckRes, CertCheckMsg, StateData0} = if StateData#state.tls_certverify, StateData#state.tls_enabled -> {Res, Msg} = ejabberd_s2s:check_peer_certificate(ejabberd_socket, @@ -322,6 +323,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, true -> {no_verify, <<"Not verified">>, StateData} end, + RemoteStreamID = xml:get_attr_s(<<"id">>, Attrs), + NewStateData = StateData0#state{remote_streamid = RemoteStreamID}, case {xml:get_attr_s(<<"xmlns">>, Attrs), xml:get_attr_s(<<"xmlns:db">>, Attrs), xml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} @@ -958,10 +961,10 @@ terminate(Reason, StateName, StateData) -> ?DEBUG("terminated: ~p", [{Reason, StateName}]), case StateData#state.new of false -> ok; - Key -> + true -> ejabberd_s2s:remove_connection({StateData#state.myname, StateData#state.server}, - self(), Key) + self()) end, bounce_queue(StateData#state.queue, ?ERR_REMOTE_SERVER_NOT_FOUND), @@ -1029,19 +1032,18 @@ bounce_messages(Error) -> send_db_request(StateData) -> Server = StateData#state.server, New = case StateData#state.new of - false -> - case ejabberd_s2s:try_register({StateData#state.myname, - Server}) - of - {key, Key} -> Key; - false -> false - end; - Key -> Key + false -> + ejabberd_s2s:try_register({StateData#state.myname, Server}); + true -> + true end, NewStateData = StateData#state{new = New}, try case New of - false -> ok; - Key1 -> + false -> ok; + true -> + Key1 = ejabberd_s2s:make_key( + {StateData#state.myname, Server}, + StateData#state.remote_streamid), send_element(StateData, #xmlel{name = <<"db:result">>, attrs = From 65e6dfb9ddadacc147fe460cfd9bd499a83db429 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 11 Jan 2016 14:35:11 +0300 Subject: [PATCH 466/695] Do not fail on incorrect data coming from SQL (898) --- src/mod_mam.erl | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 6dfff605816..f334152f72f 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -756,25 +756,34 @@ select(LServer, #jid{luser = LUser} = JidRequestor, true -> {Res, true} end, - {lists:map( + {lists:flatmap( fun([TS, XML, PeerBin, Kind, Nick]) -> - #xmlel{} = El = xml_stream:parse_element(XML), - Now = usec_to_now(jlib:binary_to_integer(TS)), - PeerJid = jid:tolower(jid:from_string(PeerBin)), - T = case Kind of - <<"">> -> chat; - null -> chat; - _ -> jlib:binary_to_atom(Kind) - end, - {TS, jlib:binary_to_integer(TS), - msg_to_el(#archive_msg{timestamp = Now, - packet = El, - type = T, - nick = Nick, - peer = PeerJid}, - MsgType, - JidRequestor)} - end, Res1), IsComplete, jlib:binary_to_integer(Count)}; + try + #xmlel{} = El = xml_stream:parse_element(XML), + Now = usec_to_now(jlib:binary_to_integer(TS)), + PeerJid = jid:tolower(jid:from_string(PeerBin)), + T = case Kind of + <<"">> -> chat; + null -> chat; + _ -> jlib:binary_to_atom(Kind) + end, + [{TS, jlib:binary_to_integer(TS), + msg_to_el(#archive_msg{timestamp = Now, + packet = El, + type = T, + nick = Nick, + peer = PeerJid}, + MsgType, + JidRequestor)}] + catch _:Err -> + ?ERROR_MSG("failed to parse data from SQL: ~p. " + "The data was: " + "timestamp = ~s, xml = ~s, " + "peer = ~s, kind = ~s, nick = ~s", + [Err, TS, XML, PeerBin, Kind, Nick]), + [] + end + end, Res1), IsComplete, jlib:binary_to_integer(Count)}; _ -> {[], false, 0} end. From 64d96778b452aad72349b21d2ac94e744617b07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20Wei=C3=9F?= Date: Tue, 12 Jan 2016 10:20:35 +0100 Subject: [PATCH 467/695] Don't return error for blocked MUC messages If a message stanza is blocked as per XEP-0016 or XEP-0191, return an error only if the type of the blocked message is "normal" or "chat". This makes sure users won't be kicked from MUC rooms when blocking other participants. Closes #897. --- src/ejabberd_c2s.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index fbea2a8e347..c21683f898c 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1636,6 +1636,8 @@ handle_info({route, From, To, deny -> case xml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; + <<"groupchat">> -> ok; + <<"headline">> -> ok; <<"result">> -> ok; _ -> Err = From 776fe8b32ac9958271af16722664e8486f18ef14 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 13 Jan 2016 11:45:08 +0300 Subject: [PATCH 468/695] Fix MAM MUC for v0.4.1 --- src/mod_mam.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index f334152f72f..95fe4964ec9 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -255,8 +255,8 @@ muc_process_iq(#iq{type = set, lang = Lang, sub_el = #xmlel{name = <<"query">>, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of - ?NS_MAM_0 -> + XMLNS = xml:get_attr_s(<<"xmlns">>, Attrs), + if XMLNS == ?NS_MAM_0; XMLNS == ?NS_MAM_1 -> LServer = MUCState#state.server_host, Role = mod_muc_room:get_role(From, MUCState), Config = MUCState#state.config, @@ -277,7 +277,7 @@ muc_process_iq(#iq{type = set, lang = Lang, get_xdata_fields(SubEl), {groupchat, Role, MUCState}) end; - _ -> + true -> IQ end; muc_process_iq(IQ, _MUCState, _From, _To) -> From fd3e3a99c5647b7f3bd2e5b682da636db21fc9bf Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 13 Jan 2016 12:59:00 +0300 Subject: [PATCH 469/695] Log failed SQL requests --- src/ejabberd_odbc.erl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 123f0d558c1..ace0cda057a 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -125,7 +125,7 @@ start_link(Host, StartInterval) -> -spec sql_query(binary(), sql_query()) -> sql_query_result(). sql_query(Host, Query) -> - sql_call(Host, {sql_query, Query}). + check_error(sql_call(Host, {sql_query, Query}), Query). %% SQL transaction based on a list of queries %% This function automatically @@ -800,6 +800,12 @@ fsm_limit_opts() -> _ -> [] end. +check_error({error, Why} = Err, Query) -> + ?ERROR_MSG("SQL query '~s' failed: ~p", [Query, Why]), + Err; +check_error(Result, _Query) -> + Result. + opt_type(max_fsm_queue) -> fun (N) when is_integer(N), N > 0 -> N end; opt_type(odbc_database) -> fun iolist_to_binary/1; From f448ff608a6f63e1ff6152ab53fc16bcbd43a60d Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 13 Jan 2016 12:29:14 +0100 Subject: [PATCH 470/695] Update copyright to 2016 (#901) --- include/adhoc.hrl | 2 +- include/ejabberd.hrl | 2 +- include/ejabberd_commands.hrl | 2 +- include/ejabberd_config.hrl | 2 +- include/ejabberd_ctl.hrl | 2 +- include/ejabberd_http.hrl | 2 +- include/ejabberd_web_admin.hrl | 2 +- include/eldap.hrl | 2 +- include/http_bind.hrl | 2 +- include/jlib.hrl | 2 +- include/logger.hrl | 2 +- include/mod_muc_room.hrl | 2 +- include/mod_privacy.hrl | 2 +- include/mod_proxy65.hrl | 2 +- include/mod_roster.hrl | 2 +- include/ns.hrl | 2 +- include/pubsub.hrl | 6 +++--- rebar.config | 2 +- rebar.config.script | 2 +- rel/reltool.config.script | 2 +- sql/lite.sql | 2 +- sql/mysql.sql | 2 +- sql/pg.sql | 2 +- src/acl.erl | 2 +- src/adhoc.erl | 2 +- src/cyrsasl.erl | 2 +- src/cyrsasl_anonymous.erl | 2 +- src/cyrsasl_digest.erl | 2 +- src/cyrsasl_oauth.erl | 2 +- src/cyrsasl_plain.erl | 2 +- src/cyrsasl_scram.erl | 2 +- src/ejabberd.erl | 2 +- src/ejabberd_admin.erl | 2 +- src/ejabberd_app.erl | 2 +- src/ejabberd_auth.erl | 2 +- src/ejabberd_auth_anonymous.erl | 2 +- src/ejabberd_auth_external.erl | 2 +- src/ejabberd_auth_internal.erl | 2 +- src/ejabberd_auth_ldap.erl | 2 +- src/ejabberd_auth_odbc.erl | 2 +- src/ejabberd_auth_pam.erl | 2 +- src/ejabberd_auth_riak.erl | 2 +- src/ejabberd_c2s.erl | 2 +- src/ejabberd_c2s_config.erl | 2 +- src/ejabberd_captcha.erl | 2 +- src/ejabberd_cluster.erl | 2 +- src/ejabberd_commands.erl | 2 +- src/ejabberd_commands_doc.erl | 2 +- src/ejabberd_config.erl | 2 +- src/ejabberd_ctl.erl | 2 +- src/ejabberd_frontend_socket.erl | 2 +- src/ejabberd_hooks.erl | 2 +- src/ejabberd_http.erl | 2 +- src/ejabberd_http_bind.erl | 2 +- src/ejabberd_http_ws.erl | 2 +- src/ejabberd_idna.erl | 2 +- src/ejabberd_listener.erl | 2 +- src/ejabberd_local.erl | 2 +- src/ejabberd_logger.erl | 2 +- src/ejabberd_node_groups.erl | 2 +- src/ejabberd_oauth.erl | 2 +- src/ejabberd_odbc.erl | 2 +- src/ejabberd_odbc_sup.erl | 2 +- src/ejabberd_piefxis.erl | 2 +- src/ejabberd_rdbms.erl | 2 +- src/ejabberd_receiver.erl | 2 +- src/ejabberd_regexp.erl | 2 +- src/ejabberd_riak.erl | 4 ++-- src/ejabberd_riak_sup.erl | 2 +- src/ejabberd_router.erl | 2 +- src/ejabberd_router_multicast.erl | 2 +- src/ejabberd_s2s.erl | 2 +- src/ejabberd_s2s_in.erl | 2 +- src/ejabberd_s2s_out.erl | 2 +- src/ejabberd_service.erl | 2 +- src/ejabberd_sm.erl | 2 +- src/ejabberd_sm_mnesia.erl | 2 +- src/ejabberd_sm_odbc.erl | 2 +- src/ejabberd_sm_redis.erl | 2 +- src/ejabberd_socket.erl | 2 +- src/ejabberd_stun.erl | 2 +- src/ejabberd_sup.erl | 2 +- src/ejabberd_system_monitor.erl | 2 +- src/ejabberd_tmp_sup.erl | 2 +- src/ejabberd_update.erl | 2 +- src/ejabberd_web.erl | 2 +- src/ejabberd_web_admin.erl | 4 ++-- src/ejabberd_websocket.erl | 2 +- src/ejabberd_xmlrpc.erl | 2 +- src/ejd2odbc.erl | 2 +- src/eldap_filter.erl | 2 +- src/eldap_pool.erl | 2 +- src/eldap_utils.erl | 2 +- src/ext_mod.erl | 2 +- src/extauth.erl | 2 +- src/gen_iq_handler.erl | 2 +- src/gen_mod.erl | 2 +- src/gen_pubsub_node.erl | 2 +- src/gen_pubsub_nodetree.erl | 2 +- src/jd2ejd.erl | 2 +- src/jid.erl | 2 +- src/jlib.erl | 2 +- src/mod_adhoc.erl | 2 +- src/mod_announce.erl | 2 +- src/mod_blocking.erl | 2 +- src/mod_caps.erl | 2 +- src/mod_carboncopy.erl | 2 +- src/mod_client_state.erl | 2 +- src/mod_configure.erl | 2 +- src/mod_configure2.erl | 2 +- src/mod_disco.erl | 2 +- src/mod_echo.erl | 2 +- src/mod_fail2ban.erl | 2 +- src/mod_http_api.erl | 2 +- src/mod_http_bind.erl | 2 +- src/mod_http_fileserver.erl | 2 +- src/mod_http_upload.erl | 2 +- src/mod_http_upload_quota.erl | 2 +- src/mod_ip_blacklist.erl | 2 +- src/mod_irc.erl | 4 ++-- src/mod_irc_connection.erl | 2 +- src/mod_last.erl | 2 +- src/mod_mam.erl | 2 +- src/mod_metrics.erl | 2 +- src/mod_muc.erl | 4 ++-- src/mod_muc_log.erl | 2 +- src/mod_muc_room.erl | 2 +- src/mod_multicast.erl | 4 ++-- src/mod_offline.erl | 2 +- src/mod_ping.erl | 2 +- src/mod_pres_counter.erl | 2 +- src/mod_privacy.erl | 2 +- src/mod_private.erl | 2 +- src/mod_proxy65.erl | 2 +- src/mod_proxy65_lib.erl | 2 +- src/mod_proxy65_service.erl | 4 ++-- src/mod_proxy65_sm.erl | 2 +- src/mod_proxy65_stream.erl | 2 +- src/mod_pubsub.erl | 4 ++-- src/mod_register.erl | 2 +- src/mod_register_web.erl | 2 +- src/mod_roster.erl | 2 +- src/mod_service_log.erl | 2 +- src/mod_shared_roster.erl | 2 +- src/mod_shared_roster_ldap.erl | 2 +- src/mod_sic.erl | 2 +- src/mod_sip.erl | 2 +- src/mod_sip_proxy.erl | 2 +- src/mod_sip_registrar.erl | 2 +- src/mod_stats.erl | 2 +- src/mod_time.erl | 2 +- src/mod_vcard.erl | 6 +++--- src/mod_vcard_ldap.erl | 6 +++--- src/mod_version.erl | 2 +- src/node_buddy.erl | 2 +- src/node_club.erl | 2 +- src/node_dag.erl | 2 +- src/node_dispatch.erl | 2 +- src/node_flat.erl | 2 +- src/node_flat_odbc.erl | 2 +- src/node_hometree.erl | 2 +- src/node_hometree_odbc.erl | 2 +- src/node_mb.erl | 2 +- src/node_online.erl | 2 +- src/node_pep.erl | 2 +- src/node_pep_odbc.erl | 2 +- src/node_private.erl | 2 +- src/node_public.erl | 2 +- src/nodetree_dag.erl | 2 +- src/nodetree_tree.erl | 2 +- src/nodetree_tree_odbc.erl | 2 +- src/nodetree_virtual.erl | 2 +- src/odbc_queries.erl | 2 +- src/pubsub_db_odbc.erl | 2 +- src/pubsub_index.erl | 2 +- src/pubsub_migrate.erl | 2 +- src/pubsub_subscription.erl | 2 +- src/pubsub_subscription_odbc.erl | 2 +- src/randoms.erl | 2 +- src/scram.erl | 2 +- src/shaper.erl | 2 +- src/str.erl | 2 +- src/translate.erl | 2 +- src/win32_dns.erl | 2 +- test/ejabberd_SUITE.erl | 2 +- test/ejabberd_hooks_test.exs | 2 +- test/elixir_SUITE.erl | 2 +- test/ldap_srv.erl | 2 +- test/suite.erl | 2 +- vars.config.in | 2 +- 190 files changed, 203 insertions(+), 203 deletions(-) diff --git a/include/adhoc.hrl b/include/adhoc.hrl index f16aedd3b0c..bd1bfaa6f51 100644 --- a/include/adhoc.hrl +++ b/include/adhoc.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd.hrl b/include/ejabberd.hrl index f07dc0aafdf..6316d781346 100644 --- a/include/ejabberd.hrl +++ b/include/ejabberd.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_commands.hrl b/include/ejabberd_commands.hrl index 44f170e841b..0742e3ba4d6 100644 --- a/include/ejabberd_commands.hrl +++ b/include/ejabberd_commands.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_config.hrl b/include/ejabberd_config.hrl index eb4de2609c6..2d688931369 100644 --- a/include/ejabberd_config.hrl +++ b/include/ejabberd_config.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_ctl.hrl b/include/ejabberd_ctl.hrl index 8b56ad26148..3951129e758 100644 --- a/include/ejabberd_ctl.hrl +++ b/include/ejabberd_ctl.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_http.hrl b/include/ejabberd_http.hrl index 7e3d40ee196..8b8fab2b086 100644 --- a/include/ejabberd_http.hrl +++ b/include/ejabberd_http.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ejabberd_web_admin.hrl b/include/ejabberd_web_admin.hrl index 852e537b648..33ff3a451b4 100644 --- a/include/ejabberd_web_admin.hrl +++ b/include/ejabberd_web_admin.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/eldap.hrl b/include/eldap.hrl index 6c30f54566e..6dfc894a88e 100644 --- a/include/eldap.hrl +++ b/include/eldap.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/http_bind.hrl b/include/http_bind.hrl index 7c0e04a9802..cd8512f0e5b 100644 --- a/include/http_bind.hrl +++ b/include/http_bind.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/jlib.hrl b/include/jlib.hrl index 1bda9a09636..f09e392fbf1 100644 --- a/include/jlib.hrl +++ b/include/jlib.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/logger.hrl b/include/logger.hrl index b8fdc31f939..3accc56aba0 100644 --- a/include/logger.hrl +++ b/include/logger.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index 51e575db01e..4d82856ca29 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_privacy.hrl b/include/mod_privacy.hrl index b3dfd4e7c38..8fe5abcca45 100644 --- a/include/mod_privacy.hrl +++ b/include/mod_privacy.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_proxy65.hrl b/include/mod_proxy65.hrl index 70181bf82a4..1d8ceb3c668 100644 --- a/include/mod_proxy65.hrl +++ b/include/mod_proxy65.hrl @@ -2,7 +2,7 @@ %%% RFC 1928 constants. %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/mod_roster.hrl b/include/mod_roster.hrl index ea060a5cbc9..b05114e3ed2 100644 --- a/include/mod_roster.hrl +++ b/include/mod_roster.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/ns.hrl b/include/ns.hrl index 644874f2d0d..372b68b7c54 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -1,6 +1,6 @@ %%%---------------------------------------------------------------------- %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/include/pubsub.hrl b/include/pubsub.hrl index f43e1644bf5..209f802db42 100644 --- a/include/pubsub.hrl +++ b/include/pubsub.hrl @@ -13,12 +13,12 @@ %%% %%% %%% The Initial Developer of the Original Code is ProcessOne. -%%% Portions created by ProcessOne are Copyright 2006-2015, ProcessOne +%%% Portions created by ProcessOne are Copyright 2006-2016, ProcessOne %%% All Rights Reserved.'' -%%% This software is copyright 2006-2015, ProcessOne. +%%% This software is copyright 2006-2016, ProcessOne. %%% %%% -%%% copyright 2006-2015 ProcessOne +%%% copyright 2006-2016 ProcessOne %%% %%% This file contains pubsub types definition. %%% ==================================================================== diff --git a/rebar.config b/rebar.config index 30c03609e6c..8c2c73bafbe 100644 --- a/rebar.config +++ b/rebar.config @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @copyright (C) 2013-2016, Evgeniy Khramtsov %%% @doc %%% %%% @end diff --git a/rebar.config.script b/rebar.config.script index ab6a69999c3..a7120b12a43 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @copyright (C) 2013-2016, Evgeniy Khramtsov %%% @doc %%% %%% @end diff --git a/rel/reltool.config.script b/rel/reltool.config.script index bb664b67c0b..d84c202a307 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @copyright (C) 2013-2016, Evgeniy Khramtsov %%% @doc %%% %%% @end diff --git a/sql/lite.sql b/sql/lite.sql index 89d68eadd32..5132c917232 100644 --- a/sql/lite.sql +++ b/sql/lite.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2015 ProcessOne +-- ejabberd, Copyright (C) 2002-2016 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/mysql.sql b/sql/mysql.sql index e546fc88671..cc603c1b158 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2015 ProcessOne +-- ejabberd, Copyright (C) 2002-2016 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/sql/pg.sql b/sql/pg.sql index 09935691716..87cccd4845b 100644 --- a/sql/pg.sql +++ b/sql/pg.sql @@ -1,5 +1,5 @@ -- --- ejabberd, Copyright (C) 2002-2015 ProcessOne +-- ejabberd, Copyright (C) 2002-2016 ProcessOne -- -- This program is free software; you can redistribute it and/or -- modify it under the terms of the GNU General Public License as diff --git a/src/acl.erl b/src/acl.erl index 41e29ce8c8a..fdf397d8891 100644 --- a/src/acl.erl +++ b/src/acl.erl @@ -5,7 +5,7 @@ %%% Created : 18 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/adhoc.erl b/src/adhoc.erl index f2bd2dbeee4..d252a6cbb24 100644 --- a/src/adhoc.erl +++ b/src/adhoc.erl @@ -5,7 +5,7 @@ %%% Created : 31 Oct 2005 by Magnus Henoch %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index b15bcdfbdee..5d2d89d67c1 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -5,7 +5,7 @@ %%% Created : 8 Mar 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/cyrsasl_anonymous.erl b/src/cyrsasl_anonymous.erl index adbde246d4b..2b2a9f63cf7 100644 --- a/src/cyrsasl_anonymous.erl +++ b/src/cyrsasl_anonymous.erl @@ -6,7 +6,7 @@ %%% Created : 23 Aug 2005 by Magnus Henoch %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 4b14bafd35a..8ccd90952ba 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -5,7 +5,7 @@ %%% Created : 11 Mar 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/cyrsasl_oauth.erl b/src/cyrsasl_oauth.erl index 8d23a31857e..16f1e3dfb77 100644 --- a/src/cyrsasl_oauth.erl +++ b/src/cyrsasl_oauth.erl @@ -5,7 +5,7 @@ %%% Created : 17 Sep 2015 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/cyrsasl_plain.erl b/src/cyrsasl_plain.erl index d2fb373e420..a9c1de056e7 100644 --- a/src/cyrsasl_plain.erl +++ b/src/cyrsasl_plain.erl @@ -5,7 +5,7 @@ %%% Created : 8 Mar 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl index 17a32ef9bfb..059938f5e77 100644 --- a/src/cyrsasl_scram.erl +++ b/src/cyrsasl_scram.erl @@ -5,7 +5,7 @@ %%% Created : 7 Aug 2011 by Stephen Röttger %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd.erl b/src/ejabberd.erl index 3191e9817a5..e1b92c26b84 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -5,7 +5,7 @@ %%% Created : 16 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index ab758fb3610..5352ae1eee6 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -5,7 +5,7 @@ %%% Created : 7 May 2006 by Mickael Remond %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 7d94a6276ad..628b4a8ad01 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -5,7 +5,7 @@ %%% Created : 31 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 9a77de140ae..2cc37c6e0ff 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -5,7 +5,7 @@ %%% Created : 23 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_anonymous.erl b/src/ejabberd_auth_anonymous.erl index ab04534f2ec..7b21752a26d 100644 --- a/src/ejabberd_auth_anonymous.erl +++ b/src/ejabberd_auth_anonymous.erl @@ -5,7 +5,7 @@ %%% Created : 17 Feb 2006 by Mickael Remond %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 393bf1e021d..2a1cbf085fd 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_internal.erl b/src/ejabberd_auth_internal.erl index 78ec4c189ef..d60e0fc5f9a 100644 --- a/src/ejabberd_auth_internal.erl +++ b/src/ejabberd_auth_internal.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_ldap.erl b/src/ejabberd_auth_ldap.erl index d637b6b85ba..dd5d54a74a5 100644 --- a/src/ejabberd_auth_ldap.erl +++ b/src/ejabberd_auth_ldap.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index d57c185da02..b8b4594b630 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 12 Dec 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_pam.erl b/src/ejabberd_auth_pam.erl index 312bcf46eca..ee5123c5eb9 100644 --- a/src/ejabberd_auth_pam.erl +++ b/src/ejabberd_auth_pam.erl @@ -5,7 +5,7 @@ %%% Created : 5 Jul 2007 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_auth_riak.erl b/src/ejabberd_auth_riak.erl index 3d7f1c1dba4..64bf12c6aa2 100644 --- a/src/ejabberd_auth_riak.erl +++ b/src/ejabberd_auth_riak.erl @@ -5,7 +5,7 @@ %%% Created : 12 Nov 2012 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index c21683f898c..0035ed6d183 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -5,7 +5,7 @@ %%% Created : 16 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_c2s_config.erl b/src/ejabberd_c2s_config.erl index 43bba6726ca..3384e338705 100644 --- a/src/ejabberd_c2s_config.erl +++ b/src/ejabberd_c2s_config.erl @@ -6,7 +6,7 @@ %%% Created : 2 Nov 2007 by Mickael Remond %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index 4d906f3248e..cc3e2e9f43b 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -5,7 +5,7 @@ %%% Created : 26 Apr 2008 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_cluster.erl b/src/ejabberd_cluster.erl index eb523fee20c..1e3f02a9e78 100644 --- a/src/ejabberd_cluster.erl +++ b/src/ejabberd_cluster.erl @@ -5,7 +5,7 @@ %%% Created : 7 Oct 2015 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index b82c962b40b..547da028d01 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -5,7 +5,7 @@ %%% Created : 20 May 2008 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index 8d25897efd7..ac48623e66c 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -5,7 +5,7 @@ %%% Created : 20 May 2008 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 6e2cabb5770..8d2d19975b3 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -5,7 +5,7 @@ %%% Created : 14 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index a8d15c169f0..2bf20c2e72d 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -5,7 +5,7 @@ %%% Created : 11 Jan 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_frontend_socket.erl b/src/ejabberd_frontend_socket.erl index ad227b039e4..09eeded9c35 100644 --- a/src/ejabberd_frontend_socket.erl +++ b/src/ejabberd_frontend_socket.erl @@ -5,7 +5,7 @@ %%% Created : 23 Aug 2006 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_hooks.erl b/src/ejabberd_hooks.erl index dd03e4ca48e..c1daa4c0e41 100644 --- a/src/ejabberd_hooks.erl +++ b/src/ejabberd_hooks.erl @@ -5,7 +5,7 @@ %%% Created : 8 Aug 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 920361017c1..b95f982078f 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -5,7 +5,7 @@ %%% Created : 27 Feb 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index e7239772661..c4cfdddd9a2 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -6,7 +6,7 @@ %%% Modified: may 2009 by Mickael Remond, Alexey Schepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index ed88c03d9d9..3b50e44a342 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -5,7 +5,7 @@ %%% Created : 09-10-2010 by Eric Cestari %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_idna.erl b/src/ejabberd_idna.erl index bee3f87ed32..f889b411a34 100644 --- a/src/ejabberd_idna.erl +++ b/src/ejabberd_idna.erl @@ -5,7 +5,7 @@ %%% Created : 10 Apr 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_listener.erl b/src/ejabberd_listener.erl index ac981fcff22..a9cc441e989 100644 --- a/src/ejabberd_listener.erl +++ b/src/ejabberd_listener.erl @@ -5,7 +5,7 @@ %%% Created : 16 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index afb499a07f9..66f530c8f4c 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -5,7 +5,7 @@ %%% Created : 30 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 3545abe848e..1b0719c4a85 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -5,7 +5,7 @@ %%% @end %%% Created : 12 May 2013 by Evgeniy Khramtsov %%% -%%% ejabberd, Copyright (C) 2013-2015 ProcessOne +%%% ejabberd, Copyright (C) 2013-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_node_groups.erl b/src/ejabberd_node_groups.erl index 87942b7937b..352757dd853 100644 --- a/src/ejabberd_node_groups.erl +++ b/src/ejabberd_node_groups.erl @@ -5,7 +5,7 @@ %%% Created : 1 Nov 2006 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl index 4855a757349..a688bb39ea0 100644 --- a/src/ejabberd_oauth.erl +++ b/src/ejabberd_oauth.erl @@ -5,7 +5,7 @@ %%% Created : 20 Mar 2015 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index ace0cda057a..d7b8fa83a0c 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 8 Dec 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_odbc_sup.erl b/src/ejabberd_odbc_sup.erl index de2ffead85d..65fa3c1c6e2 100644 --- a/src/ejabberd_odbc_sup.erl +++ b/src/ejabberd_odbc_sup.erl @@ -5,7 +5,7 @@ %%% Created : 22 Dec 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index ebf8aebac4d..50c8e323c59 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -8,7 +8,7 @@ %%% @doc %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_rdbms.erl b/src/ejabberd_rdbms.erl index 3c7b9a765a2..ae405db0a49 100644 --- a/src/ejabberd_rdbms.erl +++ b/src/ejabberd_rdbms.erl @@ -5,7 +5,7 @@ %%% Created : 31 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 9c3702424c1..785855294a4 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -5,7 +5,7 @@ %%% Created : 10 Nov 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_regexp.erl b/src/ejabberd_regexp.erl index 86ebd1846db..b79774e31d5 100644 --- a/src/ejabberd_regexp.erl +++ b/src/ejabberd_regexp.erl @@ -5,7 +5,7 @@ %%% Created : 8 Dec 2011 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_riak.erl b/src/ejabberd_riak.erl index 7f89775e0a8..22da9d2e9de 100644 --- a/src/ejabberd_riak.erl +++ b/src/ejabberd_riak.erl @@ -4,9 +4,9 @@ %%% Interface for Riak database %%% @end %%% Created : 29 Dec 2011 by Alexey Shchepin -%%% @copyright (C) 2002-2015 ProcessOne +%%% @copyright (C) 2002-2016 ProcessOne %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index 78d6fc6e778..319d1707df1 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -5,7 +5,7 @@ %%% Created : 29 Dec 2011 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 81fedfe0fd4..8a579814c5f 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -5,7 +5,7 @@ %%% Created : 27 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_router_multicast.erl b/src/ejabberd_router_multicast.erl index da4b45968d9..fa32c8ed7ac 100644 --- a/src/ejabberd_router_multicast.erl +++ b/src/ejabberd_router_multicast.erl @@ -5,7 +5,7 @@ %%% Created : 11 Aug 2007 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 24694f3f0e8..06cad6af69d 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -5,7 +5,7 @@ %%% Created : 7 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 4159dee4ab6..29dd5e9dfdd 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -5,7 +5,7 @@ %%% Created : 6 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 331f5443658..69618573939 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -5,7 +5,7 @@ %%% Created : 6 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index f80675c8ef0..a9b771b8988 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -5,7 +5,7 @@ %%% Created : 6 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index c550409f8ee..ddc5697f2c4 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -5,7 +5,7 @@ %%% Created : 24 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sm_mnesia.erl b/src/ejabberd_sm_mnesia.erl index 7acc1022dbd..b900da31524 100644 --- a/src/ejabberd_sm_mnesia.erl +++ b/src/ejabberd_sm_mnesia.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2015, Evgeny Khramtsov +%%% @copyright (C) 2015-2016, Evgeny Khramtsov %%% @doc %%% %%% @end diff --git a/src/ejabberd_sm_odbc.erl b/src/ejabberd_sm_odbc.erl index 946f58ffa6c..debeafe9990 100644 --- a/src/ejabberd_sm_odbc.erl +++ b/src/ejabberd_sm_odbc.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2015, Evgeny Khramtsov +%%% @copyright (C) 2015-2016, Evgeny Khramtsov %%% @doc %%% %%% @end diff --git a/src/ejabberd_sm_redis.erl b/src/ejabberd_sm_redis.erl index 1a3ce5ab8cf..637e1364718 100644 --- a/src/ejabberd_sm_redis.erl +++ b/src/ejabberd_sm_redis.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeny Khramtsov -%%% @copyright (C) 2015, Evgeny Khramtsov +%%% @copyright (C) 2015-2016, Evgeny Khramtsov %%% @doc %%% %%% @end diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index 3ebd4cc2342..16ffd192ee3 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -5,7 +5,7 @@ %%% Created : 23 Aug 2006 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index b609da5bdf2..f7ae19cd416 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -6,7 +6,7 @@ %%% @end %%% Created : 8 May 2014 by Evgeny Khramtsov %%% -%%% ejabberd, Copyright (C) 2013-2015 ProcessOne +%%% ejabberd, Copyright (C) 2013-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index 9e635220268..56dccdcd9cf 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -5,7 +5,7 @@ %%% Created : 31 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index d1844b8040c..9a0213c1db2 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -5,7 +5,7 @@ %%% Created : 21 Mar 2007 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_tmp_sup.erl b/src/ejabberd_tmp_sup.erl index 5852e666df6..8b9f4fc12ac 100644 --- a/src/ejabberd_tmp_sup.erl +++ b/src/ejabberd_tmp_sup.erl @@ -5,7 +5,7 @@ %%% Created : 18 Jul 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_update.erl b/src/ejabberd_update.erl index aebcbd2254d..75ccc3deaa4 100644 --- a/src/ejabberd_update.erl +++ b/src/ejabberd_update.erl @@ -5,7 +5,7 @@ %%% Created : 27 Jan 2006 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_web.erl b/src/ejabberd_web.erl index 61cd079ab18..459423aa4b5 100644 --- a/src/ejabberd_web.erl +++ b/src/ejabberd_web.erl @@ -6,7 +6,7 @@ %%% Created : 28 Feb 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index c4a191eb0b5..d711f2fc39e 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -5,7 +5,7 @@ %%% Created : 9 Apr 2004 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -342,7 +342,7 @@ make_xhtml(Els, Host, Node, Lang, JID) -> [?XAE(<<"div">>, [{<<"id">>, <<"copyright">>}], [?XE(<<"p">>, [?AC(<<"https://www.ejabberd.im/">>, <<"ejabberd">>), - ?C(<<" (c) 2002-2015 ">>), + ?C(<<" (c) 2002-2016 ">>), ?AC(<<"https://www.process-one.net/">>, <<"ProcessOne, leader in messaging and push solutions">>)] )])])])]}}. diff --git a/src/ejabberd_websocket.erl b/src/ejabberd_websocket.erl index d922787b5ef..d9a1bafc7ed 100644 --- a/src/ejabberd_websocket.erl +++ b/src/ejabberd_websocket.erl @@ -33,7 +33,7 @@ %%% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE %%% POSSIBILITY OF SUCH DAMAGE. %%% ========================================================================================================== -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%%---------------------------------------------------------------------- -module(ejabberd_websocket). diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index db109920cbd..6b25adc4c0d 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -5,7 +5,7 @@ %%% Created : 21 Aug 2007 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index 2580ffe6b16..4cb937ef94f 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -5,7 +5,7 @@ %%% Created : 22 Aug 2005 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/eldap_filter.erl b/src/eldap_filter.erl index e8ce625c8ab..d46e410a48b 100644 --- a/src/eldap_filter.erl +++ b/src/eldap_filter.erl @@ -6,7 +6,7 @@ %%% Author: Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/eldap_pool.erl b/src/eldap_pool.erl index 51761c0701e..8e0096f86a5 100644 --- a/src/eldap_pool.erl +++ b/src/eldap_pool.erl @@ -5,7 +5,7 @@ %%% Created : 12 Nov 2006 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/eldap_utils.erl b/src/eldap_utils.erl index 3c475e20b76..9b9e5fbce6a 100644 --- a/src/eldap_utils.erl +++ b/src/eldap_utils.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Mickael Remond %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/ext_mod.erl b/src/ext_mod.erl index ccc847eebdf..148c94178fb 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -5,7 +5,7 @@ %%% Created : 19 Feb 2015 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2006-2015 ProcessOne +%%% ejabberd, Copyright (C) 2006-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/extauth.erl b/src/extauth.erl index 1d312624653..50330b47b33 100644 --- a/src/extauth.erl +++ b/src/extauth.erl @@ -5,7 +5,7 @@ %%% Created : 30 Jul 2004 by Leif Johansson %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/gen_iq_handler.erl b/src/gen_iq_handler.erl index fa2a97737eb..c2b4252c94e 100644 --- a/src/gen_iq_handler.erl +++ b/src/gen_iq_handler.erl @@ -5,7 +5,7 @@ %%% Created : 22 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/gen_mod.erl b/src/gen_mod.erl index bf48634f3b9..c45642d47f3 100644 --- a/src/gen_mod.erl +++ b/src/gen_mod.erl @@ -5,7 +5,7 @@ %%% Created : 24 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/gen_pubsub_node.erl b/src/gen_pubsub_node.erl index c477466e130..0148da2e2c6 100644 --- a/src/gen_pubsub_node.erl +++ b/src/gen_pubsub_node.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/gen_pubsub_nodetree.erl b/src/gen_pubsub_nodetree.erl index 281234a6b5a..73583af0268 100644 --- a/src/gen_pubsub_nodetree.erl +++ b/src/gen_pubsub_nodetree.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl index 26c2a2914fb..cda8d11ce89 100644 --- a/src/jd2ejd.erl +++ b/src/jd2ejd.erl @@ -5,7 +5,7 @@ %%% Created : 2 Feb 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/jid.erl b/src/jid.erl index c09e06488db..cc387ecbe4d 100644 --- a/src/jid.erl +++ b/src/jid.erl @@ -6,7 +6,7 @@ %%% Created : 24 Nov 2015 by Evgeny Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/jlib.erl b/src/jlib.erl index 2196ba57e00..cb46c591dcf 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -5,7 +5,7 @@ %%% Created : 23 Nov 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_adhoc.erl b/src/mod_adhoc.erl index f476dabfbd3..9947c84acd4 100644 --- a/src/mod_adhoc.erl +++ b/src/mod_adhoc.erl @@ -5,7 +5,7 @@ %%% Created : 15 Nov 2005 by Magnus Henoch %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 76d59d40965..3d0924a6d08 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -5,7 +5,7 @@ %%% Created : 11 Aug 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 18d8828839b..4f9c82734d0 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -5,7 +5,7 @@ %%% Created : 24 Aug 2008 by Stephan Maka %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_caps.erl b/src/mod_caps.erl index ac4499a35c4..7d764c4bf5b 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -5,7 +5,7 @@ %%% Created : 7 Oct 2006 by Magnus Henoch %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index c3ee6ad2289..a4ca45ddfb6 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -7,7 +7,7 @@ %%% {mod_carboncopy, []} %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index e89ec6883d0..3c046d77621 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -5,7 +5,7 @@ %%% Created : 11 Sep 2014 by Holger Weiss %%% %%% -%%% ejabberd, Copyright (C) 2014-2015 ProcessOne +%%% ejabberd, Copyright (C) 2014-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 7524830df3a..a101ebf3cc6 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -5,7 +5,7 @@ %%% Created : 19 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index 109df2455fa..3e00a9cf73d 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -5,7 +5,7 @@ %%% Created : 26 Oct 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_disco.erl b/src/mod_disco.erl index afa7d39081e..6e0b9c929c5 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -5,7 +5,7 @@ %%% Created : 1 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 59918b9cf93..3f91f1d036d 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_fail2ban.erl b/src/mod_fail2ban.erl index 394a7186f87..fed10670049 100644 --- a/src/mod_fail2ban.erl +++ b/src/mod_fail2ban.erl @@ -6,7 +6,7 @@ %%% Created : 15 Aug 2014 by Evgeny Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2014-2015 ProcessOne +%%% ejabberd, Copyright (C) 2014-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl index 742772b9afb..7f86d5cc182 100644 --- a/src/mod_http_api.erl +++ b/src/mod_http_api.erl @@ -5,7 +5,7 @@ %%% Created : 15 Sep 2014 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_bind.erl b/src/mod_http_bind.erl index fd871705fd8..1a07867e09a 100644 --- a/src/mod_http_bind.erl +++ b/src/mod_http_bind.erl @@ -5,7 +5,7 @@ %%% Created : Tue Feb 20 13:15:52 CET 2007 %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_fileserver.erl b/src/mod_http_fileserver.erl index 7ebbc81ff53..346dc41c868 100644 --- a/src/mod_http_fileserver.erl +++ b/src/mod_http_fileserver.erl @@ -5,7 +5,7 @@ %%% Created : %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 077ca0f4969..a5e8e1726cd 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -5,7 +5,7 @@ %%% Created : 20 Aug 2015 by Holger Weiss %%% %%% -%%% ejabberd, Copyright (C) 2015 ProcessOne +%%% ejabberd, Copyright (C) 2015-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index 4f656b18bcb..eea23d34bf9 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -5,7 +5,7 @@ %%% Created : 15 Oct 2015 by Holger Weiss %%% %%% -%%% ejabberd, Copyright (C) 2015 ProcessOne +%%% ejabberd, Copyright (C) 2015-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_ip_blacklist.erl b/src/mod_ip_blacklist.erl index b0777d28ec6..a6f9f619d3e 100644 --- a/src/mod_ip_blacklist.erl +++ b/src/mod_ip_blacklist.erl @@ -7,7 +7,7 @@ %%% {mod_ip_blacklist, []} %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_irc.erl b/src/mod_irc.erl index c6162d94987..183088956cc 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -5,7 +5,7 @@ %%% Created : 15 Feb 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -474,7 +474,7 @@ iq_get_vcard(Lang) -> [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd IRC module">>))/binary, - "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2003-2016 ProcessOne">>}]}]. command_items(ServerHost, Host, Lang) -> lists:map(fun ({Node, Name, _Function}) -> diff --git a/src/mod_irc_connection.erl b/src/mod_irc_connection.erl index eed7006c957..ae709dc27b5 100644 --- a/src/mod_irc_connection.erl +++ b/src/mod_irc_connection.erl @@ -5,7 +5,7 @@ %%% Created : 15 Feb 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_last.erl b/src/mod_last.erl index 6cd598a187f..d76b604918e 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -5,7 +5,7 @@ %%% Created : 24 Oct 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 95fe4964ec9..ae6ab3d4d44 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -6,7 +6,7 @@ %%% Created : 4 Jul 2013 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2013-2015 ProcessOne +%%% ejabberd, Copyright (C) 2013-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl index b712def152a..3e64da95272 100644 --- a/src/mod_metrics.erl +++ b/src/mod_metrics.erl @@ -5,7 +5,7 @@ %%% Created : 22 Oct 2015 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_muc.erl b/src/mod_muc.erl index b03dde3c668..48d094202b0 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -5,7 +5,7 @@ %%% Created : 19 Mar 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -1109,7 +1109,7 @@ iq_get_vcard(Lang) -> [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd MUC module">>))/binary, - "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2003-2016 ProcessOne">>}]}]. broadcast_service_message(Host, Msg) -> lists:foreach( diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 49adf034b41..0f4553189ec 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -5,7 +5,7 @@ %%% Created : 12 Mar 2006 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 6dfda260f2a..96d4c654838 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -5,7 +5,7 @@ %%% Created : 19 Mar 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index bc166b81d35..96ebcb6f2ac 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -5,7 +5,7 @@ %%% Created : 29 May 2007 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -304,7 +304,7 @@ iq_vcard(Lang) -> [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd Multicast service">>))/binary, - "\nCopyright (c) 2002-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2002-2016 ProcessOne">>}]}]. %%%------------------------- %%% Route diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 73039b55b05..1b1627e87d3 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -5,7 +5,7 @@ %%% Created : 5 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_ping.erl b/src/mod_ping.erl index d8dc5d7ced5..e8a977dedb4 100644 --- a/src/mod_ping.erl +++ b/src/mod_ping.erl @@ -5,7 +5,7 @@ %%% Created : 11 Jul 2009 by Brian Cully %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index 9834c4360a9..34fdcdb75bf 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -5,7 +5,7 @@ %%% Created : 23 Sep 2010 by Ahmed Omar %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 02ff07a1b82..9c2af037b93 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -5,7 +5,7 @@ %%% Created : 21 Jul 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_private.erl b/src/mod_private.erl index 52b317a5dac..a03d83e5aa3 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -5,7 +5,7 @@ %%% Created : 16 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl index 8d58c891868..2737de7ad00 100644 --- a/src/mod_proxy65.erl +++ b/src/mod_proxy65.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_lib.erl b/src/mod_proxy65_lib.erl index 6c5967688e7..3cacbf98b48 100644 --- a/src/mod_proxy65_lib.erl +++ b/src/mod_proxy65_lib.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index d1c5c32e175..97d5b00afbb 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -246,7 +246,7 @@ iq_vcard(Lang) -> [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd SOCKS5 Bytestreams module">>))/binary, - "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2003-2016 ProcessOne">>}]}]. parse_options(ServerHost, Opts) -> MyHost = gen_mod:get_opt_host(ServerHost, Opts, diff --git a/src/mod_proxy65_sm.erl b/src/mod_proxy65_sm.erl index f120f828b94..d86b06c4bb9 100644 --- a/src/mod_proxy65_sm.erl +++ b/src/mod_proxy65_sm.erl @@ -5,7 +5,7 @@ %%% Created : 12 Oct 2006 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl index 2d777589eec..36dd7af196b 100644 --- a/src/mod_proxy65_stream.erl +++ b/src/mod_proxy65_stream.erl @@ -4,7 +4,7 @@ %%% Purpose : Bytestream process. %%% Created : 12 Oct 2006 by Evgeniy Khramtsov %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 9c334ebc0c6..616c64929d1 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -1220,7 +1220,7 @@ iq_get_vcard(Lang) -> #xmlel{name = <<"DESC">>, attrs = [], children = [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd Publish-Subscribe module">>))/binary, - "\nCopyright (c) 2004-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2004-2016 ProcessOne">>}]}]. -spec(iq_pubsub/6 :: ( diff --git a/src/mod_register.erl b/src/mod_register.erl index 5628dbf8c32..c7bfd963b8b 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -5,7 +5,7 @@ %%% Created : 8 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index dd069593d71..35f52f3b20c 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -5,7 +5,7 @@ %%% Created : 4 May 2008 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_roster.erl b/src/mod_roster.erl index eb987a2df21..adc2210db2c 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -5,7 +5,7 @@ %%% Created : 11 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_service_log.erl b/src/mod_service_log.erl index 83c8a20ffdf..3e1da3a4ea1 100644 --- a/src/mod_service_log.erl +++ b/src/mod_service_log.erl @@ -5,7 +5,7 @@ %%% Created : 24 Aug 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 52828245169..cde0f66b862 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -5,7 +5,7 @@ %%% Created : 5 Mar 2005 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 9064a671100..a4ac65c10e0 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -7,7 +7,7 @@ %%% Created : 5 Mar 2005 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sic.erl b/src/mod_sic.erl index 3f5bf0dab08..3ffd9c917c7 100644 --- a/src/mod_sic.erl +++ b/src/mod_sic.erl @@ -5,7 +5,7 @@ %%% Created : 6 Mar 2010 by Karim Gemayel %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sip.erl b/src/mod_sip.erl index c8c95337947..6ffe563315e 100644 --- a/src/mod_sip.erl +++ b/src/mod_sip.erl @@ -6,7 +6,7 @@ %%% Created : 21 Apr 2014 by Evgeny Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2014-2015 ProcessOne +%%% ejabberd, Copyright (C) 2014-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl index bf297bc88d8..04ae55ae7aa 100644 --- a/src/mod_sip_proxy.erl +++ b/src/mod_sip_proxy.erl @@ -6,7 +6,7 @@ %%% Created : 21 Apr 2014 by Evgeny Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2014-2015 ProcessOne +%%% ejabberd, Copyright (C) 2014-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_sip_registrar.erl b/src/mod_sip_registrar.erl index 44091ed391d..fcaa4236596 100644 --- a/src/mod_sip_registrar.erl +++ b/src/mod_sip_registrar.erl @@ -6,7 +6,7 @@ %%% Created : 23 Apr 2014 by Evgeny Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2014-2015 ProcessOne +%%% ejabberd, Copyright (C) 2014-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_stats.erl b/src/mod_stats.erl index 2604f1bb500..c9f659d3c7c 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -5,7 +5,7 @@ %%% Created : 11 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_time.erl b/src/mod_time.erl index 4c2e6e567d6..8bfe9f9f9c2 100644 --- a/src/mod_time.erl +++ b/src/mod_time.erl @@ -6,7 +6,7 @@ %%% Created : 18 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index f82a0625b1a..db19b557071 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -5,7 +5,7 @@ %%% Created : 2 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -166,7 +166,7 @@ process_local_iq(_From, _To, [{xmlcdata, <<(translate:translate(Lang, <<"Erlang Jabber Server">>))/binary, - "\nCopyright (c) 2002-2015 ProcessOne">>}]}, + "\nCopyright (c) 2002-2016 ProcessOne">>}]}, #xmlel{name = <<"BDAY">>, attrs = [], children = [{xmlcdata, <<"2002-11-16">>}]}]}]} @@ -578,7 +578,7 @@ iq_get_vcard(Lang) -> [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd vCard module">>))/binary, - "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2003-2016 ProcessOne">>}]}]. find_xdata_el(#xmlel{children = SubEls}) -> find_xdata_el1(SubEls). diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 92105fdb918..b24356d8e59 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -5,7 +5,7 @@ %%% Created : 2 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -223,7 +223,7 @@ process_local_iq(_From, _To, [{xmlcdata, <<(translate:translate(Lang, <<"Erlang Jabber Server">>))/binary, - "\nCopyright (c) 2002-2015 ProcessOne">>}]}, + "\nCopyright (c) 2002-2016 ProcessOne">>}]}, #xmlel{name = <<"BDAY">>, attrs = [], children = [{xmlcdata, <<"2002-11-16">>}]}]}]} @@ -584,7 +584,7 @@ iq_get_vcard(Lang) -> [{xmlcdata, <<(translate:translate(Lang, <<"ejabberd vCard module">>))/binary, - "\nCopyright (c) 2003-2015 ProcessOne">>}]}]. + "\nCopyright (c) 2003-2016 ProcessOne">>}]}]. -define(LFIELD(Label, Var), #xmlel{name = <<"field">>, diff --git a/src/mod_version.erl b/src/mod_version.erl index 55609d1ea04..0e3b96bd1ce 100644 --- a/src/mod_version.erl +++ b/src/mod_version.erl @@ -5,7 +5,7 @@ %%% Created : 18 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_buddy.erl b/src/node_buddy.erl index 412e58ed000..1ebef4e1591 100644 --- a/src/node_buddy.erl +++ b/src/node_buddy.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_club.erl b/src/node_club.erl index 25334cac9d7..a7ef35bd31c 100644 --- a/src/node_club.erl +++ b/src/node_club.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_dag.erl b/src/node_dag.erl index 23f0ca46b6d..cbb8e18c69d 100644 --- a/src/node_dag.erl +++ b/src/node_dag.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jun 2009 by Brian Cully %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_dispatch.erl b/src/node_dispatch.erl index a8ad2ba96ed..f9bfaf4f2da 100644 --- a/src/node_dispatch.erl +++ b/src/node_dispatch.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_flat.erl b/src/node_flat.erl index e35dd6e9b27..3687bb64054 100644 --- a/src/node_flat.erl +++ b/src/node_flat.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 96779cb6d33..794d3f986bc 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_hometree.erl b/src/node_hometree.erl index 138773e80a3..2d26c0eeb91 100644 --- a/src/node_hometree.erl +++ b/src/node_hometree.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_hometree_odbc.erl b/src/node_hometree_odbc.erl index 1d7ef88ab3b..6ac5c37b8bb 100644 --- a/src/node_hometree_odbc.erl +++ b/src/node_hometree_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_mb.erl b/src/node_mb.erl index 99fc40dfe04..1213805c47d 100644 --- a/src/node_mb.erl +++ b/src/node_mb.erl @@ -5,7 +5,7 @@ %%% Created : 25 Sep 2008 by Eric Cestari %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_online.erl b/src/node_online.erl index 0249aab11aa..1e9e2953353 100644 --- a/src/node_online.erl +++ b/src/node_online.erl @@ -5,7 +5,7 @@ %%% Created : 15 Dec 2015 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_pep.erl b/src/node_pep.erl index 647a8cb0a1e..726146b90ae 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_pep_odbc.erl b/src/node_pep_odbc.erl index 21afb8c140a..6eb0de04034 100644 --- a/src/node_pep_odbc.erl +++ b/src/node_pep_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_private.erl b/src/node_private.erl index b5a4ff06810..de80d870ff6 100644 --- a/src/node_private.erl +++ b/src/node_private.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/node_public.erl b/src/node_public.erl index 560cbfea8b0..df4f1c08071 100644 --- a/src/node_public.erl +++ b/src/node_public.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_dag.erl b/src/nodetree_dag.erl index 4baf7e3b54d..8ac56b27de9 100644 --- a/src/nodetree_dag.erl +++ b/src/nodetree_dag.erl @@ -5,7 +5,7 @@ %%% Created : 15 Jun 2009 by Brian Cully %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_tree.erl b/src/nodetree_tree.erl index ec3c213ea70..e3f7e251e8d 100644 --- a/src/nodetree_tree.erl +++ b/src/nodetree_tree.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_tree_odbc.erl b/src/nodetree_tree_odbc.erl index 881531dbb90..ef1c20b6b3e 100644 --- a/src/nodetree_tree_odbc.erl +++ b/src/nodetree_tree_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/nodetree_virtual.erl b/src/nodetree_virtual.erl index 9fc9b53c501..934950dd231 100644 --- a/src/nodetree_virtual.erl +++ b/src/nodetree_virtual.erl @@ -5,7 +5,7 @@ %%% Created : 1 Dec 2007 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index e33af54e258..2f488a0bd4a 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -5,7 +5,7 @@ %%% Created : by Mickael Remond %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_db_odbc.erl b/src/pubsub_db_odbc.erl index 53df71d4676..cfdeda1ef60 100644 --- a/src/pubsub_db_odbc.erl +++ b/src/pubsub_db_odbc.erl @@ -5,7 +5,7 @@ %%% Created : 7 Aug 2009 by Pablo Polvorin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_index.erl b/src/pubsub_index.erl index acfdbcf1ae2..983356a183d 100644 --- a/src/pubsub_index.erl +++ b/src/pubsub_index.erl @@ -5,7 +5,7 @@ %%% Created : 30 Apr 2009 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_migrate.erl b/src/pubsub_migrate.erl index 7ac54ffec48..c493b58f9eb 100644 --- a/src/pubsub_migrate.erl +++ b/src/pubsub_migrate.erl @@ -5,7 +5,7 @@ %%% Created : 26 Jul 2014 by Christophe Romain %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index d302f5f3b0f..9918a2c3553 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -5,7 +5,7 @@ %%% Created : 29 May 2009 by Brian Cully %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index b17d95b016f..6791c4ac73a 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -6,7 +6,7 @@ %%% Created : 7 Aug 2009 by Pablo Polvorin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/randoms.erl b/src/randoms.erl index 9d9b392f6a2..52fceef4e61 100644 --- a/src/randoms.erl +++ b/src/randoms.erl @@ -5,7 +5,7 @@ %%% Created : 13 Dec 2002 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/scram.erl b/src/scram.erl index b9605375489..2c4d265bc63 100644 --- a/src/scram.erl +++ b/src/scram.erl @@ -5,7 +5,7 @@ %%% Created : 7 Aug 2011 by Stephen Röttger %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/shaper.erl b/src/shaper.erl index a2fd09dfa63..a136c2130d7 100644 --- a/src/shaper.erl +++ b/src/shaper.erl @@ -5,7 +5,7 @@ %%% Created : 9 Feb 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/str.erl b/src/str.erl index 80d7b05b09b..27d21075a4a 100644 --- a/src/str.erl +++ b/src/str.erl @@ -5,7 +5,7 @@ %%% Created : 23 Feb 2012 by Evgeniy Khramtsov %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/translate.erl b/src/translate.erl index 277dfa445a5..e9f61ab8c03 100644 --- a/src/translate.erl +++ b/src/translate.erl @@ -5,7 +5,7 @@ %%% Created : 6 Jan 2003 by Alexey Shchepin %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/src/win32_dns.erl b/src/win32_dns.erl index f0e4b5f283b..5dda22b9859 100644 --- a/src/win32_dns.erl +++ b/src/win32_dns.erl @@ -5,7 +5,7 @@ %%% Created : 5 Mar 2009 by Geoff Cant %%% %%% -%%% ejabberd, Copyright (C) 2002-2015 ProcessOne +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 11ed6f74385..543437e08cf 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2002-2015, ProcessOne +%%% @copyright (C) 2002-2016, ProcessOne %%% @doc %%% %%% @end diff --git a/test/ejabberd_hooks_test.exs b/test/ejabberd_hooks_test.exs index cbb12638414..ff753a7bbca 100644 --- a/test/ejabberd_hooks_test.exs +++ b/test/ejabberd_hooks_test.exs @@ -1,6 +1,6 @@ # ---------------------------------------------------------------------- # -# ejabberd, Copyright (C) 2002-2015 ProcessOne +# ejabberd, Copyright (C) 2002-2016 ProcessOne # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as diff --git a/test/elixir_SUITE.erl b/test/elixir_SUITE.erl index b0a76bfa4d4..6243456bdeb 100644 --- a/test/elixir_SUITE.erl +++ b/test/elixir_SUITE.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Mickael Remond -%%% @copyright (C) 2002-2015, ProcessOne +%%% @copyright (C) 2002-2016, ProcessOne %%% @doc %%% This is a common test wrapper to run our ejabberd tests written in %%% Elixir from standard common test code. diff --git a/test/ldap_srv.erl b/test/ldap_srv.erl index 132f53e04d4..69b8a27e75a 100644 --- a/test/ldap_srv.erl +++ b/test/ldap_srv.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @copyright (C) 2013-2016, Evgeniy Khramtsov %%% @doc %%% Simple LDAP server intended for LDAP modules testing %%% @end diff --git a/test/suite.erl b/test/suite.erl index fd5e175eae1..74d9b0628cf 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov <> -%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @copyright (C) 2013-2016, Evgeniy Khramtsov %%% @doc %%% %%% @end diff --git a/vars.config.in b/vars.config.in index fceff7d673a..991d20c9eaa 100644 --- a/vars.config.in +++ b/vars.config.in @@ -1,6 +1,6 @@ %%%------------------------------------------------------------------- %%% @author Evgeniy Khramtsov -%%% @copyright (C) 2013, Evgeniy Khramtsov +%%% @copyright (C) 2013-2016, Evgeniy Khramtsov %%% @doc %%% %%% @end From 0183b2487e4e5cc0033eb7ad0c8a6f0165c495a5 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 13 Jan 2016 20:30:44 +0100 Subject: [PATCH 471/695] Advertise MUC MAM v0.4.1 in room JID's disco#info --- src/mod_muc_room.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 96d4c654838..58974633db2 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -4152,7 +4152,7 @@ process_iq_disco_info(_From, get, Lang, StateData) -> ++ case {gen_mod:is_loaded(StateData#state.server_host, mod_mam), Config#config.mam} of {true, true} -> - [?FEATURE(?NS_MAM_0)]; + [?FEATURE(?NS_MAM_0), ?FEATURE(?NS_MAM_1)]; _ -> [] end From a61b0c303d919fb8e1850518b0f0b6ae7ced6850 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 13 Jan 2016 21:38:08 +0100 Subject: [PATCH 472/695] mod_mam: Add "request_activates_archiving" option Enabling "request_activates_archiving" tells mod_mam not to store any messages for a user until his client issued a MAM request, regardless of mod_mam's "default" option. Once a MAM request is issued, messages are archived as usual. --- src/mod_mam.erl | 62 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index ae6ab3d4d44..1bcb5bc188c 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -360,7 +360,13 @@ process_iq(#jid{luser = LUser, lserver = LServer}, process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. -process_iq(LServer, From, To, IQ, SubEl, Fs, MsgType) -> +process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) -> + case MsgType of + chat -> + maybe_activate_mam(LUser, LServer); + {groupchat, _Role, _MUCState} -> + ok + end, case catch lists:foldl( fun({<<"start">>, [Data|_]}, {_, End, With, RSM}) -> {{_, _, _} = jlib:datetime_string_to_timestamp(Data), @@ -620,13 +626,21 @@ get_prefs(LUser, LServer) -> {ok, Prefs} -> Prefs; error -> - Default = gen_mod:get_module_opt( - LServer, ?MODULE, default, - fun(always) -> always; - (never) -> never; - (roster) -> roster - end, never), - #archive_prefs{us = {LUser, LServer}, default = Default} + ActivateOpt = gen_mod:get_module_opt( + LServer, ?MODULE, request_activates_archiving, + fun(B) when is_boolean(B) -> B end, false), + case ActivateOpt of + true -> + #archive_prefs{us = {LUser, LServer}, default = never}; + false -> + Default = gen_mod:get_module_opt( + LServer, ?MODULE, default, + fun(always) -> always; + (never) -> never; + (roster) -> roster + end, never), + #archive_prefs{us = {LUser, LServer}, default = Default} + end end. get_prefs(LUser, LServer, mnesia) -> @@ -654,6 +668,34 @@ get_prefs(LUser, LServer, odbc) -> error end. +maybe_activate_mam(LUser, LServer) -> + ActivateOpt = gen_mod:get_module_opt(LServer, ?MODULE, + request_activates_archiving, + fun(B) when is_boolean(B) -> B end, + false), + case ActivateOpt of + true -> + Res = cache_tab:lookup(archive_prefs, {LUser, LServer}, + fun() -> + get_prefs(LUser, LServer, + gen_mod:db_type(LServer, + ?MODULE)) + end), + case Res of + {ok, _Prefs} -> + ok; + error -> + Default = gen_mod:get_module_opt(LServer, ?MODULE, default, + fun(always) -> always; + (never) -> never; + (roster) -> roster + end, never), + write_prefs(LUser, LServer, LServer, Default, [], []) + end; + false -> + ok + end. + select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType) -> DBType = case gen_mod:db_type(LServer, ?MODULE) of odbc -> {odbc, LServer}; @@ -1131,8 +1173,10 @@ mod_opt_type(default) -> (roster) -> roster end; mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(request_activates_archiving) -> + fun (B) when is_boolean(B) -> B end; mod_opt_type(store_body_only) -> fun (B) when is_boolean(B) -> B end; mod_opt_type(_) -> [cache_life_time, cache_size, db_type, default, iqdisc, - store_body_only]. + request_activates_archiving, store_body_only]. From 3dccc20d8bce2d70c321810faa808a00204b6c02 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 13 Jan 2016 22:46:30 +0100 Subject: [PATCH 473/695] mod_mam: Add "delete_old_mam_messages" command The new "delete_old_mam_messages" command allows for purging all MAM messages of the specified type older than the specified number of days. (Currently only implemented for Mnesia archives.) --- src/mod_mam.erl | 57 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 1bcb5bc188c..1398cf1be07 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -36,12 +36,13 @@ -export([user_send_packet/4, user_receive_packet/5, process_iq_v0_2/3, process_iq_v0_3/3, disco_sm_features/5, remove_user/2, remove_user/3, mod_opt_type/1, muc_process_iq/4, - muc_filter_message/5]). + muc_filter_message/5, delete_old_messages/2]). -include_lib("stdlib/include/ms_transform.hrl"). -include("jlib.hrl"). -include("logger.hrl"). -include("mod_muc_room.hrl"). +-include("ejabberd_commands.hrl"). -record(archive_msg, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', @@ -94,6 +95,7 @@ start(Host, Opts) -> remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), + ejabberd_commands:register_commands(commands()), ok. init_db(mnesia, _Host) -> @@ -138,6 +140,7 @@ stop(Host) -> remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), + ejabberd_commands:unregister_commands(commands()), ok. remove_user(User, Server) -> @@ -305,6 +308,49 @@ disco_sm_features({result, OtherFeatures}, disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. +delete_old_messages(TypeBin, Days) when TypeBin == <<"chat">>; + TypeBin == <<"groupchat">>; + TypeBin == <<"all">> -> + Diff = Days * 24 * 60 * 60 * 1000000, + TimeStamp = usec_to_now(p1_time_compat:system_time(micro_seconds) - Diff), + Type = jlib:binary_to_atom(TypeBin), + {Results, _} = + lists:foldl(fun(Host, {Results, MnesiaDone}) -> + case {gen_mod:db_type(Host, ?MODULE), MnesiaDone} of + {mnesia, true} -> + {Results, true}; + {mnesia, false} -> + Res = delete_old_messages(TimeStamp, Type, + global, mnesia), + {[Res|Results], true}; + {DBType, _} -> + Res = delete_old_messages(TimeStamp, Type, + Host, DBType), + {[Res|Results], MnesiaDone} + end + end, {[], false}, ?MYHOSTS), + case lists:filter(fun(Res) -> Res /= ok end, Results) of + [] -> ok; + [NotOk|_] -> NotOk + end; +delete_old_messages(_TypeBin, _Days) -> + unsupported_type. + +delete_old_messages(TimeStamp, Type, global, mnesia) -> + MS = ets:fun2ms(fun(#archive_msg{timestamp = MsgTS, + type = MsgType} = Msg) + when MsgTS < TimeStamp, + MsgType == Type orelse Type == all -> + Msg + end), + OldMsgs = mnesia:dirty_select(archive_msg, MS), + lists:foreach(fun(Rec) -> + ok = mnesia:dirty_delete_object(Rec) + end, OldMsgs); +delete_old_messages(_TimeStamp, _Type, _Host, _DBType) -> + %% TODO + not_implemented. + %%%=================================================================== %%% Internal functions %%%=================================================================== @@ -1162,6 +1208,15 @@ update(LServer, Table, Fields, Vals, Where) -> join([], _Sep) -> []; join([H | T], Sep) -> [H, [[Sep, X] || X <- T]]. +commands() -> + [#ejabberd_commands{name = delete_old_mam_messages, tags = [purge], + desc = "Delete MAM messages older than DAYS", + longdesc = "Valid message TYPEs: " + "\"chat\", \"groupchat\", \"all\".", + module = ?MODULE, function = delete_old_messages, + args = [{type, binary}, {days, integer}], + result = {res, rescode}}]. + mod_opt_type(cache_life_time) -> fun (I) when is_integer(I), I > 0 -> I end; mod_opt_type(cache_size) -> From 9cd048c442b0183280730945eb19c3e850a7c21e Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 13 Jan 2016 23:01:51 +0100 Subject: [PATCH 474/695] mod_mam: Improve binary comparison of message UIDs Make sure the binary comparison performed when clients use message UIDs to page through Mnesia archives yields correct results even if the specified UIDs don't have the same number of digits as the UIDs of the stored messages. This way, MAM will continue to work as expected after migrating from mod_mam_mnesia to mod_mam. --- src/mod_mam.erl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 1398cf1be07..1bcf1b0dc8e 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -44,6 +44,13 @@ -include("mod_muc_room.hrl"). -include("ejabberd_commands.hrl"). +-define(BIN_GREATER_THAN(A, B), + ((A > B andalso byte_size(A) == byte_size(B)) + orelse byte_size(A) > byte_size(B))). +-define(BIN_LESS_THAN(A, B), + ((A < B andalso byte_size(A) == byte_size(B)) + orelse byte_size(A) < byte_size(B))). + -record(archive_msg, {us = {<<"">>, <<"">>} :: {binary(), binary()} | '$2', id = <<>> :: binary() | '_', @@ -1014,11 +1021,12 @@ filter_by_rsm(Msgs, #rsm_in{max = Max, direction = Direction, id = ID}) -> aft when ID /= <<"">> -> lists:filter( fun(#archive_msg{id = I}) -> - I > ID + ?BIN_GREATER_THAN(I, ID) end, Msgs); before when ID /= <<"">> -> lists:foldl( - fun(#archive_msg{id = I} = Msg, Acc) when I < ID -> + fun(#archive_msg{id = I} = Msg, Acc) + when ?BIN_LESS_THAN(I, ID) -> [Msg|Acc]; (_, Acc) -> Acc From 89b1700279b437917bb09cf1b8c1ac0082e527cf Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 13 Jan 2016 23:17:23 +0100 Subject: [PATCH 475/695] mod_mam: Add 'from' attribute to tag --- src/mod_mam.erl | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 1bcf1b0dc8e..7a17b0148b5 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -884,16 +884,13 @@ select(LServer, #jid{luser = LUser} = JidRequestor, end. msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, - MsgType, JidRequestor) -> - Delay = jlib:now_to_utc_string(TS), - Pkt = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick), - #xmlel{name = <<"forwarded">>, - attrs = [{<<"xmlns">>, ?NS_FORWARD}], - children = [#xmlel{name = <<"delay">>, - attrs = [{<<"xmlns">>, ?NS_DELAY}, - {<<"stamp">>, Delay}]}, - xml:replace_tag_attr( - <<"xmlns">>, <<"jabber:client">>, Pkt)]}. + MsgType, #jid{lserver = LServer} = JidRequestor) -> + Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick), + Pkt3 = #xmlel{name = <<"forwarded">>, + attrs = [{<<"xmlns">>, ?NS_FORWARD}], + children = [xml:replace_tag_attr( + <<"xmlns">>, <<"jabber:client">>, Pkt2)]}, + jlib:add_delay_info(Pkt3, LServer, TS). maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of From 8117092e6a6b27bd935db41b050a5c57d03a0b77 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 13 Jan 2016 23:56:05 +0100 Subject: [PATCH 476/695] mod_mam: Respond to form requests If the client requests a data form with the supported filters, return it as per XEP-0313 v0.3 and newer. --- src/mod_mam.erl | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 7a17b0148b5..fb470f07927 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -258,6 +258,10 @@ process_iq_v0_3(#jid{lserver = LServer} = From, #jid{lserver = LServer} = To, #iq{type = set, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> process_iq(LServer, From, To, IQ, SubEl, get_xdata_fields(SubEl), chat); +process_iq_v0_3(#jid{lserver = LServer}, + #jid{lserver = LServer}, + #iq{type = get, sub_el = #xmlel{name = <<"query">>}} = IQ) -> + process_iq(LServer, IQ); process_iq_v0_3(From, To, IQ) -> process_iq(From, To, IQ). @@ -290,6 +294,17 @@ muc_process_iq(#iq{type = set, lang = Lang, true -> IQ end; +muc_process_iq(#iq{type = get, + sub_el = #xmlel{name = <<"query">>, + attrs = Attrs} = SubEl} = IQ, + MUCState, From, To) -> + case xml:get_attr_s(<<"xmlns">>, Attrs) of + ?NS_MAM_0 -> + LServer = MUCState#state.server_host, + process_iq(LServer, IQ); + _ -> + IQ + end; muc_process_iq(IQ, _MUCState, _From, _To) -> IQ. @@ -362,6 +377,44 @@ delete_old_messages(_TimeStamp, _Type, _Host, _DBType) -> %%% Internal functions %%%=================================================================== +process_iq(LServer, #iq{sub_el = #xmlel{attrs = Attrs}} = IQ) -> + NS = case xml:get_attr_s(<<"xmlns">>, Attrs) of + ?NS_MAM_0 -> + ?NS_MAM_0; + _ -> + ?NS_MAM_1 + end, + CommonFields = [#xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"hidden">>}, + {<<"var">>, <<"FORM_TYPE">>}], + children = [#xmlel{name = <<"value">>, + children = [{xmlcdata, NS}]}]}, + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"jid-single">>}, + {<<"var">>, <<"with">>}]}, + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"text-single">>}, + {<<"var">>, <<"start">>}]}, + #xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"text-single">>}, + {<<"var">>, <<"end">>}]}], + Fields = case gen_mod:db_type(LServer, ?MODULE) of + odbc -> + WithText = #xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"text-single">>}, + {<<"var">>, <<"withtext">>}]}, + [WithText|CommonFields]; + _ -> + CommonFields + end, + Form = #xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"form">>}], + children = Fields}, + IQ#iq{type = result, + sub_el = [#xmlel{name = <<"query">>, + attrs = [{<<"xmlns">>, NS}], + children = [Form]}]}. + % Preference setting (both v0.2 & v0.3) process_iq(#jid{luser = LUser, lserver = LServer}, #jid{lserver = LServer}, From 85f4f90b4549affea1f1a60acfb970f26f738048 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 Jan 2016 00:58:48 +0100 Subject: [PATCH 477/695] mod_mam: Support XEP-0313 v0.2 MUC archive queries --- src/mod_mam.erl | 84 ++++++++++++++++++++++++-------------------- src/mod_muc.erl | 2 ++ src/mod_muc_room.erl | 4 ++- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index fb470f07927..31fa79777d0 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -218,11 +218,15 @@ muc_filter_message(Pkt, #state{config = Config} = MUCState, NewPkt = strip_my_archived_tag(Pkt, LServer), case store_muc(MUCState, NewPkt, RoomJID, From, FromNick) of {ok, ID} -> + Archived = #xmlel{name = <<"archived">>, + attrs = [{<<"by">>, LServer}, + {<<"xmlns">>, ?NS_MAM_TMP}, + {<<"id">>, ID}]}, StanzaID = #xmlel{name = <<"stanza-id">>, attrs = [{<<"by">>, LServer}, {<<"xmlns">>, ?NS_SID_0}, {<<"id">>, ID}]}, - NewEls = [StanzaID|NewPkt#xmlel.children], + NewEls = [Archived, StanzaID|NewPkt#xmlel.children], NewPkt#xmlel{children = NewEls}; _ -> NewPkt @@ -235,20 +239,7 @@ muc_filter_message(Pkt, #state{config = Config} = MUCState, process_iq_v0_2(#jid{lserver = LServer} = From, #jid{lserver = LServer} = To, #iq{type = get, sub_el = #xmlel{name = <<"query">>} = SubEl} = IQ) -> - Fs = lists:flatmap( - fun (#xmlel{name = <<"start">>} = El) -> - [{<<"start">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"end">>} = El) -> - [{<<"end">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"with">>} = El) -> - [{<<"with">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"withtext">>} = El) -> - [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; - (#xmlel{name = <<"set">>}) -> - [{<<"set">>, SubEl}]; - (_) -> - [] - end, SubEl#xmlel.children), + Fs = parse_query_v0_2(SubEl), process_iq(LServer, From, To, IQ, SubEl, Fs, chat); process_iq_v0_2(From, To, IQ) -> process_iq(From, To, IQ). @@ -269,29 +260,10 @@ muc_process_iq(#iq{type = set, lang = Lang, sub_el = #xmlel{name = <<"query">>, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> - XMLNS = xml:get_attr_s(<<"xmlns">>, Attrs), - if XMLNS == ?NS_MAM_0; XMLNS == ?NS_MAM_1 -> - LServer = MUCState#state.server_host, - Role = mod_muc_room:get_role(From, MUCState), - Config = MUCState#state.config, - if Config#config.members_only -> - case mod_muc_room:is_occupant_or_admin(From, MUCState) of - true -> - process_iq(LServer, From, To, IQ, SubEl, - get_xdata_fields(SubEl), - {groupchat, Role, MUCState}); - false -> - Text = <<"Only members are allowed to query " - "archives of this room">>, - Error = ?ERRT_FORBIDDEN(Lang, Text), - IQ#iq{type = error, sub_el = [SubEl, Error]} - end; - true -> - process_iq(LServer, From, To, IQ, SubEl, - get_xdata_fields(SubEl), - {groupchat, Role, MUCState}) - end; - true -> + case xml:get_attr_s(<<"xmlns">>, Attrs) of + NS when NS == ?NS_MAM_0; NS == ?NS_MAM_1 -> + muc_process_iq(IQ, MUCState, From, To, get_xdata_fields(SubEl)); + _ -> IQ end; muc_process_iq(#iq{type = get, @@ -299,7 +271,9 @@ muc_process_iq(#iq{type = get, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> case xml:get_attr_s(<<"xmlns">>, Attrs) of - ?NS_MAM_0 -> + ?NS_MAM_TMP -> + muc_process_iq(IQ, MUCState, From, To, parse_query_v0_2(SubEl)); + NS when NS == ?NS_MAM_0; NS == ?NS_MAM_1 -> LServer = MUCState#state.server_host, process_iq(LServer, IQ); _ -> @@ -497,6 +471,38 @@ process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) -> With, RSM, IQ, MsgType) end. +muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ, + #state{config = #config{members_only = MembersOnly}} = MUCState, + From, To, Fs) -> + case not MembersOnly orelse + mod_muc_room:is_occupant_or_admin(From, MUCState) of + true -> + LServer = MUCState#state.server_host, + Role = mod_muc_room:get_role(From, MUCState), + process_iq(LServer, From, To, IQ, SubEl, Fs, + {groupchat, Role, MUCState}); + false -> + Text = <<"Only members may query archives of this room">>, + Error = ?ERRT_FORBIDDEN(Lang, Text), + IQ#iq{type = error, sub_el = [SubEl, Error]} + end. + +parse_query_v0_2(Query) -> + lists:flatmap( + fun (#xmlel{name = <<"start">>} = El) -> + [{<<"start">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"end">>} = El) -> + [{<<"end">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"with">>} = El) -> + [{<<"with">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"withtext">>} = El) -> + [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; + (#xmlel{name = <<"set">>}) -> + [{<<"set">>, Query}]; + (_) -> + [] + end, Query#xmlel.children). + should_archive(#xmlel{name = <<"message">>} = Pkt, LServer) -> case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of <<"error">> -> diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 48d094202b0..a5405559248 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -756,6 +756,8 @@ iq_disco_info(ServerHost, Lang) -> case gen_mod:is_loaded(ServerHost, mod_mam) of true -> [#xmlel{name = <<"feature">>, + attrs = [{<<"var">>, ?NS_MAM_TMP}]}, + #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MAM_0}]}, #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_MAM_1}]}]; diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 58974633db2..d19bc5f3d11 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -4152,7 +4152,9 @@ process_iq_disco_info(_From, get, Lang, StateData) -> ++ case {gen_mod:is_loaded(StateData#state.server_host, mod_mam), Config#config.mam} of {true, true} -> - [?FEATURE(?NS_MAM_0), ?FEATURE(?NS_MAM_1)]; + [?FEATURE(?NS_MAM_TMP), + ?FEATURE(?NS_MAM_0), + ?FEATURE(?NS_MAM_1)]; _ -> [] end From 89f63a4fdfbf5e240060e63b11fb2722e4cebe22 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 Jan 2016 01:13:16 +0100 Subject: [PATCH 478/695] mod_mam: Check whether MUC message is desired --- src/mod_mam.erl | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 31fa79777d0..3be7312a1cd 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -579,9 +579,30 @@ should_archive_peer(C2SState, end end. -should_archive_muc(_MUCState, _Peer) -> - %% TODO - true. +should_archive_muc(Pkt) -> + case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of + <<"groupchat">> -> + case check_store_hint(Pkt) of + store -> + true; + no_store -> + false; + none -> + case xml:get_subtag_cdata(Pkt, <<"body">>) of + <<>> -> + case xml:get_subtag_cdata(Pkt, <<"subject">>) of + <<>> -> + false; + _ -> + true + end; + _ -> + true + end + end; + _ -> + false + end. check_store_hint(Pkt) -> case has_store_hint(Pkt) of @@ -635,7 +656,7 @@ store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> end. store_muc(MUCState, Pkt, RoomJID, Peer, Nick) -> - case should_archive_muc(MUCState, Peer) of + case should_archive_muc(Pkt) of true -> LServer = MUCState#state.server_host, {U, S, _} = jid:tolower(RoomJID), From 11afa45646779a67b660e4b554e5cb04f453a44d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 Jan 2016 01:15:11 +0100 Subject: [PATCH 479/695] mod_mam: Remove unused variable --- src/mod_mam.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 3be7312a1cd..16b62300300 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -256,7 +256,7 @@ process_iq_v0_3(#jid{lserver = LServer}, process_iq_v0_3(From, To, IQ) -> process_iq(From, To, IQ). -muc_process_iq(#iq{type = set, lang = Lang, +muc_process_iq(#iq{type = set, sub_el = #xmlel{name = <<"query">>, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> From 35ec0d58a47dea0d0ea494706ea456fa8d59d854 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 Jan 2016 01:39:19 +0100 Subject: [PATCH 480/695] mod_mam: Reject -based paging If an is specified in the MAM request, reject the request rather than ignoring the desired index and returning wrong results. XEP-0059 says that the server "MAY return a error." --- src/mod_mam.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 16b62300300..05bb401de86 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -466,6 +466,8 @@ process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) -> end, {none, [], none, none}, Fs) of {'EXIT', _} -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; + {_Start, _End, _With, #rsm_in{index = Index}} when is_integer(Index) -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}; {Start, End, With, RSM} -> select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType) From 58c8fc57709b91960d2cce5d67baf674b27b4a3d Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 Jan 2016 02:12:28 +0100 Subject: [PATCH 481/695] mod_mam: Limit result set page size If the client doesn't specify a maximum number of messages to retrieve per page, set a limit of 50 messages. If the client specifies a limit larger than 250, cap the number to 250 messages. These limits aren't enforced for MAM v0.2 requests though, as that version of the XEP doesn't require clients to support RSM. The newer revisions say that "a server MAY place a reasonable limit on how many stanzas may be pushed to a client in one request. Whether or not the client query included a element, the server MAY simply return its limited results, modifying the element it returns appropriately." --- src/mod_mam.erl | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 05bb401de86..6bc8c0c0185 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -44,6 +44,9 @@ -include("mod_muc_room.hrl"). -include("ejabberd_commands.hrl"). +-define(DEF_PAGE_SIZE, 50). +-define(MAX_PAGE_SIZE, 250). + -define(BIN_GREATER_THAN(A, B), ((A > B andalso byte_size(A) == byte_size(B)) orelse byte_size(A) > byte_size(B))). @@ -469,8 +472,9 @@ process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) -> {_Start, _End, _With, #rsm_in{index = Index}} when is_integer(Index) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}; {Start, End, With, RSM} -> + NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), select_and_send(LServer, From, To, Start, End, - With, RSM, IQ, MsgType) + With, limit_max(RSM, NS), IQ, MsgType) end. muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ, @@ -910,12 +914,12 @@ select(LServer, #jid{luser = LUser} = JidRequestor, end, {Query, CountQuery} = make_sql_query(User, LServer, Start, End, With, RSM), - % XXX TODO from XEP-0313: - % To conserve resources, a server MAY place a reasonable limit on - % how many stanzas may be pushed to a client in one request. If a - % query returns a number of stanzas greater than this limit and - % the client did not specify a limit using RSM then the server - % should return a policy-violation error to the client. + % TODO from XEP-0313 v0.2: "To conserve resources, a server MAY place a + % reasonable limit on how many stanzas may be pushed to a client in one + % request. If a query returns a number of stanzas greater than this limit + % and the client did not specify a limit using RSM then the server should + % return a policy-violation error to the client." We currently don't do this + % for v0.2 requests, but we do limit #rsm_in.max for v0.3 and newer. case {ejabberd_odbc:sql_query(Host, Query), ejabberd_odbc:sql_query(Host, CountQuery)} of {{selected, _, Res}, {selected, _, [[Count]]}} -> @@ -1124,6 +1128,15 @@ filter_by_max(Msgs, Len) when is_integer(Len), Len >= 0 -> filter_by_max(_Msgs, _Junk) -> {[], true}. +limit_max(RSM, ?NS_MAM_TMP) -> + RSM; % XEP-0313 v0.2 doesn't require clients to support RSM. +limit_max(#rsm_in{max = Max} = RSM, _NS) when not is_integer(Max) -> + RSM#rsm_in{max = ?DEF_PAGE_SIZE}; +limit_max(#rsm_in{max = Max} = RSM, _NS) when Max > ?MAX_PAGE_SIZE -> + RSM#rsm_in{max = ?MAX_PAGE_SIZE}; +limit_max(RSM, _NS) -> + RSM. + match_interval(Now, Start, End) -> (Now >= Start) and (Now =< End). From db04cdf2ca7eea42024b4cc7bae5e9bea4f4e5e8 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 14 Jan 2016 02:27:02 +0100 Subject: [PATCH 482/695] mod_mam: Sort messages returned by Mnesia Sort the messages retrieved from an Mnesia archive before selecting the subset limited by the value. This makes sure the desired subset of messages is sent to the client. --- src/mod_mam.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 6bc8c0c0185..c20a941df71 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -898,7 +898,8 @@ select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor, Start, End, With, RSM, MsgType, mnesia) -> MS = make_matchspec(LUser, LServer, Start, End, With), Msgs = mnesia:dirty_select(archive_msg, MS), - {FilteredMsgs, IsComplete} = filter_by_rsm(Msgs, RSM), + SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs), + {FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM), Count = length(Msgs), {lists:map( fun(Msg) -> From 6cb1905f7c35e161a54ae011b998f16cc5a32f89 Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Thu, 14 Jan 2016 23:09:03 +0900 Subject: [PATCH 483/695] add stats processes command --- src/mod_admin_extra.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 30e2a32eb10..c5e2cc10df3 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -485,7 +485,7 @@ commands() -> result = {res, rescode}}, #ejabberd_commands{name = stats, tags = [stats], - desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds", + desc = "Get statistical value: registeredusers onlineusers onlineusersnode uptimeseconds processes", policy = admin, module = ?MODULE, function = stats, args = [{name, binary}], @@ -1355,6 +1355,7 @@ privacy_set(Username, Host, QueryS) -> stats(Name) -> case Name of <<"uptimeseconds">> -> trunc(element(1, erlang:statistics(wall_clock))/1000); + <<"processes">> -> length(erlang:processes()); <<"registeredusers">> -> lists:foldl(fun(Host, Sum) -> ejabberd_auth:get_vh_registered_users_number(Host) + Sum end, 0, ?MYHOSTS); <<"onlineusersnode">> -> length(ejabberd_sm:dirty_get_my_sessions_list()); <<"onlineusers">> -> length(ejabberd_sm:dirty_get_sessions_list()) From b244bce49c0de9dbfa0f68befc57366c2011b652 Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Thu, 14 Jan 2016 23:10:01 +0900 Subject: [PATCH 484/695] don't escape ERL_OPTIONS --- ejabberdctl.template | 1 - 1 file changed, 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index f90f71e5345..33f8b0959fd 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -103,7 +103,6 @@ ERL_INETRC=$ETC_DIR/inetrc # define mnesia options MNESIA_OPTS="-mnesia dir \"\\\"$SPOOL_DIR\\\"\" $MNESIA_OPTIONS" # define erl parameters -ERL_OPTIONS=$(echo $ERL_OPTIONS | sed 's/ /\\ /g') ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" KERNEL_OPTS="" if [ "$FIREWALL_WINDOW" != "" ] ; then From ddaa409ee2aaa9a9402a33c59aacf3cd7d3e9bbb Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 15 Jan 2016 01:08:22 +0100 Subject: [PATCH 485/695] XEP-0198: Let MAM take care of pending messages If a stream management session times out for a user who appears to be using MAM, drop any unacknowledged messages rather than resending or bouncing them. This avoids duplicates or bogus error messages. However, this is only done if the new mod_mam option "assume_mam_usage" is set to 'if_enabled' or 'on_request'. In the former case, a user is assumed to be using MAM if archiving is enabled for his account. In the latter case, MAM usage is assumed only if archiving was explicitly requested by the client, or if archiving was enabled by means of mod_mam's "request_activates_archiving" option. --- src/ejabberd_c2s.erl | 11 ++++++++- src/mod_mam.erl | 59 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 0035ed6d183..021fb97397d 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2878,7 +2878,16 @@ handle_unacked_stanzas(StateData) ?DEBUG("Dropping forwarded message stanza from ~s", [xml:get_attr_s(<<"from">>, El#xmlel.attrs)]); false -> - ReRoute(From, To, El, Time) + case ejabberd_hooks:run_fold(message_is_archived, + StateData#state.server, + false, + [StateData, From, + StateData#state.jid, El]) of + true -> + ok; + false -> + ReRoute(From, To, El, Time) + end end end, handle_unacked_stanzas(StateData, F); diff --git a/src/mod_mam.erl b/src/mod_mam.erl index c20a941df71..f4943b3d286 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -36,7 +36,7 @@ -export([user_send_packet/4, user_receive_packet/5, process_iq_v0_2/3, process_iq_v0_3/3, disco_sm_features/5, remove_user/2, remove_user/3, mod_opt_type/1, muc_process_iq/4, - muc_filter_message/5, delete_old_messages/2]). + muc_filter_message/5, message_is_archived/5, delete_old_messages/2]). -include_lib("stdlib/include/ms_transform.hrl"). -include("jlib.hrl"). @@ -105,6 +105,17 @@ start(Host, Opts) -> remove_user, 50), ejabberd_hooks:add(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), + case gen_mod:get_opt(assume_mam_usage, Opts, + fun(if_enabled) -> if_enabled; + (on_request) -> on_request; + (never) -> never + end, never) of + never -> + ok; + _ -> + ejabberd_hooks:add(message_is_archived, Host, ?MODULE, + message_is_archived, 50) + end, ejabberd_commands:register_commands(commands()), ok. @@ -150,6 +161,17 @@ stop(Host) -> remove_user, 50), ejabberd_hooks:delete(anonymous_purge_hook, Host, ?MODULE, remove_user, 50), + case gen_mod:get_module_opt(Host, ?MODULE, assume_mam_usage, + fun(if_enabled) -> if_enabled; + (on_request) -> on_request; + (never) -> never + end, never) of + never -> + ok; + _ -> + ejabberd_hooks:delete(message_is_archived, Host, ?MODULE, + message_is_archived, 50) + end, ejabberd_commands:unregister_commands(commands()), ok. @@ -307,6 +329,34 @@ disco_sm_features({result, OtherFeatures}, disco_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. +message_is_archived(true, _C2SState, _Peer, _JID, _Pkt) -> + true; +message_is_archived(false, C2SState, Peer, + #jid{luser = LUser, lserver = LServer}, Pkt) -> + Res = case gen_mod:get_module_opt(LServer, ?MODULE, assume_mam_usage, + fun(if_enabled) -> if_enabled; + (on_request) -> on_request; + (never) -> never + end, never) of + if_enabled -> + get_prefs(LUser, LServer); + on_request -> + DBType = gen_mod:db_type(LServer, ?MODULE), + cache_tab:lookup(archive_prefs, {LUser, LServer}, + fun() -> + get_prefs(LUser, LServer, DBType) + end); + never -> + error + end, + case Res of + {ok, Prefs} -> + should_archive(strip_my_archived_tag(Pkt, LServer), LServer) + andalso should_archive_peer(C2SState, Prefs, Peer); + error -> + false + end. + delete_old_messages(TypeBin, Days) when TypeBin == <<"chat">>; TypeBin == <<"groupchat">>; TypeBin == <<"all">> -> @@ -1318,6 +1368,11 @@ commands() -> args = [{type, binary}, {days, integer}], result = {res, rescode}}]. +mod_opt_type(assume_mam_usage) -> + fun(if_enabled) -> if_enabled; + (on_request) -> on_request; + (never) -> never + end; mod_opt_type(cache_life_time) -> fun (I) when is_integer(I), I > 0 -> I end; mod_opt_type(cache_size) -> @@ -1334,5 +1389,5 @@ mod_opt_type(request_activates_archiving) -> mod_opt_type(store_body_only) -> fun (B) when is_boolean(B) -> B end; mod_opt_type(_) -> - [cache_life_time, cache_size, db_type, default, iqdisc, + [assume_mam_usage, cache_life_time, cache_size, db_type, default, iqdisc, request_activates_archiving, store_body_only]. From fc1237963a80d0e2de2e4cda070a3b38b9dbacf4 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 15 Jan 2016 10:40:49 +0100 Subject: [PATCH 486/695] Update translations files --- priv/msgs/ca.po | 54 ++++++++++++++++++++-------------------- priv/msgs/cs.po | 54 ++++++++++++++++++++-------------------- priv/msgs/de.po | 54 ++++++++++++++++++++-------------------- priv/msgs/ejabberd.pot | 56 +++++++++++++++++++++--------------------- priv/msgs/el.po | 54 ++++++++++++++++++++-------------------- priv/msgs/eo.po | 54 ++++++++++++++++++++-------------------- priv/msgs/es.po | 54 ++++++++++++++++++++-------------------- priv/msgs/fr.po | 54 ++++++++++++++++++++-------------------- priv/msgs/gl.po | 54 ++++++++++++++++++++-------------------- priv/msgs/he.msg | 13 ++++++++-- priv/msgs/he.po | 51 +++++++++++++++++++------------------- priv/msgs/id.po | 54 ++++++++++++++++++++-------------------- priv/msgs/it.po | 54 ++++++++++++++++++++-------------------- priv/msgs/ja.po | 54 ++++++++++++++++++++-------------------- priv/msgs/nl.po | 54 ++++++++++++++++++++-------------------- priv/msgs/no.po | 54 ++++++++++++++++++++-------------------- priv/msgs/pl.po | 54 ++++++++++++++++++++-------------------- priv/msgs/pt-br.po | 54 ++++++++++++++++++++-------------------- priv/msgs/pt.po | 54 ++++++++++++++++++++-------------------- priv/msgs/ru.po | 54 ++++++++++++++++++++-------------------- priv/msgs/sk.po | 54 ++++++++++++++++++++-------------------- priv/msgs/sv.po | 54 ++++++++++++++++++++-------------------- priv/msgs/th.po | 54 ++++++++++++++++++++-------------------- priv/msgs/tr.po | 54 ++++++++++++++++++++-------------------- priv/msgs/uk.po | 54 ++++++++++++++++++++-------------------- priv/msgs/vi.po | 54 ++++++++++++++++++++-------------------- priv/msgs/wa.po | 54 ++++++++++++++++++++-------------------- priv/msgs/zh.po | 54 ++++++++++++++++++++-------------------- 28 files changed, 740 insertions(+), 730 deletions(-) diff --git a/priv/msgs/ca.po b/priv/msgs/ca.po index 519d7a09a92..575ba7e2316 100644 --- a/priv/msgs/ca.po +++ b/priv/msgs/ca.po @@ -32,13 +32,13 @@ msgstr "Reemplaçat per una nova connexió" msgid "has been kicked" msgstr "Has sigut expulsat" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" "La teva llista de privacitat activa ha denegat l'encaminament d'aquesta " "stanza." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Massa missatges sense haver reconegut la seva recepció" @@ -849,11 +849,11 @@ msgstr "" "Massa autenticacions (~p) han fallat des d'aquesta adreça IP (~s). L'adreça " "serà desbloquejada en ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -973,9 +973,9 @@ msgstr "Codificació pel servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Només els moderadors poden canviar l'assumpte d'aquesta sala" #: mod_muc.erl:585 @@ -996,37 +996,37 @@ msgstr "La sala de conferències no existeix" msgid "Chatrooms" msgstr "Sales de xat" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necessites un client amb suport x:data per a poder registrar el sobrenom" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registre del sobrenom en " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Introdueix el sobrenom que vols registrar" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Sobrenom" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "El nickname ja està registrat per una altra persona" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Deus d'omplir el camp \"Nickname\" al formulari" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "mòdul ejabberd MUC" @@ -1193,8 +1193,8 @@ msgstr "El llímit de tràfic ha sigut sobrepassat" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1233,7 +1233,7 @@ msgstr "El receptor no està en la sala de conferència" msgid "It is not allowed to send private messages" msgstr "No està permés enviar missatges privats" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Sols els ocupants poden enviar missatges a la sala" @@ -1317,7 +1317,7 @@ msgstr "Afiliació invàlida: ~s" msgid "Invalid role: ~s" msgstr "Rol invàlid: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Es requerixen privilegis de propietari de la sala" @@ -1329,7 +1329,7 @@ msgstr "Configuració de la sala ~s" msgid "Room title" msgstr "Títol de la sala" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Descripció de la sala:" @@ -1460,35 +1460,35 @@ msgstr "Habilitar el registre de la conversa" msgid "You need an x:data capable client to configure room" msgstr "Necessites un client amb suport x:data per a configurar la sala" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Número d'ocupants" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privat" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Petició de veu" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Aprova o denega la petició de veu" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "JID del usuari " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Concedir veu a aquesta persona?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s et convida a la sala ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "la contrasenya és" diff --git a/priv/msgs/cs.po b/priv/msgs/cs.po index 3055b4fb3b3..352989084da 100644 --- a/priv/msgs/cs.po +++ b/priv/msgs/cs.po @@ -25,11 +25,11 @@ msgstr "Nahrazeno novým spojením" msgid "has been kicked" msgstr "byl(a) vyhozen(a) z místnosti" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Vaše nastavení soukromí znemožnilo směrování této stance." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -841,11 +841,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -962,9 +962,9 @@ msgstr "Kódování pro server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Jen moderátoři mají povoleno měnit téma místnosti" #: mod_muc.erl:585 @@ -983,36 +983,36 @@ msgstr "Konferenční místnost neexistuje" msgid "Chatrooms" msgstr "Konference" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Pro registraci přezdívky potřebujete klienta s podporou x:data" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registrace přezdívky na " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Zadejte přezdívku, kterou chcete zaregistrovat" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Přezdívka" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Přezdívka je zaregistrována jinou osobou" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Musíte vyplnit políčko \"Přezdívka\" ve formuláři" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -1182,8 +1182,8 @@ msgstr "Byl překročen limit" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1222,7 +1222,7 @@ msgstr "Příjemce se nenachází v konferenční místnosti" msgid "It is not allowed to send private messages" msgstr "Je zakázáno posílat soukromé zprávy" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Jen členové mají povolené zasílat zprávy do konference" @@ -1305,7 +1305,7 @@ msgstr "Neplatné přiřazení: ~s" msgid "Invalid role: ~s" msgstr "Neplatná role: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Jsou vyžadována práva vlastníka" @@ -1317,7 +1317,7 @@ msgstr "Konfigurace místnosti ~s" msgid "Room title" msgstr "Název místnosti" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Popis místnosti" @@ -1446,35 +1446,35 @@ msgstr "Zaznamenávat konverzace" msgid "You need an x:data capable client to configure room" msgstr "Ke konfiguraci místnosti potřebujete klienta podporujícího x:data" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Počet účastníků" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "soukromá, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Žádost o voice práva" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Povolit nebo odmítnout voice žádost." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Jabber ID uživatele" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Udělit voice práva této osobě?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s vás zve do místnosti ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "heslo je" diff --git a/priv/msgs/de.po b/priv/msgs/de.po index d8ad2b59b96..4f3d2a370de 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -35,12 +35,12 @@ msgstr "Durch neue Verbindung ersetzt" msgid "has been kicked" msgstr "wurde entfernt" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" "Ihre aktive Privacy Liste hat die Weiterleitung des Stanzas unterbunden." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Zu viele unbestätigte Stanzas" @@ -853,11 +853,11 @@ msgstr "" "Zu viele (~p) fehlgeschlagene Anmeldeversuche von dieser IP Adresse (~s). " "Die Adresse wird bis ~s UTC blockiert." -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -977,9 +977,9 @@ msgstr "Kodierung für Server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Nur Moderatoren dürfen das Thema in diesem Raum ändern" #: mod_muc.erl:585 @@ -999,38 +999,38 @@ msgstr "Konferenzraum existiert nicht" msgid "Chatrooms" msgstr "Chaträume" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um Ihren Benutzernamen " "zu registrieren" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registrieren des Benutzernames auf" -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Geben sie den zu registrierenden Benutzernamen ein" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Benutzername" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Dieser Benutzername wurde bereits von jemand anderem registriert" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Sie müssen das Feld \"Benutzername\" ausfüllen" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC-Modul" @@ -1197,8 +1197,8 @@ msgstr "Datenratenlimit wurde überschritten" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1241,7 +1241,7 @@ msgstr "Der Empfänger ist nicht im Raum" msgid "It is not allowed to send private messages" msgstr "Es ist nicht erlaubt private Nachrichten zu senden" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Nur Teilnehmer dürfen Nachrichten an den Raum schicken" @@ -1323,7 +1323,7 @@ msgstr "Ungültige Mitgliedschaft: ~s" msgid "Invalid role: ~s" msgstr "Ungültige Rolle: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Besitzerrechte benötigt" @@ -1335,7 +1335,7 @@ msgstr "Konfiguration für Raum ~s" msgid "Room title" msgstr "Raumname" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Raum Beschreibung" @@ -1466,35 +1466,35 @@ msgstr "" "Sie benötigen einen Client, der x:data unterstützt, um den Raum zu " "konfigurieren" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Anzahl der Teilnehmer" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Anfrage für Sprachrechte" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Diese Anfrage für Sprachrechte bestätigen oder ablehnen." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Benutzer JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Sprachrechte dieser Person erteilen?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s lädt sie in den Raum ~s ein" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "das Passwort lautet" diff --git a/priv/msgs/ejabberd.pot b/priv/msgs/ejabberd.pot index 7f903ffd94b..c62ee20b1ec 100644 --- a/priv/msgs/ejabberd.pot +++ b/priv/msgs/ejabberd.pot @@ -1,6 +1,6 @@ msgid "" msgstr "" -"Project-Id-Version: 15.11.117\n" +"Project-Id-Version: 15.11.127\n" "X-Language: Language Name\n" "Last-Translator: Translator name and contact method\n" "MIME-Version: 1.0\n" @@ -24,11 +24,11 @@ msgstr "" msgid "has been kicked" msgstr "" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -826,11 +826,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -937,8 +937,8 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_mam.erl:270 -msgid "Only members are allowed to query archives of this room" +#: mod_mam.erl:541 +msgid "Only members may query archives of this room" msgstr "" #: mod_muc.erl:585 @@ -957,36 +957,36 @@ msgstr "" msgid "Chatrooms" msgstr "" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "" -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "" @@ -1153,8 +1153,8 @@ msgstr "" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1193,7 +1193,7 @@ msgstr "" msgid "It is not allowed to send private messages" msgstr "" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "" @@ -1275,7 +1275,7 @@ msgstr "" msgid "Invalid role: ~s" msgstr "" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "" @@ -1287,7 +1287,7 @@ msgstr "" msgid "Room title" msgstr "" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "" @@ -1415,35 +1415,35 @@ msgstr "" msgid "You need an x:data capable client to configure room" msgstr "" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "" diff --git a/priv/msgs/el.po b/priv/msgs/el.po index 28db8614aa3..b97ac1d54b8 100644 --- a/priv/msgs/el.po +++ b/priv/msgs/el.po @@ -28,13 +28,13 @@ msgstr "Αντικαταστάθικε από νέα σύνδεση" msgid "has been kicked" msgstr "αποβλήθηκε " -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" "Ο ενεργός κατάλογος απορρήτου, έχει αρνηθεί τη δρομολόγηση αυτής της στροφής " "(stanza)." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -859,11 +859,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -983,9 +983,9 @@ msgstr "Κωδικοποίηση για διακομιστή ~b" msgid "Server ~b" msgstr "Διακομιστής ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Μόνο οι συντονιστές μπορούν να αλλάξουν το θέμα αυτής της αίθουσας" #: mod_muc.erl:585 @@ -1006,36 +1006,36 @@ msgstr "Αίθουσα σύνεδριασης δεν υπάρχει" msgid "Chatrooms" msgstr "Αίθουσες σύνεδριασης" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για εγγραφή με ψευδώνυμο" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Εγγραφή με Ψευδώνυμο στο " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Πληκτρολογήστε το ψευδώνυμο που θέλετε να εγγραφείτε" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Ψευδώνυμο" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Αυτό το ψευδώνυμο είναι καταχωρημένο από άλλο πρόσωπο" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Θα πρέπει να συμπληρώσετε το πεδίο \"Ψευδώνυμο\" στη φόρμα" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC module" @@ -1205,8 +1205,8 @@ msgstr "Υπέρφορτωση" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1245,7 +1245,7 @@ msgstr "Παραλήπτης δεν είναι στην αίθουσα συνε msgid "It is not allowed to send private messages" msgstr "Δεν επιτρέπεται η αποστολή προσωπικών μηνυμάτων" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Μόνο οι συμμετέχωντες μπορούν να στέλνουν μηνύματα στο συνέδριο" @@ -1334,7 +1334,7 @@ msgstr "Άκυρη υπαγωγή: ~s" msgid "Invalid role: ~s" msgstr "Άκυρος ρόλο: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Aπαιτούνται προνόμια ιδιοκτήτη" @@ -1346,7 +1346,7 @@ msgstr "Διαμόρφωση Αίθουσας σύνεδριασης ~s" msgid "Room title" msgstr "Τίτλος Αίθουσας " -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Περιγραφή Αίθουσας" @@ -1477,35 +1477,35 @@ msgstr "Ενεργοποίηση καταγραφής" msgid "You need an x:data capable client to configure room" msgstr "Χρειάζεστε ένα x:data ικανό πελάτη για να ρυθμίσετε την αίθουσα " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Αριθμός συμετεχόντων" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "ιδιωτικό," -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Αίτημα φωνής" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Είτε εγκρίνετε ή απορρίψτε το αίτημα φωνής." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "JID Χρήστη" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Παραχώρηση φωνής σε αυτό το άτομο;" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s σας προσκαλεί στην αίθουσα ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "ο κωδικός πρόσβασης είναι" diff --git a/priv/msgs/eo.po b/priv/msgs/eo.po index fd5e5fb68ce..0662768fcdb 100644 --- a/priv/msgs/eo.po +++ b/priv/msgs/eo.po @@ -29,11 +29,11 @@ msgstr "Anstataŭigita je nova konekto" msgid "has been kicked" msgstr "estas forpelita" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Via aktiva privatec-listo malpermesas enkursigi ĉi-tiun pakaĵon" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Tro da neagnoskitaj stancoj" @@ -840,11 +840,11 @@ msgstr "" "Tro da malsukcesaj aŭtentprovoj (~p) de ĉi tiu IP-adreso (~s). La adreso " "estos malbarata je ~s UTC." -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -962,9 +962,9 @@ msgstr "Enkodigo por servilo ~b" msgid "Server ~b" msgstr "Servilo ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Nur moderigantoj rajtas ŝanĝi la temon en ĉi tiu babilejo" #: mod_muc.erl:585 @@ -983,36 +983,36 @@ msgstr "Babilejo ne ekzistas" msgid "Chatrooms" msgstr "Babilejoj" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Vi bezonas klienton subtenante x:data-funkcio por registri kaŝnomon" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Kaŝnomo-registrado je " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Enmetu kaŝnomon kiun vi volas registri" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Kaŝnomo" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Kaŝnomo estas registrita de alia persono" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Vi devas kompletigi la \"Kaŝnomo\" kampon" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC-modulo" @@ -1179,8 +1179,8 @@ msgstr "Trafikrapida limigo superita" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1219,7 +1219,7 @@ msgstr "Ricevanto ne ĉeestas en la babilejo " msgid "It is not allowed to send private messages" msgstr "Ne estas permesata sendi privatajn mesaĝojn" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Nur partoprenantoj rajtas sendi mesaĝojn al la babilejo" @@ -1303,7 +1303,7 @@ msgstr "Nevalida aparteneco: ~s" msgid "Invalid role: ~s" msgstr "Nevalida rolo: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Mastraj rajtoj bezonata" @@ -1315,7 +1315,7 @@ msgstr "Agordo de babilejo ~s" msgid "Room title" msgstr "Babilejo-nomo" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Babilejo-priskribo" @@ -1444,35 +1444,35 @@ msgstr "Ŝaltu protokoladon" msgid "You need an x:data capable client to configure room" msgstr "Vi bezonas klienton kun x:data-funkcio por agordi la babilejon" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Nombro de ĉeestantoj" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privata, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Voĉ-peto" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Ĉu aprobu, aŭ malaprobu la voĉ-peton." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Uzant-JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Koncedu voĉon al ĉi-persono?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s invitas vin al la babilejo ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "la pasvorto estas" diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 43c9454bc26..34b21f76d95 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -31,11 +31,11 @@ msgstr "Reemplazado por una nueva conexión" msgid "has been kicked" msgstr "ha sido expulsado" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Tu lista de privacidad activa ha denegado el encío de este paquete." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Demasiados mensajes sin haber reconocido recibirlos" @@ -848,11 +848,11 @@ msgstr "" "Demasiadas (~p) autenticaciones fallidas de esta dirección IP (~s). La " "dirección será desbloqueada en ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -972,9 +972,9 @@ msgstr "Codificación del servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" #: mod_muc.erl:585 @@ -995,37 +995,37 @@ msgstr "La sala de conferencias no existe" msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder registrar el apodo" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registro del apodo en " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Introduce el apodo que quieras registrar" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Apodo" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "El apodo ya está registrado por otra persona" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Debes rellenar el campo \"Apodo\" en el formulario" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" @@ -1192,8 +1192,8 @@ msgstr "Se ha exedido el límite de tráfico" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1232,7 +1232,7 @@ msgstr "El receptor no está en la sala de conferencia" msgid "It is not allowed to send private messages" msgstr "No está permitido enviar mensajes privados" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Solo los ocupantes pueden enviar mensajes a la sala" @@ -1315,7 +1315,7 @@ msgstr "Afiliación no válida: ~s" msgid "Invalid role: ~s" msgstr "Rol no válido: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Se requieren privilegios de propietario de la sala" @@ -1327,7 +1327,7 @@ msgstr "Configuración para la sala ~s" msgid "Room title" msgstr "Título de la sala" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Descripción de la sala" @@ -1458,35 +1458,35 @@ msgstr "Guardar históricos" msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar la sala" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Petición de voz" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Aprueba o rechaza la petición de voz." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Jabber ID del usuario" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "¿Conceder voz a esta persona?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s te invita a la sala ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "la contraseña es" diff --git a/priv/msgs/fr.po b/priv/msgs/fr.po index f3a58099db9..47a1377e824 100644 --- a/priv/msgs/fr.po +++ b/priv/msgs/fr.po @@ -32,11 +32,11 @@ msgstr "Remplacé par une nouvelle connexion" msgid "has been kicked" msgstr "a été expulsé" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Votre règle de flitrage active a empêché le routage de ce stanza." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Trop de stanzas sans accusé de réception (ack)" @@ -852,11 +852,11 @@ msgstr "" "Trop (~p) d'authentification ont échoué pour cette adresse IP (~s). " "L'adresse sera débloquée à ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -975,9 +975,9 @@ msgstr "Codage pour le serveur ~b" msgid "Server ~b" msgstr "Serveur ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Seuls les modérateurs peuvent changer le sujet dans ce salon" #: mod_muc.erl:585 @@ -998,38 +998,38 @@ msgstr "La salle de conférence n'existe pas" msgid "Chatrooms" msgstr "Salons de discussion" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Vous avez besoin d'un client prenant en charge x:data pour enregistrer un " "pseudo" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Enregistrement d'un pseudo sur " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Entrez le pseudo que vous souhaitez enregistrer" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Pseudo" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Le pseudo est enregistré par une autre personne" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Vous devez préciser le champ \"pseudo\" dans le formulaire" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Module MUC ejabberd" @@ -1196,8 +1196,8 @@ msgstr "La limite de trafic a été dépassée" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1238,7 +1238,7 @@ msgstr "Le destinataire n'est pas dans la conférence" msgid "It is not allowed to send private messages" msgstr "L'envoi de messages privés n'est pas autorisé" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Seuls les occupants peuvent envoyer des messages à la conférence" @@ -1327,7 +1327,7 @@ msgstr "Affiliation invalide : ~s" msgid "Invalid role: ~s" msgstr "Role invalide : ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Les droits de propriétaire sont nécessaires" @@ -1339,7 +1339,7 @@ msgstr "Configuration pour le salon ~s" msgid "Room title" msgstr "Titre du salon" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Description :" @@ -1470,35 +1470,35 @@ msgid "You need an x:data capable client to configure room" msgstr "" "Vous avez besoin d'un client supportant x:data pour configurer le salon" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Nombre d'occupants" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privé" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Demande de 'voice'" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Approuver ou refuser la demande de 'voice'" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "JID de l'utilisateur " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Accorder 'voice' à cet utilisateur" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s vous a invité dans la salle de discussion ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "le mot de passe est" diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index c5cfabc003b..7a8b27dcf1e 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -24,11 +24,11 @@ msgstr "Substituído por unha nova conexión" msgid "has been kicked" msgstr "foi expulsado" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -845,11 +845,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -969,9 +969,9 @@ msgstr "Codificación de servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Só os moderadores están autorizados a cambiar o tema nesta sala" #: mod_muc.erl:585 @@ -992,38 +992,38 @@ msgstr "A sala de conferencias non existe" msgid "Chatrooms" msgstr "Salas de charla" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Rexistro do alcume en " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Introduce o alcume que queiras rexistrar" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Alcume" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "O alcume xa está rexistrado por outra persoa" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Debes encher o campo \"Alcumo\" no formulario" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" @@ -1197,8 +1197,8 @@ msgstr "Hase exedido o límite de tráfico" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1238,7 +1238,7 @@ msgstr "O receptor non está na sala de conferencia" msgid "It is not allowed to send private messages" msgstr "Non está permitido enviar mensaxes privadas" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Só os ocupantes poden enviar mensaxes á sala" @@ -1324,7 +1324,7 @@ msgstr "Afiliación non válida: ~s" msgid "Invalid role: ~s" msgstr "Rol non válido: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Requírense privilexios de propietario da sala" @@ -1336,7 +1336,7 @@ msgstr "Configuración para a sala ~s" msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Descrición da sala" @@ -1468,36 +1468,36 @@ msgstr "Gardar históricos" msgid "You need an x:data capable client to configure room" msgstr "Necesitas un cliente con soporte de x:data para configurar a sala" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Número de ocupantes" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Usuario " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s invítache á sala ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "a contrasinal é" diff --git a/priv/msgs/he.msg b/priv/msgs/he.msg index 286fdd4fe00..2fa51b74b6f 100644 --- a/priv/msgs/he.msg +++ b/priv/msgs/he.msg @@ -88,6 +88,7 @@ {"ejabberd Web Admin","מנהל רשת ejabberd"}. {"Elements","אלמנטים"}. {"Email","דוא״ל"}. +{"Empty Rooms","חדרים ריקים"}. {"Enable logging","אפשר רישום פעילות"}. {"Enable message archiving","אפשר אחסון הודעות"}. {"Encoding for server ~b","קידוד עבור שרת ~b"}. @@ -143,6 +144,7 @@ {"Import Users from Dir at ","ייבוא משתמשים מתוך מדור אצל "}. {"Import Users From jabberd14 Spool Files","יבא משתמשים מתוך קבצי סליל (Spool Files) של jabberd14"}. {"Improper message type","טיפוס הודעה לא מתאים"}. +{"Incoming s2s Connections:","חיבורי s2s נכנסים:"}. {"Incorrect password","מילת מעבר שגויה"}. {"Invalid affiliation: ~s","סינוף שגוי: ~s"}. {"Invalid role: ~s","תפקיד שגוי: ~s"}. @@ -155,8 +157,9 @@ {"IRC username","שם משתמש IRC"}. {"IRC Username","שם משתמש IRC"}. {"is now known as","ידועה כעת בכינוי"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","אין זה מותר לשלוח הודעות שגיאה לחדר. משתתף זה (~s) שלח הודעת שגיאה (~s) ונבעט מתוך החדר"}. {"It is not allowed to send private messages of type \"groupchat\"","אין זה מותר לשלוח הודעות פרטיות מן טיפוס \"groupchat\""}. -{"It is not allowed to send private messages to the conference","אין זה מותר לשלוח הודעות פרטיות אל הועידה"}. +{"It is not allowed to send private messages to the conference","אין זה מותר לשלוח הודעות פרטיות לועידה"}. {"It is not allowed to send private messages","אין זה מותר לשלוח הודעות פרטיות"}. {"Jabber Account Registration","רישום חשבון Jabber"}. {"Jabber ID ~s is invalid","מזהה Jabber ‏~s הינו שגוי"}. @@ -199,6 +202,7 @@ {"Minimum interval between voice requests (in seconds)","תדירות מינימלית בין בקשות ביטוי (בשניות)"}. {"Moderator privileges required","נדרשות הרשאות אחראי"}. {"moderators only","לאחראים בלבד"}. +{"Moderator","אחראי"}. {"Modified modules","מודולים שהותאמו"}. {"Modules at ~p","מודולים אצל ~p"}. {"Modules","מודולים"}. @@ -253,6 +257,7 @@ {"Outgoing s2s Connections","חיבורי s2s יוצאים"}. {"Owner privileges required","נדרשות הרשאות בעלים"}. {"Packet","חבילת מידע"}. +{"Participant","משתתף"}. {"Password ~b","סיסמה ~b"}. {"Password Verification:","אימות סיסמה:"}. {"Password Verification","אימות סיסמה"}. @@ -266,6 +271,8 @@ {"Persist items to storage","פריטים קבועים לאחסון"}. {"Ping","פינג"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","אנא שים לב כי אפשרויות אלו יגבו את מסד הנתונים המובנה Mnesia בלבד. אם הינך עושה שימוש במודול ODBC, עליך גם לגבות את מסד הנתונים SQL אשר מצוי ברשותך בנפרד."}. +{"Please specify file name.","אנא ציין שם קובץ."}. +{"Please specify file size.","אנא ציין גודל קובץ."}. {"Please, wait for a while before sending new voice request","אנא, המתן לזמן מה לפני שליחת בקשת ביטוי חדשה"}. {"Pong","פונג"}. {"Port ~b","פורט ~b"}. @@ -301,6 +308,7 @@ {"Restore binary backup immediately:","שחזר גיבוי בינארי לאלתר:"}. {"Restore plain text backup immediately:","שחזר גיבוי טקסט גלוי (plain text) לאלתר:"}. {"Restore","שחזר"}. +{"Roles for which Presence is Broadcasted","תפקידים להם נוכחות הינה משודרת"}. {"Room Configuration","תצורת חדר"}. {"Room creation is denied by service policy","יצירת חדר נדחתה על ידי פוליסת שירות"}. {"Room description","תיאור חדר"}. @@ -332,7 +340,7 @@ {"Show Ordinary Table","הצג טבלה רגילה"}. {"Shut Down Service","כבה שירות"}. {"~s invites you to the room ~s","‫~s מזמינך לחדר ~s"}. -{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","לקוחות Jabber מסוימים יכולים לאחסן את הסיסמה שלך על המחשב שלך. השתמש בתכונה זו רק אם אתה סמוך כי המחשב שלך הינו מוגן."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","ישנם לקוחות Jabber אשר מסוגלים לאחסן את הסיסמה שלך בתוך המחשב, אולם עליך לעשות זאת רק בתוך המחשב האישי שלך מסיבות ביטחוניות."}. {"Specify the access model","ציין מודל גישה"}. {"Specify the event message type","ציין טיפוס הודעת אירוע"}. {"Specify the publisher model","ציין מודל פרסום"}. @@ -410,6 +418,7 @@ {"Virtual Hosts","מארחים מדומים"}. {"Visitors are not allowed to change their nicknames in this room","מבקרים אינם מורשים לשנות את שמות הכינויים שלהם בחדר זה"}. {"Visitors are not allowed to send messages to all occupants","מבקרים אינם מורשים לשלוח הודעות אל כל הנוכחים"}. +{"Visitor","מבקר"}. {"Voice requests are disabled in this conference","בקשות ביטוי מנוטרלות בועידה זו"}. {"Voice request","בקשת ביטוי"}. {"Wednesday","יום רביעי"}. diff --git a/priv/msgs/he.po b/priv/msgs/he.po index 1390d15dd7c..e048826ee18 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -32,11 +32,11 @@ msgstr "הוחלף בחיבור חדש" msgid "has been kicked" msgstr "נבעט/ה" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "רשימת הפרטיות הפעילה שלך אסרה את הניתוב של סטנזה זו." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "יותר מדי סטנזות בלי אישורי קבלה" @@ -852,11 +852,11 @@ msgstr "" "יותר מדי (~p) אימותים כושלים מתוך כתובת IP זו (~s). הכתובת תורשה לקבל גישה " "בשעה ~s UTC" -#: mod_http_upload.erl:587 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "אנא ציין גודל קובץ." -#: mod_http_upload.erl:591 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "אנא ציין שם קובץ." @@ -974,8 +974,9 @@ msgstr "קידוד עבור שרת ~b" msgid "Server ~b" msgstr "שרת ~b" -#: mod_mam.erl:270 -msgid "Only members are allowed to query archives of this room" +#: mod_mam.erl:541 +#, fuzzy +msgid "Only members may query archives of this room" msgstr "רק חברים רשאים לתשאל ארכיונים של חדר זה" #: mod_muc.erl:585 @@ -994,38 +995,38 @@ msgstr "חדר ועידה לא קיים" msgid "Chatrooms" msgstr "חדרי שיחה" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "חדרים ריקים" # to register nickname -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "עליך להשתמש בלקוח אשר תומך x:data כדי לרשום את השם כינוי" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "רישום שם כינוי אצל " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "הזן שם כינוי אשר ברצונך לרשום" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "שם כינוי" # note: another person > someone else -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "שם כינוי זה הינו רשום על ידי מישהו אחר" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "עליך למלא את השדה \"שם כינוי\" בתוך התבנית" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "מודול MUC של ejabberd" @@ -1237,7 +1238,7 @@ msgstr "מקבל אינו מצוי בחדר הועידה" msgid "It is not allowed to send private messages" msgstr "אין זה מותר לשלוח הודעות פרטיות" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "רק נוכחים רשאים לשלוח הודעות אל הועידה" @@ -1321,7 +1322,7 @@ msgstr "סינוף שגוי: ~s" msgid "Invalid role: ~s" msgstr "תפקיד שגוי: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "נדרשות הרשאות בעלים" @@ -1334,7 +1335,7 @@ msgstr "תצורת חדר ~s" msgid "Room title" msgstr "כותרת חדר" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "תיאור חדר" @@ -1462,35 +1463,35 @@ msgstr "אפשר רישום פעילות" msgid "You need an x:data capable client to configure room" msgstr "עליך להשתמש בלקוח אשר מסוגל להבין x:data כדי להגדיר חדר" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "מספר של נוכחים" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "פרטי, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "בקשת ביטוי" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "אשר או דחה בקשת ביטוי." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "‏JID משתמש" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "להעניק ביטוי לאישיות זו?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "‫~s מזמינך לחדר ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "הסיסמה היא" diff --git a/priv/msgs/id.po b/priv/msgs/id.po index bd774603922..5ec25466338 100644 --- a/priv/msgs/id.po +++ b/priv/msgs/id.po @@ -28,11 +28,11 @@ msgstr "Diganti dengan koneksi baru" msgid "has been kicked" msgstr "telah dikick" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Daftar privasi aktif Anda telah menolak routing ztanza ini" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -848,11 +848,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -971,9 +971,9 @@ msgstr "Pengkodean untuk layanan ~b" msgid "Server ~b" msgstr "Layanan ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "" "Hanya moderator yang diperbolehkan untuk mengubah topik dalam ruangan ini" @@ -995,36 +995,36 @@ msgstr "Ruang Konferensi tidak ada" msgid "Chatrooms" msgstr "Ruangan Chat" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Anda memerlukan klien yang mendukung x:data untuk mendaftar julukan" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Pendaftaran Julukan pada" -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Masukkan nama julukan Anda jika ingin mendaftar" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Nama Julukan" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Julukan tersebut telah didaftarkan oleh orang lain" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Anda harus mengisi kolom \"Julukan\" dalam formulir" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC Module" @@ -1194,8 +1194,8 @@ msgstr "Lalu lintas melebihi batas" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1236,7 +1236,7 @@ msgstr "Penerima tidak berada di ruangan konferensi" msgid "It is not allowed to send private messages" msgstr "Hal ini tidak diperbolehkan untuk mengirim pesan pribadi" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Hanya penghuni yang diizinkan untuk mengirim pesan ke konferensi" @@ -1322,7 +1322,7 @@ msgstr "Afiliasi tidak valid: ~s" msgid "Invalid role: ~s" msgstr "Peran tidak valid: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Hak istimewa owner dibutuhkan" @@ -1334,7 +1334,7 @@ msgstr "Pengaturan ruangan ~s" msgid "Room title" msgstr "Nama Ruangan" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Keterangan ruangan" @@ -1465,36 +1465,36 @@ msgstr "Aktifkan catatan" msgid "You need an x:data capable client to configure room" msgstr "Anda memerlukan x:data klien untuk dapat mengkonfigurasi ruangan" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Jumlah Penghuni" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "pribadi, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Pengguna" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s mengundang anda ke ruangan ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "kata sandi yaitu:" diff --git a/priv/msgs/it.po b/priv/msgs/it.po index e69d6ed9095..d47248c6926 100644 --- a/priv/msgs/it.po +++ b/priv/msgs/it.po @@ -32,13 +32,13 @@ msgstr "Sostituito da una nuova connessione" msgid "has been kicked" msgstr "è stata/o espulsa/o" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" "In base alla tua attuale lista privacy questa stanza è stata esclusa dalla " "navigazione." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -854,11 +854,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -978,9 +978,9 @@ msgstr "Codifica per il server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "" "La modifica dell'oggetto di questa stanza è consentita soltanto ai moderatori" @@ -1002,36 +1002,36 @@ msgstr "La stanza per conferenze non esiste" msgid "Chatrooms" msgstr "Stanze" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Per registrare il nickname è necessario un client che supporti x:data" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registrazione di un nickname su " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Immettere il nickname che si vuole registrare" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Nickname" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Questo nickname è registrato da un'altra persona" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Si deve riempire il campo \"Nickname\" nel modulo" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Modulo MUC per ejabberd" @@ -1201,8 +1201,8 @@ msgstr "Limite di traffico superato" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1242,7 +1242,7 @@ msgstr "Il destinatario non è nella stanza per conferenze" msgid "It is not allowed to send private messages" msgstr "Non è consentito l'invio di messaggi privati" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "L'invio di messaggi alla conferenza è consentito soltanto ai presenti" @@ -1327,7 +1327,7 @@ msgstr "Affiliazione non valida: ~s" msgid "Invalid role: ~s" msgstr "Ruolo non valido: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Necessari i privilegi di proprietario" @@ -1339,7 +1339,7 @@ msgstr "Configurazione per la stanza ~s" msgid "Room title" msgstr "Titolo della stanza" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Descrizione della stanza" @@ -1471,35 +1471,35 @@ msgid "You need an x:data capable client to configure room" msgstr "" "Per la configurazione della stanza è necessario un client che supporti x:data" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Numero di presenti" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privato, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Richiesta di parola" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Approva oppure respingi la richiesta di parola." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "JID utente" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Dare parola a questa persona?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s ti invita nella stanza ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "la password è" diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index e405db64769..868f60ecd9f 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -27,11 +27,11 @@ msgstr "新しいコネクションによって置き換えられました" msgid "has been kicked" msgstr "はキックされました" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "あなたのプライバシーリストはこのスタンザのルーティングを拒否しました。" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "多くのスタンザが応答していません" @@ -839,11 +839,11 @@ msgid "" msgstr "" "~p回の認証に失敗しました。このIPアドレス(~s)は~s UTCまでブロックされます。" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -961,9 +961,9 @@ msgstr "サーバーのエンコーディング ~b" msgid "Server ~b" msgstr "サーバー ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "モデレーターのみがチャットルームの件名を変更できます" #: mod_muc.erl:585 @@ -982,36 +982,36 @@ msgstr "会議室は存在しません" msgid "Chatrooms" msgstr "チャットルーム" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "ニックネームを登録するには x:data をサポートするクライアントが必要です" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "ニックネーム登録: " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "登録するニックネームを入力してください" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "ニックネーム" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "ニックネームはほかの人によって登録されています" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "フォームの\"ニックネーム\"欄を入力する必要があります" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUCモジュール" @@ -1178,8 +1178,8 @@ msgstr "トラフィックレートの制限を超えました" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1219,7 +1219,7 @@ msgstr "受信者はこの会議室にいません" msgid "It is not allowed to send private messages" msgstr "プライベートメッセージを送信することはできません" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "在室者のみがこの会議にメッセージを送ることができます" @@ -1301,7 +1301,7 @@ msgstr "無効な分掌です: ~s" msgid "Invalid role: ~s" msgstr "無効な役です: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "主宰者の権限が必要です" @@ -1313,7 +1313,7 @@ msgstr "チャットルーム ~s の設定" msgid "Room title" msgstr "チャットルームのタイトル" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "チャットルームの説明" @@ -1443,35 +1443,35 @@ msgid "You need an x:data capable client to configure room" msgstr "" "チャットルームを設定するには x:data をサポートするクライアントが必要です" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "在室者の数" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "プライベート、" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "発言権を要求" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "発言権の要求を承認または却下します。" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "ユーザー JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "この人に発言権を与えますか ?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s はあなたをチャットルーム ~s に招待しています" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "パスワードは" diff --git a/priv/msgs/nl.po b/priv/msgs/nl.po index f707892ebf4..54a467d1ec1 100644 --- a/priv/msgs/nl.po +++ b/priv/msgs/nl.po @@ -30,11 +30,11 @@ msgstr "Vervangen door een nieuwe verbinding" msgid "has been kicked" msgstr "is weggestuurd" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Uw actieve privacy-lijst verbied het routeren van dit stanza." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Te veel niet-bevestigde stanzas" @@ -847,11 +847,11 @@ msgstr "" "Te veel (~p) mislukte authenticatie-pogingen van dit IP-adres (~s). Dit " "adres zal worden gedeblokkeerd om ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -971,9 +971,9 @@ msgstr "Karakterset voor server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Alleen moderators mogen het onderwerp van deze chatruimte veranderen" #: mod_muc.erl:585 @@ -996,37 +996,37 @@ msgstr "De chatruimte bestaat niet" msgid "Chatrooms" msgstr "Groepsgesprekken" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "U hebt een client nodig die x:data ondersteunt om een bijnaam te registreren" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registratie van een bijnaam op " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Voer de bijnaam in die u wilt registreren" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Bijnaam" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Deze bijnaam is al geregistreerd door iemand anders" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "U moet het veld \"bijnaam\" invullen" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd's MUC module" @@ -1195,8 +1195,8 @@ msgstr "Dataverkeerslimiet overschreden" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1236,7 +1236,7 @@ msgstr "De ontvanger is niet in de chatruimte" msgid "It is not allowed to send private messages" msgstr "Het is niet toegestaan priveberichten te sturen" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Alleen aanwezigen mogen berichten naar de chatruimte verzenden" @@ -1321,7 +1321,7 @@ msgstr "Ongeldige affiliatie: ~s" msgid "Invalid role: ~s" msgstr "Ongeldige rol: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "U hebt eigenaarsprivileges nodig" @@ -1333,7 +1333,7 @@ msgstr "Instellingen van chatruimte ~s" msgid "Room title" msgstr "Naam van de chatruimte" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Beschrijving" @@ -1464,35 +1464,35 @@ msgstr "" "U hebt een client nodig die x:data ondersteunt om deze chatruimte in te " "stellen" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Aantal aanwezigen" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Stemaanvraag" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Keur stemaanvraag goed of af." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "JID Gebruiker" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Stemaanvraag honoreren voor deze persoon?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s nodigt je uit voor het groepsgesprek ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "het wachtwoord is" diff --git a/priv/msgs/no.po b/priv/msgs/no.po index f3cfe7f338b..a90e029090c 100644 --- a/priv/msgs/no.po +++ b/priv/msgs/no.po @@ -28,11 +28,11 @@ msgstr "Erstattet av en ny tilkobling" msgid "has been kicked" msgstr "har blitt kastet ut" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Din aktive privat liste har blokkert rutingen av denne strofen." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -842,11 +842,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -964,9 +964,9 @@ msgstr "Tekstkoding for server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Bare ordstyrer tillates å endre emnet i dette rommet" #: mod_muc.erl:585 @@ -985,36 +985,36 @@ msgstr "Konferanserommet finnes ikke" msgid "Chatrooms" msgstr "Samtalerom" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Du trenger en klient som støtter x:data for å registrere kallenavnet" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registrer Kallenavn på " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Skriv inn kallenavnet du ønsker å registrere" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Kallenavn" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Det kallenavnet er registrert av en annen person" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Du må fylle inn feltet \"Nickname\" i skjemaet" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -1185,8 +1185,8 @@ msgstr "Trafikkmengde grense overskredet" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1225,7 +1225,7 @@ msgstr "Mottakeren er ikke i konferanserommet" msgid "It is not allowed to send private messages" msgstr "Det er ikke tillatt å sende private meldinger" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Bare deltakere får sende normale meldinger til konferansen" @@ -1307,7 +1307,7 @@ msgstr "Ugyldig rang: ~s" msgid "Invalid role: ~s" msgstr "Ugyldig rolle: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Eierprivilegier kreves" @@ -1319,7 +1319,7 @@ msgstr "Konfigurasjon for rom ~s" msgid "Room title" msgstr "Romtittel" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Rom beskrivelse" @@ -1448,35 +1448,35 @@ msgstr "Slå på logging" msgid "You need an x:data capable client to configure room" msgstr "Du trenger en klient som støtter x:data for å " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Antall deltakere" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Lyd forespørsel" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Enten godkjenn eller forby lyd forespørselen" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Bruker JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Gi lyd til denne personen?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s inviterer deg til rommet ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "passordet er" diff --git a/priv/msgs/pl.po b/priv/msgs/pl.po index 53273794316..53d7c45fb02 100644 --- a/priv/msgs/pl.po +++ b/priv/msgs/pl.po @@ -33,11 +33,11 @@ msgstr "Połączenie zostało zastąpione" msgid "has been kicked" msgstr "został wyrzucony" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Aktualna lista prywatności zabrania przesyłania tej stanzy" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Zbyt wiele niepotwierdzonych pakietów" @@ -851,11 +851,11 @@ msgstr "" "Zbyt wiele (~p) nieudanych prób logowanie z tego adresu IP (~s). Ten adres " "zostanie odblokowany o ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -973,9 +973,9 @@ msgstr "Kodowanie znaków dla serwera ~b" msgid "Server ~b" msgstr "Serwer ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Tylko moderatorzy mogą zmienić temat tego pokoju" #: mod_muc.erl:585 @@ -994,36 +994,36 @@ msgstr "Pokój konferencyjny nie istnieje" msgid "Chatrooms" msgstr "Pokoje rozmów" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Potrzebujesz klienta obsługującego x:data aby zarejestrować nick" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Rejestracja nazwy użytkownika na " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Wprowadz nazwę użytkownika którego chcesz zarejestrować" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Nazwa użytkownika" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Ta nazwa użytkownika jest już zarejestrowana przez inną osobę" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Musisz wypełnić pole \"Nazwa użytkownika\" w formularzu" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Moduł MUC" @@ -1190,8 +1190,8 @@ msgstr "Limit transferu przekroczony" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1230,7 +1230,7 @@ msgstr "Odbiorcy nie ma w pokoju" msgid "It is not allowed to send private messages" msgstr "Wysyłanie prywatnych wiadomości jest zabronione" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Tylko uczestnicy mogą wysyłać wiadomości na konferencję" @@ -1312,7 +1312,7 @@ msgstr "Nieprawidłowa przynależność: ~s" msgid "Invalid role: ~s" msgstr "Nieprawidłowa rola: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Wymagane uprawnienia właściciela" @@ -1324,7 +1324,7 @@ msgstr "Konfiguracja pokoju ~s" msgid "Room title" msgstr "Tytuł pokoju" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Opis pokoju" @@ -1453,35 +1453,35 @@ msgstr "Włącz logowanie" msgid "You need an x:data capable client to configure room" msgstr "Potrzebujesz klienta obsługującego x:data aby skonfigurować pokój" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Liczba uczestników" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "prywatny, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Żądanie głosowe" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Zatwierdź lub odrzuć żądanie głosowe" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Użytkownik " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Udzielić głosu tej osobie?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s zaprasza Cię do pokoju ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "hasło to:" diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index 9cdfe114f3b..ef1456655e7 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -28,11 +28,11 @@ msgstr "Substituído por nova conexão" msgid "has been kicked" msgstr "foi removido" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Sua lista de privacidade ativa negou o roteamento deste." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "número excessivo de instâncias sem confirmação" @@ -844,11 +844,11 @@ msgstr "" "Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço " "serádesbloqueado as ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -969,9 +969,9 @@ msgstr "Codificação para o servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Somente os moderadores podem alterar o assunto desta sala" #: mod_muc.erl:585 @@ -991,37 +991,37 @@ msgstr "La sala de conferencias não existe" msgid "Chatrooms" msgstr "Salas de Chat" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Você precisa de um cliente com suporte a x:data para registrar o seu apelido" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registro do apelido em " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Introduza o apelido que quer registrar" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Apelido" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "O nick já está registrado por outra pessoa" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Você deve completar o campo \"Apelido\" no formulário" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" @@ -1189,8 +1189,8 @@ msgstr "Limite de banda excedido" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1229,7 +1229,7 @@ msgstr "O receptor não está em la sala de conferencia" msgid "It is not allowed to send private messages" msgstr "Não é permitido enviar mensagens privadas" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Solo os ocupantes podem enviar mensagens a la sala" @@ -1313,7 +1313,7 @@ msgstr "Afiliação não válida: ~s" msgid "Invalid role: ~s" msgstr "Cargo (role) é não válido: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Se requere privilégios de proprietário da sala" @@ -1325,7 +1325,7 @@ msgstr "Configuração para ~s" msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Descrição da Sala" @@ -1454,35 +1454,35 @@ msgstr "Permitir criação de logs" msgid "You need an x:data capable client to configure room" msgstr "Necessitas um cliente com suporte de x:data para configurar la sala" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Número de participantes" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privado, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Requisição de voz" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Você deve aprovar/desaprovar a requisição de voz." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Usuário JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Dar 'voice' a esta usuário?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s convidou você para a sala ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "a senha é" diff --git a/priv/msgs/pt.po b/priv/msgs/pt.po index 7e239615b76..ab49665ed22 100644 --- a/priv/msgs/pt.po +++ b/priv/msgs/pt.po @@ -24,11 +24,11 @@ msgstr "" msgid "has been kicked" msgstr "" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -887,11 +887,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -1014,9 +1014,9 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Só os moderadores podem mudar o tópico desta sala" #: mod_muc.erl:585 @@ -1038,40 +1038,40 @@ msgstr "A sala não existe" msgid "Chatrooms" msgstr "" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "É necessário um cliente com suporte de x:data para poder registar a alcunha" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registo da alcunha em " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Introduza a alcunha que quer registar" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Alcunha" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 #, fuzzy msgid "That nickname is registered by another person" msgstr "A alcunha já está registada por outra pessoa" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 #, fuzzy msgid "You must fill in field \"Nickname\" in the form" msgstr "Deve preencher o campo \"alcunha\" no formulário" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Módulo MUC de ejabberd" @@ -1243,8 +1243,8 @@ msgstr "" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1285,7 +1285,7 @@ msgstr "O destinatário não está na sala" msgid "It is not allowed to send private messages" msgstr "Impedir o envio de mensagens privadas para a sala" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Só os ocupantes podem enviar mensagens para a sala" @@ -1373,7 +1373,7 @@ msgstr "Afiliação inválida: ~s" msgid "Invalid role: ~s" msgstr "Papel inválido: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "São necessários privilégios de dono" @@ -1386,7 +1386,7 @@ msgstr "Configuração para " msgid "Room title" msgstr "Título da sala" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 #, fuzzy msgid "Room description" msgstr "Subscrição" @@ -1531,36 +1531,36 @@ msgstr "Guardar históricos?" msgid "You need an x:data capable client to configure room" msgstr "É necessário um cliente com suporte de x:data para configurar a sala" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privado" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Utilizador" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 #, fuzzy msgid "the password is" msgstr "Mudar palavra-chave" diff --git a/priv/msgs/ru.po b/priv/msgs/ru.po index d75f381ac6c..fe868746054 100644 --- a/priv/msgs/ru.po +++ b/priv/msgs/ru.po @@ -34,12 +34,12 @@ msgstr "Заменено новым соединением" msgid "has been kicked" msgstr "выгнали из комнаты" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" "Маршрутизация этой строфы запрещена вашим активным списком приватности." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "Слишком много неподтверждённых пакетов" @@ -854,11 +854,11 @@ msgstr "" "Слишком много (~p) неудачных попыток аутентификации с этого IP-адреса (~s). " "Адрес будет разблокирован в ~s UTC" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -976,9 +976,9 @@ msgstr "Кодировка сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Только модераторы могут изменять тему в этой комнате" #: mod_muc.erl:585 @@ -997,36 +997,36 @@ msgstr "Конференция не существует" msgid "Chatrooms" msgstr "Комнаты" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Чтобы зарегистрировать псевдоним, требуется x:data-совместимый клиент" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Регистрация псевдонима на " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Введите псевдоним, который Вы хотели бы зарегистрировать" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдоним" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Этот псевдоним зарегистрирован кем-то другим" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Вы должны заполнить поле \"Псевдоним\" в форме" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" @@ -1193,8 +1193,8 @@ msgstr "Превышен лимит скорости посылки информ #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1234,7 +1234,7 @@ msgstr "Адресата нет в конференции" msgid "It is not allowed to send private messages" msgstr "Запрещено посылать приватные сообщения" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Только присутствующим разрешается посылать сообщения в конференцию" @@ -1316,7 +1316,7 @@ msgstr "Недопустимый ранг: ~s" msgid "Invalid role: ~s" msgstr "Недопустимая роль: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Требуются права владельца" @@ -1328,7 +1328,7 @@ msgstr "Конфигурация комнаты ~s" msgid "Room title" msgstr "Название комнаты" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Описание комнаты" @@ -1458,35 +1458,35 @@ msgstr "Включить журналирование" msgid "You need an x:data capable client to configure room" msgstr "Чтобы сконфигурировать комнату, требуется x:data-совместимый клиент" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Число присутствующих" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "приватная, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Запрос на право голоса" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Подтвердите или отклоните право голоса." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "JID пользователя" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Предоставить голос?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s приглашает вас в комнату ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "пароль:" diff --git a/priv/msgs/sk.po b/priv/msgs/sk.po index a8ae9991c1e..779a2ace302 100644 --- a/priv/msgs/sk.po +++ b/priv/msgs/sk.po @@ -29,11 +29,11 @@ msgstr "Nahradené novým spojením" msgid "has been kicked" msgstr "bol(a) vyhodený(á) z miestnosti" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Aktívny list súkromia zbránil v smerovaní tejto stanzy." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -847,11 +847,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -969,9 +969,9 @@ msgstr "Kódovanie pre server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Len moderátori majú povolené meniť tému miestnosti" #: mod_muc.erl:585 @@ -990,36 +990,36 @@ msgstr "Diskusná miestnosť neexistuje" msgid "Chatrooms" msgstr "Diskusné miestnosti" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "Na registráciu prezývky potrebujete klienta podporujúceho z x:data" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registrácia prezývky na " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Zadajte prezývku, ktorú chcete registrovať" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Prezývka" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Prezývka je už zaregistrovaná inou osobou" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Musíte vyplniť políčko \"Prezývka\" vo formulári" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -1189,8 +1189,8 @@ msgstr "Bol prekročený prenosový limit" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1229,7 +1229,7 @@ msgstr "Príjemca sa nenachádza v konferenčnej miestnosti" msgid "It is not allowed to send private messages" msgstr "Nieje povolené posielať súkromné správy" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Len členovia majú povolené zasielať správy do konferencie" @@ -1313,7 +1313,7 @@ msgstr "Neplatné priradenie: ~s" msgid "Invalid role: ~s" msgstr "Neplatná rola: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Sú vyžadované práva vlastníka" @@ -1325,7 +1325,7 @@ msgstr "Konfigurácia miestnosti ~s" msgid "Room title" msgstr "Názov miestnosti" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Popis miestnosti" @@ -1454,35 +1454,35 @@ msgstr "Zapnúť zaznamenávanie histórie" msgid "You need an x:data capable client to configure room" msgstr "Na konfiguráciu miestnosti potrebujete klienta podporujúceho x:data" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Počet zúčastnených" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "súkromná, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Žiadosť o Voice" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Povolte alebo zamietnite žiadosť o Voice." -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Používateľ " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Prideltiť Voice tejto osobe?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s Vás pozýva do miestnosti ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "heslo je" diff --git a/priv/msgs/sv.po b/priv/msgs/sv.po index 631fdb707d8..eb391fe808b 100644 --- a/priv/msgs/sv.po +++ b/priv/msgs/sv.po @@ -28,11 +28,11 @@ msgstr "Ersatt av ny anslutning" msgid "has been kicked" msgstr "har blivit kickad" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -844,11 +844,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -965,9 +965,9 @@ msgstr "Encoding för server ~b" msgid "Server ~b" msgstr "Server ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Endast moderatorer får ändra ämnet i det här rummet" #: mod_muc.erl:585 @@ -986,37 +986,37 @@ msgstr "Rummet finns inte" msgid "Chatrooms" msgstr "Chattrum" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "Du behöver en klient som stödjer x:data för att registrera smeknamn" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Registrera smeknamn på " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Skriv in smeknamnet du vill registrera" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Smeknamn" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Smeknamnet är reserverat" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Du måste fylla i fält \"smeknamn\" i formen" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC modul" @@ -1190,8 +1190,8 @@ msgstr "Trafikgränsen har överstigits" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1233,7 +1233,7 @@ msgstr "Mottagaren finns inte i rummet" msgid "It is not allowed to send private messages" msgstr "Det ar inte tillåtet att skicka privata meddelanden" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Utomstående får inte skicka medelanden till den här konferensen" @@ -1321,7 +1321,7 @@ msgstr "Ogiltlig rang: ~s" msgid "Invalid role: ~s" msgstr "Ogiltlig roll: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Ägarprivilegier krävs" @@ -1333,7 +1333,7 @@ msgstr "Konfiguration för ~s" msgid "Room title" msgstr "Rumstitel" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 #, fuzzy msgid "Room description" msgstr "Beskrivning:" @@ -1466,36 +1466,36 @@ msgstr "Möjliggör login" msgid "You need an x:data capable client to configure room" msgstr "Du behöver en klient som stödjer x:data för att konfiguera detta rum" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Antal besökare" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privat, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Användare " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s bjöd in dig till rummet ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "Lösenordet är" diff --git a/priv/msgs/th.po b/priv/msgs/th.po index c2fca4a23d4..fe3ccd1820b 100644 --- a/priv/msgs/th.po +++ b/priv/msgs/th.po @@ -24,11 +24,11 @@ msgstr "แทนที่ด้วยการเชื่อมต่อให msgid "has been kicked" msgstr "ถูกไล่ออก" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -845,11 +845,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -969,9 +969,9 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "ผู้ดูแลการสนทนาเท่านั้นที่ได้รับอนุญาตให้เปลี่ยนหัวข้อในห้องนี้" #: mod_muc.erl:585 @@ -990,38 +990,38 @@ msgstr "ไม่มีห้องประชุม" msgid "Chatrooms" msgstr "ห้องสนทนา" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อลงทะเบียนชื่อเล่น" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "การลงทะเบียนชื่อเล่นที่ " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "ป้อนชื่อเล่นที่คุณต้องการลงทะเบียน" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "ชื่อเล่น" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 #, fuzzy msgid "That nickname is registered by another person" msgstr "ชื่อเล่นถูกลงทะเบียนใช้งานโดยบุคคลอื่น" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "คุณต้องกรอกฟิลด์ \"Nickname\" ในแบบฟอร์ม" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC module" @@ -1196,8 +1196,8 @@ msgstr "อัตราของปริมาณการเข้าใช้ #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1238,7 +1238,7 @@ msgstr "ผู้รับไม่ได้อยู่ในห้องปร msgid "It is not allowed to send private messages" msgstr "ไม่อนุญาตให้ส่งข้อความส่วนตัวไปยังห้องประชุม" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "ผู้ครอบครองห้องเท่านั้นที่ได้รับอนุญาตให้ส่งข้อความไปยังห้องประชุม" @@ -1326,7 +1326,7 @@ msgstr "การเข้าร่วมที่ไม่ถูกต้อง msgid "Invalid role: ~s" msgstr "บทบาทไม่ถูกต้อง: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "ต้องมีสิทธิพิเศษของเจ้าของ" @@ -1339,7 +1339,7 @@ msgstr "การกำหนดค่าสำหรับ " msgid "Room title" msgstr "ชื่อห้อง" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 #, fuzzy msgid "Room description" msgstr "รายละเอียด:" @@ -1476,36 +1476,36 @@ msgstr "เปิดใช้งานการบันทึก" msgid "You need an x:data capable client to configure room" msgstr "คุณต้องใช้ไคลเอ็นต์ที่รองรับ x:data เพื่อกำหนดค่าห้องสนทนา " -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "จำนวนผู้ครอบครองห้อง" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "ส่วนตัว, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "ผู้ใช้" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s เชิญคุณเข้าร่วมสนทนาในห้อง ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "รหัสผ่านคือ" diff --git a/priv/msgs/tr.po b/priv/msgs/tr.po index 52ae45c1822..613b2260c15 100644 --- a/priv/msgs/tr.po +++ b/priv/msgs/tr.po @@ -30,11 +30,11 @@ msgstr "Eski bağlantı yenisi ile değiştirildi" msgid "has been kicked" msgstr "odadan atıldı" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Etkin mahremiyet listeniz bu bölümün yönlendirilmesini engelledi." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -853,11 +853,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -977,9 +977,9 @@ msgstr "Sunucu için kodlama ~b" msgid "Server ~b" msgstr "Sunucu ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Sadece moderatörlerin bu odanın konusunu değiştirmesine izin veriliyor" #: mod_muc.erl:585 @@ -998,38 +998,38 @@ msgstr "Konferans odası bulunamadı" msgid "Chatrooms" msgstr "Sohbet Odaları" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Takma isminizi kaydettirmek için x:data destekleyen bir istemciye " "gereksinimiz var" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Takma İsim Kaydı : " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Kaydettirmek istediğiniz takma ismi giriniz" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Takma isim" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "O takma isim başka biri tarafından kaydettirilmiş" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Formda \"Takma isim\" alanını doldurmanız gerekiyor" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC modülü" @@ -1199,8 +1199,8 @@ msgstr "Trafik oran sınırı aşıldı" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1239,7 +1239,7 @@ msgstr "Alıcı konferans odasında değil" msgid "It is not allowed to send private messages" msgstr "Özel mesaj gönderilmesine izin verilmiyor" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Sadece oda sakinlerinin konferansa mesaj göndermesine izin veriliyor" @@ -1325,7 +1325,7 @@ msgstr "Geçersiz ilişki: ~s" msgid "Invalid role: ~s" msgstr "Geçersiz rol: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Sahip yetkileri gerekli" @@ -1337,7 +1337,7 @@ msgstr "~s odasının ayarları" msgid "Room title" msgstr "Oda başlığı" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Oda tanımı" @@ -1469,35 +1469,35 @@ msgid "You need an x:data capable client to configure room" msgstr "" "Odayı ayarlamak için x:data becerisine sahip bir istemciye gereksinimiz var" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Oda sakini sayısı" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "özel" -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "Ses isteği" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "Ses isteğini kabul edin ya da reddedin" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "Kullanıcı JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "Bu kişiye ses verelim mi?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s sizi ~s odasına davet ediyor" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "parola :" diff --git a/priv/msgs/uk.po b/priv/msgs/uk.po index 4f6b2a0ead9..5548afb49fe 100644 --- a/priv/msgs/uk.po +++ b/priv/msgs/uk.po @@ -31,11 +31,11 @@ msgstr "Замінено новим з'єднанням" msgid "has been kicked" msgstr "вигнали з кімнати" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Маршрутизація цієї строфи була відмінена активним списком приватності." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -851,11 +851,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -975,9 +975,9 @@ msgstr "Кодування для сервера ~b" msgid "Server ~b" msgstr "Сервер ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" #: mod_muc.erl:585 @@ -996,38 +996,38 @@ msgstr "Конференція не існує" msgid "Chatrooms" msgstr "Кімнати" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Для реєстрації псевдоніму необхідно використовувати клієнт з підтримкою x:" "data" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Реєстрація псевдоніма на " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Введіть псевдонім, який ви хочете зареєструвати" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Псевдонім" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "Псевдонім зареєстровано кимось іншим" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Вам необхідно заповнити поле \"Псевдонім\" у формі" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC модуль" @@ -1197,8 +1197,8 @@ msgstr "Швидкість передачі інформації було пер #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1238,7 +1238,7 @@ msgstr "Адресата немає в конференції" msgid "It is not allowed to send private messages" msgstr "Приватні повідомлення не дозволені" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Тільки присутнім дозволяється надсилати повідомленняя в конференцію" @@ -1320,7 +1320,7 @@ msgstr "Недопустимий ранг: ~s" msgid "Invalid role: ~s" msgstr "Недопустима роль: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Необхідні права власника" @@ -1332,7 +1332,7 @@ msgstr "Конфігурація кімнати ~s" msgid "Room title" msgstr "Назва кімнати" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "Опис кімнати" @@ -1466,36 +1466,36 @@ msgstr "" "Для конфігурування кімнати потрібно використовувати клієнт з підтримкою x:" "data" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Кількість присутніх" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "приватна, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Користувач " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s запрошує вас до кімнати ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "пароль:" diff --git a/priv/msgs/vi.po b/priv/msgs/vi.po index 4302750d58b..67b9294e294 100644 --- a/priv/msgs/vi.po +++ b/priv/msgs/vi.po @@ -24,11 +24,11 @@ msgstr "Được thay thế bởi kết nối mới" msgid "has been kicked" msgstr "đã bị đẩy ra khỏi" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -850,11 +850,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -980,9 +980,9 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Chỉ có những người điều phối được phép thay đổi chủ đề trong phòng này" #: mod_muc.erl:585 @@ -1001,40 +1001,40 @@ msgstr "Phòng họp không tồn tại" msgid "Chatrooms" msgstr "Phòng trò chuyện" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để đăng ký " "bí danh" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Đăng Ký Bí Danh tại" -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Nhập bí danh bạn muốn đăng ký" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Bí danh" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 #, fuzzy msgid "That nickname is registered by another person" msgstr "Một người khác đã đăng ký bí danh này rồi" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Bạn phải điền thông tin vào ô \"Nickname\" trong biểu mẫu này" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Môdun ejabberd MUC Bản quyền" @@ -1209,8 +1209,8 @@ msgstr "Quá giới hạn tỷ lệ lưu lượng truyền tải" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1251,7 +1251,7 @@ msgstr "Người nhận không có trong phòng họp" msgid "It is not allowed to send private messages" msgstr "Không được phép gửi những thư riêng đến phòng họp" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Chỉ có những đối tượng tham gia mới được phép gửi thư đến phòng họp" @@ -1343,7 +1343,7 @@ msgstr "Tư cách không hợp lệ: ~s" msgid "Invalid role: ~s" msgstr "Vai trò không hợp lệ: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "Yêu cầu đặc quyền của người sở hữu" @@ -1356,7 +1356,7 @@ msgstr "Cấu hình cho " msgid "Room title" msgstr "Tên phòng" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 #, fuzzy msgid "Room description" msgstr "Miêu tả:" @@ -1495,36 +1495,36 @@ msgstr "" "Bạn cần có một trình ứng dụng khách hỗ trợ định dạng dữ liệu x: để xác định " "cấu hình phòng họp" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Số người tham dự" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "riêng," -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Người sử dụng " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s mời bạn vào phòng ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "mật khẩu là" diff --git a/priv/msgs/wa.po b/priv/msgs/wa.po index d5c7ef1899d..c66da1e5c39 100644 --- a/priv/msgs/wa.po +++ b/priv/msgs/wa.po @@ -24,11 +24,11 @@ msgstr "Replaecî pa on novea raloyaedje" msgid "has been kicked" msgstr "a stî pité evoye" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "" -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -848,11 +848,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -978,9 +978,9 @@ msgstr "" msgid "Server ~b" msgstr "" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" #: mod_muc.erl:585 @@ -1000,39 +1000,39 @@ msgstr "Li såle di conferince n' egzistêye nén" msgid "Chatrooms" msgstr "Såles di berdelaedje" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 #, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "Edjîstraedje di metou no amon " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "Dinez l' metou no ki vos vloz edjîstrer" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Metou no" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 #, fuzzy msgid "That nickname is registered by another person" msgstr "Li metou no est ddja edjîstré pa ene ôte sakî" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "Vos dvoz rimpli l' tchamp «Metou no» dins l' formiulaire" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "Module MUC (såles di berdelaedje) po ejabberd" @@ -1208,8 +1208,8 @@ msgstr "Li limite pol volume di trafik a stî passêye" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1249,7 +1249,7 @@ msgstr "Li riçuveu n' est nén dins l' såle di conferince" msgid "It is not allowed to send private messages" msgstr "Ci n' est nén permetou d' evoyî des messaedjes privés" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "Seulmint les prezints polèt evoyî des messaedjes al conferince" @@ -1340,7 +1340,7 @@ msgstr "Afiyaedje nén valide: ~s" msgid "Invalid role: ~s" msgstr "Role nén valide: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "I fåt des priviledjes di prôpietaire" @@ -1353,7 +1353,7 @@ msgstr "Apontiaedje po " msgid "Room title" msgstr "Tite del såle" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 #, fuzzy msgid "Room description" msgstr "Discrijhaedje:" @@ -1489,36 +1489,36 @@ msgstr "Mete en alaedje li djournå" msgid "You need an x:data capable client to configure room" msgstr "I vs fåt on cliyint ki sopoite x:data por vos poleur apontyî l' såle" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "Nombe di prezints" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "privé, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 #, fuzzy msgid "User JID" msgstr "Uzeu " -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s vos preye sol såle ~s" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "li scret est" diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index 67b8d050fc1..014fe9accce 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -26,11 +26,11 @@ msgstr "被新的连接替换" msgid "has been kicked" msgstr "已被踢出" -#: ejabberd_c2s.erl:2112 +#: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." msgstr "你的活跃私聊列表拒绝了在此房间进行路由分发." -#: ejabberd_c2s.erl:2427 +#: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" msgstr "" @@ -838,11 +838,11 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" -#: mod_http_upload.erl:593 +#: mod_http_upload.erl:586 msgid "Please specify file size." msgstr "" -#: mod_http_upload.erl:597 +#: mod_http_upload.erl:590 msgid "Please specify file name." msgstr "" @@ -956,9 +956,9 @@ msgstr "服务器 ~b 的编码" msgid "Server ~b" msgstr "服务器 ~b" -#: mod_mam.erl:270 +#: mod_mam.erl:541 #, fuzzy -msgid "Only members are allowed to query archives of this room" +msgid "Only members may query archives of this room" msgstr "只有主持人可以在此房间里更改主题" #: mod_muc.erl:585 @@ -977,36 +977,36 @@ msgstr "会议室不存在" msgid "Chatrooms" msgstr "聊天室" -#: mod_muc.erl:779 +#: mod_muc.erl:781 msgid "Empty Rooms" msgstr "" -#: mod_muc.erl:931 +#: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" msgstr "您需要一个支持 x:data 的客户端来注册昵称" -#: mod_muc.erl:941 +#: mod_muc.erl:943 msgid "Nickname Registration at " msgstr "昵称注册于 " -#: mod_muc.erl:947 +#: mod_muc.erl:949 msgid "Enter nickname you want to register" msgstr "请输入您想要注册的昵称" -#: mod_muc.erl:948 mod_muc_room.erl:4351 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "昵称" -#: mod_muc.erl:1060 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "该昵称已被另一个人注册了" -#: mod_muc.erl:1088 +#: mod_muc.erl:1090 msgid "You must fill in field \"Nickname\" in the form" msgstr "您必须填充表单中\"昵称\"项" -#: mod_muc.erl:1111 +#: mod_muc.erl:1113 msgid "ejabberd MUC module" msgstr "ejabberd MUC 模块" @@ -1176,8 +1176,8 @@ msgstr "已经超过传输率限制" #: mod_muc_room.erl:230 mod_muc_room.erl:518 mod_muc_room.erl:1059 msgid "" -"It is not allowed to send error messages to the room. This participant (~s) " -"sent an error message (~s) and gets kicked from the room" +"It is not allowed to send error messages to the room. The participant (~s) " +"has sent an error message (~s) and got kicked from the room" msgstr "" #: mod_muc_room.erl:241 @@ -1216,7 +1216,7 @@ msgstr "接收人不在会议室" msgid "It is not allowed to send private messages" msgstr "不可以发送私聊消息" -#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4592 +#: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" msgstr "只有与会人可以向大会发送消息" @@ -1298,7 +1298,7 @@ msgstr "无效加入: ~s" msgid "Invalid role: ~s" msgstr "无效角色: ~s" -#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4234 +#: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" msgstr "需要持有人权限" @@ -1310,7 +1310,7 @@ msgstr "房间 ~s 的配置 " msgid "Room title" msgstr "房间标题" -#: mod_muc_room.erl:3361 mod_muc_room.erl:4188 +#: mod_muc_room.erl:3361 mod_muc_room.erl:4190 msgid "Room description" msgstr "房间描述" @@ -1439,35 +1439,35 @@ msgstr "启用服务器端聊天记录" msgid "You need an x:data capable client to configure room" msgstr "您需要一个兼容 x:data 的客户端来配置房间" -#: mod_muc_room.erl:4190 +#: mod_muc_room.erl:4192 msgid "Number of occupants" msgstr "驻留人数" -#: mod_muc_room.erl:4260 +#: mod_muc_room.erl:4262 msgid "private, " msgstr "保密, " -#: mod_muc_room.erl:4324 +#: mod_muc_room.erl:4326 msgid "Voice request" msgstr "声音请求" -#: mod_muc_room.erl:4329 +#: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." msgstr "接受或拒绝声音请求" -#: mod_muc_room.erl:4349 +#: mod_muc_room.erl:4351 msgid "User JID" msgstr "用户 JID" -#: mod_muc_room.erl:4353 +#: mod_muc_room.erl:4355 msgid "Grant voice to this person?" msgstr "为此人授权声音?" -#: mod_muc_room.erl:4496 +#: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" msgstr "~s 邀请你到 ~s 房间" -#: mod_muc_room.erl:4507 +#: mod_muc_room.erl:4509 msgid "the password is" msgstr "密码是" From 09ab01084d8c45bd67a174456177541e000786ef Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 15 Jan 2016 12:27:22 +0100 Subject: [PATCH 487/695] Update Spanish and Catalan translation --- priv/msgs/ca.msg | 12 ++++++++++++ priv/msgs/ca.po | 34 ++++++++++++++++------------------ priv/msgs/es.msg | 12 ++++++++++++ priv/msgs/es.po | 30 ++++++++++++++---------------- 4 files changed, 54 insertions(+), 34 deletions(-) diff --git a/priv/msgs/ca.msg b/priv/msgs/ca.msg index 85907332fda..46ee1afbcb3 100644 --- a/priv/msgs/ca.msg +++ b/priv/msgs/ca.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Acceptar"}. {"Access Configuration","Configuració d'accesos"}. {"Access Control List Configuration","Configuració de la Llista de Control d'Accés"}. {"Access Control Lists","Llista de Control d'Accés"}. @@ -87,6 +88,7 @@ {"ejabberd Web Admin","Web d'administració del ejabberd"}. {"Elements","Elements"}. {"Email","Email"}. +{"Empty Rooms","Sales buides "}. {"Enable logging","Habilitar el registre de la conversa"}. {"Enable message archiving","Activar l'emmagatzematge de missatges"}. {"Encoding for server ~b","Codificació pel servidor ~b"}. @@ -142,6 +144,7 @@ {"Import Users from Dir at ","Importar usuaris des del directori en "}. {"Import Users From jabberd14 Spool Files","Importar usuaris de jabberd14"}. {"Improper message type","Tipus de missatge incorrecte"}. +{"Incoming s2s Connections:","Connexions s2s d'entrada"}. {"Incorrect password","Contrasenya incorrecta"}. {"Invalid affiliation: ~s","Afiliació invàlida: ~s"}. {"Invalid role: ~s","Rol invàlid: ~s"}. @@ -154,6 +157,7 @@ {"IRC username","Nom d'usuari al IRC"}. {"IRC Username","Nom d'usuari al IRC"}. {"is now known as","ara es conegut com"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","No està permés enviar missatges d'error a la sala. El participant (~s) ha enviat un missatge d'error (~s) i ha sigut expulsat de la sala"}. {"It is not allowed to send private messages","No està permés enviar missatges privats"}. {"It is not allowed to send private messages of type \"groupchat\"","No està permés enviar missatges del tipus \"groupchat\""}. {"It is not allowed to send private messages to the conference","No està permès l'enviament de missatges privats a la sala"}. @@ -196,6 +200,7 @@ {"Message body","Missatge"}. {"Middle Name","Segon nom"}. {"Minimum interval between voice requests (in seconds)","Interval mínim entre peticions de veu (en segons)"}. +{"Moderator","Moderador"}. {"Moderator privileges required","Es necessita tenir privilegis de moderador"}. {"moderators only","només moderadors"}. {"Modified modules","Mòduls modificats"}. @@ -239,6 +244,7 @@ {"Online Users","Usuaris conectats"}. {"Online Users:","Usuaris en línia:"}. {"Only deliver notifications to available users","Sols enviar notificacions als usuaris disponibles"}. +{"Only members may query archives of this room","Només membres poden consultar l'arxiu de missatges d'aquesta sala"}. {"Only moderators and participants are allowed to change the subject in this room","Només els moderadors i participants poden canviar l'assumpte d'aquesta sala"}. {"Only moderators are allowed to change the subject in this room","Només els moderadors poden canviar l'assumpte d'aquesta sala"}. {"Only moderators can approve voice requests","Només els moderadors poden aprovar les peticions de veu"}. @@ -252,6 +258,7 @@ {"Outgoing s2s Connections","Connexions s2s d'eixida"}. {"Owner privileges required","Es requerixen privilegis de propietari de la sala"}. {"Packet","Paquet"}. +{"Participant","Participant"}. {"Password ~b","Contrasenya ~b"}. {"Password:","Contrasenya:"}. {"Password","Contrasenya"}. @@ -265,6 +272,8 @@ {"Persist items to storage","Persistir elements al guardar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Recorda que aquestes opcions només fan còpia de seguretat de la base de dades Mnesia. Si estàs utilitzant el mòdul d'ODBC també deus de fer una còpia de seguretat de la base de dades de SQL a part."}. +{"Please specify file name.","Per favor especifica el nom del fitxer."}. +{"Please specify file size.","Per favor especifica la mida del fitxer."}. {"Please, wait for a while before sending new voice request","Si us plau, espera una mica abans d'enviar una nova petició de veu"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. @@ -300,6 +309,7 @@ {"Restore binary backup immediately:","Restaurar una còpia de seguretat binària ara mateix."}. {"Restore plain text backup immediately:","Restaurar una còpia de seguretat en format de text pla ara mateix:"}. {"Restore","Restaurar"}. +{"Roles for which Presence is Broadcasted","Rols per als que sí se difon la seua presencia"}. {"Room Configuration","Configuració de la sala"}. {"Room creation is denied by service policy","Se t'ha denegat el crear la sala per política del servei"}. {"Room description","Descripció de la sala:"}. @@ -323,6 +333,7 @@ {"September","Setembre"}. {"Server ~b","Servidor ~b"}. {"Server:","Servidor:"}. +{"Server","Servidor"}. {"Set message of the day and send to online users","Configurar el missatge del dia i enviar a tots els usuaris"}. {"Set message of the day on all hosts and send to online users","Escriure missatge del dia en tots els hosts i enviar-ho als usuaris connectats"}. {"Shared Roster Groups","Grups de contactes compartits"}. @@ -408,6 +419,7 @@ {"Virtual Hosts","Hosts virtuals"}. {"Visitors are not allowed to change their nicknames in this room","Els visitants no tenen permés canviar el seus Nicknames en esta sala"}. {"Visitors are not allowed to send messages to all occupants","Els visitants no poden enviar missatges a tots els ocupants"}. +{"Visitor","Visitant"}. {"Voice request","Petició de veu"}. {"Voice requests are disabled in this conference","Les peticions de veu es troben desactivades en aquesta conferència"}. {"Wednesday","Dimecres"}. diff --git a/priv/msgs/ca.po b/priv/msgs/ca.po index 575ba7e2316..ac1d0147808 100644 --- a/priv/msgs/ca.po +++ b/priv/msgs/ca.po @@ -3,10 +3,10 @@ msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2015-09-07 14:13+0100\n" +"PO-Revision-Date: 2016-01-15 12:25+0100\n" "Last-Translator: Badlop \n" -"Language-Team: American English \n" -"Language: en_US\n" +"Language-Team: \n" +"Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -69,9 +69,8 @@ msgid "User" msgstr "Usuari" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Servidor:" +msgstr "Servidor" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -81,7 +80,7 @@ msgstr "Contrasenya" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Acceptar" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -248,9 +247,8 @@ msgid "Outgoing s2s Connections:" msgstr "Connexions d'eixida s2s" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Connexions d'eixida s2s" +msgstr "Connexions s2s d'entrada" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -851,11 +849,11 @@ msgstr "" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Per favor especifica la mida del fitxer." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Per favor especifica el nom del fitxer." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" @@ -974,9 +972,8 @@ msgid "Server ~b" msgstr "Servidor ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Només els moderadors poden canviar l'assumpte d'aquesta sala" +msgstr "Només membres poden consultar l'arxiu de missatges d'aquesta sala" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -998,7 +995,7 @@ msgstr "Sales de xat" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Sales buides " #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1196,6 +1193,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"No està permés enviar missatges d'error a la sala. El participant (~s) ha " +"enviat un missatge d'error (~s) i ha sigut expulsat de la sala" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1371,20 +1370,19 @@ msgstr "qualsevol" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Rols per als que sí se difon la seua presencia" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "només moderadors" +msgstr "Moderador" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Participant" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Visitant" #: mod_muc_room.erl:3513 msgid "Make room members-only" diff --git a/priv/msgs/es.msg b/priv/msgs/es.msg index 29bba768826..0d585ec51a9 100644 --- a/priv/msgs/es.msg +++ b/priv/msgs/es.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Aceptar"}. {"Access Configuration","Configuración de accesos"}. {"Access Control List Configuration","Configuración de la Lista de Control de Acceso"}. {"Access control lists","Listas de Control de Acceso"}. @@ -87,6 +88,7 @@ {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elementos"}. {"Email","correo"}. +{"Empty Rooms","Salas vacías"}. {"Enable logging","Guardar históricos"}. {"Enable message archiving","Activar el almacenamiento de mensajes"}. {"Encoding for server ~b","Codificación del servidor ~b"}. @@ -142,6 +144,7 @@ {"Import Users from Dir at ","Importar usuarios desde el directorio en "}. {"Import Users From jabberd14 Spool Files","Importar usuarios de ficheros spool de jabberd-1.4"}. {"Improper message type","Tipo de mensaje incorrecto"}. +{"Incoming s2s Connections:","Conexiones S2S entrantes:"}. {"Incorrect password","Contraseña incorrecta"}. {"Invalid affiliation: ~s","Afiliación no válida: ~s"}. {"Invalid role: ~s","Rol no válido: ~s"}. @@ -154,6 +157,7 @@ {"IRC username","Nombre de usuario en IRC"}. {"IRC Username","Nombre de usuario en IRC"}. {"is now known as","se cambia el nombre a"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","No está permitido enviar mensajes de error a la sala. Este participante (~s) ha enviado un mensaje de error (~s) y fue expulsado de la sala"}. {"It is not allowed to send private messages","No está permitido enviar mensajes privados"}. {"It is not allowed to send private messages of type \"groupchat\"","No está permitido enviar mensajes privados del tipo \"groupchat\""}. {"It is not allowed to send private messages to the conference","Impedir el envio de mensajes privados a la sala"}. @@ -196,6 +200,7 @@ {"Message body","Cuerpo del mensaje"}. {"Middle Name","Segundo nombre"}. {"Minimum interval between voice requests (in seconds)","Intervalo mínimo entre peticiones de voz (en segundos)"}. +{"Moderator","Moderador"}. {"Moderator privileges required","Se necesita privilegios de moderador"}. {"moderators only","solo moderadores"}. {"Modified modules","Módulos modificados"}. @@ -239,6 +244,7 @@ {"Online Users:","Usuarios conectados:"}. {"Online Users","Usuarios conectados"}. {"Only deliver notifications to available users","Solo enviar notificaciones a los usuarios disponibles"}. +{"Only members may query archives of this room","Solo miembros pueden consultar el archivo de mensajes de la sala"}. {"Only moderators and participants are allowed to change the subject in this room","Solo los moderadores y participantes pueden cambiar el asunto de esta sala"}. {"Only moderators are allowed to change the subject in this room","Solo los moderadores pueden cambiar el asunto de esta sala"}. {"Only moderators can approve voice requests","Solo los moderadores pueden aprobar peticiones de voz"}. @@ -252,6 +258,7 @@ {"Outgoing s2s Connections","Conexiones S2S salientes"}. {"Owner privileges required","Se requieren privilegios de propietario de la sala"}. {"Packet","Paquete"}. +{"Participant","Participante"}. {"Password ~b","Contraseña ~b"}. {"Password:","Contraseña:"}. {"Password","Contraseña"}. @@ -265,6 +272,8 @@ {"Persist items to storage","Persistir elementos al almacenar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Ten en cuenta que estas opciones solo harán copia de seguridad de la base de datos Mnesia embebida. Si estás usando ODBC tendrás que hacer también copia de seguridad de tu base de datos SQL."}. +{"Please specify file name.","Por favor especifica el nombre del fichero."}. +{"Please specify file size.","Por favor especifica el tamaño del fichero."}. {"Please, wait for a while before sending new voice request","Por favor, espera un poco antes de enviar otra petición de voz"}. {"Pong","Pong"}. {"Port ~b","Puerto ~b"}. @@ -300,6 +309,7 @@ {"Restore binary backup immediately:","Restaurar inmediatamente copia de seguridad binaria:"}. {"Restore plain text backup immediately:","Restaurar copias de seguridad de texto plano inmediatamente:"}. {"Restore","Restaurar"}. +{"Roles for which Presence is Broadcasted","Roles para los que sí se difunde su Presencia"}. {"Room Configuration","Configuración de la sala"}. {"Room creation is denied by service policy","Se te ha denegado crear la sala por política del servicio"}. {"Room description","Descripción de la sala"}. @@ -323,6 +333,7 @@ {"September","septiembre"}. {"Server ~b","Servidor ~b"}. {"Server:","Servidor:"}. +{"Server","Servidor"}. {"Set message of the day and send to online users","Poner mensaje del dia y enviar a todos los usuarios conectados"}. {"Set message of the day on all hosts and send to online users","Poner mensaje del día en todos los dominios y enviar a los usuarios conectados"}. {"Shared Roster Groups","Grupos Compartidos"}. @@ -408,6 +419,7 @@ {"Virtual Hosts","Dominios Virtuales"}. {"Visitors are not allowed to change their nicknames in this room","Los visitantes no tienen permitido cambiar sus apodos en esta sala"}. {"Visitors are not allowed to send messages to all occupants","Los visitantes no pueden enviar mensajes a todos los ocupantes"}. +{"Visitor","Visitante"}. {"Voice request","Petición de voz"}. {"Voice requests are disabled in this conference","Las peticiones de voz están desactivadas en esta sala"}. {"Wednesday","miércoles"}. diff --git a/priv/msgs/es.po b/priv/msgs/es.po index 34b21f76d95..b9a950e3cbd 100644 --- a/priv/msgs/es.po +++ b/priv/msgs/es.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: es\n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2015-09-07 14:02+0100\n" +"PO-Revision-Date: 2016-01-15 12:19+0100\n" "Last-Translator: Badlop \n" "Language-Team: \n" "Language: es\n" @@ -66,9 +66,8 @@ msgid "User" msgstr "Usuario" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Servidor:" +msgstr "Servidor" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -78,7 +77,7 @@ msgstr "Contraseña" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Aceptar" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -245,9 +244,8 @@ msgid "Outgoing s2s Connections:" msgstr "Conexiones S2S salientes:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Conexiones S2S salientes:" +msgstr "Conexiones S2S entrantes:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -850,11 +848,11 @@ msgstr "" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Por favor especifica el tamaño del fichero." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Por favor especifica el nombre del fichero." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" @@ -973,9 +971,8 @@ msgid "Server ~b" msgstr "Servidor ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Solo los moderadores pueden cambiar el asunto de esta sala" +msgstr "Solo miembros pueden consultar el archivo de mensajes de la sala" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -997,7 +994,7 @@ msgstr "Salas de charla" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Salas vacías" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1195,6 +1192,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"No está permitido enviar mensajes de error a la sala. Este participante (~s) " +"ha enviado un mensaje de error (~s) y fue expulsado de la sala" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1369,20 +1368,19 @@ msgstr "cualquiera" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Roles para los que sí se difunde su Presencia" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "solo moderadores" +msgstr "Moderador" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Participante" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Visitante" #: mod_muc_room.erl:3513 msgid "Make room members-only" From 1d452c98c136105a09173273fd55fbe9a1e513ec Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 15 Jan 2016 14:32:10 +0300 Subject: [PATCH 488/695] Describe option type of 'domain_balancing' --- src/ejabberd_router.erl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 8a579814c5f..5ca1262e675 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -344,8 +344,8 @@ do_route(OrigFrom, OrigTo, OrigPacket) -> end; Rs -> Value = case - ejabberd_config:get_local_option({domain_balancing, - LDstDomain}, fun(D) when is_atom(D) -> D end) + ejabberd_config:get_option({domain_balancing, + LDstDomain}, fun(D) when is_atom(D) -> D end) of undefined -> p1_time_compat:monotonic_time(); random -> p1_time_compat:monotonic_time(); @@ -408,7 +408,13 @@ update_tables() -> false -> ok end. - +opt_type(domain_balancing) -> + fun (random) -> random; + (source) -> source; + (destination) -> destination; + (bare_source) -> bare_source; + (bare_destination) -> bare_destination + end; opt_type(domain_balancing_component_number) -> fun (N) when is_integer(N), N > 1 -> N end; -opt_type(_) -> [domain_balancing_component_number]. +opt_type(_) -> [domain_balancing, domain_balancing_component_number]. From a83c5a8f3a3de102dde0d1f7c962d0a6b754a0d5 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 15 Jan 2016 15:34:48 +0300 Subject: [PATCH 489/695] Do not redefine records --- src/mod_configure.erl | 5 +---- src/mod_muc.erl | 14 +------------- src/mod_muc_admin.erl | 4 +--- src/mod_muc_log.erl | 6 +----- 4 files changed, 4 insertions(+), 25 deletions(-) diff --git a/src/mod_configure.erl b/src/mod_configure.erl index a101ebf3cc6..0c7e752687a 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -41,14 +41,11 @@ -include("logger.hrl"). -include("jlib.hrl"). - +-include("ejabberd_sm.hrl"). -include("adhoc.hrl"). -define(T(Lang, Text), translate:translate(Lang, Text)). -%% Copied from ejabberd_sm.erl --record(session, {sid, usr, us, priority, info}). - start(Host, _Opts) -> ejabberd_hooks:add(disco_local_items, Host, ?MODULE, get_local_items, 50), diff --git a/src/mod_muc.erl b/src/mod_muc.erl index a5405559248..a64a0032657 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -58,19 +58,7 @@ -include("logger.hrl"). -include("jlib.hrl"). - --record(muc_room, {name_host = {<<"">>, <<"">>} :: {binary(), binary()} | - {'_', binary()}, - opts = [] :: list() | '_'}). - --record(muc_online_room, - {name_host = {<<"">>, <<"">>} :: {binary(), binary()} | '$1' | - {'_', binary()} | '_', - pid = self() :: pid() | '$2' | '_' | '$1'}). - --record(muc_registered, - {us_host = {{<<"">>, <<"">>}, <<"">>} :: {{binary(), binary()}, binary()} | '$1', - nick = <<"">> :: binary()}). +-include("mod_muc.hrl"). -record(state, {host = <<"">> :: binary(), diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 195cc632c9c..b713e2e5f63 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -26,13 +26,11 @@ -include("logger.hrl"). -include("jlib.hrl"). -include("mod_muc_room.hrl"). +-include("mod_muc.hrl"). -include("ejabberd_http.hrl"). -include("ejabberd_web_admin.hrl"). -include("ejabberd_commands.hrl"). -%% Copied from mod_muc/mod_muc.erl --record(muc_online_room, {name_host, pid}). - %%---------------------------- %% gen_mod %%---------------------------- diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 0f4553189ec..4d8e3965cbf 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -47,13 +47,9 @@ -include("logger.hrl"). -include("jlib.hrl"). - +-include("mod_muc.hrl"). -include("mod_muc_room.hrl"). -%% Copied from mod_muc/mod_muc.erl --record(muc_online_room, {name_host = {<<>>, <<>>} :: {binary(), binary()}, - pid = self() :: pid()}). - -define(T(Text), translate:translate(Lang, Text)). -define(PROCNAME, ejabberd_mod_muc_log). -record(room, {jid, title, subject, subject_author, config}). From 33b67f54baf5ed813c5bb7564deee0f71dff8631 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 15 Jan 2016 15:38:59 +0300 Subject: [PATCH 490/695] Include mod_muc.hrl --- include/mod_muc.hrl | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 include/mod_muc.hrl diff --git a/include/mod_muc.hrl b/include/mod_muc.hrl new file mode 100644 index 00000000000..0d3f7baf7d2 --- /dev/null +++ b/include/mod_muc.hrl @@ -0,0 +1,33 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_muc.hrl +%%% +%%% ejabberd, Copyright (C) 2002-2016 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-record(muc_room, {name_host = {<<"">>, <<"">>} :: {binary(), binary()} | + {'_', binary()}, + opts = [] :: list() | '_'}). + +-record(muc_online_room, + {name_host = {<<"">>, <<"">>} :: {binary(), binary()} | {'_', '$1'} | '$1' | '_', + timestamp = p1_time_compat:timestamp() :: erlang:timestamp() | '_', + pid = self() :: pid() | '$1' | '$2' | '_'}). + +-record(muc_registered, + {us_host = {{<<"">>, <<"">>}, <<"">>} :: {{binary(), binary()}, binary()} | '$1', + nick = <<"">> :: binary()}). From c8bc6cecdc97c09173b5358b4f582f5c6fe850ad Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 15 Jan 2016 15:46:07 +0300 Subject: [PATCH 491/695] Fix records in mod_muc.hrl --- include/mod_muc.hrl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mod_muc.hrl b/include/mod_muc.hrl index 0d3f7baf7d2..8d0c1b09dec 100644 --- a/include/mod_muc.hrl +++ b/include/mod_muc.hrl @@ -24,9 +24,9 @@ opts = [] :: list() | '_'}). -record(muc_online_room, - {name_host = {<<"">>, <<"">>} :: {binary(), binary()} | {'_', '$1'} | '$1' | '_', - timestamp = p1_time_compat:timestamp() :: erlang:timestamp() | '_', - pid = self() :: pid() | '$1' | '$2' | '_'}). + {name_host = {<<"">>, <<"">>} :: {binary(), binary()} | '$1' | + {'_', binary()} | '_', + pid = self() :: pid() | '$2' | '_' | '$1'}). -record(muc_registered, {us_host = {{<<"">>, <<"">>}, <<"">>} :: {{binary(), binary()}, binary()} | '$1', From ad448efa1de80e866fab78fff6cd3888b3294212 Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Sat, 16 Jan 2016 00:15:24 +0900 Subject: [PATCH 492/695] update japanese translation --- priv/msgs/ja.po | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index 868f60ecd9f..5528c9a0bde 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -12,11 +12,11 @@ msgstr "" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" -msgstr "STARTTLS の使用が必要です" +msgstr "STARTTLS の使用が必須です" #: ejabberd_c2s.erl:604 msgid "No resource provided" -msgstr "リソースが提供されませんでした" +msgstr "リソースが指定されていません" #: ejabberd_c2s.erl:1349 msgid "Replaced by new connection" @@ -63,7 +63,6 @@ msgid "User" msgstr "ユーザー" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" msgstr "サーバー:" @@ -242,9 +241,8 @@ msgid "Outgoing s2s Connections:" msgstr "外向き s2s コネクション:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "外向き s2s コネクション:" +msgstr "内向き s2s コネクション:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -673,7 +671,7 @@ msgstr "宛先 ~s" #: mod_configure.erl:782 msgid "From ~s" -msgstr "差出人 ~s" +msgstr "From ~s" #: mod_configure.erl:1002 msgid "Database Tables Configuration at " @@ -962,9 +960,8 @@ msgid "Server ~b" msgstr "サーバー ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "モデレーターのみがチャットルームの件名を変更できます" +msgstr "メンバーのみがこのルームのアーカイブを取得できます" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -1358,17 +1355,16 @@ msgid "Roles for which Presence is Broadcasted" msgstr "" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "モデレーターにのみ" +msgstr "モデレーター" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "参加者" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "傍聴者" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1432,7 +1428,7 @@ msgstr "メッセージアーカイブを有効化" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" -msgstr "CAPTCHA 試験を免除する Jabber ID" +msgstr "CAPTCHA 入力を免除する Jabber ID" #: mod_muc_room.erl:3621 msgid "Enable logging" @@ -1503,7 +1499,7 @@ msgstr "差出人" #: mod_offline.erl:813 msgid "To" -msgstr "宛先" +msgstr "To" #: mod_offline.erl:814 msgid "Packet" @@ -1752,7 +1748,7 @@ msgstr "新しいパスワード:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." -msgstr "ここはこの Jabber サーバーのアカウントを削除するページです。" +msgstr "このページはサーバー上のJabberアカウントを削除するページです。" #: mod_register_web.erl:480 msgid "Unregister" From 7ab3b0d793271b9b930add4d44207046f4d2018b Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Sat, 16 Jan 2016 00:35:23 +0900 Subject: [PATCH 493/695] update japanese translation --- priv/msgs/ja.po | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/priv/msgs/ja.po b/priv/msgs/ja.po index 5528c9a0bde..1cb959081ac 100644 --- a/priv/msgs/ja.po +++ b/priv/msgs/ja.po @@ -64,7 +64,7 @@ msgstr "ユーザー" #: ejabberd_oauth.erl:256 msgid "Server" -msgstr "サーバー:" +msgstr "サーバー" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -74,7 +74,7 @@ msgstr "パスワード" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "許可" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -265,7 +265,7 @@ msgstr "接続リソース:" #: ejabberd_web_admin.erl:1686 mod_register_web.erl:239 #: mod_register_web.erl:475 msgid "Password:" -msgstr "パスワード" +msgstr "パスワード:" #: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 msgid "Remove User" @@ -839,11 +839,11 @@ msgstr "" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "ファイルサイズを指定してください。" #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "ファイル名を指定してください。" #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" @@ -981,7 +981,7 @@ msgstr "チャットルーム" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "空のルーム" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1177,7 +1177,7 @@ msgstr "トラフィックレートの制限を超えました" msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" -msgstr "" +msgstr "このルームにエラーメッセージを送ることは許可されていません。参加者(~s)はエラーメッセージを(~s)を送信してルームからキックされました。" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1352,7 +1352,7 @@ msgstr "誰にでも" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "プレゼンスをブロードキャストするロール" #: mod_muc_room.erl:3486 msgid "Moderator" @@ -1805,7 +1805,7 @@ msgstr "メンバー:" #: mod_shared_roster.erl:1250 msgid "Displayed Groups:" -msgstr "表示グループ" +msgstr "表示グループ:" #: mod_shared_roster.erl:1259 msgid "Group " From 63777f830d912bb129e32242a23b74d917b6f080 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 16 Jan 2016 01:30:22 +0100 Subject: [PATCH 494/695] Use maps instead of dicts in HTTP upload modules ejabberd currently depends on Erlang/OTP 17.1 or higher, so we can now use maps. --- src/mod_http_upload.erl | 8 ++++---- src/mod_http_upload_quota.erl | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index a5e8e1726cd..36d3626be51 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -108,7 +108,7 @@ get_url :: binary(), service_url :: binary() | undefined, thumbnail :: boolean(), - slots = dict:new() :: term()}). % dict:dict() requires Erlang 17. + slots = #{} :: map()}). -record(media_info, {type :: binary(), @@ -676,18 +676,18 @@ create_slot(#state{service_url = ServiceURL}, -spec add_slot(slot(), pos_integer(), timer:tref(), state()) -> state(). add_slot(Slot, Size, Timer, #state{slots = Slots} = State) -> - NewSlots = dict:store(Slot, {Size, Timer}, Slots), + NewSlots = maps:put(Slot, {Size, Timer}, Slots), State#state{slots = NewSlots}. -spec get_slot(slot(), state()) -> {ok, {pos_integer(), timer:tref()}} | error. get_slot(Slot, #state{slots = Slots}) -> - dict:find(Slot, Slots). + maps:find(Slot, Slots). -spec del_slot(slot(), state()) -> state(). del_slot(Slot, #state{slots = Slots} = State) -> - NewSlots = dict:erase(Slot, Slots), + NewSlots = maps:remove(Slot, Slots), State#state{slots = NewSlots}. -spec slot_el(slot() | binary(), state() | binary(), binary()) -> xmlel(). diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index eea23d34bf9..db0b4aa4caf 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -62,7 +62,7 @@ access_hard_quota :: atom(), max_days :: pos_integer() | infinity, docroot :: binary(), - disk_usage = dict:new() :: term(), + disk_usage = #{} :: map(), timers :: [timer:tref()]}). -type state() :: #state{}. @@ -172,7 +172,7 @@ handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, _ -> 0 end, - OldSize = case dict:find({U, S}, DiskUsage) of + OldSize = case maps:find({U, S}, DiskUsage) of {ok, Value} -> Value; error -> @@ -202,7 +202,7 @@ handle_cast({handle_slot_request, #jid{user = U, server = S} = JID, Path, Size}, enforce_quota(Path, Size, OldSize, SoftQuota, HardQuota) end, NewDiskUsage = if is_integer(NewSize) -> - dict:store({U, S}, NewSize, DiskUsage); + maps:put({U, S}, NewSize, DiskUsage); true -> DiskUsage end, From ee1cf939c50e483badc60faba0ee05eed8d1f90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 18 Jan 2016 13:10:12 +0100 Subject: [PATCH 495/695] Make --disable-debug work again --- rebar.config | 1 + 1 file changed, 1 insertion(+) diff --git a/rebar.config b/rebar.config index 8c2c73bafbe..81100027180 100644 --- a/rebar.config +++ b/rebar.config @@ -50,6 +50,7 @@ p1_iconv]}}. {erl_opts, [nowarn_deprecated_function, + {if_var_false, debug, no_debug_info}, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, {if_var_match, db_type, mssql, {d, 'mssql'}}, {if_var_true, lager, {d, 'LAGER'}}, From 9741dba51f762c068317eebacde2bf2a5e43ade4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 18 Jan 2016 13:18:40 +0100 Subject: [PATCH 496/695] Update polish localisation --- priv/msgs/pl.po | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/priv/msgs/pl.po b/priv/msgs/pl.po index 53d7c45fb02..08bf0a03b92 100644 --- a/priv/msgs/pl.po +++ b/priv/msgs/pl.po @@ -14,7 +14,7 @@ msgstr "" "X-Additional-Translator: Marcin Owsiany\n" "X-Additional-Translator: Andrzej Smyk\n" "X-Additional-Translator: Mateusz Gajewski\n" -"X-Generator: Poedit 1.8.4\n" +"X-Generator: Poedit 1.8.6\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" @@ -67,9 +67,8 @@ msgid "User" msgstr "Użytkownik" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Serwer:" +msgstr "Serwer" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -79,7 +78,7 @@ msgstr "Hasło" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Zaakceptuj" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -151,8 +150,7 @@ msgstr "Wirtualne Hosty" msgid "Users" msgstr "Użytkownicy" -#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 mod_configure.erl:524 msgid "Online Users" msgstr "Użytkownicy zalogowani" @@ -246,9 +244,8 @@ msgid "Outgoing s2s Connections:" msgstr "Wychodzące połączenia s2s:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Wychodzące połączenia s2s:" +msgstr "Przychodzące połączenia s2s:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -853,11 +850,11 @@ msgstr "" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Proszę podać rozmiar pliku." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Proszę podać nazwę pliku." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" @@ -974,9 +971,8 @@ msgid "Server ~b" msgstr "Serwer ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Tylko moderatorzy mogą zmienić temat tego pokoju" +msgstr "Tylko moderatorzy mogą przeglądać archiwa tego pokoju" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -996,7 +992,7 @@ msgstr "Pokoje rozmów" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Puste pokoje" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1193,6 +1189,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"Użytkownik nie może wysyłać wiadomości o błędach do pokoju. Użytkownik (~s) " +"wysłał błąd (~s) i został wyrzucony z pokoju" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1366,20 +1364,19 @@ msgstr "wszystkich" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Role dla których wysyłane są statusy" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "tylko moderatorzy" +msgstr "Moderatorzy" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Uczestnicy" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Odwiedzający" #: mod_muc_room.erl:3513 msgid "Make room members-only" From bd383fb8c179e0b013b405dfae53f9617a671cd6 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 18 Jan 2016 13:27:29 +0100 Subject: [PATCH 497/695] mod_mam: Remove unused code This mod_mam version doesn't store groupchat messages in user archives, and it also doesn't support the "store_body_only" option. --- src/mod_mam.erl | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index f4943b3d286..ff362539387 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -1029,16 +1029,6 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, <<"xmlns">>, <<"jabber:client">>, Pkt2)]}, jlib:add_delay_info(Pkt3, LServer, TS). -maybe_update_from_to(Pkt, JidRequestor, Peer, chat, _Nick) -> - case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of - <<"groupchat">> when Peer /= undefined -> - Pkt2 = xml:replace_tag_attr(<<"to">>, - jid:to_string(JidRequestor), - Pkt), - xml:replace_tag_attr(<<"from">>, jid:to_string(Peer), - Pkt2); - _ -> Pkt - end; maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, Peer, {groupchat, Role, _MUCState}, Nick) -> Items = case Role of @@ -1054,7 +1044,9 @@ maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, end, Pkt1 = Pkt#xmlel{children = Items ++ Els}, Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1), - jlib:remove_attr(<<"to">>, Pkt2). + jlib:remove_attr(<<"to">>, Pkt2); +maybe_update_from_to(Pkt, _JidRequestor, _Peer, chat, _Nick) -> + Pkt. is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> PrioRes = ejabberd_sm:get_user_present_resources(U, S), @@ -1386,8 +1378,6 @@ mod_opt_type(default) -> mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; mod_opt_type(request_activates_archiving) -> fun (B) when is_boolean(B) -> B end; -mod_opt_type(store_body_only) -> - fun (B) when is_boolean(B) -> B end; mod_opt_type(_) -> [assume_mam_usage, cache_life_time, cache_size, db_type, default, iqdisc, - request_activates_archiving, store_body_only]. + request_activates_archiving]. From a150bf8fdc8061bc60e5cb1a64a1e06f962d6a4e Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 18 Jan 2016 16:33:37 +0300 Subject: [PATCH 498/695] Make C2S session establishment optional (ECS-11) --- src/ejabberd_c2s.erl | 163 ++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 86 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 021fb97397d..04e41f468f9 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -59,7 +59,7 @@ -export([init/1, wait_for_stream/2, wait_for_auth/2, wait_for_feature_request/2, wait_for_bind/2, - wait_for_session/2, wait_for_sasl_response/2, + wait_for_sasl_response/2, wait_for_resume/2, session_established/2, handle_event/3, handle_sync_event/4, code_change/4, handle_info/3, terminate/3, print_state/1, opt_type/1]). @@ -473,7 +473,8 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> children = []}, #xmlel{name = <<"session">>, attrs = [{<<"xmlns">>, ?NS_SESSION}], - children = []}] + children = + [#xmlel{name = <<"optional">>}]}] ++ RosterVersioningFeature ++ StreamManagementFeature ++ @@ -492,7 +493,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> #xmlel{name = <<"stream:features">>, attrs = [], children = []}), - fsm_next_state(wait_for_session, + fsm_next_state(session_established, StateData#state{server = Server, lang = Lang}) end end; @@ -1059,20 +1060,32 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> send_element(StateData, Err), fsm_next_state(wait_for_bind, StateData); {accept_resource, R2} -> - JID = jid:make(U, StateData#state.server, R2), - Res = IQ#iq{type = result, - sub_el = - [#xmlel{name = <<"bind">>, - attrs = [{<<"xmlns">>, ?NS_BIND}], - children = - [#xmlel{name = <<"jid">>, - attrs = [], - children = - [{xmlcdata, - jid:to_string(JID)}]}]}]}, - send_element(StateData, jlib:iq_to_xml(Res)), - fsm_next_state(wait_for_session, - StateData#state{resource = R2, jid = JID}) + JID = jid:make(U, StateData#state.server, R2), + StateData2 = + StateData#state{resource = R2, jid = JID}, + case open_session(StateData2) of + {ok, StateData3} -> + Res = + IQ#iq{ + type = result, + sub_el = + [#xmlel{name = <<"bind">>, + attrs = [{<<"xmlns">>, ?NS_BIND}], + children = + [#xmlel{name = <<"jid">>, + attrs = [], + children = + [{xmlcdata, + jid:to_string(JID)}]}]}]}, + send_element(StateData3, jlib:iq_to_xml(Res)), + fsm_next_state_pack( + session_established, + StateData3); + {error, Error} -> + Err = jlib:make_error_reply(El, Error), + send_element(StateData, Err), + fsm_next_state(wait_for_bind, StateData) + end end end; _ -> fsm_next_state(wait_for_bind, StateData) @@ -1090,75 +1103,49 @@ wait_for_bind(closed, StateData) -> wait_for_bind(stop, StateData) -> {stop, normal, StateData}. -wait_for_session({xmlstreamelement, #xmlel{name = Name} = El}, StateData) - when ?IS_STREAM_MGMT_TAG(Name) -> - fsm_next_state(wait_for_session, dispatch_stream_mgmt(El, StateData)); -wait_for_session({xmlstreamelement, El}, StateData) -> - NewStateData = update_num_stanzas_in(StateData, El), - case jlib:iq_query_info(El) of - #iq{type = set, xmlns = ?NS_SESSION} -> - U = NewStateData#state.user, - R = NewStateData#state.resource, - JID = NewStateData#state.jid, - case acl:match_rule(NewStateData#state.server, - NewStateData#state.access, JID) of - allow -> - ?INFO_MSG("(~w) Opened session for ~s", - [NewStateData#state.socket, jid:to_string(JID)]), - Res = jlib:make_result_iq_reply(El#xmlel{children = []}), - NewState = send_stanza(NewStateData, Res), - change_shaper(NewState, JID), - {Fs, Ts} = ejabberd_hooks:run_fold( - roster_get_subscription_lists, - NewState#state.server, - {[], []}, - [U, NewState#state.server]), - LJID = jid:tolower(jid:remove_resource(JID)), - Fs1 = [LJID | Fs], - Ts1 = [LJID | Ts], - PrivList = - ejabberd_hooks:run_fold( - privacy_get_user_list, - NewState#state.server, - #userlist{}, - [U, NewState#state.server]), - Conn = get_conn_type(NewState), - Info = [{ip, NewState#state.ip}, {conn, Conn}, - {auth_module, NewState#state.auth_module}], - ejabberd_sm:open_session( - NewState#state.sid, U, NewState#state.server, R, Info), - UpdatedStateData = - NewState#state{ - conn = Conn, - pres_f = ?SETS:from_list(Fs1), - pres_t = ?SETS:from_list(Ts1), - privacy_list = PrivList}, - fsm_next_state_pack(session_established, - UpdatedStateData); - _ -> - ejabberd_hooks:run(forbidden_session_hook, - NewStateData#state.server, [JID]), - ?INFO_MSG("(~w) Forbidden session for ~s", - [NewStateData#state.socket, jid:to_string(JID)]), - Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED), - send_element(NewStateData, Err), - fsm_next_state(wait_for_session, NewStateData) - end; - _ -> - fsm_next_state(wait_for_session, NewStateData) - end; -wait_for_session(timeout, StateData) -> - {stop, normal, StateData}; -wait_for_session({xmlstreamend, _Name}, StateData) -> - send_trailer(StateData), {stop, normal, StateData}; -wait_for_session({xmlstreamerror, _}, StateData) -> - send_element(StateData, ?INVALID_XML_ERR), - send_trailer(StateData), - {stop, normal, StateData}; -wait_for_session(closed, StateData) -> - {stop, normal, StateData}; -wait_for_session(stop, StateData) -> - {stop, normal, StateData}. +open_session(StateData) -> + U = StateData#state.user, + R = StateData#state.resource, + JID = StateData#state.jid, + case acl:match_rule(StateData#state.server, + StateData#state.access, JID) of + allow -> + ?INFO_MSG("(~w) Opened session for ~s", + [StateData#state.socket, jid:to_string(JID)]), + change_shaper(StateData, JID), + {Fs, Ts} = ejabberd_hooks:run_fold( + roster_get_subscription_lists, + StateData#state.server, + {[], []}, + [U, StateData#state.server]), + LJID = jid:tolower(jid:remove_resource(JID)), + Fs1 = [LJID | Fs], + Ts1 = [LJID | Ts], + PrivList = + ejabberd_hooks:run_fold( + privacy_get_user_list, + StateData#state.server, + #userlist{}, + [U, StateData#state.server]), + Conn = get_conn_type(StateData), + Info = [{ip, StateData#state.ip}, {conn, Conn}, + {auth_module, StateData#state.auth_module}], + ejabberd_sm:open_session( + StateData#state.sid, U, StateData#state.server, R, Info), + UpdatedStateData = + StateData#state{ + conn = Conn, + pres_f = ?SETS:from_list(Fs1), + pres_t = ?SETS:from_list(Ts1), + privacy_list = PrivList}, + {ok, UpdatedStateData}; + _ -> + ejabberd_hooks:run(forbidden_session_hook, + StateData#state.server, [JID]), + ?INFO_MSG("(~w) Forbidden session for ~s", + [StateData#state.socket, jid:to_string(JID)]), + {error, ?ERR_NOT_ALLOWED} + end. session_established({xmlstreamelement, #xmlel{name = Name} = El}, StateData) when ?IS_STREAM_MGMT_TAG(Name) -> @@ -1274,6 +1261,10 @@ session_established2(El, StateData) -> Xmlns == (?NS_BLOCKING) -> process_privacy_iq(FromJID, ToJID, IQ, NewStateData); + #iq{xmlns = ?NS_SESSION} -> + Res = jlib:make_result_iq_reply( + NewEl#xmlel{children = []}), + send_stanza(NewStateData, Res); _ -> NewEl0 = ejabberd_hooks:run_fold( user_send_packet, Server, NewEl, From 05bc0d4d1737a8d492aae16b730dc8a53a5253c5 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 18 Jan 2016 18:42:28 +0100 Subject: [PATCH 499/695] Update Ukrainian translation (thanks to Oleg Deordiev) --- priv/msgs/uk.po | 112 ++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 61 deletions(-) diff --git a/priv/msgs/uk.po b/priv/msgs/uk.po index 5548afb49fe..61506ab2e4d 100644 --- a/priv/msgs/uk.po +++ b/priv/msgs/uk.po @@ -5,14 +5,16 @@ msgstr "" "PO-Revision-Date: \n" "Last-Translator: Konstantin Khomoutov \n" "Language-Team: \n" -"Language: \n" +"Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Ukrainian (українська)\n" +"X-Additional-Translator: Oleg Deordiev\n" "X-Additional-Translator: Ruslan Rakhmanin\n" "X-Additional-Translator: Stoune\n" "X-Additional-Translator: Sergei Golovan\n" +"X-Generator: Poedit 1.8.6\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" @@ -37,7 +39,7 @@ msgstr "Маршрутизація цієї строфи була відміне #: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Занадто багато пакетів без відповідей" #: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" @@ -65,7 +67,6 @@ msgid "User" msgstr "Користувач" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" msgstr "Сервер:" @@ -77,7 +78,7 @@ msgstr "Пароль" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Прийняти" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -149,8 +150,7 @@ msgstr "віртуальні хости" msgid "Users" msgstr "Користувачі" -#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 mod_configure.erl:524 msgid "Online Users" msgstr "Підключені користувачі" @@ -244,9 +244,8 @@ msgid "Outgoing s2s Connections:" msgstr "Вихідні s2s-з'єднання:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Вихідні s2s-з'єднання:" +msgstr "Вхідні s2s-з'єднання:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -259,9 +258,8 @@ msgid "Change Password" msgstr "Змінити пароль" #: ejabberd_web_admin.erl:1673 -#, fuzzy msgid "User ~s" -msgstr "Користувач " +msgstr "Користувач ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" @@ -293,9 +291,8 @@ msgid "Stopped Nodes" msgstr "Зупинені вузли" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 -#, fuzzy msgid "Node ~p" -msgstr "Вузол " +msgstr "Вузол ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -332,9 +329,8 @@ msgid "RPC Call Error" msgstr "Помилка виклику RPC" #: ejabberd_web_admin.erl:1917 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Таблиці бази даних на " +msgstr "Таблиці бази даних на ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -357,9 +353,8 @@ msgid "Error" msgstr "Помилка" #: ejabberd_web_admin.erl:1955 -#, fuzzy msgid "Backup of ~p" -msgstr "Резервне копіювання " +msgstr "Резервне копіювання ~p" #: ejabberd_web_admin.erl:1959 msgid "" @@ -418,7 +413,7 @@ msgstr "Експорт даних користувачів домена до ф #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Експорт усіх таблиць, як SQL запити, у файл" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" @@ -433,9 +428,8 @@ msgid "Listened Ports at " msgstr "Відкриті порти на " #: ejabberd_web_admin.erl:2144 -#, fuzzy msgid "Modules at ~p" -msgstr "Модулі на " +msgstr "Модулі на ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" @@ -466,13 +460,12 @@ msgid "Transactions Logged:" msgstr "Транзакції запротокольовані:" #: ejabberd_web_admin.erl:2243 -#, fuzzy msgid "Update ~p" -msgstr "Поновлення " +msgstr "Оновлення ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" -msgstr "План поновлення" +msgstr "План оновлення" #: ejabberd_web_admin.erl:2255 msgid "Modified modules" @@ -528,7 +521,7 @@ msgstr "Понг" #: mod_announce.erl:523 msgid "Really delete message of the day?" -msgstr "Насправді видалити повідомлення дня?" +msgstr "Насправді, видалити повідомлення дня?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" @@ -678,7 +671,7 @@ msgstr "Керування резервним копіюванням" #: mod_configure.erl:617 msgid "Import Users From jabberd14 Spool Files" -msgstr "Імпорт користувачів зі спулу jabberd14" +msgstr "Імпорт користувачів з jabberd14 файлів \"Spool\"" #: mod_configure.erl:762 msgid "To ~s" @@ -850,18 +843,20 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Забагато (~p) помилок авторизації з цієї IP адреси (~s). Адресу буде " +"розблоковано о ~s UTC" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Будь ласка вкажіть розмір файлу." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Будь ласка вкажіть ім'я файлу." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Ця IP адреса у чорному списку ~s" #: mod_irc.erl:220 mod_muc.erl:467 msgid "Access denied by service policy" @@ -976,9 +971,8 @@ msgid "Server ~b" msgstr "Сервер ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Тільки модератори можуть змінювати тему в цій кімнаті" +msgstr "Тільки модератори можуть запитувати архіви цієї кімнати" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -998,7 +992,7 @@ msgstr "Кімнати" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Порожні кімнати" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1034,26 +1028,23 @@ msgstr "ejabberd MUC модуль" #: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 #: mod_muc_admin.erl:320 msgid "Multi-User Chat" -msgstr "" +msgstr "Багато-користувальницький чат" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Total rooms" -msgstr "Кімнати" +msgstr "Всього кімнат" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Permanent rooms" -msgstr "вийшов(ла) з кімнати" +msgstr "Постійні кімнати" #: mod_muc_admin.erl:251 -#, fuzzy msgid "Registered nicknames" -msgstr "Зареєстровані користувачі" +msgstr "Зареєстровані імена" #: mod_muc_admin.erl:254 msgid "List of rooms" -msgstr "" +msgstr "Перелік кімнат" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" @@ -1200,6 +1191,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"Не дозволяється відправляти помилкові повідомлення в кімнату. Учасник (~s) " +"відправив помилкове повідомлення (~s), та був виганий з кімнати" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1208,19 +1201,20 @@ msgstr "Не дозволяється надсилати приватні пов #: mod_muc_room.erl:316 msgid "Please, wait for a while before sending new voice request" msgstr "" +"Будь ласка, почекайте деякий час перед тим, як знову відправляти голосовий " +"запит" #: mod_muc_room.erl:329 msgid "Voice requests are disabled in this conference" -msgstr "" +msgstr "Голосові запити відключені в цій конференції" #: mod_muc_room.erl:347 msgid "Failed to extract JID from your voice request approval" -msgstr "" +msgstr "Помилка витягнення JID з вашого схвалення голосового запиту" #: mod_muc_room.erl:377 -#, fuzzy msgid "Only moderators can approve voice requests" -msgstr "Дозволити користувачам надсилати запрошення" +msgstr "Тільки модератори можуть схвалювати голосові запити" #: mod_muc_room.erl:389 msgid "Improper message type" @@ -1374,20 +1368,19 @@ msgstr "всім учасникам" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Ролі для яких поширюється наявність" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "тільки модераторам" +msgstr "Модератор" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Учасник" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Відвідувач" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1410,13 +1403,12 @@ msgid "Allow users to send private messages" msgstr "Дозволити приватні повідомлення" #: mod_muc_room.erl:3533 -#, fuzzy msgid "Allow visitors to send private messages to" -msgstr "Дозволити приватні повідомлення" +msgstr "Дозволити відвідувачам відсилати приватні повідомлення" #: mod_muc_room.erl:3551 msgid "nobody" -msgstr "" +msgstr "ніхто" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" @@ -1436,13 +1428,12 @@ msgid "Allow visitors to change nickname" msgstr "Дозволити відвідувачам змінювати псевдонім" #: mod_muc_room.erl:3589 -#, fuzzy msgid "Allow visitors to send voice requests" -msgstr "Дозволити користувачам надсилати запрошення" +msgstr "Дозволити відвідувачам надсилати голосові запрошення" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" -msgstr "" +msgstr "Мінімальний інтервал між голосовими запитами (в секундах)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" @@ -1450,7 +1441,7 @@ msgstr "Зробити кімнату захищеною капчею" #: mod_muc_room.erl:3606 msgid "Enable message archiving" -msgstr "" +msgstr "Ввімкнути архівацію повідомлень" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1476,20 +1467,19 @@ msgstr "приватна, " #: mod_muc_room.erl:4326 msgid "Voice request" -msgstr "" +msgstr "Голосовий запит" #: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." -msgstr "" +msgstr "Підтвердить або відхилите голосовий запит" #: mod_muc_room.erl:4351 -#, fuzzy msgid "User JID" -msgstr "Користувач " +msgstr "JID Користувача" #: mod_muc_room.erl:4355 msgid "Grant voice to this person?" -msgstr "" +msgstr "Надати голос персоні?" #: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" @@ -1501,11 +1491,11 @@ msgstr "пароль:" #: mod_multicast.erl:291 msgid "Multicast" -msgstr "" +msgstr "Мультікаст" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" -msgstr "" +msgstr "Мультікаст ejabberd сервіс" #: mod_offline.erl:647 msgid "" From 6b775fb9a13fc17dde852de18f83ea63bdcbf0c7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 18 Jan 2016 18:42:58 +0100 Subject: [PATCH 500/695] Update Walon translation (thanks to Pablo Saratxaga) --- priv/msgs/wa.po | 314 +++++++++++++++++++++--------------------------- 1 file changed, 139 insertions(+), 175 deletions(-) diff --git a/priv/msgs/wa.po b/priv/msgs/wa.po index c66da1e5c39..4eb6708146b 100644 --- a/priv/msgs/wa.po +++ b/priv/msgs/wa.po @@ -1,11 +1,16 @@ +# Pablo Saratxaga , 2015 msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" -"Last-Translator: Pablo Saratxaga\n" +"PO-Revision-Date: 2015-01-18 12:19+0000\n" +"Last-Translator: Pablo Saratxaga \n" +"Language-Team: Pablo Saratxaga \n" +"Language: wa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Walon (Walloon)\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" @@ -26,32 +31,31 @@ msgstr "a stî pité evoye" #: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." -msgstr "" +msgstr "Vosse djivêye di privaceye active a rfuzé l' evoyaedje di ç' messaedje ci." #: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Pår trop di messaedjes sins acertinaedje di rçuvaedje" #: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 -#, fuzzy msgid "Enter the text you see" -msgstr "Dinez l' tchimin viè l' fitchî tecse" +msgstr "Tapez l' tecse ki vos voeyoz" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" -msgstr "" +msgstr "Vos messaedjes po ~s sont blokés. Po les disbloker, alez vey ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." -msgstr "" +msgstr "Si vos n' voeyoz nole imådje CAPTCHA chal, vizitez l' pådje waibe." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" -msgstr "" +msgstr "Pådje web CAPTCHA" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." -msgstr "" +msgstr "Li CAPTCHA est valide." #: ejabberd_oauth.erl:253 ejabberd_web_admin.erl:1403 #: ejabberd_web_admin.erl:1458 mod_register.erl:265 mod_vcard.erl:490 @@ -59,9 +63,8 @@ msgid "User" msgstr "Uzeu" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Måy" +msgstr "Sierveu" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -71,12 +74,12 @@ msgstr "Sicret" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Accepter" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 msgid "Unauthorized" -msgstr "" +msgstr "Nén otorijhî" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" @@ -182,9 +185,8 @@ msgid "Statistics" msgstr "Sitatistikes" #: ejabberd_web_admin.erl:1014 -#, fuzzy msgid "Not Found" -msgstr "Nuk nén trové" +msgstr "Nén trové" #: ejabberd_web_admin.erl:1027 msgid "Node not found" @@ -239,9 +241,8 @@ msgid "Outgoing s2s Connections:" msgstr "Raloyaedjes s2s e rexhowe:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Raloyaedjes s2s e rexhowe:" +msgstr "Raloyaedjes s2s en intrêye:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -254,9 +255,8 @@ msgid "Change Password" msgstr "Candjî l' sicret" #: ejabberd_web_admin.erl:1673 -#, fuzzy msgid "User ~s" -msgstr "Uzeu " +msgstr "Uzeu ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" @@ -288,9 +288,8 @@ msgid "Stopped Nodes" msgstr "Nuks essoctés" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 -#, fuzzy msgid "Node ~p" -msgstr "Nuk " +msgstr "Nuk ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -327,9 +326,8 @@ msgid "RPC Call Error" msgstr "Aroke di houcaedje RPC" #: ejabberd_web_admin.erl:1917 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Tåves del båze di dnêyes so " +msgstr "Tåves del båze di dnêyes so ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -341,7 +339,7 @@ msgstr "Sôre di wårdaedje" #: ejabberd_web_admin.erl:1929 msgid "Elements" -msgstr "" +msgstr "Elemints" #: ejabberd_web_admin.erl:1930 msgid "Memory" @@ -349,15 +347,13 @@ msgstr "Memwere" #: ejabberd_web_admin.erl:1952 ejabberd_web_admin.erl:2123 msgid "Error" -msgstr "" +msgstr "Aroke" #: ejabberd_web_admin.erl:1955 -#, fuzzy msgid "Backup of ~p" -msgstr "Copeye di såvrité po " +msgstr "Copeye di såvrité po ~p" #: ejabberd_web_admin.erl:1959 -#, fuzzy msgid "" "Please note that these options will only backup the builtin Mnesia database. " "If you are using the ODBC module, you also need to backup your SQL database " @@ -402,38 +398,35 @@ msgstr "Rapexhî do côp foû d' ene copeye di såvrité tecse:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" -msgstr "" +msgstr "Sititchî des dnêyes uzeus foû d' on fitchî PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" -msgstr "" +msgstr "Espoirter les dnêyes di tos les uzeus do sierveu viè des fitchîs PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" -msgstr "" +msgstr "Espoirter les dnêyes di tos les uzeus do sierveu viè des fitchîs PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Espoirter totes les tåves, come des cmandes SQL, viè on fitchî" #: ejabberd_web_admin.erl:2076 -#, fuzzy msgid "Import user data from jabberd14 spool file:" -msgstr "Sititchî des uzeus Jabberd 1.4" +msgstr "Sititchî des dnêyes uzeus foû d' on fitchî spoûle jabberd14:" #: ejabberd_web_admin.erl:2087 -#, fuzzy msgid "Import users data from jabberd14 spool directory:" -msgstr "Sititchî des uzeus Jabberd 1.4" +msgstr "Sititchî des dnêyes uzeus foû d' on ridant spoûle jabberd14:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " msgstr "Pôrts drovous so " #: ejabberd_web_admin.erl:2144 -#, fuzzy msgid "Modules at ~p" -msgstr "Modules so " +msgstr "Modules so ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" @@ -464,18 +457,16 @@ msgid "Transactions Logged:" msgstr "Transaccions wårdêyes e djournå:" #: ejabberd_web_admin.erl:2243 -#, fuzzy msgid "Update ~p" -msgstr "Metaedje a djoû " +msgstr "Metaedje a djoû di ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" msgstr "Plan d' metaedje a djoû" #: ejabberd_web_admin.erl:2255 -#, fuzzy msgid "Modified modules" -msgstr "Modules metous a djoû" +msgstr "Modules di candjîs" #: ejabberd_web_admin.erl:2256 msgid "Update script" @@ -491,16 +482,15 @@ msgstr "Acertinaedje do scripe" #: ejabberd_web_admin.erl:2438 msgid "IP" -msgstr "" +msgstr "IP" #: ejabberd_web_admin.erl:2438 msgid "Port" msgstr "Pôrt" #: ejabberd_web_admin.erl:2439 -#, fuzzy msgid "Protocol" -msgstr "Pôrt" +msgstr "Protocole" #: ejabberd_web_admin.erl:2440 ejabberd_web_admin.erl:2595 msgid "Module" @@ -847,18 +837,20 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"I gn a-st avou pår trop (~p) d' otintifiaedjes k' ont fwait berwete vinant " +"di ciste adresse IP la (~s). L' adresse serè disblokêye a ~s UTC" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Dinez l' grandeu do fitchî." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Dinez l' no do fitchî." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Ciste adresse IP est so ene noere djivêye e ~s" #: mod_irc.erl:220 mod_muc.erl:467 msgid "Access denied by service policy" @@ -883,105 +875,98 @@ msgid "Registration in mod_irc for " msgstr "Edjîstraedje dins mod_irc po " #: mod_irc.erl:659 -#, fuzzy msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -"Dinez les nos d' uzeu et ls ecôdaedjes ki vos vloz eployî po vs raloyî åzès " -"sierveus IRC" +"Dinez l' no d' uzeu, les ecôdaedjes, les pôrts et les screts ki vos vloz " +"eployî po vs raloyî åzès sierveus IRC" #: mod_irc.erl:667 msgid "IRC Username" msgstr "No d' uzeu IRC" #: mod_irc.erl:682 -#, fuzzy msgid "" "If you want to specify different ports, passwords, encodings for IRC " "servers, fill this list with values in format '{\"irc server\", \"encoding" "\", port, \"password\"}'. By default this service use \"~s\" encoding, port " "~p, empty password." msgstr "" -"Si vos vloz dner des ecôdaedjes diferins po les sierveus IRC, rimplixhoz " -"cisse djivêye ci avou des valixhances del cogne «{\"sierveu irc\", " -"\"ecôdaedje\"}». Li prémetou ecôdaedje do siervice c' est «~s»." +"Si vos vloz dner des pôrts, sicrets ou ecôdaedjes diferins po les sierveus " +"IRC, rimplixhoz cisse djivêye ci avou des valixhances del cogne «{\"sierveu " +"irc\", \"ecôdaedje\", pôrt, \"sicret\"}». Les prémetowès valixhances do " +"siervice sont «~s» po l' ecôdaedje, «~p» pol pôrt, et on vude sicret." #: mod_irc.erl:704 -#, fuzzy msgid "" "Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." "net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." msgstr "" -"Egzimpe: [{\"irc.lucky.net\", \"koi8-r\"}, {\"vendetta.fef.net\", " -"\"iso8859-1\"}]." +"Egzimpe: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef." +"net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]." #: mod_irc.erl:713 msgid "Connections parameters" -msgstr "" +msgstr "Parametes des raloyaedjes" #: mod_irc.erl:886 msgid "Join IRC channel" -msgstr "" +msgstr "Radjonde canå IRC" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" -msgstr "" +msgstr "Canå IRC (èn nén mete li prumî #)" #: mod_irc.erl:903 -#, fuzzy msgid "IRC server" -msgstr "No d' uzeu IRC" +msgstr "Sierveu IRC" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." -msgstr "" +msgstr "Radjonde li canå IRC droci." #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" -msgstr "" +msgstr "Radjonde li canå IRC e cist ID Jabber: ~s" #: mod_irc.erl:1046 msgid "IRC settings" -msgstr "" +msgstr "Apontiaedjes IRC" #: mod_irc.erl:1051 -#, fuzzy msgid "" "Enter username and encodings you wish to use for connecting to IRC servers. " "Press 'Next' to get more fields to fill in. Press 'Complete' to save " "settings." msgstr "" "Dinez les nos d' uzeu et ls ecôdaedjes ki vos vloz eployî po vs raloyî åzès " -"sierveus IRC" +"sierveus IRC Clitchîz so «Shuvant» po-z aveur di pus di tchamps a rimpli. " +"Clitchîz so «Fini» po schaper les apontiaedjes." #: mod_irc.erl:1060 -#, fuzzy msgid "IRC username" msgstr "No d' uzeu IRC" #: mod_irc.erl:1126 -#, fuzzy msgid "Password ~b" -msgstr "Sicret" +msgstr "Sicret ~b" #: mod_irc.erl:1137 -#, fuzzy msgid "Port ~b" -msgstr "Pôrt" +msgstr "Pôrt ~b" #: mod_irc.erl:1150 msgid "Encoding for server ~b" -msgstr "" +msgstr "Ecôdaedje pol sierveu ~b" #: mod_irc.erl:1171 msgid "Server ~b" -msgstr "" +msgstr "Sierveu ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" +msgstr "Seulmint les mimbes polèt cweri les årtchives dins cisse såle ci" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -1002,13 +987,12 @@ msgstr "Såles di berdelaedje" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Såles vudes" #: mod_muc.erl:933 -#, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" -"Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" +"Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer l' metou no" #: mod_muc.erl:943 msgid "Nickname Registration at " @@ -1024,7 +1008,6 @@ msgid "Nickname" msgstr "Metou no" #: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 -#, fuzzy msgid "That nickname is registered by another person" msgstr "Li metou no est ddja edjîstré pa ene ôte sakî" @@ -1039,26 +1022,23 @@ msgstr "Module MUC (såles di berdelaedje) po ejabberd" #: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 #: mod_muc_admin.erl:320 msgid "Multi-User Chat" -msgstr "" +msgstr "Berdelaedje a sacwants" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Total rooms" -msgstr "Såles di berdelaedje" +msgstr "Totå di såles" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Permanent rooms" -msgstr "cwite li såle" +msgstr "Såles tofer la" #: mod_muc_admin.erl:251 -#, fuzzy msgid "Registered nicknames" -msgstr "Uzeus edjistrés" +msgstr "Metous nos edjistrés" #: mod_muc_admin.erl:254 msgid "List of rooms" -msgstr "" +msgstr "Djivêye des såles" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" @@ -1098,24 +1078,20 @@ msgid " has set the subject to: " msgstr " a candjî l' tite a: " #: mod_muc_log.erl:493 -#, fuzzy msgid "Chatroom is created" -msgstr "Såles di berdelaedje" +msgstr "Li såle di berdelaedje est ahivêye" #: mod_muc_log.erl:495 -#, fuzzy msgid "Chatroom is destroyed" -msgstr "Såles di berdelaedje" +msgstr "Li såle di berdelaedje est distrûte" #: mod_muc_log.erl:497 -#, fuzzy msgid "Chatroom is started" -msgstr "Såles di berdelaedje" +msgstr "Li såle di berdelaedje est enondêye" #: mod_muc_log.erl:499 -#, fuzzy msgid "Chatroom is stopped" -msgstr "Såles di berdelaedje" +msgstr "Li såle di berdelaedje est ahotêye" #: mod_muc_log.erl:503 msgid "Monday" @@ -1198,9 +1174,8 @@ msgid "Room Configuration" msgstr "Apontiaedje del såle" #: mod_muc_log.erl:932 -#, fuzzy msgid "Room Occupants" -msgstr "Nombe di prezints" +msgstr "Prezints el såle" #: mod_muc_room.erl:163 msgid "Traffic rate limit is exceeded" @@ -1211,6 +1186,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"On n' pout nén evoyî des messaedjes d' aroke sol såle. Li pårticipan (~s) " +"a-st evoyî on messaedje d' aroke (~s) ey a stî tapé foû." #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1218,20 +1195,20 @@ msgstr "On n' pout nén evoyî des messaedjes privés dins cisse conferince ci" #: mod_muc_room.erl:316 msgid "Please, wait for a while before sending new voice request" -msgstr "" +msgstr "Ratindez ene miete s' i vs plait divant d' rivoyî ene nouve " +"dimande di vwès" #: mod_muc_room.erl:329 msgid "Voice requests are disabled in this conference" -msgstr "" +msgstr "Les dmandes di vwès sont dismetowes e cisse conferince ci" #: mod_muc_room.erl:347 msgid "Failed to extract JID from your voice request approval" -msgstr "" +msgstr "Nén moyén di rsaetchî on JID foû d' l' aprovaedje di vosse dimande di vwès" #: mod_muc_room.erl:377 -#, fuzzy msgid "Only moderators can approve voice requests" -msgstr "Les uzeus polèt evoyî priyaedjes" +msgstr "Seulmint les moderateus polèt aprover des dmandes di vwès" #: mod_muc_room.erl:389 msgid "Improper message type" @@ -1264,7 +1241,6 @@ msgstr "" "såle ci" #: mod_muc_room.erl:961 -#, fuzzy msgid "" "Only moderators and participants are allowed to change the subject in this " "room" @@ -1273,7 +1249,6 @@ msgstr "" "cisse såle ci" #: mod_muc_room.erl:966 -#, fuzzy msgid "Only moderators are allowed to change the subject in this room" msgstr "Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci" @@ -1286,7 +1261,6 @@ msgid "Visitors are not allowed to change their nicknames in this room" msgstr "Les viziteus èn polèt nén candjî leus metous no po ç' såle ci" #: mod_muc_room.erl:1093 mod_muc_room.erl:1835 -#, fuzzy msgid "That nickname is already in use by another occupant" msgstr "Li metou no est ddja eployî pa ene ôte sakî sol såle" @@ -1295,22 +1269,20 @@ msgid "You have been banned from this room" msgstr "Vos avoz stî bani di cisse såle ci" #: mod_muc_room.erl:1826 -#, fuzzy msgid "Membership is required to enter this room" msgstr "I fåt esse mimbe po poleur intrer dins cisse såle ci" #: mod_muc_room.erl:1872 -#, fuzzy msgid "A password is required to enter this room" msgstr "I fåt dner on scret po poleur intrer dins cisse såle ci" #: mod_muc_room.erl:1898 mod_register.erl:295 msgid "Too many CAPTCHA requests" -msgstr "" +msgstr "Pår trop di dmandes CAPTCHA" #: mod_muc_room.erl:1908 mod_register.erl:301 msgid "Unable to generate a CAPTCHA" -msgstr "" +msgstr "Nén moyén di djenerer on CAPTCHA" #: mod_muc_room.erl:1919 msgid "Incorrect password" @@ -1345,18 +1317,16 @@ msgid "Owner privileges required" msgstr "I fåt des priviledjes di prôpietaire" #: mod_muc_room.erl:3348 -#, fuzzy msgid "Configuration of room ~s" -msgstr "Apontiaedje po " +msgstr "Apontiaedje del såle ~s" #: mod_muc_room.erl:3359 msgid "Room title" msgstr "Tite del såle" #: mod_muc_room.erl:3361 mod_muc_room.erl:4190 -#, fuzzy msgid "Room description" -msgstr "Discrijhaedje:" +msgstr "Discrijhaedje del såle" #: mod_muc_room.erl:3369 msgid "Make room persistent" @@ -1396,20 +1366,19 @@ msgstr "tot l' minme kî" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Roles ki leu prezince est difuzêye" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "les moderateus seulmint" +msgstr "Moderateu" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Pårticipant" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Viziteu" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1424,7 +1393,6 @@ msgid "Default users as participants" msgstr "Les uzeus sont des pårticipants come prémetowe dujhance" #: mod_muc_room.erl:3522 -#, fuzzy msgid "Allow users to change the subject" msgstr "Les uzeus polèt candjî l' tite" @@ -1433,13 +1401,12 @@ msgid "Allow users to send private messages" msgstr "Les uzeus polèt evoyî des messaedjes privés" #: mod_muc_room.erl:3533 -#, fuzzy msgid "Allow visitors to send private messages to" msgstr "Les uzeus polèt evoyî des messaedjes privés" #: mod_muc_room.erl:3551 msgid "nobody" -msgstr "" +msgstr "nolu" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" @@ -1460,26 +1427,24 @@ msgid "Allow visitors to change nickname" msgstr "Permete ki les viziteus candjexhe leus metous nos" #: mod_muc_room.erl:3589 -#, fuzzy msgid "Allow visitors to send voice requests" -msgstr "Les uzeus polèt evoyî priyaedjes" +msgstr "Les uzeus polèt evoyî des dmandes di vwès" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" -msgstr "" +msgstr "Tins minimom etur deus dmandes di vwès (e segondes)" #: mod_muc_room.erl:3599 -#, fuzzy msgid "Make room CAPTCHA protected" -msgstr "Rinde li såle di berdelaedje protedjeye pa scret" +msgstr "Rinde li såle di berdelaedje protedjeye pa CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" -msgstr "" +msgstr "Mete en alaedje l' årtchivaedje des messaedjes" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" -msgstr "" +msgstr "Esclure les IDs Jabber des kesses CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" @@ -1499,20 +1464,19 @@ msgstr "privé, " #: mod_muc_room.erl:4326 msgid "Voice request" -msgstr "" +msgstr "Dimande di vwès" #: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." -msgstr "" +msgstr "Aprover oudonbén rifuzer li dmande di vwès." #: mod_muc_room.erl:4351 -#, fuzzy msgid "User JID" -msgstr "Uzeu " +msgstr "JID d' l' uzeu" #: mod_muc_room.erl:4355 msgid "Grant voice to this person?" -msgstr "" +msgstr "Permete li vwès po cisse djin ci?" #: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" @@ -1524,11 +1488,11 @@ msgstr "li scret est" #: mod_multicast.erl:291 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" -msgstr "" +msgstr "siervice multicast d' ejabberd" #: mod_offline.erl:647 msgid "" @@ -1562,9 +1526,8 @@ msgid "Offline Messages:" msgstr "Messaedjes ki ratindèt:" #: mod_offline.erl:996 -#, fuzzy msgid "Remove All Offline Messages" -msgstr "Messaedjes ki ratindèt" +msgstr "Oister tos les messaedjes ki ratindèt" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" @@ -1649,12 +1612,11 @@ msgstr "Dinez l' modele d' eplaideu" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" -msgstr "" +msgstr "Purdjî tos les cayets cwand l' eplaideu aloyî va foû raloyaedje" #: mod_pubsub.erl:3771 -#, fuzzy msgid "Specify the event message type" -msgstr "Sipecifyî l' modele d' accès" +msgstr "Sipecifyî l' sôre do messaedje d' evenmint" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" @@ -1670,17 +1632,16 @@ msgstr "Seulmint evoyî des notifiaedje åzès uzeus disponibes" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" -msgstr "" +msgstr "Les ramexhnêyes k' on nuk est afiyî avou" #: mod_register.erl:209 msgid "The CAPTCHA verification has failed" -msgstr "" +msgstr "Li verifiaedje CAPTCHA a fwait berwete" #: mod_register.erl:253 -#, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" -"Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer on metou no" +"Vos avoz mezåjhe d' on cliyint ki sopoite x:data eyet CAPTCHA po vs edjîstrer" #: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" @@ -1688,50 +1649,48 @@ msgstr "" "Tchoezixhoz on no d' uzeu eyet on scret po vs edjîstrer so ç' sierveu ci" #: mod_register.erl:373 mod_register.erl:421 -#, fuzzy msgid "The password is too weak" -msgstr "li scret est" +msgstr "li scret est trop flåw" #: mod_register.erl:426 -#, fuzzy msgid "Users are not allowed to register accounts so quickly" msgstr "Les noveas uzeus n' si polèt nén edjîstrer si raddimint" #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." -msgstr "" +msgstr "Li conte Jabber da vosse a stî ahivé comifåt." #: mod_register_web.erl:110 msgid "There was an error creating the account: " -msgstr "" +msgstr "Åk n' a nén stî tot ahivant l' conte: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." -msgstr "" +msgstr "Li conte Jabber da vosse a stî disfacé comifåt." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " -msgstr "" +msgstr "Åk n' a nén stî tot disfaçant l' conte: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." -msgstr "" +msgstr "Li scret do conte Jabber da vosse a stî candjî comifåt." #: mod_register_web.erl:140 msgid "There was an error changing the password: " -msgstr "" +msgstr "Åk n' a nén stî tot candjant l' sicret: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" -msgstr "" +msgstr "Edjîstraedje di conte Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" -msgstr "" +msgstr "Edjîstrer on conte Jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" -msgstr "" +msgstr "Disdjîstrer on conte Jabber" #: mod_register_web.erl:214 msgid "" @@ -1739,40 +1698,45 @@ msgid "" "(Jabber IDentifier) will be of the form: username@server. Please read " "carefully the instructions to fill correctly the fields." msgstr "" +"Cisse pådje permete d' ahiver on conte Jabber so ç' sierveu Jabber ci. " +"Li JID (IDintifieu Jabber) da vosse serè del cogne: noduzeu@sierveu. Lijhoz " +"atintivmint les instruccions po bén rimpli les tchamps." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 -#, fuzzy msgid "Username:" -msgstr "No d' uzeu IRC" +msgstr "No d' uzeu:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." -msgstr "" +msgstr "Pont d' diferince etur les grandes et ptitès letes: «macbeth» est l' minme ki «MacBeth» ou co «Macbeth»" #: mod_register_web.erl:233 msgid "Characters not allowed:" -msgstr "" +msgstr "Caracteres nén permetous:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 -#, fuzzy msgid "Server:" -msgstr "Måy" +msgstr "Sierveu:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" +"Ni dnez vosse sicret a nolu, nén ddja ås manaedjeus do sierveu Jabber." #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." -msgstr "" +msgstr "Vos ploz candjî vosse sicret pus tård avou on cliyint Jabber." #: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in the computer, but you should " "do this only in your personal computer for safety reasons." msgstr "" +"Des cliyints Jabber k' i gn a polèt wårder vosse sicret sol copiutrece, mins " +"vos n' duvrîz fé çoula ki sol copiutrece da vosse, po des råjhons di " +"såvrité." #: mod_register_web.erl:256 msgid "" @@ -1780,34 +1744,33 @@ msgid "" "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" +"Rimimbrez vosse sicret, ou scrijhoz l' so on papî ki vos wådroz en ene " +"place bén a hoûte, ca avou Jabber i n' a pont moyén di rapexhî vosse " +"sicret si vos l' rovyîz." #: mod_register_web.erl:262 mod_register_web.erl:374 -#, fuzzy msgid "Password Verification:" -msgstr "Acertinaedje do scret" +msgstr "Acertinaedje do scret:" #: mod_register_web.erl:269 -#, fuzzy msgid "Register" -msgstr "Djivêye des soçons" +msgstr "Edjîstrer" #: mod_register_web.erl:366 -#, fuzzy msgid "Old Password:" -msgstr "Sicret:" +msgstr "Vî scret:" #: mod_register_web.erl:370 -#, fuzzy msgid "New Password:" -msgstr "Sicret:" +msgstr "Novea scret:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." -msgstr "" +msgstr "Cisse pådje permete di disdjîstrer on conte Jabber so ç' sierveu ci." #: mod_register_web.erl:480 msgid "Unregister" -msgstr "" +msgstr "Disdjîstrer" #: mod_roster.erl:1436 msgid "Subscription" @@ -1977,3 +1940,4 @@ msgstr "Rimplixhoz les tchamps po cweri èn uzeu Jabber" #~ msgid "Size" #~ msgstr "Grandeu" + From 3feceb82797543f363fc8aa8f5b460667df380ad Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 18 Jan 2016 19:09:58 +0100 Subject: [PATCH 501/695] Update Czech translation (thanks to Jan Pinkas) --- priv/msgs/cs.po | 85 ++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/priv/msgs/cs.po b/priv/msgs/cs.po index 352989084da..81c60756ed1 100644 --- a/priv/msgs/cs.po +++ b/priv/msgs/cs.po @@ -7,6 +7,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Language: Czech (čeština)\n" "X-Additional-Translator: Milos Svasek [DuxforD] from openheads.net\n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Language-Team: \n" +"Language: cs\n" +"X-Generator: Poedit 1.8.6\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" @@ -31,7 +36,7 @@ msgstr "Vaše nastavení soukromí znemožnilo směrování této stance." #: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Příliš mnoho nepotvrzených stanz" #: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" @@ -59,9 +64,8 @@ msgid "User" msgstr "Uživatel" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Server:" +msgstr "Server" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -71,7 +75,7 @@ msgstr "Heslo" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Přijmout" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -143,8 +147,7 @@ msgstr "Virtuální hostitelé" msgid "Users" msgstr "Uživatelé" -#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 mod_configure.erl:524 msgid "Online Users" msgstr "Online uživatelé" @@ -238,9 +241,10 @@ msgid "Outgoing s2s Connections:" msgstr "Odchozí s2s spojení:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Odchozí s2s spojení:" +msgstr "" +"Příchozí\n" +" s2s spojení:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -253,9 +257,10 @@ msgid "Change Password" msgstr "Změnit heslo" #: ejabberd_web_admin.erl:1673 -#, fuzzy msgid "User ~s" -msgstr "Uživatel " +msgstr "" +"Uživatel\n" +" ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" @@ -287,9 +292,8 @@ msgid "Stopped Nodes" msgstr "Zastavené uzly" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 -#, fuzzy msgid "Node ~p" -msgstr "Uzel " +msgstr "Uzel ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -326,9 +330,8 @@ msgid "RPC Call Error" msgstr "Chyba RPC volání" #: ejabberd_web_admin.erl:1917 -#, fuzzy msgid "Database Tables at ~p" -msgstr "Databázové tabulky na " +msgstr "Databázové tabulky na ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -351,9 +354,8 @@ msgid "Error" msgstr "Chyba" #: ejabberd_web_admin.erl:1955 -#, fuzzy msgid "Backup of ~p" -msgstr "Záloha na " +msgstr "Záloha ~p" #: ejabberd_web_admin.erl:1959 msgid "" @@ -412,7 +414,7 @@ msgstr "" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Zálohovat všechny tabulky jako SQL dotazy do souboru:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" @@ -427,9 +429,8 @@ msgid "Listened Ports at " msgstr "Otevřené porty na " #: ejabberd_web_admin.erl:2144 -#, fuzzy msgid "Modules at ~p" -msgstr "Moduly na " +msgstr "Moduly v ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" @@ -460,9 +461,8 @@ msgid "Transactions Logged:" msgstr "Transakce zaznamenána" #: ejabberd_web_admin.erl:2243 -#, fuzzy msgid "Update ~p" -msgstr "Aktualizovat " +msgstr "Aktualizovat ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" @@ -840,18 +840,20 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Příliš mnoho (~p) chybných pokusů o přihlášení z této IP adresy (~s). Adresa " +"bude zablokována do ~s UTC" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Zvolit velikost souboru." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Zvolit jméno souboru." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "IP adresa je blokována na ~s" #: mod_irc.erl:220 mod_muc.erl:467 msgid "Access denied by service policy" @@ -963,9 +965,8 @@ msgid "Server ~b" msgstr "Server ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Jen moderátoři mají povoleno měnit téma místnosti" +msgstr "Pouze moderátoři mají povoleno měnit téma místnosti" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -985,7 +986,7 @@ msgstr "Konference" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Prázdné konference" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1019,26 +1020,23 @@ msgstr "ejabberd MUC modul" #: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 #: mod_muc_admin.erl:320 msgid "Multi-User Chat" -msgstr "" +msgstr "Víceuživatelský chat" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Total rooms" -msgstr "Konference" +msgstr "Celkem konferencí" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Permanent rooms" -msgstr "opustil(a) místnost" +msgstr "Stálých konferencí" #: mod_muc_admin.erl:251 -#, fuzzy msgid "Registered nicknames" -msgstr "Registrovaní uživatelé" +msgstr "Registrované přezdívky" #: mod_muc_admin.erl:254 msgid "List of rooms" -msgstr "" +msgstr "Seznam konferencí" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" @@ -1185,6 +1183,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"Není povoleno posílat chybové zprávy do konference. Účastník (~s) odeslal " +"chybovou zprávu (~s) a byl vyhozen z konference." #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1359,20 +1359,19 @@ msgstr "každému" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Role, pro které je zpráva o stavu šířena" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "moderátorům" +msgstr "Moderátor" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Účastník" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Návštěvník" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1432,7 +1431,7 @@ msgstr "Chránit místnost pomocí CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" -msgstr "" +msgstr "Povolit ukládání historie zpráv" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" @@ -1480,11 +1479,11 @@ msgstr "heslo je" #: mod_multicast.erl:291 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" -msgstr "" +msgstr "Služba ejabberd Multicast" #: mod_offline.erl:647 msgid "" From 5e4ed4266d82f58c99614c0e6d914c09c07113b9 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 19 Jan 2016 00:39:10 +0100 Subject: [PATCH 502/695] mod_mam: Strip existing JID tags from MUC messages Strip any pre-existing tags which have an child with a 'jid' attribute from MUC MAM messages. This way, if such a tag exists, clients can be sure it was added by mod_mam. --- src/mod_mam.erl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index ff362539387..88206716c32 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -241,7 +241,8 @@ muc_filter_message(Pkt, #state{config = Config} = MUCState, if Config#config.mam -> LServer = RoomJID#jid.lserver, NewPkt = strip_my_archived_tag(Pkt, LServer), - case store_muc(MUCState, NewPkt, RoomJID, From, FromNick) of + StorePkt = strip_x_jid_tags(NewPkt), + case store_muc(MUCState, StorePkt, RoomJID, From, FromNick) of {ok, ID} -> Archived = #xmlel{name = <<"archived">>, attrs = [{<<"by">>, LServer}, @@ -606,6 +607,18 @@ strip_my_archived_tag(Pkt, LServer) -> end, Pkt#xmlel.children), Pkt#xmlel{children = NewEls}. +strip_x_jid_tags(Pkt) -> + NewEls = lists:filter( + fun(#xmlel{name = <<"x">>} = XEl) -> + not lists:any(fun(ItemEl) -> + xml:get_tag_attr(<<"jid">>, ItemEl) + /= false + end, xml:get_subtags(XEl, <<"item">>)); + (_) -> + true + end, Pkt#xmlel.children), + Pkt#xmlel{children = NewEls}. + should_archive_peer(C2SState, #archive_prefs{default = Default, always = Always, From 2ddbd032ee96778434c07389f075b7b59f52f49e Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 19 Jan 2016 16:16:04 +0100 Subject: [PATCH 503/695] Add error handling to send_stanza --- src/mod_admin_extra.erl | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index e7911fc2644..1c228a350a4 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -1332,16 +1332,28 @@ build_packet(Type, Subject, Body) -> [{xmlel, <<"body">>, [], [{xmlcdata, Body}]} | Tail] }. -send_stanza(FromString, ToString, Data) -> - Stanza = {xmlel, _, _, _} = xml_stream:parse_element(Data), - From = jid:from_string(FromString), - To = jid:from_string(ToString), - ejabberd_router:route(From, To, Stanza). +send_stanza(FromString, ToString, Stanza) -> + case xml_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) + end. send_stanza_c2s(Username, Host, Resource, Stanza) -> - C2sPid = ejabberd_sm:get_session_pid(Username, Host, Resource), - XmlEl = xml_stream:parse_element(Stanza), - p1_fsm:send_event(C2sPid, {xmlstreamelement, XmlEl}). + case {xml_stream:parse_element(Stanza), + ejabberd_sm:get_session_pid(Username, Host, Resource)} + of + {{error, Error}, _} -> + {error, Error}; + {_, none} -> + {error, no_session}; + {XmlEl, C2sPid} -> + p1_fsm:send_event(C2sPid, {xmlstreamelement, XmlEl}) + end. privacy_set(Username, Host, QueryS) -> From = jid:make(Username, Host, <<"">>), From 278d8a6fcd2aaf38f3a85e519816bae34e61bed7 Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 19 Jan 2016 22:34:58 +0100 Subject: [PATCH 504/695] Fix fuzzy tag in correct string --- priv/msgs/he.po | 1 - 1 file changed, 1 deletion(-) diff --git a/priv/msgs/he.po b/priv/msgs/he.po index e048826ee18..80c1155e560 100644 --- a/priv/msgs/he.po +++ b/priv/msgs/he.po @@ -975,7 +975,6 @@ msgid "Server ~b" msgstr "שרת ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" msgstr "רק חברים רשאים לתשאל ארכיונים של חדר זה" From b62607037a5628818e3d965914e0e91b119281a6 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 20 Jan 2016 00:02:40 +0100 Subject: [PATCH 505/695] mod_mam: Expose MUC occupant JID in more cases Include the occupant JID with MUC MAM messages if the room is not anonymous, and also when the MAM user sent the MUC message himself (not just in the case where he is a room moderator). --- src/mod_mam.erl | 53 ++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 88206716c32..75694b6660e 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -915,12 +915,12 @@ select_and_send(LServer, From, To, Start, End, With, RSM, IQ, MsgType, DBType) - select_and_start(LServer, From, To, Start, End, With, RSM, MsgType, DBType) -> case MsgType of chat -> - select(LServer, From, Start, End, With, RSM, MsgType, DBType); + select(LServer, From, From, Start, End, With, RSM, MsgType, DBType); {groupchat, _Role, _MUCState} -> - select(LServer, To, Start, End, With, RSM, MsgType, DBType) + select(LServer, From, To, Start, End, With, RSM, MsgType, DBType) end. -select(_LServer, JidRequestor, Start, End, _With, RSM, +select(_LServer, JidRequestor, JidArchive, Start, End, _With, RSM, {groupchat, _Role, #state{config = #config{mam = false}, history = History}} = MsgType, _DBType) -> @@ -940,8 +940,8 @@ select(_LServer, JidRequestor, Start, End, _With, RSM, peer = undefined, nick = Nick, packet = Pkt}, - MsgType, - JidRequestor)}], I+1}; + MsgType, JidRequestor, JidArchive)}], + I+1}; false -> {[], I+1} end @@ -957,7 +957,8 @@ select(_LServer, JidRequestor, Start, End, _With, RSM, _ -> {Msgs, true, L} end; -select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor, +select(_LServer, JidRequestor, + #jid{luser = LUser, lserver = LServer} = JidArchive, Start, End, With, RSM, MsgType, mnesia) -> MS = make_matchspec(LUser, LServer, Start, End, With), Msgs = mnesia:dirty_select(archive_msg, MS), @@ -968,13 +969,13 @@ select(_LServer, #jid{luser = LUser, lserver = LServer} = JidRequestor, fun(Msg) -> {Msg#archive_msg.id, jlib:binary_to_integer(Msg#archive_msg.id), - msg_to_el(Msg, MsgType, JidRequestor)} + msg_to_el(Msg, MsgType, JidRequestor, JidArchive)} end, FilteredMsgs), IsComplete, Count}; -select(LServer, #jid{luser = LUser} = JidRequestor, +select(LServer, JidRequestor, #jid{luser = LUser} = JidArchive, Start, End, With, RSM, MsgType, {odbc, Host}) -> User = case MsgType of chat -> LUser; - {groupchat, _Role, _MUCState} -> jid:to_string(JidRequestor) + {groupchat, _Role, _MUCState} -> jid:to_string(JidArchive) end, {Query, CountQuery} = make_sql_query(User, LServer, Start, End, With, RSM), @@ -1018,8 +1019,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor, type = T, nick = Nick, peer = PeerJid}, - MsgType, - JidRequestor)}] + MsgType, JidRequestor, JidArchive)}] catch _:Err -> ?ERROR_MSG("failed to parse data from SQL: ~p. " "The data was: " @@ -1034,31 +1034,44 @@ select(LServer, #jid{luser = LUser} = JidRequestor, end. msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, - MsgType, #jid{lserver = LServer} = JidRequestor) -> - Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick), + MsgType, JidRequestor, #jid{lserver = LServer} = JidArchive) -> + Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, JidArchive, Peer, MsgType, + Nick), Pkt3 = #xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}], children = [xml:replace_tag_attr( <<"xmlns">>, <<"jabber:client">>, Pkt2)]}, jlib:add_delay_info(Pkt3, LServer, TS). -maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, - Peer, {groupchat, Role, _MUCState}, Nick) -> - Items = case Role of - moderator when Peer /= undefined -> +maybe_update_from_to(#xmlel{children = Els} = Pkt, JidRequestor, JidArchive, + Peer, {groupchat, Role, + #state{config = #config{anonymous = Anon}}}, + Nick) -> + ExposeJID = case {Peer, JidRequestor} of + {undefined, _JidRequestor} -> + false; + {{U, S, _R}, #jid{luser = U, lserver = S}} -> + true; + {_Peer, _JidRequestor} when not Anon; Role == moderator -> + true; + {_Peer, _JidRequestor} -> + false + end, + Items = case ExposeJID of + true -> [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}], children = [#xmlel{name = <<"item">>, attrs = [{<<"jid">>, jid:to_string(Peer)}]}]}]; - _ -> + false -> [] end, Pkt1 = Pkt#xmlel{children = Items ++ Els}, - Pkt2 = jlib:replace_from(jid:replace_resource(JidRequestor, Nick), Pkt1), + Pkt2 = jlib:replace_from(jid:replace_resource(JidArchive, Nick), Pkt1), jlib:remove_attr(<<"to">>, Pkt2); -maybe_update_from_to(Pkt, _JidRequestor, _Peer, chat, _Nick) -> +maybe_update_from_to(Pkt, _JidRequestor, _JidArchive, _Peer, chat, _Nick) -> Pkt. is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> From 3d3034cd11e374699a295dda59a6415201ec6c91 Mon Sep 17 00:00:00 2001 From: Shelley Shyan Date: Wed, 20 Jan 2016 23:07:45 +0800 Subject: [PATCH 506/695] Update zh.po to be continued --- priv/msgs/zh.po | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index 014fe9accce..9d3afa1604e 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -72,7 +72,7 @@ msgstr "密码" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "接受" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -254,9 +254,8 @@ msgid "Change Password" msgstr "更改密码" #: ejabberd_web_admin.erl:1673 -#, fuzzy msgid "User ~s" -msgstr "用户 " +msgstr "用户 ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" @@ -288,9 +287,8 @@ msgid "Stopped Nodes" msgstr "已经停止的节点" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 -#, fuzzy msgid "Node ~p" -msgstr "节点 " +msgstr "节点 ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -327,9 +325,8 @@ msgid "RPC Call Error" msgstr "RPC 调用错误" #: ejabberd_web_admin.erl:1917 -#, fuzzy msgid "Database Tables at ~p" -msgstr "数据库列表位于 " +msgstr "位于~p的数据库表" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -352,9 +349,8 @@ msgid "Error" msgstr "错误" #: ejabberd_web_admin.erl:1955 -#, fuzzy msgid "Backup of ~p" -msgstr "备份来源 " +msgstr "~p的备份" #: ejabberd_web_admin.erl:1959 msgid "" @@ -409,7 +405,7 @@ msgstr "将某主机的用户数据导出到 PIEFXIS 文件 (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "将所有表以SQL查询语句导出到文件:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" @@ -424,9 +420,8 @@ msgid "Listened Ports at " msgstr "监听的端口位于 " #: ejabberd_web_admin.erl:2144 -#, fuzzy msgid "Modules at ~p" -msgstr "模块位于 " +msgstr "位于~p的模块" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" @@ -457,9 +452,8 @@ msgid "Transactions Logged:" msgstr "记入日志的事务:" #: ejabberd_web_admin.erl:2243 -#, fuzzy msgid "Update ~p" -msgstr "更新 " +msgstr "更新 ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" From e2c1368e0e8752fd40e14f5d014db6f801c8c042 Mon Sep 17 00:00:00 2001 From: Shelley Shyan Date: Thu, 21 Jan 2016 01:01:14 +0800 Subject: [PATCH 507/695] Update zh.po Translated untranslated. Fixed fuzzy messages. Other fixes. --- priv/msgs/zh.po | 173 +++++++++++++++++++++++------------------------- 1 file changed, 83 insertions(+), 90 deletions(-) diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index 9d3afa1604e..ae96f5fb391 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -32,7 +32,7 @@ msgstr "你的活跃私聊列表拒绝了在此房间进行路由分发." #: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" -msgstr "" +msgstr "未被确认的节太多" #: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" @@ -40,7 +40,7 @@ msgstr "请输入您所看到的文本" #: ejabberd_captcha.erl:147 msgid "Your messages to ~s are being blocked. To unblock them, visit ~s" -msgstr "您发送给 ~s 的消息已被阻止. 要解除阻止, 请访问 ~s" +msgstr "您发送给~s的消息已被阻止. 要解除阻止, 请访问 ~s" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." @@ -60,9 +60,8 @@ msgid "User" msgstr "用户" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "服务器:" +msgstr "服务器" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -81,7 +80,7 @@ msgstr "未认证的" #: ejabberd_web_admin.erl:303 ejabberd_web_admin.erl:335 msgid "ejabberd Web Admin" -msgstr "ejabberd 网页管理" +msgstr "ejabberd网页管理" #: ejabberd_web_admin.erl:669 ejabberd_web_admin.erl:680 msgid "Administration" @@ -134,7 +133,7 @@ msgstr "访问规则" #: ejabberd_web_admin.erl:913 msgid "~s access rule configuration" -msgstr "~s 访问规则配置" +msgstr "~s访问规则配置" #: ejabberd_web_admin.erl:931 msgid "Virtual Hosts" @@ -239,9 +238,8 @@ msgid "Outgoing s2s Connections:" msgstr "出站 s2s 连接:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "出站 s2s 连接:" +msgstr "入站 s2s 连接:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -255,7 +253,7 @@ msgstr "更改密码" #: ejabberd_web_admin.erl:1673 msgid "User ~s" -msgstr "用户 ~s" +msgstr "用户~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" @@ -288,7 +286,7 @@ msgstr "已经停止的节点" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 msgid "Node ~p" -msgstr "节点 ~p" +msgstr "节点~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -413,11 +411,11 @@ msgstr "从 jabberd14 Spool 文件导入用户数据:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" -msgstr "从 jabberd14 Spool 目录导入用户数据:" +msgstr "从jabberd14 Spool目录导入用户数据:" #: ejabberd_web_admin.erl:2115 msgid "Listened Ports at " -msgstr "监听的端口位于 " +msgstr "监听的端口位于" #: ejabberd_web_admin.erl:2144 msgid "Modules at ~p" @@ -425,7 +423,7 @@ msgstr "位于~p的模块" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" -msgstr "~p 的统计" +msgstr "~p的统计" #: ejabberd_web_admin.erl:2179 msgid "Uptime:" @@ -433,7 +431,7 @@ msgstr "正常运行时间:" #: ejabberd_web_admin.erl:2183 msgid "CPU Time:" -msgstr "CPU 时间:" +msgstr "CPU时间:" #: ejabberd_web_admin.erl:2191 msgid "Transactions Committed:" @@ -453,7 +451,7 @@ msgstr "记入日志的事务:" #: ejabberd_web_admin.erl:2243 msgid "Update ~p" -msgstr "更新 ~p" +msgstr "更新~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" @@ -740,7 +738,7 @@ msgstr "请输入文本文件的路径" #: mod_configure.erl:1156 msgid "Import User from File at " -msgstr "导入用户的文件位于 " +msgstr "导入用户的文件位于" #: mod_configure.erl:1162 msgid "Enter path to jabberd14 spool file" @@ -748,11 +746,11 @@ msgstr "请输入 jabberd14 spool 文件的路径" #: mod_configure.erl:1177 msgid "Import Users from Dir at " -msgstr "导入用户的目录位于 " +msgstr "导入用户的目录位于" #: mod_configure.erl:1183 msgid "Enter path to jabberd14 spool dir" -msgstr "请输入 jabberd14 spool 目录的路径" +msgstr "请输入jabberd14 spool目录的路径" #: mod_configure.erl:1184 msgid "Path to Dir" @@ -808,7 +806,7 @@ msgstr "花名册大小" #: mod_configure.erl:1965 msgid "IP addresses" -msgstr "IP 地址" +msgstr "IP地址" #: mod_configure.erl:1967 msgid "Resources" @@ -830,19 +828,19 @@ msgstr "编辑属性" msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" -msgstr "" +msgstr "来自IP地址(~s)的(~p)失败认证太多. 该地址将在UTC时间~s被禁用." #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "请指定文件大小." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "请指定文件名称." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "此IP地址在~s中已被列入黑名单" #: mod_irc.erl:220 mod_muc.erl:467 msgid "Access denied by service policy" @@ -850,7 +848,7 @@ msgstr "访问被服务策略拒绝" #: mod_irc.erl:439 msgid "IRC Transport" -msgstr "IRC 传输" +msgstr "IRC传输" #: mod_irc.erl:476 msgid "ejabberd IRC module" @@ -858,7 +856,7 @@ msgstr "ejabberd IRC 模块" #: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" -msgstr "您需要一个兼容 x:data 的客户端来配置 mod_irc 设置" +msgstr "您需要一个兼容 x:data 的客户端来配置mod_irc设置" #: mod_irc.erl:653 msgid "Registration in mod_irc for " @@ -872,7 +870,7 @@ msgstr "请输入您想使用的用来连接到IRC服务器的用户名, 编码, #: mod_irc.erl:667 msgid "IRC Username" -msgstr "IRC 用户名" +msgstr "IRC用户名" #: mod_irc.erl:682 msgid "" @@ -899,27 +897,27 @@ msgstr "连接参数" #: mod_irc.erl:886 msgid "Join IRC channel" -msgstr "加入 IRC 频道" +msgstr "加入IRC频道" #: mod_irc.erl:893 msgid "IRC channel (don't put the first #)" -msgstr "IRC 频道 (不要输入第一个#号)" +msgstr "IRC频道 (不要输入第一个#号)" #: mod_irc.erl:903 msgid "IRC server" -msgstr "IRC 服务器" +msgstr "IRC服务器" #: mod_irc.erl:950 mod_irc.erl:958 msgid "Join the IRC channel here." -msgstr "在这里加入 IRC 频道." +msgstr "在这里加入IRC频道." #: mod_irc.erl:967 msgid "Join the IRC channel in this Jabber ID: ~s" -msgstr "用此 Jabber ID: ~s 加入 IRC 频道" +msgstr "用此Jabber ID ~s加入IRC频道" #: mod_irc.erl:1046 msgid "IRC settings" -msgstr "IRC 设置" +msgstr "IRC设置" #: mod_irc.erl:1051 msgid "" @@ -932,28 +930,27 @@ msgstr "" #: mod_irc.erl:1060 msgid "IRC username" -msgstr "IRC 用户名" +msgstr "IRC用户名" #: mod_irc.erl:1126 msgid "Password ~b" -msgstr "~b 的密码" +msgstr "~b的密码" #: mod_irc.erl:1137 msgid "Port ~b" -msgstr "~b 的端口" +msgstr "~b的端口" #: mod_irc.erl:1150 msgid "Encoding for server ~b" -msgstr "服务器 ~b 的编码" +msgstr "服务器~b的编码" #: mod_irc.erl:1171 msgid "Server ~b" -msgstr "服务器 ~b" +msgstr "服务器~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "只有主持人可以在此房间里更改主题" +msgstr "只有会员可以查询本房间的存档" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -973,7 +970,7 @@ msgstr "聊天室" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "空房间" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -981,7 +978,7 @@ msgstr "您需要一个支持 x:data 的客户端来注册昵称" #: mod_muc.erl:943 msgid "Nickname Registration at " -msgstr "昵称注册于 " +msgstr "昵称注册于" #: mod_muc.erl:949 msgid "Enter nickname you want to register" @@ -1007,26 +1004,23 @@ msgstr "ejabberd MUC 模块" #: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 #: mod_muc_admin.erl:320 msgid "Multi-User Chat" -msgstr "" +msgstr "多用户聊天" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Total rooms" -msgstr "聊天室" +msgstr "所有房间" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Permanent rooms" -msgstr "离开房间" +msgstr "永久房间" #: mod_muc_admin.erl:251 -#, fuzzy msgid "Registered nicknames" -msgstr "注册用户" +msgstr "注册的昵称" #: mod_muc_admin.erl:254 msgid "List of rooms" -msgstr "" +msgstr "房间列表" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" @@ -1172,7 +1166,7 @@ msgstr "已经超过传输率限制" msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" -msgstr "" +msgstr "不允许将错误消息发送到该房间. 参与者(~s)已发送过一条消息(~s)并已被踢出房间" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1282,7 +1276,7 @@ msgstr "Jabber ID ~s 无效" #: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" -msgstr "昵称 ~s 不在该房间" +msgstr "昵称~s不在该房间" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" @@ -1298,7 +1292,7 @@ msgstr "需要持有人权限" #: mod_muc_room.erl:3348 msgid "Configuration of room ~s" -msgstr "房间 ~s 的配置 " +msgstr "房间~s的配置 " #: mod_muc_room.erl:3359 msgid "Room title" @@ -1334,7 +1328,7 @@ msgstr "不限" #: mod_muc_room.erl:3436 msgid "Present real Jabber IDs to" -msgstr "将真实 Jabber ID 显示给" +msgstr "将真实Jabber ID显示给" #: mod_muc_room.erl:3450 mod_muc_room.erl:3560 msgid "moderators only" @@ -1346,20 +1340,19 @@ msgstr "任何人" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "广播存在性的角色" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "仅主持人" +msgstr "主持人" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "参与人" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "访客" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1419,11 +1412,11 @@ msgstr "保护房间验证码" #: mod_muc_room.erl:3606 msgid "Enable message archiving" -msgstr "" +msgstr "启用消息归档" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" -msgstr "从验证码挑战中排除 Jabber ID" +msgstr "从验证码挑战中排除Jabber ID" #: mod_muc_room.erl:3621 msgid "Enable logging" @@ -1451,7 +1444,7 @@ msgstr "接受或拒绝声音请求" #: mod_muc_room.erl:4351 msgid "User JID" -msgstr "用户 JID" +msgstr "用户JID" #: mod_muc_room.erl:4355 msgid "Grant voice to this person?" @@ -1459,7 +1452,7 @@ msgstr "为此人授权声音?" #: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" -msgstr "~s 邀请你到 ~s 房间" +msgstr "~s邀请你到房间~s" #: mod_muc_room.erl:4509 msgid "the password is" @@ -1467,11 +1460,11 @@ msgstr "密码是" #: mod_multicast.erl:291 msgid "Multicast" -msgstr "" +msgstr "多重映射" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd多重映射服务" #: mod_offline.erl:647 msgid "" @@ -1480,7 +1473,7 @@ msgstr "您的联系人离线消息队列已满. 消息已被丢弃" #: mod_offline.erl:798 msgid "~s's Offline Messages Queue" -msgstr "~s 的离线消息队列" +msgstr "~s的离线消息队列" #: mod_offline.erl:811 msgid "Time" @@ -1520,7 +1513,7 @@ msgstr "ejabberd 发行-订阅模块" #: mod_pubsub.erl:1537 msgid "PubSub subscriber request" -msgstr "PubSub 订阅人请求" +msgstr "PubSub订阅人请求" #: mod_pubsub.erl:1543 msgid "Choose whether to approve this entity's subscription." @@ -1528,7 +1521,7 @@ msgstr "选择是否允许该实体的订阅" #: mod_pubsub.erl:1559 msgid "Node ID" -msgstr "节点 ID" +msgstr "节点ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" @@ -1536,7 +1529,7 @@ msgstr "订阅人地址" #: mod_pubsub.erl:1584 msgid "Allow this Jabber ID to subscribe to this pubsub node?" -msgstr "允许该 Jabber ID 订阅该 pubsub 节点?" +msgstr "允许该Jabber ID订阅该pubsub节点?" #: mod_pubsub.erl:3745 msgid "Deliver payloads with event notifications" @@ -1633,7 +1626,7 @@ msgstr "不允许用户太频繁地注册帐户" #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." -msgstr "你的 Jabber 帐户已成功创建." +msgstr "你的Jabber帐户已成功创建." #: mod_register_web.erl:110 msgid "There was an error creating the account: " @@ -1649,7 +1642,7 @@ msgstr "帐户删除失败: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." -msgstr "你的 Jabber 帐户密码已成功更新." +msgstr "你的Jabber帐户密码已成功更新." #: mod_register_web.erl:140 msgid "There was an error changing the password: " @@ -1657,15 +1650,15 @@ msgstr "修改密码出错: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" -msgstr "Jabber 帐户注册" +msgstr "Jabber帐户注册" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" -msgstr "注册 Jabber 帐户" +msgstr "注册Jabber帐户" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" -msgstr "注销 Jabber 帐户" +msgstr "注销Jabber帐户" #: mod_register_web.erl:214 msgid "" @@ -1673,7 +1666,7 @@ msgid "" "(Jabber IDentifier) will be of the form: username@server. Please read " "carefully the instructions to fill correctly the fields." msgstr "" -"本页面允许在此服务器上创建 Jabber 帐户. 你的 JID (Jabber ID) 的形式如下: 用户" +"本页面允许在此服务器上创建Jabber帐户. 你的JID (Jabber ID) 的形式如下: 用户" "名@服务器. 请仔细阅读说明并正确填写相应字段." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 @@ -1696,11 +1689,11 @@ msgstr "服务器:" msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." -msgstr "不要将密码告诉任何人, 就算是 Jabber 服务器的管理员也不可以." +msgstr "不要将密码告诉任何人, 就算是Jabber服务器的管理员也不可以." #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." -msgstr "你可以稍后用 Jabber 客户端修改你的密码." +msgstr "你可以稍后用Jabber客户端修改你的密码." #: mod_register_web.erl:252 msgid "" @@ -1716,7 +1709,7 @@ msgid "" "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" -"记住你的密码, 或将其记到纸上并放于安全位置. 如果你忘记了密码, Jabber 也没有自" +"记住你的密码, 或将其记到纸上并放于安全位置. 如果你忘记了密码, Jabber也没有自" "动恢复密码的方式." #: mod_register_web.erl:262 mod_register_web.erl:374 @@ -1733,11 +1726,11 @@ msgstr "旧密码: " #: mod_register_web.erl:370 msgid "New Password:" -msgstr "新密码: " +msgstr "新密码:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." -msgstr "此页面允许在此 Jabber 服务器上注销 Jabber 帐户" +msgstr "此页面允许在此Jabber服务器上注销Jabber帐户" #: mod_register_web.erl:480 msgid "Unregister" @@ -1765,11 +1758,11 @@ msgstr "移除" #: mod_roster.erl:1490 msgid "Roster of " -msgstr "花名册属于 " +msgstr "花名册属于" #: mod_roster.erl:1504 msgid "Add Jabber ID" -msgstr "添加 Jabber ID" +msgstr "添加Jabber ID" #: mod_roster.erl:1622 msgid "Roster" @@ -1802,7 +1795,7 @@ msgstr "组" #: mod_vcard.erl:168 mod_vcard_ldap.erl:225 msgid "Erlang Jabber Server" -msgstr "Erlang Jabber 服务器" +msgstr "Erlang Jabber服务器" #: mod_vcard.erl:490 mod_vcard.erl:622 msgid "Birthday" @@ -1828,7 +1821,7 @@ msgstr "姓氏" msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" -msgstr "填充表单以搜索任何匹配的 Jabber 用户(在字段末添加*来匹配子串)" +msgstr "填充表单以搜索任何匹配的Jabber用户(在字段末添加*来匹配子串)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" @@ -1848,7 +1841,7 @@ msgstr "组织单位" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "Search users in " -msgstr "搜索用户于 " +msgstr "搜索用户于" #: mod_vcard.erl:490 mod_vcard_ldap.erl:502 msgid "You need an x:data capable client to search" @@ -1856,11 +1849,11 @@ msgstr "您需要一个兼容 x:data 的客户端来搜索" #: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" -msgstr "vCard 用户搜索" +msgstr "vCard用户搜索" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" -msgstr "ejabberd vCard 模块" +msgstr "ejabberd vCard模块" #: mod_vcard.erl:609 mod_vcard_ldap.erl:602 msgid "Search Results for " @@ -1868,7 +1861,7 @@ msgstr "搜索结果属于关键词 " #: mod_vcard_ldap.erl:502 msgid "Fill in fields to search for any matching Jabber User" -msgstr "填充字段以搜索任何匹配的 Jabber 用户" +msgstr "填充字段以搜索任何匹配的Jabber用户" #~ msgid "Outgoing s2s Servers:" #~ msgstr "出站 s2s 服务器" @@ -1881,16 +1874,16 @@ msgstr "填充字段以搜索任何匹配的 Jabber 用户" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message" -#~ msgstr "该参与人由于发送了错误消息而被踢出了聊天室" +#~ msgstr "该参与人由于发送了错误消息而被踢出了房间" #~ msgid "" #~ "This participant is kicked from the room because he sent an error message " #~ "to another participant" -#~ msgstr "该参与人由于给其他人发送了出错消息而被踢出了聊天室" +#~ msgstr "该参与人由于给其他人发送了出错消息而被踢出了房间" #~ msgid "" #~ "This participant is kicked from the room because he sent an error presence" -#~ msgstr "该用户由于发送了错误状态而被踢出了聊天室" +#~ msgstr "该用户由于发送了错误状态而被踢出了房间" #~ msgid "Captcha test failed" #~ msgstr "验证码检测失败." From 42f86e7c3bf13acc41c973d3a3cf031af4510d67 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 20 Jan 2016 19:43:12 +0100 Subject: [PATCH 508/695] Fix order of arguments references --- priv/msgs/zh.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/priv/msgs/zh.po b/priv/msgs/zh.po index ae96f5fb391..113e7564a3f 100644 --- a/priv/msgs/zh.po +++ b/priv/msgs/zh.po @@ -828,7 +828,7 @@ msgstr "编辑属性" msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" -msgstr "来自IP地址(~s)的(~p)失败认证太多. 该地址将在UTC时间~s被禁用." +msgstr "来自IP地址(~p)的(~s)失败认证太多. 该地址将在UTC时间~s被禁用." #: mod_http_upload.erl:586 msgid "Please specify file size." From a189655f31a26ad46c58508962d919abafdcb49b Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 21 Jan 2016 12:56:03 +0100 Subject: [PATCH 509/695] Add missing ref key --- mix.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index b002e36b760..2ef48b5c443 100644 --- a/mix.exs +++ b/mix.exs @@ -41,11 +41,11 @@ defmodule Ejabberd.Mixfile do {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.0"}, {:p1_yaml, git: "https://github.com/processone/p1_yaml", tag: "1.0.0"}, {:jiffy, git: "https://github.com/davisp/jiffy", tag: "0.14.5"}, - {:oauth2, git: "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}, + {:oauth2, git: "https://github.com/kivra/oauth2", ref: "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}, {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git", tag: "1.15"}, {:p1_mysql, git: "https://github.com/processone/mysql", tag: "1.0.0"}, {:p1_pgsql, git: "https://github.com/processone/pgsql", tag: "1.0.0"}, - {:sqlite3, git: "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}, + {:sqlite3, git: "https://github.com/alexeyr/erlang-sqlite3", ref: "cbc3505f7a131254265d3ef56191b2581b8cc172"}, {:p1_zlib, git: "https://github.com/processone/zlib", tag: "1.0.0"}, {:p1_iconv, git: "https://github.com/processone/eiconv", tag: "0.9.0"}, {:eredis, git: "https://github.com/wooga/eredis", tag: "v1.0.8"}, From 5a85b0fb52bb0d00699d568cfd05c4adb876cf39 Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Sat, 23 Jan 2016 17:56:12 +0900 Subject: [PATCH 510/695] rename timestamp function #917 --- src/jlib.erl | 18 +++++++++++++++--- src/mod_admin_extra.erl | 2 +- src/mod_muc_admin.erl | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/jlib.erl b/src/jlib.erl index cb46c591dcf..61aaf690e17 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -45,7 +45,7 @@ iq_to_xml/1, parse_xdata_submit/1, is_standalone_chat_state/1, add_delay_info/3, add_delay_info/4, - timestamp_to_iso/1, timestamp_to_iso/2, + timestamp_to_legacy/1, timestamp_to_iso_basic/1, timestamp_to_iso/2, now_to_utc_string/1, now_to_local_string/1, datetime_string_to_timestamp/1, term_to_base64/1, base64_to_term/1, @@ -612,6 +612,9 @@ create_delay_tag(DateTime, Host, Desc) when is_binary(Host) -> %% Minutes = integer() -spec timestamp_to_iso(calendar:datetime(), tz()) -> {binary(), binary()}. +%% This is the XEP-0082 date and time format +%% http://xmpp.org/extensions/xep-0082.html + timestamp_to_iso({{Year, Month, Day}, {Hour, Minute, Second}}, Timezone) -> @@ -632,13 +635,22 @@ timestamp_to_iso({{Year, Month, Day}, end, {iolist_to_binary(Timestamp_string), iolist_to_binary(Timezone_string)}. --spec timestamp_to_iso(calendar:datetime()) -> binary(). -timestamp_to_iso({{Year, Month, Day}, +-spec timestamp_to_legacy(calendar:datetime()) -> binary(). +%% This is the jabber legacy format +%% http://xmpp.org/extensions/xep-0091.html#time +timestamp_to_legacy({{Year, Month, Day}, {Hour, Minute, Second}}) -> iolist_to_binary(io_lib:format("~4..0B~2..0B~2..0BT~2..0B:~2..0B:~2..0B", [Year, Month, Day, Hour, Minute, Second])). +-spec timestamp_to_iso_basic(calendar:datetime()) -> binary(). +%% This is the ISO 8601 basic bormat +timestamp_to_iso_basic({{Year, Month, Day}, + {Hour, Minute, Second}}) -> + iolist_to_binary(io_lib:format("~4..0B~2..0B~2..0BT~2..0B~2..0B~2..0B", + [Year, Month, Day, Hour, Minute, Second])). + -spec now_to_utc_string(erlang:timestamp()) -> binary(). now_to_utc_string({MegaSecs, Secs, MicroSecs}) -> diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 1c228a350a4..fed2a037a78 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -702,7 +702,7 @@ set_random_password(User, Server, Reason) -> set_password_auth(User, Server, NewPass). build_random_password(Reason) -> - Date = jlib:timestamp_to_iso(calendar:universal_time()), + Date = jlib:timestamp_to_legacy(calendar:universal_time()), RandomString = randoms:get_string(), <<"BANNED_ACCOUNT--", Date/binary, "--", RandomString/binary, "--", Reason/binary>>. diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index b713e2e5f63..603e96c65c3 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -355,7 +355,7 @@ build_info_room({Name, Host, Pid}) -> false -> Last_message1 = queue:last(History), {_, _, _, Ts_last, _} = Last_message1, - jlib:timestamp_to_iso(Ts_last) + jlib:timestamp_to_legacy(Ts_last) end, {<>, From f933cae2d6484cf5d694b1ed7a53fbd0bacbe6a6 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 17:29:18 +0100 Subject: [PATCH 511/695] Update Elixir dependency to latest p1_utils and cache_tab --- mix.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 2ef48b5c443..fab8e92377d 100644 --- a/mix.exs +++ b/mix.exs @@ -32,8 +32,8 @@ defmodule Ejabberd.Mixfile do defp deps do [{:lager, git: "https://github.com/basho/lager", tag: "3.0.2"}, - {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.2"}, - {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.1"}, + {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3"}, + {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.2"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.0"}, {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.1"}, From dae1ec2b7b3f587e73edbfaaeff82dbc7ac0cb2d Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 17:36:40 +0100 Subject: [PATCH 512/695] Make sure mix does not trigger conflict on p1_utils --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index fab8e92377d..a6e5f70e786 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,7 @@ defmodule Ejabberd.Mixfile do defp deps do [{:lager, git: "https://github.com/basho/lager", tag: "3.0.2"}, - {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3"}, + {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3", override: true}, {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.2"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.0"}, From 7cc951ab1b77c9e0d7526041b6a84cdf59abdba0 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 18:42:16 +0100 Subject: [PATCH 513/695] Make sure all version are consistent before big repositories changes --- mix.exs | 12 ++++++------ rebar.config | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mix.exs b/mix.exs index a6e5f70e786..58b37c4875a 100644 --- a/mix.exs +++ b/mix.exs @@ -32,14 +32,14 @@ defmodule Ejabberd.Mixfile do defp deps do [{:lager, git: "https://github.com/basho/lager", tag: "3.0.2"}, - {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3", override: true}, + {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3"}, {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.2"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, - {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.0"}, - {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.1"}, - {:p1_stun, git: "https://github.com/processone/stun", tag: "0.9.0"}, - {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.0"}, - {:p1_yaml, git: "https://github.com/processone/p1_yaml", tag: "1.0.0"}, + {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.1"}, + {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.2"}, + {:p1_stun, git: "https://github.com/processone/stun", tag: "0.9.1"}, + {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.1"}, + {:p1_yaml, git: "https://github.com/processone/p1_yaml", tag: "1.0.1"}, {:jiffy, git: "https://github.com/davisp/jiffy", tag: "0.14.5"}, {:oauth2, git: "https://github.com/kivra/oauth2", ref: "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}, {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git", tag: "1.15"}, diff --git a/rebar.config b/rebar.config index 81100027180..c96fbb4e9be 100644 --- a/rebar.config +++ b/rebar.config @@ -9,14 +9,14 @@ {deps, [{if_var_true, lager, {lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.0.2"}}}}, {if_var_false, lager, {p1_logger, ".*", {git, "https://github.com/processone/p1_logger", {tag, "1.0.0"}}}}, - {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.2"}}}, - {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.1"}}}, + {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.3"}}}, + {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.2"}}}, {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, - {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.0"}}}, - {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.1"}}}, - {p1_stun, ".*", {git, "https://github.com/processone/stun", "0.9.0"}}, - {esip, ".*", {git, "https://github.com/processone/p1_sip", "1.0.0"}}, - {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", {tag, "1.0.0"}}}, + {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.1"}}}, + {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, + {p1_stun, ".*", {git, "https://github.com/processone/stun", {tag, "0.9.1"}}}, + {esip, ".*", {git, "https://github.com/processone/p1_sip", "1.0.1"}}, + {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", {tag, "1.0.1"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.5"}}}, {oauth2, ".*", {git, "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}}, {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc", {tag, "1.15"}}}, From a3931e6b736f1b1a3196835bd0fb8cd082e4074d Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 18:43:06 +0100 Subject: [PATCH 514/695] lager is the default logger, we need to reverse the define flag --- src/ejabberd_logger.erl | 120 ++++++++++++++++++++-------------------- src/ext_mod.erl | 2 +- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 1b0719c4a85..243864c7e41 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -74,7 +74,67 @@ opt_type(log_rate_limit) -> opt_type(_) -> [log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit]. --ifdef(LAGER). +%% Default logger module is LAGER, defined in else clause. +%% TODO: Remove p1_logger usage and allow using Elixir logger if running in Elixir context. +-ifdef(P1LOGGER). + +start() -> + set(4), + LogPath = get_log_path(), + error_logger:add_report_handler(p1_logger_h, LogPath), + ok. + +reopen_log() -> + %% TODO: Use the Reopen log API for logger_h ? + p1_logger_h:reopen_log(), + reopen_sasl_log(). + +rotate_log() -> + %% Not implemented. + ok. + +get() -> + p1_loglevel:get(). + +set(LogLevel) when LogLevel >=0, LogLevel =< 5 -> + p1_loglevel:set(LogLevel); +set(LogLevel) -> + throw({wrong_loglevel, LogLevel}). + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +reopen_sasl_log() -> + case application:get_env(sasl,sasl_error_logger) of + {ok, {file, SASLfile}} -> + error_logger:delete_report_handler(sasl_report_file_h), + rotate_sasl_log(SASLfile), + error_logger:add_report_handler(sasl_report_file_h, + {SASLfile, get_sasl_error_logger_type()}); + _ -> false + end, + ok. + +rotate_sasl_log(Filename) -> + case file:read_file_info(Filename) of + {ok, _FileInfo} -> + file:rename(Filename, [Filename, ".0"]), + ok; + {error, _Reason} -> + ok + end. + +%% Function copied from Erlang/OTP lib/sasl/src/sasl.erl which doesn't export it +get_sasl_error_logger_type () -> + case application:get_env (sasl, errlog_type) of + {ok, error} -> error; + {ok, progress} -> progress; + {ok, all} -> all; + {ok, Bad} -> exit ({bad_config, {sasl, {errlog_type, Bad}}}); + _ -> all + end. + +-else. get_integer_env(Name, Default) -> case application:get_env(ejabberd, Name) of @@ -183,62 +243,4 @@ set({_LogLevel, _}) -> error_logger:error_msg("custom loglevels are not supported for 'lager'"), {module, lager}. --else. - -start() -> - set(4), - LogPath = get_log_path(), - error_logger:add_report_handler(p1_logger_h, LogPath), - ok. - -reopen_log() -> - %% TODO: Use the Reopen log API for logger_h ? - p1_logger_h:reopen_log(), - reopen_sasl_log(). - -rotate_log() -> - %% Not implemented. - ok. - -get() -> - p1_loglevel:get(). - -set(LogLevel) when LogLevel >=0, LogLevel =< 5 -> - p1_loglevel:set(LogLevel); -set(LogLevel) -> - throw({wrong_loglevel, LogLevel}). - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== -reopen_sasl_log() -> - case application:get_env(sasl,sasl_error_logger) of - {ok, {file, SASLfile}} -> - error_logger:delete_report_handler(sasl_report_file_h), - rotate_sasl_log(SASLfile), - error_logger:add_report_handler(sasl_report_file_h, - {SASLfile, get_sasl_error_logger_type()}); - _ -> false - end, - ok. - -rotate_sasl_log(Filename) -> - case file:read_file_info(Filename) of - {ok, _FileInfo} -> - file:rename(Filename, [Filename, ".0"]), - ok; - {error, _Reason} -> - ok - end. - -%% Function copied from Erlang/OTP lib/sasl/src/sasl.erl which doesn't export it -get_sasl_error_logger_type () -> - case application:get_env (sasl, errlog_type) of - {ok, error} -> error; - {ok, progress} -> progress; - {ok, all} -> all; - {ok, Bad} -> exit ({bad_config, {sasl, {errlog_type, Bad}}}); - _ -> all - end. - -endif. diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 148c94178fb..c6fbf50960b 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -510,7 +510,7 @@ compile(_Module, _Spec, DestDir) -> EjabBin = filename:dirname(code:which(ejabberd)), EjabInc = filename:join(filename:dirname(EjabBin), "include"), XmlHrl = filename:join(EjabInc, "xml.hrl"), - Logger = [{d, 'LAGER'} || code:is_loaded(lager)=/=false], + Logger = [{d, 'P1LOGGER'} || code:is_loaded(lager)==false], ExtLib = [{d, 'NO_EXT_LIB'} || filelib:is_file(XmlHrl)], Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc}, verbose, report_errors, report_warnings] From e97195b3a6daf224b623849f2aa5869a677cd96b Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 18:44:38 +0100 Subject: [PATCH 515/695] Mix requires override --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 58b37c4875a..eafddcb977a 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,7 @@ defmodule Ejabberd.Mixfile do defp deps do [{:lager, git: "https://github.com/basho/lager", tag: "3.0.2"}, - {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3"}, + {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3", override: true}, {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.2"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.1"}, From 0920511de27c65bfe9c10900644c612b6cf96c1d Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 18:57:29 +0100 Subject: [PATCH 516/695] lager is the default logger, we need to reverse the define flag Also make sure that configure without option does not force lager to false --- configure.ac | 2 +- include/logger.hrl | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index f8a41508828..85f65134f97 100644 --- a/configure.ac +++ b/configure.ac @@ -103,7 +103,7 @@ AC_ARG_ENABLE(all, [AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; - no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false lager=false tools=false ;; + no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) diff --git a/include/logger.hrl b/include/logger.hrl index 3accc56aba0..b800cd0d5a0 100644 --- a/include/logger.hrl +++ b/include/logger.hrl @@ -19,38 +19,40 @@ %%%---------------------------------------------------------------------- -define(PRINT(Format, Args), io:format(Format, Args)). --ifdef(LAGER). --compile([{parse_transform, lager_transform}]). +-ifdef(P1LOGGER). -define(DEBUG(Format, Args), - lager:debug(Format, Args)). + p1_logger:debug_msg(?MODULE, ?LINE, Format, Args)). -define(INFO_MSG(Format, Args), - lager:info(Format, Args)). + p1_logger:info_msg(?MODULE, ?LINE, Format, Args)). -define(WARNING_MSG(Format, Args), - lager:warning(Format, Args)). + p1_logger:warning_msg(?MODULE, ?LINE, Format, Args)). -define(ERROR_MSG(Format, Args), - lager:error(Format, Args)). + p1_logger:error_msg(?MODULE, ?LINE, Format, Args)). -define(CRITICAL_MSG(Format, Args), - lager:critical(Format, Args)). + p1_logger:critical_msg(?MODULE, ?LINE, Format, Args)). -else. +-compile([{parse_transform, lager_transform}]). + -define(DEBUG(Format, Args), - p1_logger:debug_msg(?MODULE, ?LINE, Format, Args)). + lager:debug(Format, Args)). -define(INFO_MSG(Format, Args), - p1_logger:info_msg(?MODULE, ?LINE, Format, Args)). + lager:info(Format, Args)). -define(WARNING_MSG(Format, Args), - p1_logger:warning_msg(?MODULE, ?LINE, Format, Args)). + lager:warning(Format, Args)). -define(ERROR_MSG(Format, Args), - p1_logger:error_msg(?MODULE, ?LINE, Format, Args)). + lager:error(Format, Args)). -define(CRITICAL_MSG(Format, Args), - p1_logger:critical_msg(?MODULE, ?LINE, Format, Args)). + lager:critical(Format, Args)). + -endif. From dae41ec18332e9541d6a30882aa3d79f3610953e Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 23 Jan 2016 19:00:22 +0100 Subject: [PATCH 517/695] ejabberd will handle Mnesia start Mix need to know if must not autostart Mnesia before ejabberd --- mix.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index eafddcb977a..141189eb3c0 100644 --- a/mix.exs +++ b/mix.exs @@ -16,8 +16,8 @@ defmodule Ejabberd.Mixfile do def application do [mod: {:ejabberd_app, []}, - applications: [:ssl, :mnesia], - included_applications: [:lager, :p1_utils, :cache_tab, + applications: [:ssl], + included_applications: [:lager, :mnesia, :p1_utils, :cache_tab, :p1_tls, :p1_stringprep, :p1_xml, :p1_stun, :p1_yaml, :p1_zlib, :p1_iconv, :esip, :jiffy, :oauth2, :xmlrpc, :eredis, From 67b5162df953c433a5efbedd212e0d0523cfa2ab Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sun, 24 Jan 2016 10:07:12 +0100 Subject: [PATCH 518/695] Prepare hex.pm release --- mix.exs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mix.exs b/mix.exs index 141189eb3c0..e7a7cc3211b 100644 --- a/mix.exs +++ b/mix.exs @@ -53,10 +53,13 @@ defmodule Ejabberd.Mixfile do end defp package do - [licenses: ["GPLv2"], - links: %{"Site" => "https://www.ejabberd.im", - "Documentation" => "http://docs.ejabberd.im", - "Source" => "https://github.com/processone/ejabberd"}] + [# These are the default files included in the package + files: ["lib", "src", "priv", "mix.exs", "include", "README.md", "COPYING"], + maintainers: ["ProcessOne"], + licenses: ["GPLv2"], + links: %{"Site" => "https://www.ejabberd.im", + "Documentation" => "http://docs.ejabberd.im", + "Source" => "https://github.com/processone/ejabberd"}] end end From 14c0ff1c8224669aa8605e5eb377a9ff19d18c17 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sun, 24 Jan 2016 10:19:28 +0100 Subject: [PATCH 519/695] Add missing description --- mix.exs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mix.exs b/mix.exs index e7a7cc3211b..9a1f7072237 100644 --- a/mix.exs +++ b/mix.exs @@ -4,6 +4,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, version: "16.01.0", + description: description, elixir: "~> 1.1", elixirc_paths: ["lib"], compile_path: ".", @@ -14,6 +15,12 @@ defmodule Ejabberd.Mixfile do deps: deps] end + defp description do + """ + Robust, ubiquitous and massively scalable Jabber / XMPP Instant Messaging platform. + """ + end + def application do [mod: {:ejabberd_app, []}, applications: [:ssl], From 60175784f0575a1d2c21e9fbad6b9e16019c9225 Mon Sep 17 00:00:00 2001 From: Badlop Date: Sun, 24 Jan 2016 19:59:53 +0100 Subject: [PATCH 520/695] =?UTF-8?q?Updated=20Portuguese-Brazilian=20transl?= =?UTF-8?q?ation=20(thanks=20to=20Ot=C3=A1vio=20Fernandes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- priv/msgs/pt-br.po | 332 ++++++++++++++++++++++----------------------- 1 file changed, 165 insertions(+), 167 deletions(-) diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index ef1456655e7..e60153a8b69 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -11,28 +11,28 @@ msgstr "" "X-Additional-Translator: Felipe Brito Vasconcellos\n" "X-Additional-Translator: Victor Hugo dos Santos\n" -#: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 +#: ejabberd_c2s.erl:506 ejabberd_c2s.erl:854 msgid "Use of STARTTLS required" msgstr "É obrigatório uso de STARTTLS" -#: ejabberd_c2s.erl:604 +#: ejabberd_c2s.erl:605 msgid "No resource provided" msgstr "Nenhum recurso foi informado" -#: ejabberd_c2s.erl:1349 +#: ejabberd_c2s.erl:1340 msgid "Replaced by new connection" msgstr "Substituído por nova conexão" -#: ejabberd_c2s.erl:1353 mod_configure.erl:1854 mod_muc_log.erl:427 -#: mod_muc_log.erl:430 +#: ejabberd_c2s.erl:1344 mod_configure.erl:1851 mod_muc_log.erl:423 +#: mod_muc_log.erl:426 msgid "has been kicked" msgstr "foi removido" -#: ejabberd_c2s.erl:2114 +#: ejabberd_c2s.erl:2105 msgid "Your active privacy list has denied the routing of this stanza." msgstr "Sua lista de privacidade ativa negou o roteamento deste." -#: ejabberd_c2s.erl:2429 +#: ejabberd_c2s.erl:2420 msgid "Too many unacked stanzas" msgstr "número excessivo de instâncias sem confirmação" @@ -63,19 +63,18 @@ msgid "User" msgstr "Usuário" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Servidor:" +msgstr "Servidor" -#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 -#: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 +#: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1395 +#: mod_configure.erl:1482 mod_configure.erl:1886 mod_configure.erl:2120 #: mod_muc_room.erl:3383 mod_register.erl:275 msgid "Password" msgstr "Senha" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Aceito" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -90,8 +89,8 @@ msgstr "ejabberd Web Admin" msgid "Administration" msgstr "Administração" -#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:196 -#: mod_configure.erl:532 +#: ejabberd_web_admin.erl:737 ejabberd_web_admin.erl:773 mod_configure.erl:193 +#: mod_configure.erl:529 msgid "Access Control Lists" msgstr "Listas de Controle de Acesso" @@ -130,8 +129,8 @@ msgstr "Intocado" msgid "Delete Selected" msgstr "Remover os selecionados" -#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:198 -#: mod_configure.erl:533 +#: ejabberd_web_admin.erl:839 ejabberd_web_admin.erl:872 mod_configure.erl:195 +#: mod_configure.erl:530 msgid "Access Rules" msgstr "Regras de Acesso" @@ -148,7 +147,7 @@ msgid "Users" msgstr "Usuários" #: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 -#: mod_configure.erl:524 +#: mod_configure.erl:521 msgid "Online Users" msgstr "Usuários conectados" @@ -181,7 +180,7 @@ msgid "Show Integral Table" msgstr "Mostrar Tabela Integral" #: ejabberd_web_admin.erl:1004 ejabberd_web_admin.erl:1847 -#: mod_muc_admin.erl:247 +#: mod_muc_admin.erl:245 msgid "Statistics" msgstr "Estatísticas" @@ -205,8 +204,8 @@ msgstr "Máquina" msgid "Registered Users" msgstr "Usuários Registrados" -#: ejabberd_web_admin.erl:1417 mod_configure.erl:177 mod_configure.erl:539 -#: mod_configure.erl:1386 +#: ejabberd_web_admin.erl:1417 mod_configure.erl:174 mod_configure.erl:536 +#: mod_configure.erl:1383 msgid "Add User" msgstr "Adicionar usuário" @@ -219,12 +218,12 @@ msgid "Last Activity" msgstr "Última atividade" #: ejabberd_web_admin.erl:1478 ejabberd_web_admin.erl:1660 -#: mod_configure.erl:1916 +#: mod_configure.erl:1913 msgid "Never" msgstr "Nunca" #: ejabberd_web_admin.erl:1496 ejabberd_web_admin.erl:1671 -#: mod_configure.erl:1926 +#: mod_configure.erl:1923 msgid "Online" msgstr "Conectado" @@ -242,9 +241,8 @@ msgid "Outgoing s2s Connections:" msgstr "Conexões que partem de s2s" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Conexões que partem de s2s" +msgstr "Conexões que entram de s2s" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -269,7 +267,7 @@ msgstr "Recursos conectados:" msgid "Password:" msgstr "Senha:" -#: ejabberd_web_admin.erl:1693 mod_configure.erl:2117 +#: ejabberd_web_admin.erl:1693 mod_configure.erl:2114 msgid "Remove User" msgstr "Remover usuário" @@ -281,11 +279,11 @@ msgstr "Nenhum dado" msgid "Nodes" msgstr "Nós" -#: ejabberd_web_admin.erl:1814 mod_configure.erl:528 +#: ejabberd_web_admin.erl:1814 mod_configure.erl:525 msgid "Running Nodes" msgstr "Nos em execução" -#: ejabberd_web_admin.erl:1815 mod_configure.erl:529 +#: ejabberd_web_admin.erl:1815 mod_configure.erl:526 msgid "Stopped Nodes" msgstr "Nos parados" @@ -293,11 +291,11 @@ msgstr "Nos parados" msgid "Node ~p" msgstr "Nó ~p" -#: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 +#: ejabberd_web_admin.erl:1842 mod_configure.erl:147 mod_configure.erl:608 msgid "Database" msgstr "Base de dados" -#: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 +#: ejabberd_web_admin.erl:1843 mod_configure.erl:156 mod_configure.erl:645 msgid "Backup" msgstr "Salvar cópia de segurança" @@ -319,7 +317,7 @@ msgstr "Reiniciar" msgid "Stop" msgstr "Parar" -#: ejabberd_web_admin.erl:1861 mod_configure.erl:613 mod_configure.erl:626 +#: ejabberd_web_admin.erl:1861 mod_configure.erl:610 mod_configure.erl:623 msgid "Modules" msgstr "Módulos" @@ -524,11 +522,11 @@ msgstr "Pong" msgid "Really delete message of the day?" msgstr "Deletar realmente a mensagem do dia?" -#: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 +#: mod_announce.erl:536 mod_configure.erl:1235 mod_configure.erl:1295 msgid "Subject" msgstr "Assunto" -#: mod_announce.erl:544 mod_configure.erl:1244 mod_configure.erl:1304 +#: mod_announce.erl:544 mod_configure.erl:1241 mod_configure.erl:1301 msgid "Message body" msgstr "Corpo da mensagem" @@ -552,7 +550,7 @@ msgstr "Enviar aviso para todos os usuários em todos os hosts" msgid "Send announcement to all online users" msgstr "Enviar anúncio a todos os usuárions online" -#: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 +#: mod_announce.erl:670 mod_configure.erl:1228 mod_configure.erl:1288 msgid "Send announcement to all online users on all hosts" msgstr "Enviar anúncio a todos usuários online em todas as máquinas" @@ -581,258 +579,258 @@ msgstr "Apagar mensagem do dia" msgid "Delete message of the day on all hosts" msgstr "Apagar a mensagem do dia em todos os hosts" -#: mod_configure.erl:140 mod_configure.erl:296 mod_configure.erl:318 -#: mod_configure.erl:522 +#: mod_configure.erl:137 mod_configure.erl:293 mod_configure.erl:315 +#: mod_configure.erl:519 msgid "Configuration" msgstr "Configuração" -#: mod_configure.erl:153 mod_configure.erl:636 +#: mod_configure.erl:150 mod_configure.erl:633 msgid "Start Modules" msgstr "Iniciar módulos" -#: mod_configure.erl:156 mod_configure.erl:638 +#: mod_configure.erl:153 mod_configure.erl:635 msgid "Stop Modules" msgstr "Parar módulos" -#: mod_configure.erl:162 mod_configure.erl:650 +#: mod_configure.erl:159 mod_configure.erl:647 msgid "Restore" msgstr "Restaurar" -#: mod_configure.erl:165 mod_configure.erl:652 +#: mod_configure.erl:162 mod_configure.erl:649 msgid "Dump to Text File" msgstr "Exportar para arquivo texto" -#: mod_configure.erl:168 mod_configure.erl:663 +#: mod_configure.erl:165 mod_configure.erl:660 msgid "Import File" msgstr "Importar arquivo" -#: mod_configure.erl:171 mod_configure.erl:665 +#: mod_configure.erl:168 mod_configure.erl:662 msgid "Import Directory" msgstr "Importar diretório" -#: mod_configure.erl:173 mod_configure.erl:619 mod_configure.erl:1205 +#: mod_configure.erl:170 mod_configure.erl:616 mod_configure.erl:1202 msgid "Restart Service" msgstr "Reiniciar Serviço" -#: mod_configure.erl:175 mod_configure.erl:621 mod_configure.erl:1265 +#: mod_configure.erl:172 mod_configure.erl:618 mod_configure.erl:1262 msgid "Shut Down Service" msgstr "Parar Serviço" -#: mod_configure.erl:179 mod_configure.erl:540 mod_configure.erl:1419 +#: mod_configure.erl:176 mod_configure.erl:537 mod_configure.erl:1416 msgid "Delete User" msgstr "Deletar Usuário" -#: mod_configure.erl:181 mod_configure.erl:542 mod_configure.erl:1437 +#: mod_configure.erl:178 mod_configure.erl:539 mod_configure.erl:1434 msgid "End User Session" msgstr "Terminar Sessão do Usuário" -#: mod_configure.erl:183 mod_configure.erl:544 mod_configure.erl:1455 -#: mod_configure.erl:1473 +#: mod_configure.erl:180 mod_configure.erl:541 mod_configure.erl:1452 +#: mod_configure.erl:1470 msgid "Get User Password" msgstr "Obter Senha do Usuário" -#: mod_configure.erl:185 mod_configure.erl:546 +#: mod_configure.erl:182 mod_configure.erl:543 msgid "Change User Password" msgstr "Alterar Senha do Usuário" -#: mod_configure.erl:187 mod_configure.erl:548 mod_configure.erl:1500 +#: mod_configure.erl:184 mod_configure.erl:545 mod_configure.erl:1497 msgid "Get User Last Login Time" msgstr "Obter a Data do Último Login" -#: mod_configure.erl:189 mod_configure.erl:550 mod_configure.erl:1517 +#: mod_configure.erl:186 mod_configure.erl:547 mod_configure.erl:1514 msgid "Get User Statistics" msgstr "Obter Estatísticas do Usuário" -#: mod_configure.erl:191 mod_configure.erl:552 +#: mod_configure.erl:188 mod_configure.erl:549 msgid "Get Number of Registered Users" msgstr "Obter Número de Usuários Registrados" -#: mod_configure.erl:194 mod_configure.erl:554 +#: mod_configure.erl:191 mod_configure.erl:551 msgid "Get Number of Online Users" msgstr "Obter Número de Usuários Online" -#: mod_configure.erl:320 mod_configure.erl:523 +#: mod_configure.erl:317 mod_configure.erl:520 msgid "User Management" msgstr "Gerenciamento de Usuários" -#: mod_configure.erl:525 +#: mod_configure.erl:522 msgid "All Users" msgstr "Todos os usuários" -#: mod_configure.erl:526 +#: mod_configure.erl:523 msgid "Outgoing s2s Connections" msgstr "Conexões que partam de s2s" -#: mod_configure.erl:615 +#: mod_configure.erl:612 msgid "Backup Management" msgstr "Gestão de Backup" -#: mod_configure.erl:617 +#: mod_configure.erl:614 msgid "Import Users From jabberd14 Spool Files" msgstr "Importar usuários de arquivos jabberd14 (spool files)" -#: mod_configure.erl:762 +#: mod_configure.erl:759 msgid "To ~s" msgstr "Para ~s" -#: mod_configure.erl:782 +#: mod_configure.erl:779 msgid "From ~s" msgstr "De ~s" -#: mod_configure.erl:1002 +#: mod_configure.erl:999 msgid "Database Tables Configuration at " msgstr "Configuração de Tabelas de Base de dados em " -#: mod_configure.erl:1008 +#: mod_configure.erl:1005 msgid "Choose storage type of tables" msgstr "Selecione o tipo de armazenamento das tabelas" -#: mod_configure.erl:1017 mod_configure.erl:1019 +#: mod_configure.erl:1014 mod_configure.erl:1016 msgid "Disc only copy" msgstr "Somente copia em disco" -#: mod_configure.erl:1017 mod_configure.erl:1019 +#: mod_configure.erl:1014 mod_configure.erl:1016 msgid "RAM and disc copy" msgstr "Copias na RAM e disco rígido" -#: mod_configure.erl:1017 mod_configure.erl:1019 +#: mod_configure.erl:1014 mod_configure.erl:1016 msgid "RAM copy" msgstr "Copia em RAM" -#: mod_configure.erl:1017 mod_configure.erl:1019 +#: mod_configure.erl:1014 mod_configure.erl:1016 msgid "Remote copy" msgstr "Copia remota" -#: mod_configure.erl:1045 +#: mod_configure.erl:1042 msgid "Stop Modules at " msgstr "Parar módulos em " -#: mod_configure.erl:1051 +#: mod_configure.erl:1048 msgid "Choose modules to stop" msgstr "Selecione módulos a parar" -#: mod_configure.erl:1072 +#: mod_configure.erl:1069 msgid "Start Modules at " msgstr "Iniciar módulos em " -#: mod_configure.erl:1078 +#: mod_configure.erl:1075 msgid "Enter list of {Module, [Options]}" msgstr "Introduza lista de {módulo, [opções]}" -#: mod_configure.erl:1080 +#: mod_configure.erl:1077 msgid "List of modules to start" msgstr "Listas de módulos para inicializar" -#: mod_configure.erl:1094 +#: mod_configure.erl:1091 msgid "Backup to File at " msgstr "Salvar backup para arquivo em " -#: mod_configure.erl:1099 mod_configure.erl:1120 +#: mod_configure.erl:1096 mod_configure.erl:1117 msgid "Enter path to backup file" msgstr "Introduza o caminho do arquivo de backup" -#: mod_configure.erl:1100 mod_configure.erl:1121 mod_configure.erl:1142 -#: mod_configure.erl:1163 +#: mod_configure.erl:1097 mod_configure.erl:1118 mod_configure.erl:1139 +#: mod_configure.erl:1160 msgid "Path to File" msgstr "Caminho do arquivo" -#: mod_configure.erl:1115 +#: mod_configure.erl:1112 msgid "Restore Backup from File at " msgstr "Restaurar backup a partir do arquivo em " -#: mod_configure.erl:1136 +#: mod_configure.erl:1133 msgid "Dump Backup to Text File at " msgstr "Exportar backup para texto em " -#: mod_configure.erl:1141 +#: mod_configure.erl:1138 msgid "Enter path to text file" msgstr "Introduza caminho para o arquivo texto" -#: mod_configure.erl:1156 +#: mod_configure.erl:1153 msgid "Import User from File at " msgstr "Importar usuário a partir do arquivo em " -#: mod_configure.erl:1162 +#: mod_configure.erl:1159 msgid "Enter path to jabberd14 spool file" msgstr "Insira o caminho para a fila (arquivo) do jabberd14" -#: mod_configure.erl:1177 +#: mod_configure.erl:1174 msgid "Import Users from Dir at " msgstr "Importar usuários a partir do diretório em " -#: mod_configure.erl:1183 +#: mod_configure.erl:1180 msgid "Enter path to jabberd14 spool dir" msgstr "Introduza o caminho para o diretório de fila do jabberd14" -#: mod_configure.erl:1184 +#: mod_configure.erl:1181 msgid "Path to Dir" msgstr "Caminho para o diretório" -#: mod_configure.erl:1209 mod_configure.erl:1269 +#: mod_configure.erl:1206 mod_configure.erl:1266 msgid "Time delay" msgstr "Intervalo (Tempo)" -#: mod_configure.erl:1316 +#: mod_configure.erl:1313 msgid "Access Control List Configuration" msgstr "Configuração da Lista de Controle de Acesso" -#: mod_configure.erl:1321 +#: mod_configure.erl:1318 msgid "Access control lists" msgstr "Listas de Controle de Acesso" -#: mod_configure.erl:1352 +#: mod_configure.erl:1349 msgid "Access Configuration" msgstr "Configuração de Acesso" -#: mod_configure.erl:1356 +#: mod_configure.erl:1353 msgid "Access rules" msgstr "Regras de acesso" -#: mod_configure.erl:1390 mod_configure.erl:1423 mod_configure.erl:1441 -#: mod_configure.erl:1459 mod_configure.erl:1477 mod_configure.erl:1504 -#: mod_configure.erl:1521 mod_configure.erl:1887 mod_configure.erl:1934 -#: mod_configure.erl:1961 mod_roster.erl:1434 mod_vcard.erl:613 +#: mod_configure.erl:1387 mod_configure.erl:1420 mod_configure.erl:1438 +#: mod_configure.erl:1456 mod_configure.erl:1474 mod_configure.erl:1501 +#: mod_configure.erl:1518 mod_configure.erl:1884 mod_configure.erl:1931 +#: mod_configure.erl:1958 mod_roster.erl:1434 mod_vcard.erl:613 #: mod_vcard_ldap.erl:606 msgid "Jabber ID" msgstr "ID Jabber" -#: mod_configure.erl:1407 +#: mod_configure.erl:1404 msgid "Password Verification" msgstr "Verificação de Senha" -#: mod_configure.erl:1540 +#: mod_configure.erl:1537 msgid "Number of registered users" msgstr "Número de usuários registrados" -#: mod_configure.erl:1559 +#: mod_configure.erl:1556 msgid "Number of online users" msgstr "Número de usuários online" -#: mod_configure.erl:1936 +#: mod_configure.erl:1933 msgid "Last login" msgstr "Último login" -#: mod_configure.erl:1963 +#: mod_configure.erl:1960 msgid "Roster size" msgstr "Tamanho da Lista" -#: mod_configure.erl:1965 +#: mod_configure.erl:1962 msgid "IP addresses" msgstr "Endereços IP" -#: mod_configure.erl:1967 +#: mod_configure.erl:1964 msgid "Resources" msgstr "Recursos" -#: mod_configure.erl:2095 +#: mod_configure.erl:2092 msgid "Administration of " msgstr "Administração de " -#: mod_configure.erl:2100 +#: mod_configure.erl:2097 msgid "Action on user" msgstr "Ação no usuário" -#: mod_configure.erl:2108 +#: mod_configure.erl:2105 msgid "Edit Properties" msgstr "Editar propriedades" @@ -846,17 +844,17 @@ msgstr "" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Por favor informe o tamanho do arquivo." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Por favor informe o nome do arquivo." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" msgstr "Este endereço IP está bloqueado em ~s" -#: mod_irc.erl:220 mod_muc.erl:467 +#: mod_irc.erl:220 mod_muc.erl:455 msgid "Access denied by service policy" msgstr "Aceso denegado por la política do serviço" @@ -969,217 +967,216 @@ msgstr "Codificação para o servidor ~b" msgid "Server ~b" msgstr "Servidor ~b" -#: mod_mam.erl:541 -#, fuzzy +#: mod_mam.erl:542 msgid "Only members may query archives of this room" -msgstr "Somente os moderadores podem alterar o assunto desta sala" +msgstr "Somente os membros podem procurar nos arquivos desta sala" -#: mod_muc.erl:585 +#: mod_muc.erl:573 msgid "Only service administrators are allowed to send service messages" msgstr "" "Apenas administradores possuem permissão para enviar mensagens de serviço" -#: mod_muc.erl:622 +#: mod_muc.erl:610 msgid "Room creation is denied by service policy" -msgstr "Se te a denegado criar la sala por política do serviço" +msgstr "Sala não pode ser criada devido a política de serviço" -#: mod_muc.erl:629 +#: mod_muc.erl:617 msgid "Conference room does not exist" -msgstr "La sala de conferencias não existe" +msgstr "A sala de conferência não existe" -#: mod_muc.erl:740 mod_muc_admin.erl:321 +#: mod_muc.erl:728 mod_muc_admin.erl:319 msgid "Chatrooms" msgstr "Salas de Chat" -#: mod_muc.erl:781 +#: mod_muc.erl:769 msgid "Empty Rooms" -msgstr "" +msgstr "Salas vazias" -#: mod_muc.erl:933 +#: mod_muc.erl:921 msgid "You need a client that supports x:data to register the nickname" msgstr "" "Você precisa de um cliente com suporte a x:data para registrar o seu apelido" -#: mod_muc.erl:943 +#: mod_muc.erl:931 msgid "Nickname Registration at " msgstr "Registro do apelido em " -#: mod_muc.erl:949 +#: mod_muc.erl:937 msgid "Enter nickname you want to register" msgstr "Introduza o apelido que quer registrar" -#: mod_muc.erl:950 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 +#: mod_muc.erl:938 mod_muc_room.erl:4353 mod_roster.erl:1435 mod_vcard.erl:490 #: mod_vcard.erl:621 msgid "Nickname" msgstr "Apelido" -#: mod_muc.erl:1062 mod_muc_room.erl:1104 mod_muc_room.erl:1843 +#: mod_muc.erl:1050 mod_muc_room.erl:1104 mod_muc_room.erl:1843 msgid "That nickname is registered by another person" msgstr "O nick já está registrado por outra pessoa" -#: mod_muc.erl:1090 +#: mod_muc.erl:1078 msgid "You must fill in field \"Nickname\" in the form" msgstr "Você deve completar o campo \"Apelido\" no formulário" -#: mod_muc.erl:1113 +#: mod_muc.erl:1101 msgid "ejabberd MUC module" msgstr "Módulo de MUC para ejabberd" -#: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 -#: mod_muc_admin.erl:320 +#: mod_muc_admin.erl:229 mod_muc_admin.erl:232 mod_muc_admin.erl:244 +#: mod_muc_admin.erl:318 msgid "Multi-User Chat" msgstr "Chat multi-usuário" -#: mod_muc_admin.erl:249 +#: mod_muc_admin.erl:247 msgid "Total rooms" msgstr "Salas no total" -#: mod_muc_admin.erl:250 +#: mod_muc_admin.erl:248 msgid "Permanent rooms" msgstr "Salas permanentes" -#: mod_muc_admin.erl:251 +#: mod_muc_admin.erl:249 msgid "Registered nicknames" msgstr "Usuários registrados" -#: mod_muc_admin.erl:254 +#: mod_muc_admin.erl:252 msgid "List of rooms" msgstr "Lista de salas" -#: mod_muc_log.erl:398 mod_muc_log.erl:407 +#: mod_muc_log.erl:394 mod_muc_log.erl:403 msgid "Chatroom configuration modified" msgstr "Configuração da sala de bate-papo modificada" -#: mod_muc_log.erl:410 +#: mod_muc_log.erl:406 msgid "joins the room" msgstr "Entrar na sala" -#: mod_muc_log.erl:413 mod_muc_log.erl:416 +#: mod_muc_log.erl:409 mod_muc_log.erl:412 msgid "leaves the room" msgstr "Sair da sala" -#: mod_muc_log.erl:420 mod_muc_log.erl:423 +#: mod_muc_log.erl:416 mod_muc_log.erl:419 msgid "has been banned" msgstr "foi banido" -#: mod_muc_log.erl:435 +#: mod_muc_log.erl:431 msgid "has been kicked because of an affiliation change" msgstr "foi desconectado porque por afiliação inválida" -#: mod_muc_log.erl:440 +#: mod_muc_log.erl:436 msgid "has been kicked because the room has been changed to members-only" msgstr "" "foi desconectado porque a política da sala mudou, só membros são permitidos" -#: mod_muc_log.erl:445 +#: mod_muc_log.erl:441 msgid "has been kicked because of a system shutdown" msgstr "foi desconectado porque o sistema foi desligado" -#: mod_muc_log.erl:450 +#: mod_muc_log.erl:446 msgid "is now known as" msgstr "é agora conhecido como" -#: mod_muc_log.erl:453 mod_muc_log.erl:792 +#: mod_muc_log.erl:449 mod_muc_log.erl:788 msgid " has set the subject to: " msgstr " a posto o assunto: " -#: mod_muc_log.erl:493 +#: mod_muc_log.erl:489 msgid "Chatroom is created" msgstr "A sala de chat está criada" -#: mod_muc_log.erl:495 +#: mod_muc_log.erl:491 msgid "Chatroom is destroyed" msgstr "A sala de chat está destruída" -#: mod_muc_log.erl:497 +#: mod_muc_log.erl:493 msgid "Chatroom is started" msgstr "A sala de chat está inciada" -#: mod_muc_log.erl:499 +#: mod_muc_log.erl:495 msgid "Chatroom is stopped" msgstr "A sala de chat está parada" -#: mod_muc_log.erl:503 +#: mod_muc_log.erl:499 msgid "Monday" msgstr "Segunda" -#: mod_muc_log.erl:504 +#: mod_muc_log.erl:500 msgid "Tuesday" msgstr "Terça" -#: mod_muc_log.erl:505 +#: mod_muc_log.erl:501 msgid "Wednesday" msgstr "Quarta" -#: mod_muc_log.erl:506 +#: mod_muc_log.erl:502 msgid "Thursday" msgstr "Quinta" -#: mod_muc_log.erl:507 +#: mod_muc_log.erl:503 msgid "Friday" msgstr "Sexta" -#: mod_muc_log.erl:508 +#: mod_muc_log.erl:504 msgid "Saturday" msgstr "Sábado" -#: mod_muc_log.erl:509 +#: mod_muc_log.erl:505 msgid "Sunday" msgstr "Domingo" -#: mod_muc_log.erl:513 +#: mod_muc_log.erl:509 msgid "January" msgstr "Janeiro" -#: mod_muc_log.erl:514 +#: mod_muc_log.erl:510 msgid "February" msgstr "Fevereiro" -#: mod_muc_log.erl:515 +#: mod_muc_log.erl:511 msgid "March" msgstr "Março" -#: mod_muc_log.erl:516 +#: mod_muc_log.erl:512 msgid "April" msgstr "Abril" -#: mod_muc_log.erl:517 +#: mod_muc_log.erl:513 msgid "May" msgstr "Maio" -#: mod_muc_log.erl:518 +#: mod_muc_log.erl:514 msgid "June" msgstr "Junho" -#: mod_muc_log.erl:519 +#: mod_muc_log.erl:515 msgid "July" msgstr "Julho" -#: mod_muc_log.erl:520 +#: mod_muc_log.erl:516 msgid "August" msgstr "Agosto" -#: mod_muc_log.erl:521 +#: mod_muc_log.erl:517 msgid "September" msgstr "Setembro" -#: mod_muc_log.erl:522 +#: mod_muc_log.erl:518 msgid "October" msgstr "Outubro" -#: mod_muc_log.erl:523 +#: mod_muc_log.erl:519 msgid "November" msgstr "Novembro" -#: mod_muc_log.erl:524 +#: mod_muc_log.erl:520 msgid "December" msgstr "Dezembro" -#: mod_muc_log.erl:912 +#: mod_muc_log.erl:908 msgid "Room Configuration" msgstr "Configuração de salas" -#: mod_muc_log.erl:932 +#: mod_muc_log.erl:928 msgid "Room Occupants" msgstr "Número de participantes" @@ -1192,6 +1189,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"Não é permitido o envio de mensagens de erro a esta sala. O membro " +"(~s)enviou uma mensagem de erro (~s) e foi desconectado (\"kicked\")." #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1367,20 +1366,19 @@ msgstr "qualquer um" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Para quem a presença será notificada" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "apenas moderadores" +msgstr "Moderador" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Participante" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Visitante" #: mod_muc_room.erl:3513 msgid "Make room members-only" From 0b492f43fe169db1947fd5ecad08e3b2de5e7b09 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 25 Jan 2016 10:47:20 +0100 Subject: [PATCH 521/695] If lager is false, we will use p1_logger --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index c96fbb4e9be..b1aae44eed9 100644 --- a/rebar.config +++ b/rebar.config @@ -53,7 +53,7 @@ {if_var_false, debug, no_debug_info}, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, {if_var_match, db_type, mssql, {d, 'mssql'}}, - {if_var_true, lager, {d, 'LAGER'}}, + {if_var_false, lager, {d, 'P1LOGGER'}}, {if_var_true, erlang_deprecated_types, {d, 'ERL_DEPRECATED_TYPES'}}, {if_var_true, hipe, native}, {src_dirs, [asn1, src, From 22696e83886d9a2f2217af4af09959aaf5a25f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 25 Jan 2016 16:51:54 +0100 Subject: [PATCH 522/695] Geenarte markdown that is acceptable by docs.ejabberd.org processor --- src/ejabberd_commands_doc.erl | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index ac48623e66c..999d4cd806c 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -75,7 +75,7 @@ md_tag(dd, V) -> md_tag(li, V) -> [<<"- ">>, V, <<"\n">>]; md_tag(pre, V) -> - [<<"\n">>, V, <<"\n">>]; + [V, <<"\n">>]; md_tag(p, V) -> [<<"\n\n">>, V, <<"\n">>]; md_tag(h1, V) -> @@ -111,7 +111,7 @@ perl_gen({Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> [?ARG(Name), ?OP_L(" => ["), list_join_with(Res, [?OP_L(", ")]), ?OP_L("]")]. perl_call(Name, ArgsDesc, Values, HTMLOutput) -> - {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!perl\n">>} end, + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<"~~~ perl\n">>} end, [Preamble, Indent, ?ID_L("XMLRPC::Lite"), ?OP_L("->"), ?ID_L("proxy"), ?OP_L("("), ?ID_L("$url"), ?OP_L(")->"), ?ID_L("call"), ?OP_L("("), ?STR_A(Name), ?OP_L(", {"), ?BR, Indent, <<" ">>, @@ -150,7 +150,7 @@ java_gen({Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> list_join_with(Res, [?OP_L(","), NI]), NI2, ?OP_L("});")]. java_call(Name, ArgsDesc, Values, HTMLOutput) -> - {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!java\n">>} end, + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<"~~~ java\n">>} end, [Preamble, Indent, ?ID_L("XmlRpcClientConfigImpl config"), ?OP_L(" = "), ?KW_L("new "), ?ID_L("XmlRpcClientConfigImpl"), ?OP_L("();"), ?BR, Indent, ?ID_L("config"), ?OP_L("."), ?ID_L("setServerURL"), ?OP_L("("), ?ID_L("url"), ?OP_L(");"), ?BR, Indent, ?BR, @@ -202,7 +202,7 @@ xml_gen({Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> ?XML(value, Indent, 1, [?XML(array, Indent, 2, [?XML(data, Indent, 3, Res)])])])]. xml_call(Name, ArgsDesc, Values, HTMLOutput) -> - {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!xml">>} end, + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<"~~~ xml">>} end, Res = lists:map(fun({A, B}) -> xml_gen(A, B, <>, HTMLOutput) end, lists:zip(ArgsDesc, Values)), [Preamble, ?XML(methodCall, Indent, @@ -241,7 +241,7 @@ json_gen({_Name, {list, ElDesc}}, List, Indent, HTMLOutput) -> [?OP_L("["), ?BR, Indent2, list_join_with(Res, [?OP_L(","), ?BR, Indent2]), ?BR, Indent, ?OP_L("]")]. json_call(Name, ArgsDesc, Values, ResultDesc, Result, HTMLOutput) -> - {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<" #!json\n">>} end, + {Indent, Preamble} = if HTMLOutput -> {<<"">>, []}; true -> {<<" ">>, <<"~~~ json\n">>} end, {Code, ResultStr} = case {ResultDesc, Result} of {{_, rescode}, V} when V == true; V == ok -> {200, [?STR_L("")]}; @@ -324,10 +324,16 @@ gen_calls(#ejabberd_commands{args_example=Values, args=ArgsDesc, case lists:member(<<"xmlrpc">>, Langs) of true -> ?TAG(li, ?TAG(pre, XML)); _ -> [] end, case lists:member(<<"json">>, Langs) of true -> ?TAG(li, ?TAG(pre, JSON)); _ -> [] end])]; true -> - [case lists:member(<<"java">>, Langs) of true -> [<<"Java example\n\n">>, ?TAG(pre, Java)]; _ -> [] end, - case lists:member(<<"perl">>, Langs) of true -> [<<"Perl example\n\n">>, ?TAG(pre, Perl)]; _ -> [] end, - case lists:member(<<"xmlrpc">>, Langs) of true -> [<<"XmlRPC example\n\n">>, ?TAG(pre, XML)]; _ -> [] end, - case lists:member(<<"json">>, Langs) of true -> [<<"JSON example\n\n">>, ?TAG(pre, JSON)]; _ -> [] end] + [<<"\n">>, case lists:member(<<"java">>, Langs) of true -> <<"* Java\n">>; _ -> [] end, + case lists:member(<<"perl">>, Langs) of true -> <<"* Perl\n">>; _ -> [] end, + case lists:member(<<"xmlrpc">>, Langs) of true -> <<"* XmlRPC\n">>; _ -> [] end, + case lists:member(<<"json">>, Langs) of true -> <<"* JSON\n">>; _ -> [] end, + <<"{: .code-samples-labels}\n">>, + case lists:member(<<"java">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, Java), <<"~~~\n">>]; _ -> [] end, + case lists:member(<<"perl">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, Perl), <<"~~~\n">>]; _ -> [] end, + case lists:member(<<"xmlrpc">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, XML), <<"~~~\n">>]; _ -> [] end, + case lists:member(<<"json">>, Langs) of true -> [<<"\n* ">>, ?TAG(pre, JSON), <<"~~~\n">>]; _ -> [] end, + <<"{: .code-samples-tabs}\n\n">>] end. gen_doc(#ejabberd_commands{name=Name, tags=_Tags, desc=Desc, longdesc=LongDesc, From 28569d62091a54d88f184c39385ea25890ae43e2 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 25 Jan 2016 23:28:27 +0100 Subject: [PATCH 523/695] As default, attempt to add path to Elixir --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index f6e174ce6c6..44026f67e1e 100644 --- a/README +++ b/README @@ -162,7 +162,7 @@ https://github.com/processone/ejabberd-vagrant-dev. To start ejabberd in development mode from the repository directory, you can type a command like: - EJABBERD_CONFIG_PATH=ejabberd.yml erl -pa ebin -pa deps/*/ebin -pa test -s ejabberd + EJABBERD_CONFIG_PATH=ejabberd.yml erl -pa ebin -pa deps/*/ebin -pa test -pa deps/elixir/lib/*/ebin/ -s ejabberd Links ----- From bdeb4a7e32dbf6b998018196781cdd142bff3c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 26 Jan 2016 10:00:11 +0100 Subject: [PATCH 524/695] Add a way to get all ejabberd_commands, not only those that was registered This is part of (TECH-1828). --- src/ejabberd_admin.erl | 9 +++++---- src/ejabberd_commands.erl | 15 +++++++++------ src/ejabberd_commands_doc.erl | 29 ++++++++++++++++++++++------- src/ejabberd_s2s.erl | 9 +++++---- src/ejabberd_sm.erl | 9 +++++---- src/ext_mod.erl | 8 ++++---- src/mod_admin_extra.erl | 8 ++++---- src/mod_mam.erl | 9 +++++---- src/mod_muc_admin.erl | 8 ++++---- 9 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 5352ae1eee6..4aa5faedbb7 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -51,7 +51,8 @@ install_fallback_mnesia/1, dump_to_textfile/1, dump_to_textfile/2, mnesia_change_nodename/4, - restore/1 % Still used by some modules + restore/1, % Still used by some modules + get_commands_spec/0 ]). -include("ejabberd.hrl"). @@ -59,16 +60,16 @@ -include("ejabberd_commands.hrl"). start() -> - ejabberd_commands:register_commands(commands()). + ejabberd_commands:register_commands(get_commands_spec()). stop() -> - ejabberd_commands:unregister_commands(commands()). + ejabberd_commands:unregister_commands(get_commands_spec()). %%% %%% ejabberd commands %%% -commands() -> +get_commands_spec() -> [ %% The commands status, stop and restart are implemented also in ejabberd_ctl %% They are defined here so that other interfaces can use them too diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index 547da028d01..265d7141fdd 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -219,7 +219,8 @@ unregister_commands/1, execute_command/2, execute_command/4, - opt_type/1 + opt_type/1, + get_commands_spec/0 ]). -include("ejabberd_commands.hrl"). @@ -228,10 +229,8 @@ -define(POLICY_ACCESS, '$policy'). -init() -> - ets:new(ejabberd_commands, [named_table, set, public, - {keypos, #ejabberd_commands.name}]), - register_commands([ +get_commands_spec() -> + [ #ejabberd_commands{name = gen_html_doc_for_commands, tags = [documentation], desc = "Generates html documentation for ejabberd_commands", module = ejabberd_commands_doc, function = generate_html_output, @@ -259,7 +258,11 @@ init() -> "that will have example invocation include in markdown document"], result_desc = "0 if command failed, 1 when succedded", args_example = ["/home/me/docs/api.html", "mod_admin", "java,json"], - result_example = ok}]). + result_example = ok}]. +init() -> + ets:new(ejabberd_commands, [named_table, set, public, + {keypos, #ejabberd_commands.name}]), + register_commands(get_commands_spec()). -spec register_commands([ejabberd_commands()]) -> ok. diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index 999d4cd806c..3368e3dec91 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -5,7 +5,7 @@ %%% Created : 20 May 2008 by Badlop %%% %%% -%%% ejabberd, Copyright (C) 2002-2016 ProcessOne +%%% ejabberd, Copyright (C) 2002-2015 ProcessOne %%% %%% This program is free software; you can redistribute it and/or %%% modify it under the terms of the GNU General Public License as @@ -373,10 +373,27 @@ gen_doc(#ejabberd_commands{name=Name, tags=_Tags, desc=Desc, longdesc=LongDesc, ?TAG(h2, <<"Examples:">>), gen_calls(Cmd, HTMLOutput, Langs)]. +find_commands_definitions() -> + case code:lib_dir(ejabberd, ebin) of + {error, _} -> + lists:map(fun({N, _, _}) -> + ejabberd_commands:get_command_definition(N) + end, ejabberd_commands:list_commands()); + Path -> + lists:flatmap(fun(P) -> + Mod = list_to_atom(filename:rootname(P)), + code:ensure_loaded(Mod), + case erlang:function_exported(Mod, get_commands_spec, 0) of + true -> + apply(Mod, get_commands_spec, []); + _ -> + [] + end + end, filelib:wildcard("*.beam", Path)) + end. + generate_html_output(File, RegExp, Languages) -> - Cmds = lists:map(fun({N, _, _}) -> - ejabberd_commands:get_command_definition(N) - end, ejabberd_commands:list_commands()), + Cmds = find_commands_definitions(), {ok, RE} = re:compile(RegExp), Cmds2 = lists:filter(fun(#ejabberd_commands{name=Name, module=Module}) -> re:run(atom_to_list(Name), RE, [{capture, none}]) == match orelse @@ -393,9 +410,7 @@ generate_html_output(File, RegExp, Languages) -> ok. generate_md_output(File, RegExp, Languages) -> - Cmds = lists:map(fun({N, _, _}) -> - ejabberd_commands:get_command_definition(N) - end, ejabberd_commands:list_commands()), + Cmds = find_commands_definitions(), {ok, RE} = re:compile(RegExp), Cmds2 = lists:filter(fun(#ejabberd_commands{name=Name, module=Module}) -> re:run(atom_to_list(Name), RE, [{capture, none}]) == match orelse diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 06cad6af69d..2f026b32adc 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -42,7 +42,8 @@ clean_temporarily_blocked_table/0, list_temporarily_blocked_hosts/0, external_host_overloaded/1, is_temporarly_blocked/1, - check_peer_certificate/3]). + check_peer_certificate/3, + get_commands_spec/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, @@ -239,7 +240,7 @@ init([]) -> {attributes, record_info(fields, s2s)}]), mnesia:add_table_copy(s2s, node(), ram_copies), mnesia:subscribe(system), - ejabberd_commands:register_commands(commands()), + ejabberd_commands:register_commands(get_commands_spec()), mnesia:create_table(temporarily_blocked, [{ram_copies, [node()]}, {attributes, record_info(fields, temporarily_blocked)}]), @@ -265,7 +266,7 @@ handle_info({route, From, To, Packet}, State) -> handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> - ejabberd_commands:unregister_commands(commands()), + ejabberd_commands:unregister_commands(get_commands_spec()), ok. code_change(_OldVsn, State, _Extra) -> @@ -469,7 +470,7 @@ send_element(Pid, El) -> %%%---------------------------------------------------------------------- %%% ejabberd commands -commands() -> +get_commands_spec() -> [#ejabberd_commands{name = incoming_s2s_number, tags = [stats, s2s], desc = diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index ddc5697f2c4..3045a417b1c 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -63,7 +63,8 @@ get_user_ip/3, get_max_user_sessions/2, get_all_pids/0, - is_existing_resource/3 + is_existing_resource/3, + get_commands_spec/0 ]). -export([init/1, handle_call/3, handle_cast/2, @@ -323,7 +324,7 @@ init([]) -> ejabberd_hooks:add(remove_user, Host, ejabberd_sm, disconnect_removed_user, 100) end, ?MYHOSTS), - ejabberd_commands:register_commands(commands()), + ejabberd_commands:register_commands(get_commands_spec()), {ok, #state{}}. handle_call(_Request, _From, State) -> @@ -361,7 +362,7 @@ handle_info({unregister_iq_handler, Host, XMLNS}, handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> - ejabberd_commands:unregister_commands(commands()), + ejabberd_commands:unregister_commands(get_commands_spec()), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. @@ -723,7 +724,7 @@ get_sm_backend() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% ejabberd commands -commands() -> +get_commands_spec() -> [#ejabberd_commands{name = connected_users, tags = [session], desc = "List all established sessions", diff --git a/src/ext_mod.erl b/src/ext_mod.erl index c6fbf50960b..46ece873c54 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -33,7 +33,7 @@ installed_command/0, installed/0, installed/1, install/1, uninstall/1, upgrade/0, upgrade/1, add_sources/2, del_sources/1, modules_dir/0, - config_dir/0, opt_type/1]). + config_dir/0, opt_type/1, get_commands_spec/0]). -include("ejabberd_commands.hrl"). -include("logger.hrl"). @@ -46,12 +46,12 @@ start() -> [code:add_patha(module_ebin_dir(Module)) || {Module, _} <- installed()], application:start(inets), - ejabberd_commands:register_commands(commands()). + ejabberd_commands:register_commands(get_commands_spec()). stop() -> - ejabberd_commands:unregister_commands(commands()). + ejabberd_commands:unregister_commands(get_commands_spec()). -commands() -> +get_commands_spec() -> [#ejabberd_commands{name = modules_update_specs, tags = [admin,modules], desc = "", diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index fed2a037a78..dae775e4712 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -47,7 +47,7 @@ srg_delete/2, srg_list/1, srg_get_info/2, srg_get_members/2, srg_user_add/4, srg_user_del/4, send_message/5, send_stanza/3, send_stanza_c2s/4, privacy_set/3, - stats/1, stats/2, mod_opt_type/1]). + stats/1, stats/2, mod_opt_type/1, get_commands_spec/0]). -include("ejabberd.hrl"). @@ -61,17 +61,17 @@ %%% start(_Host, _Opts) -> - ejabberd_commands:register_commands(commands()). + ejabberd_commands:register_commands(get_commands_spec()). stop(_Host) -> - ejabberd_commands:unregister_commands(commands()). + ejabberd_commands:unregister_commands(get_commands_spec()). %%% %%% Register commands %%% -commands() -> +get_commands_spec() -> Vcard1FieldsString = "Some vcard field names in get/set_vcard are:\n" " FN - Full Name\n" " NICKNAME - Nickname\n" diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 88206716c32..d6e4e93685e 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -36,7 +36,8 @@ -export([user_send_packet/4, user_receive_packet/5, process_iq_v0_2/3, process_iq_v0_3/3, disco_sm_features/5, remove_user/2, remove_user/3, mod_opt_type/1, muc_process_iq/4, - muc_filter_message/5, message_is_archived/5, delete_old_messages/2]). + muc_filter_message/5, message_is_archived/5, delete_old_messages/2, + get_commands_spec/0]). -include_lib("stdlib/include/ms_transform.hrl"). -include("jlib.hrl"). @@ -116,7 +117,7 @@ start(Host, Opts) -> ejabberd_hooks:add(message_is_archived, Host, ?MODULE, message_is_archived, 50) end, - ejabberd_commands:register_commands(commands()), + ejabberd_commands:register_commands(get_commands_spec()), ok. init_db(mnesia, _Host) -> @@ -172,7 +173,7 @@ stop(Host) -> ejabberd_hooks:delete(message_is_archived, Host, ?MODULE, message_is_archived, 50) end, - ejabberd_commands:unregister_commands(commands()), + ejabberd_commands:unregister_commands(get_commands_spec()), ok. remove_user(User, Server) -> @@ -1364,7 +1365,7 @@ update(LServer, Table, Fields, Vals, Where) -> join([], _Sep) -> []; join([H | T], Sep) -> [H, [[Sep, X] || X <- T]]. -commands() -> +get_commands_spec() -> [#ejabberd_commands{name = delete_old_mam_messages, tags = [purge], desc = "Delete MAM messages older than DAYS", longdesc = "Valid message TYPEs: " diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 603e96c65c3..c08757375d3 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -20,7 +20,7 @@ change_room_option/4, get_room_options/2, set_room_affiliation/4, get_room_affiliations/2, web_menu_main/2, web_page_main/2, web_menu_host/3, - web_page_host/3, mod_opt_type/1]). + web_page_host/3, mod_opt_type/1, get_commands_spec/0]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -36,14 +36,14 @@ %%---------------------------- start(Host, _Opts) -> - ejabberd_commands:register_commands(commands()), + ejabberd_commands:register_commands(get_commands_spec()), ejabberd_hooks:add(webadmin_menu_main, ?MODULE, web_menu_main, 50), ejabberd_hooks:add(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50), ejabberd_hooks:add(webadmin_page_main, ?MODULE, web_page_main, 50), ejabberd_hooks:add(webadmin_page_host, Host, ?MODULE, web_page_host, 50). stop(Host) -> - ejabberd_commands:unregister_commands(commands()), + ejabberd_commands:unregister_commands(get_commands_spec()), ejabberd_hooks:delete(webadmin_menu_main, ?MODULE, web_menu_main, 50), ejabberd_hooks:delete(webadmin_menu_host, Host, ?MODULE, web_menu_host, 50), ejabberd_hooks:delete(webadmin_page_main, ?MODULE, web_page_main, 50), @@ -53,7 +53,7 @@ stop(Host) -> %%% Register commands %%% -commands() -> +get_commands_spec() -> [ #ejabberd_commands{name = muc_online_rooms, tags = [muc], desc = "List existing rooms ('global' to get all vhosts)", From 621dff7307734b962e403cb503818508b059e5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 26 Jan 2016 10:46:38 +0100 Subject: [PATCH 525/695] Add header to generated markdown file --- src/ejabberd_commands_doc.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index 3368e3dec91..adcbc6d97ef 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -420,9 +420,10 @@ generate_md_output(File, RegExp, Languages) -> N1 =< N2 end, Cmds2), Langs = binary:split(Languages, <<",">>, [global]), + Header = <<"---\ntitle: Administration API reference\nbodyclass: nocomment\n---">>, Out = lists:map(fun(C) -> gen_doc(C, false, Langs) end, Cmds3), {ok, Fh} = file:open(File, [write]), - io:format(Fh, "~s", [[Out]]), + io:format(Fh, "~s~s", [Header, Out]), file:close(Fh), ok. From b2c6e397fc26ce9dd8372e6a32e1a07bf413875d Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 26 Jan 2016 13:47:24 +0100 Subject: [PATCH 526/695] Set set utf8mb4 charset on mysql connection --- src/ejabberd_odbc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index d7b8fa83a0c..a15c66b5d29 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -618,7 +618,7 @@ mysql_connect(Server, Port, DB, Username, Password) -> of {ok, Ref} -> p1_mysql_conn:fetch( - Ref, [<<"set names 'utf8';">>], self()), + Ref, [<<"set names 'utf8mb4' collate 'utf8mb4_bin';">>], self()), {ok, Ref}; Err -> Err end. From 239b1c6f7458e1c763b2e28de8eaf50f01ac7392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 26 Jan 2016 14:33:01 +0100 Subject: [PATCH 527/695] Always use lagger --- configure.ac | 13 ++------- include/logger.hrl | 22 -------------- rebar.config | 4 +-- src/ejabberd_logger.erl | 64 ----------------------------------------- vars.config.in | 1 - 5 files changed, 3 insertions(+), 101 deletions(-) diff --git a/configure.ac b/configure.ac index 85f65134f97..e5d92c89d8a 100644 --- a/configure.ac +++ b/configure.ac @@ -100,9 +100,9 @@ AC_ARG_ENABLE(mssql, esac],[db_type=generic]) AC_ARG_ENABLE(all, -[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-lager --enable-tools (useful for Dialyzer checks, default: no)])], +[AC_HELP_STRING([--enable-all], [same as --enable-odbc --enable-mysql --enable-pgsql --enable-sqlite --enable-pam --enable-zlib --enable-riak --enable-redis --enable-elixir --enable-iconv --enable-debug --enable-tools (useful for Dialyzer checks, default: no)])], [case "${enableval}" in - yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true lager=true tools=true ;; + yes) odbc=true mysql=true pgsql=true sqlite=true pam=true zlib=true riak=true redis=true elixir=true iconv=true debug=true tools=true ;; no) odbc=false mysql=false pgsql=false sqlite=false pam=false zlib=false riak=false redis=false elixir=false iconv=false debug=false tools=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-all) ;; esac],[]) @@ -203,14 +203,6 @@ AC_ARG_ENABLE(debug, *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; esac],[if test "x$debug" = "x"; then debug=true; fi]) -AC_ARG_ENABLE(lager, -[AC_HELP_STRING([--enable-lager], [enable lager support (default: yes)])], -[case "${enableval}" in - yes) lager=true ;; - no) lager=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-lager) ;; -esac],[if test "x$lager" = "x"; then lager=true; fi]) - AC_ARG_ENABLE(latest_deps, [AC_HELP_STRING([--enable-latest-deps], [makes rebar use latest commits for dependences instead of tagged versions (default: no)])], [case "${enableval}" in @@ -261,7 +253,6 @@ AC_SUBST(redis) AC_SUBST(elixir) AC_SUBST(iconv) AC_SUBST(debug) -AC_SUBST(lager) AC_SUBST(tools) AC_SUBST(latest_deps) AC_SUBST(CFLAGS) diff --git a/include/logger.hrl b/include/logger.hrl index b800cd0d5a0..18dc7041ccf 100644 --- a/include/logger.hrl +++ b/include/logger.hrl @@ -18,26 +18,6 @@ %%% %%%---------------------------------------------------------------------- -define(PRINT(Format, Args), io:format(Format, Args)). - --ifdef(P1LOGGER). - --define(DEBUG(Format, Args), - p1_logger:debug_msg(?MODULE, ?LINE, Format, Args)). - --define(INFO_MSG(Format, Args), - p1_logger:info_msg(?MODULE, ?LINE, Format, Args)). - --define(WARNING_MSG(Format, Args), - p1_logger:warning_msg(?MODULE, ?LINE, Format, Args)). - --define(ERROR_MSG(Format, Args), - p1_logger:error_msg(?MODULE, ?LINE, Format, Args)). - --define(CRITICAL_MSG(Format, Args), - p1_logger:critical_msg(?MODULE, ?LINE, Format, Args)). - --else. - -compile([{parse_transform, lager_transform}]). -define(DEBUG(Format, Args), @@ -54,5 +34,3 @@ -define(CRITICAL_MSG(Format, Args), lager:critical(Format, Args)). - --endif. diff --git a/rebar.config b/rebar.config index b1aae44eed9..05d2ac1bafc 100644 --- a/rebar.config +++ b/rebar.config @@ -7,8 +7,7 @@ %%% Created : 1 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- -{deps, [{if_var_true, lager, {lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.0.2"}}}}, - {if_var_false, lager, {p1_logger, ".*", {git, "https://github.com/processone/p1_logger", {tag, "1.0.0"}}}}, +{deps, [{lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.0.2"}}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.3"}}}, {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.2"}}}, {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, @@ -53,7 +52,6 @@ {if_var_false, debug, no_debug_info}, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, {if_var_match, db_type, mssql, {d, 'mssql'}}, - {if_var_false, lager, {d, 'P1LOGGER'}}, {if_var_true, erlang_deprecated_types, {d, 'ERL_DEPRECATED_TYPES'}}, {if_var_true, hipe, native}, {src_dirs, [asn1, src, diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 243864c7e41..05499b45cae 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -74,68 +74,6 @@ opt_type(log_rate_limit) -> opt_type(_) -> [log_rotate_date, log_rotate_size, log_rotate_count, log_rate_limit]. -%% Default logger module is LAGER, defined in else clause. -%% TODO: Remove p1_logger usage and allow using Elixir logger if running in Elixir context. --ifdef(P1LOGGER). - -start() -> - set(4), - LogPath = get_log_path(), - error_logger:add_report_handler(p1_logger_h, LogPath), - ok. - -reopen_log() -> - %% TODO: Use the Reopen log API for logger_h ? - p1_logger_h:reopen_log(), - reopen_sasl_log(). - -rotate_log() -> - %% Not implemented. - ok. - -get() -> - p1_loglevel:get(). - -set(LogLevel) when LogLevel >=0, LogLevel =< 5 -> - p1_loglevel:set(LogLevel); -set(LogLevel) -> - throw({wrong_loglevel, LogLevel}). - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== -reopen_sasl_log() -> - case application:get_env(sasl,sasl_error_logger) of - {ok, {file, SASLfile}} -> - error_logger:delete_report_handler(sasl_report_file_h), - rotate_sasl_log(SASLfile), - error_logger:add_report_handler(sasl_report_file_h, - {SASLfile, get_sasl_error_logger_type()}); - _ -> false - end, - ok. - -rotate_sasl_log(Filename) -> - case file:read_file_info(Filename) of - {ok, _FileInfo} -> - file:rename(Filename, [Filename, ".0"]), - ok; - {error, _Reason} -> - ok - end. - -%% Function copied from Erlang/OTP lib/sasl/src/sasl.erl which doesn't export it -get_sasl_error_logger_type () -> - case application:get_env (sasl, errlog_type) of - {ok, error} -> error; - {ok, progress} -> progress; - {ok, all} -> all; - {ok, Bad} -> exit ({bad_config, {sasl, {errlog_type, Bad}}}); - _ -> all - end. - --else. - get_integer_env(Name, Default) -> case application:get_env(ejabberd, Name) of {ok, I} when is_integer(I), I>=0 -> @@ -242,5 +180,3 @@ set(LogLevel) when is_integer(LogLevel) -> set({_LogLevel, _}) -> error_logger:error_msg("custom loglevels are not supported for 'lager'"), {module, lager}. - --endif. diff --git a/vars.config.in b/vars.config.in index 991d20c9eaa..44316f8ae45 100644 --- a/vars.config.in +++ b/vars.config.in @@ -27,7 +27,6 @@ {riak, @riak@}. {redis, @redis@}. {elixir, @elixir@}. -{lager, @lager@}. {iconv, @iconv@}. %% Version From d89bbba18167c593a9d6bb7137f53f685fa27330 Mon Sep 17 00:00:00 2001 From: Louis Pilfold Date: Tue, 26 Jan 2016 21:25:34 +0000 Subject: [PATCH 528/695] Remove empty and unused module --- lib/ejabberd.ex | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 lib/ejabberd.ex diff --git a/lib/ejabberd.ex b/lib/ejabberd.ex deleted file mode 100644 index a843abc97ea..00000000000 --- a/lib/ejabberd.ex +++ /dev/null @@ -1,2 +0,0 @@ -defmodule Ejabberd do -end From aaa84dc11823f57319a4bc8584c9190e0aa65787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 27 Jan 2016 11:42:13 +0100 Subject: [PATCH 529/695] Need extra line before ## in markdown --- src/ejabberd_commands_doc.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index adcbc6d97ef..277ed0c784f 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -79,9 +79,9 @@ md_tag(pre, V) -> md_tag(p, V) -> [<<"\n\n">>, V, <<"\n">>]; md_tag(h1, V) -> - [<<"\n## ">>, V, <<"\n">>]; + [<<"\\nn## ">>, V, <<"\n">>]; md_tag(h2, V) -> - [<<"\n### ">>, V, <<"\n">>]; + [<<"\n\n### ">>, V, <<"\n">>]; md_tag(strong, V) -> [<<"*">>, V, <<"*">>]; md_tag(_, V) -> From b20db3b73678024b4fb786435355ab66f21de351 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 28 Jan 2016 14:23:51 +0300 Subject: [PATCH 530/695] Initial version of migration script from Prosody to ejabberd --- rebar.config | 2 + src/mod_offline.erl | 4 + src/mod_private.erl | 31 +++-- src/mod_roster.erl | 9 +- src/mod_vcard.erl | 2 +- src/prosody2ejabberd.erl | 288 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 320 insertions(+), 16 deletions(-) create mode 100644 src/prosody2ejabberd.erl diff --git a/rebar.config b/rebar.config index 05d2ac1bafc..44b73fd95ed 100644 --- a/rebar.config +++ b/rebar.config @@ -19,6 +19,7 @@ {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.5"}}}, {oauth2, ".*", {git, "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}}, {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc", {tag, "1.15"}}}, + {luerl, ".*", {git, "https://github.com/rvirding/luerl", "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/mysql", {tag, "1.0.0"}}}}, {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", {tag, "1.0.0"}}}}, {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}}}, @@ -39,6 +40,7 @@ p1_stringprep, p1_xml, esip, + luerl, p1_stun, p1_yaml, p1_utils, diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 1b1627e87d3..abdbcfdbd04 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -43,6 +43,7 @@ start_link/2, stop/1, store_packet/3, + store_offline_msg/5, resend_offline_messages/2, pop_offline_messages/3, get_sm_features/5, @@ -185,6 +186,9 @@ terminate(_Reason, State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. +store_offline_msg(Host, US, Msgs, Len, MaxOfflineMsgs) -> + DBType = gen_mod:db_type(Host, ?MODULE), + store_offline_msg(Host, US, Msgs, Len, MaxOfflineMsgs, DBType). store_offline_msg(_Host, US, Msgs, Len, MaxOfflineMsgs, mnesia) -> diff --git a/src/mod_private.erl b/src/mod_private.erl index a03d83e5aa3..e074b7185f7 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -33,7 +33,7 @@ -export([start/2, stop/1, process_sm_iq/3, import/3, remove_user/2, get_data/2, export/1, import/1, - mod_opt_type/1]). + mod_opt_type/1, set_data/3]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -82,19 +82,7 @@ process_sm_iq(#jid{luser = LUser, lserver = LServer}, IQ#iq{type = error, sub_el = [IQ#iq.sub_el, ?ERR_NOT_ACCEPTABLE]}; Data -> - DBType = gen_mod:db_type(LServer, ?MODULE), - F = fun () -> - lists:foreach(fun (Datum) -> - set_data(LUser, LServer, - Datum, DBType) - end, - Data) - end, - case DBType of - odbc -> ejabberd_odbc:sql_transaction(LServer, F); - mnesia -> mnesia:transaction(F); - riak -> F() - end, + set_data(LUser, LServer, Data), IQ#iq{type = result, sub_el = []} end; _ -> @@ -144,6 +132,21 @@ filter_xmlels([#xmlel{attrs = Attrs} = Xmlel | Xmlels], filter_xmlels([_ | Xmlels], Data) -> filter_xmlels(Xmlels, Data). +set_data(LUser, LServer, Data) -> + DBType = gen_mod:db_type(LServer, ?MODULE), + F = fun () -> + lists:foreach(fun (Datum) -> + set_data(LUser, LServer, + Datum, DBType) + end, + Data) + end, + case DBType of + odbc -> ejabberd_odbc:sql_transaction(LServer, F); + mnesia -> mnesia:transaction(F); + riak -> F() + end. + set_data(LUser, LServer, {XmlNS, Xmlel}, mnesia) -> mnesia:write(#private_storage{usns = {LUser, LServer, XmlNS}, diff --git a/src/mod_roster.erl b/src/mod_roster.erl index adc2210db2c..278e9cb99ef 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -50,7 +50,7 @@ webadmin_user/4, get_versioning_feature/2, roster_versioning_enabled/1, roster_version/2, record_to_string/1, groups_to_string/1, - mod_opt_type/1]). + mod_opt_type/1, set_roster/1]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -411,6 +411,13 @@ get_roster(LUser, LServer, odbc) -> _ -> [] end. +set_roster(#roster{us = {LUser, LServer}, jid = LJID} = Item) -> + transaction( + LServer, + fun() -> + roster_subscribe_t(LUser, LServer, LJID, Item) + end). + item_to_xml(Item) -> Attrs1 = [{<<"jid">>, jid:to_string(Item#roster.jid)}], diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index db19b557071..daeccb352fa 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -35,7 +35,7 @@ -export([start/2, init/3, stop/1, get_sm_features/5, process_local_iq/3, process_sm_iq/3, reindex_vcards/0, remove_user/2, export/1, import/1, import/3, - mod_opt_type/1]). + mod_opt_type/1, set_vcard/3]). -include("ejabberd.hrl"). -include("logger.hrl"). diff --git a/src/prosody2ejabberd.erl b/src/prosody2ejabberd.erl new file mode 100644 index 00000000000..ce46e3991ec --- /dev/null +++ b/src/prosody2ejabberd.erl @@ -0,0 +1,288 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 20 Jan 2016 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-module(prosody2ejabberd). + +%% API +-export([from_dir/1]). + +-include("ejabberd.hrl"). +-include("jlib.hrl"). +-include("logger.hrl"). +-include("mod_roster.hrl"). +-include("mod_offline.hrl"). + +%%%=================================================================== +%%% API +%%%=================================================================== +from_dir(ProsodyDir) -> + case file:list_dir(ProsodyDir) of + {ok, HostDirs} -> + lists:foreach( + fun(HostDir) -> + Host = list_to_binary(HostDir), + lists:foreach( + fun(SubDir) -> + Path = filename:join( + [ProsodyDir, HostDir, SubDir]), + convert_dir(Path, Host, SubDir) + end, ["vcard", "accounts", "roster", + "private", "config", "offline"]) + end, HostDirs); + {error, Why} = Err -> + ?ERROR_MSG("failed to list ~s: ~s", + [ProsodyDir, file:format_error(Why)]), + Err + end. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +convert_dir(Path, Host, Type) -> + case file:list_dir(Path) of + {ok, Files} -> + lists:foreach( + fun(File) -> + FilePath = filename:join(Path, File), + case eval_file(FilePath) of + {ok, Data} -> + Name = iolist_to_binary(filename:rootname(File)), + convert_data(Host, Type, Name, Data); + Err -> + Err + end + end, Files); + {error, enoent} -> + ok; + {error, Why} = Err -> + ?ERROR_MSG("failed to list ~s: ~s", + [Path, file:format_error(Why)]), + Err + end. + +eval_file(Path) -> + case file:read_file(Path) of + {ok, Data} -> + State0 = luerl:init(), + State1 = luerl:set_table([item], + fun([X], State) -> {[X], State} end, + State0), + NewData = case filename:extension(Path) of + ".list" -> + <<"return {", Data/binary, "};">>; + _ -> + Data + end, + case luerl:eval(NewData, State1) of + {ok, _} = Res -> + Res; + {error, Why} = Err -> + ?ERROR_MSG("failed to eval ~s: ~p", [Path, Why]), + Err + end; + {error, Why} = Err -> + ?ERROR_MSG("failed to read file ~s: ~s", + [Path, file:format_error(Why)]), + Err + end. + +convert_data(Host, "accounts", User, [Data]) -> + Password = proplists:get_value(<<"password">>, Data, <<>>), + case ejabberd_auth:try_register(User, Host, Password) of + {atomic, ok} -> + ok; + Err -> + ?ERROR_MSG("failed to register user ~s@~s: ~p", + [User, Host, Err]), + Err + end; +convert_data(Host, "roster", User, [Data]) -> + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Host), + Rosters = + lists:flatmap( + fun({<<"pending">>, L}) -> + convert_pending_item(LUser, LServer, L); + ({S, L}) when is_binary(S) -> + convert_roster_item(LUser, LServer, S, L); + (_) -> + [] + end, Data), + lists:foreach(fun mod_roster:set_roster/1, Rosters); +convert_data(Host, "private", User, [Data]) -> + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Host), + PrivData = lists:flatmap( + fun({_TagXMLNS, Raw}) -> + case deserialize(Raw) of + [El] -> + XMLNS = xml:get_tag_attr_s(<<"xmlns">>, El), + [{XMLNS, El}]; + _ -> + [] + end + end, Data), + mod_private:set_data(LUser, LServer, PrivData); +convert_data(Host, "vcard", User, [Data]) -> + LServer = jid:nameprep(Host), + case deserialize(Data) of + [VCard] -> + mod_vcard:set_vcard(User, LServer, VCard); + _ -> + ok + end; +convert_data(_Host, "config", _User, [Data]) -> + RoomJID = jid:from_string(proplists:get_value(<<"jid">>, Data, <<"">>)), + Config = proplists:get_value(<<"_data">>, Data, []), + RoomCfg = convert_room_config(Data), + case proplists:get_bool(<<"persistent">>, Config) of + true when RoomJID /= error -> + mod_muc:store_room(?MYNAME, RoomJID#jid.lserver, + RoomJID#jid.luser, RoomCfg); + _ -> + ok + end; +convert_data(Host, "offline", User, [Data]) -> + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Host), + Msgs = lists:flatmap( + fun({_, RawXML}) -> + case deserialize(RawXML) of + [El] -> el_to_offline_msg(LUser, LServer, El); + _ -> [] + end + end, Data), + mod_offline:store_offline_msg( + LServer, {LUser, LServer}, Msgs, length(Msgs), infinity); +convert_data(_Host, _Type, _User, _Data) -> + ok. + +convert_pending_item(LUser, LServer, LuaList) -> + lists:flatmap( + fun({S, true}) -> + case jid:from_string(S) of + #jid{} = J -> + LJID = jid:tolower(J), + [#roster{usj = {LUser, LServer, LJID}, + us = {LUser, LServer}, + jid = LJID, + ask = in}]; + error -> + [] + end; + (_) -> + [] + end, LuaList). + +convert_roster_item(LUser, LServer, JIDstring, LuaList) -> + case jid:from_string(JIDstring) of + #jid{} = JID -> + LJID = jid:tolower(JID), + InitR = #roster{usj = {LUser, LServer, LJID}, + us = {LUser, LServer}, + jid = LJID}, + Roster = + lists:foldl( + fun({<<"groups">>, Val}, R) -> + Gs = lists:flatmap( + fun({G, true}) -> [G]; + (_) -> [] + end, Val), + R#roster{groups = Gs}; + ({<<"subscription">>, Sub}, R) -> + R#roster{subscription = jlib:binary_to_atom(Sub)}; + ({<<"ask">>, <<"subscribe">>}, R) -> + R#roster{ask = out}; + ({<<"name">>, Name}, R) -> + R#roster{name = Name} + end, InitR, LuaList), + [Roster]; + error -> + [] + end. + +convert_room_affiliations(Data) -> + lists:flatmap( + fun({J, Aff}) -> + case jid:from_string(J) of + #jid{luser = U, lserver = S} -> + [{{U, S, <<>>}, jlib:binary_to_atom(Aff)}]; + error -> + [] + end + end, proplists:get_value(<<"_affiliations">>, Data, [])). + +convert_room_config(Data) -> + Config = proplists:get_value(<<"_data">>, Data, []), + Pass = case proplists:get_value(<<"password">>, Config, <<"">>) of + <<"">> -> + []; + Password -> + [{password_protected, true}, + {password, Password}] + end, + Subj = case jid:from_string( + proplists:get_value( + <<"subject_from">>, Config, <<"">>)) of + #jid{lresource = Nick} when Nick /= <<"">> -> + [{subject, proplists:get_value(<<"subject">>, Config, <<"">>)}, + {subject_author, Nick}]; + _ -> + [] + end, + Anonymous = case proplists:get_value(<<"whois">>, Config, <<"moderators">>) of + <<"moderators">> -> true; + _ -> false + end, + [{affiliations, convert_room_affiliations(Data)}, + {allow_change_subj, proplists:get_bool(<<"changesubject">>, Config)}, + {description, proplists:get_value(<<"description">>, Config, <<"">>)}, + {members_only, proplists:get_bool(<<"members_only">>, Config)}, + {moderated, proplists:get_bool(<<"moderated">>, Config)}, + {anonymous, Anonymous}] ++ Pass ++ Subj. + +el_to_offline_msg(LUser, LServer, #xmlel{attrs = Attrs} = El) -> + case jlib:datetime_string_to_timestamp( + xml:get_attr_s(<<"stamp">>, Attrs)) of + {_, _, _} = TS -> + Attrs1 = lists:filter( + fun(<<"stamp">>) -> false; + (<<"stamp_legacy">>) -> false; + (_) -> true + end, Attrs), + Packet = El#xmlel{attrs = Attrs1}, + case {jid:from_string(xml:get_attr_s(<<"from">>, Attrs)), + jid:from_string(xml:get_attr_s(<<"to">>, Attrs))} of + {#jid{} = From, #jid{} = To} -> + [#offline_msg{ + us = {LUser, LServer}, + timestamp = TS, + expire = never, + from = From, + to = To, + packet = Packet}]; + _ -> + [] + end; + _ -> + [] + end. + +deserialize(L) -> + deserialize(L, #xmlel{}, []). + +deserialize([{<<"attr">>, Attrs}|T], El, Acc) -> + deserialize(T, El#xmlel{attrs = Attrs ++ El#xmlel.attrs}, Acc); +deserialize([{<<"name">>, Name}|T], El, Acc) -> + deserialize(T, El#xmlel{name = Name}, Acc); +deserialize([{_, S}|T], #xmlel{children = Els} = El, Acc) when is_binary(S) -> + deserialize(T, El#xmlel{children = [{xmlcdata, S}|Els]}, Acc); +deserialize([{_, L}|T], #xmlel{children = Els} = El, Acc) when is_list(L) -> + deserialize(T, El#xmlel{children = deserialize(L) ++ Els}, Acc); +deserialize([], El, Acc) -> + [El|Acc]. From 54dc2f56c6170dc54b4f3ca64c9cc3f3921af6bd Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 29 Jan 2016 14:14:08 +0300 Subject: [PATCH 531/695] Import privacy lists from Prosody --- src/mod_privacy.erl | 32 ++++++++++++++++++++++- src/prosody2ejabberd.erl | 55 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 9c2af037b93..62b043db03d 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -35,7 +35,8 @@ process_iq_set/4, process_iq_get/5, get_user_list/3, check_packet/6, remove_user/2, item_to_raw/1, raw_to_item/1, is_list_needdb/1, updated_list/3, - item_to_xml/1, get_user_lists/2, import/3]). + item_to_xml/1, get_user_lists/2, import/3, + set_privacy_list/1]). -export([sql_add_privacy_list/2, sql_get_default_privacy_list/2, @@ -529,6 +530,35 @@ remove_privacy_list(LUser, LServer, Name, odbc) -> end, odbc_queries:sql_transaction(LServer, F). +set_privacy_list(#privacy{us = {_, LServer}} = Privacy) -> + DBType = gen_mod:db_type(LServer, ?MODULE), + set_privacy_list(Privacy, DBType). + +set_privacy_list(Privacy, mnesia) -> + mnesia:dirty_write(Privacy); +set_privacy_list(Privacy, riak) -> + ejabberd_riak:put(Privacy, privacy_schema()); +set_privacy_list(#privacy{us = {LUser, LServer}, + default = Default, + lists = Lists}, odbc) -> + F = fun() -> + lists:foreach( + fun({Name, List}) -> + sql_add_privacy_list(LUser, Name), + {selected, [<<"id">>], [[I]]} = + sql_get_privacy_list_id_t(LUser, Name), + RItems = lists:map(fun item_to_raw/1, List), + sql_set_privacy_list(I, RItems), + if is_binary(Default) -> + sql_set_default_privacy_list(LUser, Default), + ok; + true -> + ok + end + end, Lists) + end, + odbc_queries:sql_transaction(LServer, F). + set_privacy_list(LUser, LServer, Name, List, mnesia) -> F = fun () -> case mnesia:wread({privacy, {LUser, LServer}}) of diff --git a/src/prosody2ejabberd.erl b/src/prosody2ejabberd.erl index ce46e3991ec..d16437209c6 100644 --- a/src/prosody2ejabberd.erl +++ b/src/prosody2ejabberd.erl @@ -16,6 +16,7 @@ -include("logger.hrl"). -include("mod_roster.hrl"). -include("mod_offline.hrl"). +-include("mod_privacy.hrl"). %%%=================================================================== %%% API @@ -32,7 +33,8 @@ from_dir(ProsodyDir) -> [ProsodyDir, HostDir, SubDir]), convert_dir(Path, Host, SubDir) end, ["vcard", "accounts", "roster", - "private", "config", "offline"]) + "private", "config", "offline", + "privacy"]) end, HostDirs); {error, Why} = Err -> ?ERROR_MSG("failed to list ~s: ~s", @@ -159,6 +161,23 @@ convert_data(Host, "offline", User, [Data]) -> end, Data), mod_offline:store_offline_msg( LServer, {LUser, LServer}, Msgs, length(Msgs), infinity); +convert_data(Host, "privacy", User, [Data]) -> + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Host), + Lists = proplists:get_value(<<"lists">>, Data, []), + Priv = #privacy{ + us = {LUser, LServer}, + default = proplists:get_value(<<"default">>, Data, none), + lists = lists:flatmap( + fun({Name, Vals}) -> + Items = proplists:get_value(<<"items">>, Vals, []), + case lists:map(fun convert_privacy_item/1, + Items) of + [] -> []; + ListItems -> [{Name, ListItems}] + end + end, Lists)}, + mod_privacy:set_privacy_list(Priv); convert_data(_Host, _Type, _User, _Data) -> ok. @@ -246,6 +265,40 @@ convert_room_config(Data) -> {moderated, proplists:get_bool(<<"moderated">>, Config)}, {anonymous, Anonymous}] ++ Pass ++ Subj. +convert_privacy_item({_, Item}) -> + Action = proplists:get_value(<<"action">>, Item, <<"allow">>), + Order = proplists:get_value(<<"order">>, Item, 0), + T = jlib:binary_to_atom(proplists:get_value(<<"type">>, Item, <<"none">>)), + V = proplists:get_value(<<"value">>, Item, <<"">>), + MatchIQ = proplists:get_bool(<<"iq">>, Item), + MatchMsg = proplists:get_bool(<<"message">>, Item), + MatchPresIn = proplists:get_bool(<<"presence-in">>, Item), + MatchPresOut = proplists:get_bool(<<"presence-out">>, Item), + MatchAll = if (MatchIQ == false) and (MatchMsg == false) and + (MatchPresIn == false) and (MatchPresOut == false) -> + true; + true -> + false + end, + {Type, Value} = try case T of + none -> {T, none}; + group -> {T, V}; + jid -> {T, jid:tolower(jid:from_string(V))}; + subscription -> {T, jlib:binary_to_atom(V)} + end + catch _:_ -> + {none, none} + end, + #listitem{type = Type, + value = Value, + action = jlib:binary_to_atom(Action), + order = erlang:trunc(Order), + match_all = MatchAll, + match_iq = MatchIQ, + match_message = MatchMsg, + match_presence_in = MatchPresIn, + match_presence_out = MatchPresOut}. + el_to_offline_msg(LUser, LServer, #xmlel{attrs = Attrs} = El) -> case jlib:datetime_string_to_timestamp( xml:get_attr_s(<<"stamp">>, Attrs)) of From d3ee2a9c184ca3cb6b8afb92c5e444a593ff81f7 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 29 Jan 2016 14:30:50 +0300 Subject: [PATCH 532/695] Add 'import_prosody' command --- src/ejabberd_admin.erl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 4aa5faedbb7..c9e5b1780d1 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -201,6 +201,11 @@ get_commands_spec() -> module = ejabberd_auth_odbc, function = convert_to_scram, args = [{host, binary}], result = {res, rescode}}, + #ejabberd_commands{name = import_prosody, tags = [mnesia, odbc, riak], + desc = "Import data from Prosody", + module = prosody2ejabberd, function = from_dir, + args = [{dir, string}], result = {res, rescode}}, + #ejabberd_commands{name = convert_to_yaml, tags = [config], desc = "Convert the input file from Erlang to YAML format", module = ejabberd_config, function = convert_to_yaml, From dc52ec904c439f2fbd399939fb9442281986a361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 1 Feb 2016 11:30:17 +0100 Subject: [PATCH 533/695] Send presence with code 170 only in initial presence from MUC --- src/mod_muc_room.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index d19bc5f3d11..4f6c688100b 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2217,7 +2217,8 @@ send_new_presence1(NJID, Reason, StateData, OldStateData) -> | Status2]; false -> Status2 end, - Status4 = case (StateData#state.config)#config.logging of + Status4 = case (StateData#state.config)#config.logging == true + andalso NJID == Info#user.jid of true -> [#xmlel{name = <<"status">>, attrs = From fa55ac5c8fe6f50e2daf3db1577db86df159d16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 1 Feb 2016 12:09:34 +0100 Subject: [PATCH 534/695] More strict checking for MUC initial presence --- src/mod_muc_room.erl | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 4f6c688100b..3306e48a421 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2220,12 +2220,17 @@ send_new_presence1(NJID, Reason, StateData, OldStateData) -> Status4 = case (StateData#state.config)#config.logging == true andalso NJID == Info#user.jid of true -> - [#xmlel{name = <<"status">>, - attrs = - [{<<"code">>, <<"170">>}], - children = []} - | Status3]; - false -> Status3 + case (?DICT):find(jid:tolower(LJID), + OldStateData#state.users) of + {ok, _} -> Status3; + _ -> + [#xmlel{name = <<"status">>, + attrs = + [{<<"code">>, <<"170">>}], + children = []} + | Status3] + end; + false -> Status3 end, Packet = xml:append_subtags(Presence, [#xmlel{name = <<"x">>, From 80fc34fb0c603a033958f14ae7b5ccabaf8562e4 Mon Sep 17 00:00:00 2001 From: Nathan Bruning Date: Tue, 19 Jan 2016 23:48:48 +0100 Subject: [PATCH 535/695] Fix presence-based delivery --- src/mod_pubsub.erl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 616c64929d1..b6185852b7e 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3170,17 +3170,15 @@ sub_option_can_deliver(_, _, _) -> true. presence_can_deliver(_, false) -> true; presence_can_deliver({User, Server, Resource}, true) -> - case mnesia:dirty_match_object({session, '_', '_', {User, Server}, '_', '_'}) of + case ejabberd_sm:get_user_present_resources(User, Server) of [] -> false; Ss -> lists:foldl(fun (_, true) -> true; - ({session, _, _, _, undefined, _}, _Acc) -> - false; - ({session, {_, _, R}, _, _, _Priority, _}, _Acc) -> - case Resource of + ({_, R}, _Acc) -> + case Resource of <<>> -> true; R -> true; _ -> false From e8ba7bce24fa5b4893f4c07b77fbd91e49dbd753 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 10:12:25 +0100 Subject: [PATCH 536/695] Use stringprep app name --- mix.exs | 4 ++-- rebar.config | 6 +++--- src/ejabberd_app.erl | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mix.exs b/mix.exs index 9a1f7072237..cfe78d20489 100644 --- a/mix.exs +++ b/mix.exs @@ -25,7 +25,7 @@ defmodule Ejabberd.Mixfile do [mod: {:ejabberd_app, []}, applications: [:ssl], included_applications: [:lager, :mnesia, :p1_utils, :cache_tab, - :p1_tls, :p1_stringprep, :p1_xml, + :p1_tls, :stringprep, :p1_xml, :p1_stun, :p1_yaml, :p1_zlib, :p1_iconv, :esip, :jiffy, :oauth2, :xmlrpc, :eredis, :p1_mysql, :p1_pgsql, :sqlite3]] @@ -42,7 +42,7 @@ defmodule Ejabberd.Mixfile do {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3", override: true}, {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.2"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, - {:p1_stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.1"}, + {:stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.2"}, {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.2"}, {:p1_stun, git: "https://github.com/processone/stun", tag: "0.9.1"}, {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.1"}, diff --git a/rebar.config b/rebar.config index 44b73fd95ed..ffc4885eb35 100644 --- a/rebar.config +++ b/rebar.config @@ -11,7 +11,7 @@ {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.3"}}}, {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.2"}}}, {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, - {p1_stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.1"}}}, + {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.2"}}}, {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, {p1_stun, ".*", {git, "https://github.com/processone/stun", {tag, "0.9.1"}}}, {esip, ".*", {git, "https://github.com/processone/p1_sip", "1.0.1"}}, @@ -37,7 +37,7 @@ {floating_deps, [p1_logger, cache_tab, p1_tls, - p1_stringprep, + stringprep, p1_xml, esip, luerl, @@ -94,7 +94,7 @@ {eunit_compile_opts, [{i, "tools"}]}. {post_hook_configure, [{"p1_tls", []}, - {"p1_stringprep", []}, + {"stringprep", []}, {"p1_yaml", []}, {"esip", []}, {"p1_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 628b4a8ad01..ae74b5963d1 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -255,7 +255,7 @@ start_apps() -> ejabberd:start_app(p1_yaml), ejabberd:start_app(p1_tls), ejabberd:start_app(p1_xml), - ejabberd:start_app(p1_stringprep), + ejabberd:start_app(stringprep), ejabberd:start_app(p1_zlib), ejabberd:start_app(cache_tab). From a457105831a7f9019f5700c83a932e34480979f1 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 10:16:05 +0100 Subject: [PATCH 537/695] Run ejabberd test on Erlang R18 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 5379f848b9b..d1215b2bb0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: erlang otp_release: - 17.1 - 17.5 + - 18.0 services: - riak From 9b837860cd7560412eb443017f9ceb90c630aad7 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 10:55:40 +0100 Subject: [PATCH 538/695] Switch a few version to hex.pm version --- mix.exs | 22 +++++++++++----------- mix.lock | 31 ++++++++++++++++++++++++------- rebar.config | 12 ++++++------ 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/mix.exs b/mix.exs index cfe78d20489..52d40d73e5f 100644 --- a/mix.exs +++ b/mix.exs @@ -38,25 +38,25 @@ defmodule Ejabberd.Mixfile do end defp deps do - [{:lager, git: "https://github.com/basho/lager", tag: "3.0.2"}, - {:p1_utils, git: "https://github.com/processone/p1_utils", tag: "1.0.3", override: true}, - {:cache_tab, git: "https://github.com/processone/cache_tab", tag: "1.0.2"}, + [{:lager, "~> 3.0"}, + {:p1_utils, "~> 1.0", override: true}, + {:cache_tab, "~> 1.0"}, + {:stringprep, "~> 1.0"}, + {:fast_yaml, "~> 1.0"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, - {:stringprep, git: "https://github.com/processone/stringprep", tag: "1.0.2"}, {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.2"}, {:p1_stun, git: "https://github.com/processone/stun", tag: "0.9.1"}, {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.1"}, - {:p1_yaml, git: "https://github.com/processone/p1_yaml", tag: "1.0.1"}, - {:jiffy, git: "https://github.com/davisp/jiffy", tag: "0.14.5"}, - {:oauth2, git: "https://github.com/kivra/oauth2", ref: "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}, - {:xmlrpc, git: "https://github.com/rds13/xmlrpc.git", tag: "1.15"}, + {:jiffy, "~> 0.14.7"}, + {:p1_oauth2, "~> 0.6.1"}, + {:p1_xmlrpc, "~> 1.15"}, {:p1_mysql, git: "https://github.com/processone/mysql", tag: "1.0.0"}, {:p1_pgsql, git: "https://github.com/processone/pgsql", tag: "1.0.0"}, - {:sqlite3, git: "https://github.com/alexeyr/erlang-sqlite3", ref: "cbc3505f7a131254265d3ef56191b2581b8cc172"}, + {:sqlite3, "~> 1.1"}, {:p1_zlib, git: "https://github.com/processone/zlib", tag: "1.0.0"}, {:p1_iconv, git: "https://github.com/processone/eiconv", tag: "0.9.0"}, - {:eredis, git: "https://github.com/wooga/eredis", tag: "v1.0.8"}, - {:exrm, "0.19.9"}] + {:eredis, "~> 1.0"}, + {:exrm, "~> 1.0.0-rc7", only: :dev}] end defp package do diff --git a/mix.lock b/mix.lock index 5f4955115bd..4f88c5f220e 100644 --- a/mix.lock +++ b/mix.lock @@ -1,8 +1,25 @@ -%{"bbmustache": {:hex, :bbmustache, "1.0.4"}, - "erlware_commons": {:hex, :erlware_commons, "0.18.0"}, +%{"bbmustache": {:hex, :bbmustache, "1.0.3"}, + "cache_tab": {:hex, :cache_tab, "1.0.2"}, + "eredis": {:hex, :eredis, "1.0.8"}, + "erlware_commons": {:hex, :erlware_commons, "0.15.0"}, + "esip": {:git, "https://github.com/processone/p1_sip", "3bcccd4dfe705cb90f205887f749b1c5195fcad1", [tag: "1.0.1"]}, + "exrm": {:hex, :exrm, "1.0.0-rc7"}, + "fast_yaml": {:hex, :fast_yaml, "1.0.2"}, "getopt": {:hex, :getopt, "0.8.2"}, - "providers": {:hex, :providers, "1.6.0"}, - "cf": {:hex, :cf, "0.2.1"}, - "relx": {:hex, :relx, "3.11.0"}, - "conform": {:hex, :conform, "0.17.0"}, - "neotoma": {:hex, :neotoma, "1.7.3"}} + "goldrush": {:hex, :goldrush, "0.1.7"}, + "jiffy": {:hex, :jiffy, "0.14.7"}, + "lager": {:hex, :lager, "3.0.2"}, + "p1_iconv": {:git, "https://github.com/processone/eiconv", "9751f86baa5a60ed1420490793e7514a0757462a", [tag: "0.9.0"]}, + "p1_mysql": {:git, "https://github.com/processone/mysql", "064948ad3c77e582d85cbc09ccd11016ae97de0e", [tag: "1.0.0"]}, + "p1_oauth2": {:hex, :p1_oauth2, "0.6.1"}, + "p1_pgsql": {:git, "https://github.com/processone/pgsql", "248b6903cad82c748dc7f5be75e014dd8d47a3d1", [tag: "1.0.0"]}, + "p1_stun": {:git, "https://github.com/processone/stun", "c3dc4d9ae6dbab311cc3ed1c116be71d17c6c771", [tag: "0.9.1"]}, + "p1_tls": {:git, "https://github.com/processone/tls", "f19e1f701e0a3980ffc70b3917c4aa85e68d8520", [tag: "1.0.0"]}, + "p1_utils": {:hex, :p1_utils, "1.0.3"}, + "p1_xml": {:git, "https://github.com/processone/xml", "79c6d54e56bf991f1ec70ceb5e255afcb8dbf53f", [tag: "1.1.2"]}, + "p1_xmlrpc": {:hex, :p1_xmlrpc, "1.15.1"}, + "p1_zlib": {:git, "https://github.com/processone/zlib", "e1f928e61553cf85638eaac7d024c8f68ce0ff36", [tag: "1.0.0"]}, + "providers": {:hex, :providers, "1.4.1"}, + "relx": {:hex, :relx, "3.5.0"}, + "sqlite3": {:hex, :sqlite3, "1.1.5"}, + "stringprep": {:hex, :stringprep, "1.0.2"}} diff --git a/rebar.config b/rebar.config index ffc4885eb35..b0220d19e13 100644 --- a/rebar.config +++ b/rebar.config @@ -15,10 +15,10 @@ {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, {p1_stun, ".*", {git, "https://github.com/processone/stun", {tag, "0.9.1"}}}, {esip, ".*", {git, "https://github.com/processone/p1_sip", "1.0.1"}}, - {p1_yaml, ".*", {git, "https://github.com/processone/p1_yaml", {tag, "1.0.1"}}}, - {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.5"}}}, - {oauth2, ".*", {git, "https://github.com/kivra/oauth2", "8d129fbf8866930b4ffa6dd84e65bd2b32b9acb8"}}, - {xmlrpc, ".*", {git, "https://github.com/rds13/xmlrpc", {tag, "1.15"}}}, + {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.2"}}}, + {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.7"}}}, + {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2.git", {tag, "0.6.1"}}}, + {p1_xmlrpc, ".*", {git, "https://github.com/processone/p1_xmlrpc", {tag, "1.15.1"}}}, {luerl, ".*", {git, "https://github.com/rvirding/luerl", "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/mysql", {tag, "1.0.0"}}}}, {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", {tag, "1.0.0"}}}}, @@ -42,7 +42,7 @@ esip, luerl, p1_stun, - p1_yaml, + fast_yaml, p1_utils, p1_mysql, p1_pgsql, @@ -95,7 +95,7 @@ {post_hook_configure, [{"p1_tls", []}, {"stringprep", []}, - {"p1_yaml", []}, + {"fast_yaml", []}, {"esip", []}, {"p1_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, {if_var_true, pam, {"p1_pam", []}}, From ba11165fb479e28bf7577e7cbf74e4ae43246b1f Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 11:00:12 +0100 Subject: [PATCH 539/695] Syntax highlight file + comment on rebar_elixir_plugin --- rebar.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rebar.config b/rebar.config index b0220d19e13..991ec6b6c8a 100644 --- a/rebar.config +++ b/rebar.config @@ -28,6 +28,7 @@ {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.1.0"}}}}, + %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, {if_var_true, iconv, {p1_iconv, ".*", {git, "https://github.com/processone/eiconv", {tag, "0.9.0"}}}}, {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, @@ -105,3 +106,8 @@ {port_env, [{"CFLAGS", "-g -O2 -Wall"}]}. {port_specs, [{"priv/lib/jid.so", ["c_src/jid.c"]}]}. + +%% Local Variables: +%% mode: erlang +%% End: +%% vim: set filetype=erlang tabstop=8: \ No newline at end of file From bad50b8dd1b0da7ba293acc02acf1a7154ffdb6c Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 11:10:11 +0100 Subject: [PATCH 540/695] Move database dependencies to new repository / modules --- mix.exs | 4 ++-- rebar.config | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mix.exs b/mix.exs index 52d40d73e5f..f9ce0400c4c 100644 --- a/mix.exs +++ b/mix.exs @@ -50,8 +50,8 @@ defmodule Ejabberd.Mixfile do {:jiffy, "~> 0.14.7"}, {:p1_oauth2, "~> 0.6.1"}, {:p1_xmlrpc, "~> 1.15"}, - {:p1_mysql, git: "https://github.com/processone/mysql", tag: "1.0.0"}, - {:p1_pgsql, git: "https://github.com/processone/pgsql", tag: "1.0.0"}, + {:p1_mysql, "~> 1.0"}, + {:p1_pgsql, "~> 1.0"}, {:sqlite3, "~> 1.1"}, {:p1_zlib, git: "https://github.com/processone/zlib", tag: "1.0.0"}, {:p1_iconv, git: "https://github.com/processone/eiconv", tag: "0.9.0"}, diff --git a/rebar.config b/rebar.config index 991ec6b6c8a..8e86e41ce6e 100644 --- a/rebar.config +++ b/rebar.config @@ -20,9 +20,9 @@ {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2.git", {tag, "0.6.1"}}}, {p1_xmlrpc, ".*", {git, "https://github.com/processone/p1_xmlrpc", {tag, "1.15.1"}}}, {luerl, ".*", {git, "https://github.com/rvirding/luerl", "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, - {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/mysql", {tag, "1.0.0"}}}}, - {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/pgsql", {tag, "1.0.0"}}}}, - {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/alexeyr/erlang-sqlite3", "cbc3505f7a131254265d3ef56191b2581b8cc172"}}}, + {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.1"}}}}, + {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.0.1"}}}}, + {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.5"}}}}, {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.0"}}}}, {if_var_true, zlib, {p1_zlib, ".*", {git, "https://github.com/processone/zlib", {tag, "1.0.0"}}}}, {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 @@ -110,4 +110,4 @@ %% Local Variables: %% mode: erlang %% End: -%% vim: set filetype=erlang tabstop=8: \ No newline at end of file +%% vim: set filetype=erlang tabstop=8: From 99b5c5712c2a068f90250e0283840a3f0093d65e Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 11:17:16 +0100 Subject: [PATCH 541/695] Move to new iconv package --- mix.exs | 2 +- rebar.config | 6 +++--- src/mod_irc.erl | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mix.exs b/mix.exs index f9ce0400c4c..668773333ca 100644 --- a/mix.exs +++ b/mix.exs @@ -54,7 +54,7 @@ defmodule Ejabberd.Mixfile do {:p1_pgsql, "~> 1.0"}, {:sqlite3, "~> 1.1"}, {:p1_zlib, git: "https://github.com/processone/zlib", tag: "1.0.0"}, - {:p1_iconv, git: "https://github.com/processone/eiconv", tag: "0.9.0"}, + {:iconv, "~> 1.0"}, {:eredis, "~> 1.0"}, {:exrm, "~> 1.0.0-rc7", only: :dev}] end diff --git a/rebar.config b/rebar.config index 8e86e41ce6e..0d413d24906 100644 --- a/rebar.config +++ b/rebar.config @@ -30,7 +30,7 @@ {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.1.0"}}}}, %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, - {if_var_true, iconv, {p1_iconv, ".*", {git, "https://github.com/processone/eiconv", {tag, "0.9.0"}}}}, + {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv", {tag, "1.0.0"}}}}, {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}}]}. @@ -49,7 +49,7 @@ p1_pgsql, p1_pam, p1_zlib, - p1_iconv]}}. + iconv]}}. {erl_opts, [nowarn_deprecated_function, {if_var_false, debug, no_debug_info}, @@ -101,7 +101,7 @@ {"p1_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, {if_var_true, pam, {"p1_pam", []}}, {if_var_true, zlib, {"p1_zlib", []}}, - {if_var_true, iconv, {"p1_iconv", []}}]}. + {if_var_true, iconv, {"iconv", []}}]}. {port_env, [{"CFLAGS", "-g -O2 -Wall"}]}. diff --git a/src/mod_irc.erl b/src/mod_irc.erl index 183088956cc..25b3245de03 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -116,7 +116,7 @@ stop(Host) -> %% Description: Initiates the server %%-------------------------------------------------------------------- init([Host, Opts]) -> - ejabberd:start_app(p1_iconv), + ejabberd:start_app(iconv), MyHost = gen_mod:get_opt_host(Host, Opts, <<"irc.@HOST@">>), case gen_mod:db_type(Host, Opts) of From b137ee3beb014e6b0cd4815624c1a0351a12ea36 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 11:26:14 +0100 Subject: [PATCH 542/695] Move to new dependencies for SIP and STUN --- mix.exs | 4 ++-- rebar.config | 4 ++-- src/ejabberd_stun.erl | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mix.exs b/mix.exs index 668773333ca..1052e4c2819 100644 --- a/mix.exs +++ b/mix.exs @@ -45,8 +45,8 @@ defmodule Ejabberd.Mixfile do {:fast_yaml, "~> 1.0"}, {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.2"}, - {:p1_stun, git: "https://github.com/processone/stun", tag: "0.9.1"}, - {:esip, git: "https://github.com/processone/p1_sip", tag: "1.0.1"}, + {:stun, "~> 1.0"}, + {:esip, "~> 1.0"}, {:jiffy, "~> 0.14.7"}, {:p1_oauth2, "~> 0.6.1"}, {:p1_xmlrpc, "~> 1.15"}, diff --git a/rebar.config b/rebar.config index 0d413d24906..ef89077f59b 100644 --- a/rebar.config +++ b/rebar.config @@ -13,8 +13,8 @@ {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.2"}}}, {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, - {p1_stun, ".*", {git, "https://github.com/processone/stun", {tag, "0.9.1"}}}, - {esip, ".*", {git, "https://github.com/processone/p1_sip", "1.0.1"}}, + {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.0"}}}, + {esip, ".*", {git, "https://github.com/processone/esip", "1.0.1"}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.2"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.7"}}}, {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2.git", {tag, "0.6.1"}}}, diff --git a/src/ejabberd_stun.erl b/src/ejabberd_stun.erl index f7ae19cd416..3c91117d12c 100644 --- a/src/ejabberd_stun.erl +++ b/src/ejabberd_stun.erl @@ -38,11 +38,11 @@ %%% API %%%=================================================================== tcp_init(Socket, Opts) -> - ejabberd:start_app(p1_stun), + ejabberd:start_app(stun), stun:tcp_init(Socket, prepare_turn_opts(Opts)). udp_init(Socket, Opts) -> - ejabberd:start_app(p1_stun), + ejabberd:start_app(stun), stun:udp_init(Socket, prepare_turn_opts(Opts)). udp_recv(Socket, Addr, Port, Packet, Opts) -> From 0de222d998e372661c7ba1c1d0cecc8b7a23b0aa Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 11:30:48 +0100 Subject: [PATCH 543/695] Convert code to use Fast YAML --- src/ejabberd_app.erl | 2 +- src/ejabberd_config.erl | 6 +++--- src/ext_mod.erl | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index ae74b5963d1..5589c31b9b0 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -252,7 +252,7 @@ start_apps() -> crypto:start(), ejabberd:start_app(sasl), ejabberd:start_app(ssl), - ejabberd:start_app(p1_yaml), + ejabberd:start_app(fast_yaml), ejabberd:start_app(p1_tls), ejabberd:start_app(p1_xml), ejabberd:start_app(stringprep), diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 8d2d19975b3..1f2eaa142c6 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -162,7 +162,7 @@ convert_to_yaml(File, Output) -> fun({Host, Opts1}) -> {host_config, [{Host, Opts1}]} end, HOpts), - Data = p1_yaml:encode(lists:reverse(NewOpts)), + Data = fast_yaml:encode(lists:reverse(NewOpts)), case Output of stdout -> io:format("~s~n", [Data]); @@ -226,14 +226,14 @@ get_plain_terms_file(File1, Opts) -> consult(File) -> case filename:extension(File) of Ex when (Ex == ".yml") or (Ex == ".yaml") -> - case p1_yaml:decode_from_file(File, [plain_as_atom]) of + case fast_yaml:decode_from_file(File, [plain_as_atom]) of {ok, []} -> {ok, []}; {ok, [Document|_]} -> {ok, parserl(Document)}; {error, Err} -> Msg1 = "Cannot load " ++ File ++ ": ", - Msg2 = p1_yaml:format_error(Err), + Msg2 = fast_yaml:format_error(Err), {error, Msg1 ++ Msg2} end; _ -> diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 46ece873c54..14ac21316e5 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -589,10 +589,10 @@ rebar_dep({App, _, {git, Url, Ref}}) -> %% -- YAML spec parser consult(File) -> - case p1_yaml:decode_from_file(File, [plain_as_atom]) of + case fast_yaml:decode_from_file(File, [plain_as_atom]) of {ok, []} -> {ok, []}; {ok, [Doc|_]} -> {ok, [format(Spec) || Spec <- Doc]}; - {error, Err} -> {error, p1_yaml:format_error(Err)} + {error, Err} -> {error, fast_yaml:format_error(Err)} end. format({Key, Val}) when is_binary(Val) -> From e83ae9e46177c01d72a173a9fbe159588ce07a8f Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 11:31:23 +0100 Subject: [PATCH 544/695] Proper name for included applications --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 1052e4c2819..0164649e7bd 100644 --- a/mix.exs +++ b/mix.exs @@ -26,7 +26,7 @@ defmodule Ejabberd.Mixfile do applications: [:ssl], included_applications: [:lager, :mnesia, :p1_utils, :cache_tab, :p1_tls, :stringprep, :p1_xml, - :p1_stun, :p1_yaml, :p1_zlib, :p1_iconv, + :stun, :yaml, :p1_zlib, :iconv, :esip, :jiffy, :oauth2, :xmlrpc, :eredis, :p1_mysql, :p1_pgsql, :sqlite3]] end From 9ae1371c6e6edc70085286ec034dfa091302b35d Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 12:30:12 +0100 Subject: [PATCH 545/695] Convert more dependencies to new repository / packages --- mix.exs | 4 ++-- mix.lock | 15 ++++++++------- rebar.config | 10 +++++----- src/ejabberd_app.erl | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/mix.exs b/mix.exs index 0164649e7bd..51787e74450 100644 --- a/mix.exs +++ b/mix.exs @@ -26,7 +26,7 @@ defmodule Ejabberd.Mixfile do applications: [:ssl], included_applications: [:lager, :mnesia, :p1_utils, :cache_tab, :p1_tls, :stringprep, :p1_xml, - :stun, :yaml, :p1_zlib, :iconv, + :stun, :yaml, :ezlib, :iconv, :esip, :jiffy, :oauth2, :xmlrpc, :eredis, :p1_mysql, :p1_pgsql, :sqlite3]] end @@ -53,7 +53,7 @@ defmodule Ejabberd.Mixfile do {:p1_mysql, "~> 1.0"}, {:p1_pgsql, "~> 1.0"}, {:sqlite3, "~> 1.1"}, - {:p1_zlib, git: "https://github.com/processone/zlib", tag: "1.0.0"}, + {:ezlib, "~> 1.0"}, {:iconv, "~> 1.0"}, {:eredis, "~> 1.0"}, {:exrm, "~> 1.0.0-rc7", only: :dev}] diff --git a/mix.lock b/mix.lock index 4f88c5f220e..a91a94c59d2 100644 --- a/mix.lock +++ b/mix.lock @@ -2,24 +2,25 @@ "cache_tab": {:hex, :cache_tab, "1.0.2"}, "eredis": {:hex, :eredis, "1.0.8"}, "erlware_commons": {:hex, :erlware_commons, "0.15.0"}, - "esip": {:git, "https://github.com/processone/p1_sip", "3bcccd4dfe705cb90f205887f749b1c5195fcad1", [tag: "1.0.1"]}, + "esip": {:hex, :esip, "1.0.2"}, "exrm": {:hex, :exrm, "1.0.0-rc7"}, + "ezlib": {:hex, :ezlib, "1.0.1"}, + "fast_tls": {:hex, :fast_tls, "1.0.1"}, "fast_yaml": {:hex, :fast_yaml, "1.0.2"}, "getopt": {:hex, :getopt, "0.8.2"}, "goldrush": {:hex, :goldrush, "0.1.7"}, + "iconv": {:hex, :iconv, "1.0.0"}, "jiffy": {:hex, :jiffy, "0.14.7"}, "lager": {:hex, :lager, "3.0.2"}, - "p1_iconv": {:git, "https://github.com/processone/eiconv", "9751f86baa5a60ed1420490793e7514a0757462a", [tag: "0.9.0"]}, - "p1_mysql": {:git, "https://github.com/processone/mysql", "064948ad3c77e582d85cbc09ccd11016ae97de0e", [tag: "1.0.0"]}, + "p1_mysql": {:hex, :p1_mysql, "1.0.1"}, "p1_oauth2": {:hex, :p1_oauth2, "0.6.1"}, - "p1_pgsql": {:git, "https://github.com/processone/pgsql", "248b6903cad82c748dc7f5be75e014dd8d47a3d1", [tag: "1.0.0"]}, - "p1_stun": {:git, "https://github.com/processone/stun", "c3dc4d9ae6dbab311cc3ed1c116be71d17c6c771", [tag: "0.9.1"]}, + "p1_pgsql": {:hex, :p1_pgsql, "1.0.1"}, "p1_tls": {:git, "https://github.com/processone/tls", "f19e1f701e0a3980ffc70b3917c4aa85e68d8520", [tag: "1.0.0"]}, "p1_utils": {:hex, :p1_utils, "1.0.3"}, "p1_xml": {:git, "https://github.com/processone/xml", "79c6d54e56bf991f1ec70ceb5e255afcb8dbf53f", [tag: "1.1.2"]}, "p1_xmlrpc": {:hex, :p1_xmlrpc, "1.15.1"}, - "p1_zlib": {:git, "https://github.com/processone/zlib", "e1f928e61553cf85638eaac7d024c8f68ce0ff36", [tag: "1.0.0"]}, "providers": {:hex, :providers, "1.4.1"}, "relx": {:hex, :relx, "3.5.0"}, "sqlite3": {:hex, :sqlite3, "1.1.5"}, - "stringprep": {:hex, :stringprep, "1.0.2"}} + "stringprep": {:hex, :stringprep, "1.0.2"}, + "stun": {:hex, :stun, "1.0.1"}} diff --git a/rebar.config b/rebar.config index ef89077f59b..f0559f5ee1b 100644 --- a/rebar.config +++ b/rebar.config @@ -13,8 +13,8 @@ {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.2"}}}, {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, - {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.0"}}}, - {esip, ".*", {git, "https://github.com/processone/esip", "1.0.1"}}, + {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.1"}}}, + {esip, ".*", {git, "https://github.com/processone/esip", "1.0.2"}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.2"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.7"}}}, {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2.git", {tag, "0.6.1"}}}, @@ -24,7 +24,7 @@ {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.0.1"}}}}, {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.5"}}}}, {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.0"}}}}, - {if_var_true, zlib, {p1_zlib, ".*", {git, "https://github.com/processone/zlib", {tag, "1.0.0"}}}}, + {if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.1"}}}}, {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.1.0"}}}}, @@ -48,7 +48,7 @@ p1_mysql, p1_pgsql, p1_pam, - p1_zlib, + ezlib, iconv]}}. {erl_opts, [nowarn_deprecated_function, @@ -100,7 +100,7 @@ {"esip", []}, {"p1_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, {if_var_true, pam, {"p1_pam", []}}, - {if_var_true, zlib, {"p1_zlib", []}}, + {if_var_true, zlib, {"ezlib", []}}, {if_var_true, iconv, {"iconv", []}}]}. {port_env, [{"CFLAGS", "-g -O2 -Wall"}]}. diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 5589c31b9b0..78d67f2d6ec 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -256,7 +256,7 @@ start_apps() -> ejabberd:start_app(p1_tls), ejabberd:start_app(p1_xml), ejabberd:start_app(stringprep), - ejabberd:start_app(p1_zlib), + ejabberd:start_app(ezlib), ejabberd:start_app(cache_tab). opt_type(net_ticktime) -> From 71ee0d56fabf88099c5154ee04375866c08fe01b Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 16:13:16 +0100 Subject: [PATCH 546/695] Switch to fast_tls and update app names --- include/ejabberd_http.hrl | 4 ++-- mix.exs | 8 ++++---- mix.lock | 1 - rebar.config | 8 ++++---- src/ejabberd_app.erl | 2 +- src/ejabberd_c2s.erl | 8 ++++---- src/ejabberd_frontend_socket.erl | 16 ++++++++-------- src/ejabberd_http.erl | 8 ++++---- src/ejabberd_receiver.erl | 14 +++++++------- src/ejabberd_s2s.erl | 2 +- src/ejabberd_socket.erl | 16 ++++++++-------- src/ejabberd_websocket.erl | 6 +++--- 12 files changed, 46 insertions(+), 47 deletions(-) diff --git a/include/ejabberd_http.hrl b/include/ejabberd_http.hrl index 8b8fab2b086..b8cbe37087b 100644 --- a/include/ejabberd_http.hrl +++ b/include/ejabberd_http.hrl @@ -35,8 +35,8 @@ headers = [] :: [{atom() | binary(), binary()}]}). -record(ws, - {socket :: inet:socket() | p1_tls:tls_socket(), - sockmod = gen_tcp :: gen_tcp | p1_tls, + {socket :: inet:socket() | fast_tls:tls_socket(), + sockmod = gen_tcp :: gen_tcp | fast_tls, ip :: {inet:ip_address(), inet:port_number()}, host = <<"">> :: binary(), port = 5280 :: inet:port_number(), diff --git a/mix.exs b/mix.exs index 51787e74450..e9545b1786e 100644 --- a/mix.exs +++ b/mix.exs @@ -25,9 +25,9 @@ defmodule Ejabberd.Mixfile do [mod: {:ejabberd_app, []}, applications: [:ssl], included_applications: [:lager, :mnesia, :p1_utils, :cache_tab, - :p1_tls, :stringprep, :p1_xml, - :stun, :yaml, :ezlib, :iconv, - :esip, :jiffy, :oauth2, :xmlrpc, :eredis, + :fast_tls, :stringprep, :p1_xml, + :stun, :fast_yaml, :ezlib, :iconv, + :esip, :jiffy, :p1_oauth2, :p1_xmlrpc, :eredis, :p1_mysql, :p1_pgsql, :sqlite3]] end @@ -43,7 +43,7 @@ defmodule Ejabberd.Mixfile do {:cache_tab, "~> 1.0"}, {:stringprep, "~> 1.0"}, {:fast_yaml, "~> 1.0"}, - {:p1_tls, git: "https://github.com/processone/tls", tag: "1.0.0"}, + {:fast_tls, "~> 1.0"}, {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.2"}, {:stun, "~> 1.0"}, {:esip, "~> 1.0"}, diff --git a/mix.lock b/mix.lock index a91a94c59d2..d905ac77e8a 100644 --- a/mix.lock +++ b/mix.lock @@ -15,7 +15,6 @@ "p1_mysql": {:hex, :p1_mysql, "1.0.1"}, "p1_oauth2": {:hex, :p1_oauth2, "0.6.1"}, "p1_pgsql": {:hex, :p1_pgsql, "1.0.1"}, - "p1_tls": {:git, "https://github.com/processone/tls", "f19e1f701e0a3980ffc70b3917c4aa85e68d8520", [tag: "1.0.0"]}, "p1_utils": {:hex, :p1_utils, "1.0.3"}, "p1_xml": {:git, "https://github.com/processone/xml", "79c6d54e56bf991f1ec70ceb5e255afcb8dbf53f", [tag: "1.1.2"]}, "p1_xmlrpc": {:hex, :p1_xmlrpc, "1.15.1"}, diff --git a/rebar.config b/rebar.config index f0559f5ee1b..f3d52f9e40b 100644 --- a/rebar.config +++ b/rebar.config @@ -10,7 +10,7 @@ {deps, [{lager, ".*", {git, "https://github.com/basho/lager", {tag, "3.0.2"}}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.3"}}}, {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.2"}}}, - {p1_tls, ".*", {git, "https://github.com/processone/tls", {tag, "1.0.0"}}}, + {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.1"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.2"}}}, {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.1"}}}, @@ -37,12 +37,12 @@ {if_var_true, latest_deps, {floating_deps, [p1_logger, cache_tab, - p1_tls, + fast_tls, stringprep, p1_xml, esip, luerl, - p1_stun, + stun, fast_yaml, p1_utils, p1_mysql, @@ -94,7 +94,7 @@ {eunit_compile_opts, [{i, "tools"}]}. -{post_hook_configure, [{"p1_tls", []}, +{post_hook_configure, [{"fast_tls", []}, {"stringprep", []}, {"fast_yaml", []}, {"esip", []}, diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 78d67f2d6ec..bc68a98849f 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -253,7 +253,7 @@ start_apps() -> ejabberd:start_app(sasl), ejabberd:start_app(ssl), ejabberd:start_app(fast_yaml), - ejabberd:start_app(p1_tls), + ejabberd:start_app(fast_tls), ejabberd:start_app(p1_xml), ejabberd:start_app(stringprep), ejabberd:start_app(ezlib), diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 04e41f468f9..a1a25aa116d 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -408,7 +408,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> (StateData#state.sockmod):get_sockmod(StateData#state.socket), Zlib = StateData#state.zlib, CompressFeature = case Zlib andalso - ((SockMod == gen_tcp) orelse (SockMod == p1_tls)) of + ((SockMod == gen_tcp) orelse (SockMod == fast_tls)) of true -> [#xmlel{name = <<"compression">>, attrs = [{<<"xmlns">>, ?NS_FEATURE_COMPRESS}], @@ -813,7 +813,7 @@ wait_for_feature_request({xmlstreamelement, El}, tls_enabled = true}); {?NS_COMPRESS, <<"compress">>} when Zlib == true, - (SockMod == gen_tcp) or (SockMod == p1_tls) -> + (SockMod == gen_tcp) or (SockMod == fast_tls) -> case xml:get_subtag(El, <<"method">>) of false -> send_element(StateData, @@ -1955,11 +1955,11 @@ get_auth_tags([], U, P, D, R) -> get_conn_type(StateData) -> case (StateData#state.sockmod):get_sockmod(StateData#state.socket) of gen_tcp -> c2s; - p1_tls -> c2s_tls; + fast_tls -> c2s_tls; ezlib -> case ezlib:get_sockmod((StateData#state.socket)#socket_state.socket) of gen_tcp -> c2s_compressed; - p1_tls -> c2s_compressed_tls + fast_tls -> c2s_compressed_tls end; ejabberd_http_bind -> http_bind; ejabberd_http_ws -> websocket; diff --git a/src/ejabberd_frontend_socket.erl b/src/ejabberd_frontend_socket.erl index 09eeded9c35..b8e706f239d 100644 --- a/src/ejabberd_frontend_socket.erl +++ b/src/ejabberd_frontend_socket.erl @@ -148,20 +148,20 @@ init([Module, SockMod, Socket, Opts, Receiver]) -> receiver = Receiver}}. handle_call({starttls, TLSOpts}, _From, State) -> - {ok, TLSSocket} = p1_tls:tcp_to_tls(State#state.socket, TLSOpts), + {ok, TLSSocket} = fast_tls:tcp_to_tls(State#state.socket, TLSOpts), ejabberd_receiver:starttls(State#state.receiver, TLSSocket), Reply = ok, - {reply, Reply, State#state{socket = TLSSocket, sockmod = p1_tls}, + {reply, Reply, State#state{socket = TLSSocket, sockmod = fast_tls}, ?HIBERNATE_TIMEOUT}; handle_call({starttls, TLSOpts, Data}, _From, State) -> - {ok, TLSSocket} = p1_tls:tcp_to_tls(State#state.socket, TLSOpts), + {ok, TLSSocket} = fast_tls:tcp_to_tls(State#state.socket, TLSOpts), ejabberd_receiver:starttls(State#state.receiver, TLSSocket), catch (State#state.sockmod):send( State#state.socket, Data), Reply = ok, {reply, Reply, - State#state{socket = TLSSocket, sockmod = p1_tls}, + State#state{socket = TLSSocket, sockmod = fast_tls}, ?HIBERNATE_TIMEOUT}; handle_call({compress, Data}, _From, State) -> {ok, ZlibSocket} = @@ -187,10 +187,10 @@ handle_call(get_sockmod, _From, State) -> Reply = State#state.sockmod, {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(get_peer_certificate, _From, State) -> - Reply = p1_tls:get_peer_certificate(State#state.socket), + Reply = fast_tls:get_peer_certificate(State#state.socket), {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(get_verify_result, _From, State) -> - Reply = p1_tls:get_verify_result(State#state.socket), + Reply = fast_tls:get_verify_result(State#state.socket), {reply, Reply, State, ?HIBERNATE_TIMEOUT}; handle_call(close, _From, State) -> ejabberd_receiver:close(State#state.receiver), @@ -236,9 +236,9 @@ check_starttls(SockMod, Socket, Receiver, Opts) -> (_) -> false end, Opts), if TLSEnabled -> - {ok, TLSSocket} = p1_tls:tcp_to_tls(Socket, TLSOpts), + {ok, TLSSocket} = fast_tls:tcp_to_tls(Socket, TLSOpts), ejabberd_receiver:starttls(Receiver, TLSSocket), - {p1_tls, TLSSocket}; + {fast_tls, TLSSocket}; true -> {SockMod, Socket} end. diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index b95f982078f..6c5a37212ed 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -117,9 +117,9 @@ init({SockMod, Socket}, Opts) -> TLSOpts = [verify_none | TLSOpts3], {SockMod1, Socket1} = if TLSEnabled -> inet:setopts(Socket, [{recbuf, 8192}]), - {ok, TLSSocket} = p1_tls:tcp_to_tls(Socket, + {ok, TLSSocket} = fast_tls:tcp_to_tls(Socket, TLSOpts), - {p1_tls, TLSSocket}; + {fast_tls, TLSSocket}; true -> {SockMod, Socket} end, Captcha = case proplists:get_bool(captcha, Opts) of @@ -328,8 +328,8 @@ get_transfer_protocol(SockMod, HostPort) -> {gen_tcp, []} -> {Host, 80, http}; {gen_tcp, [Port]} -> {Host, jlib:binary_to_integer(Port), http}; - {p1_tls, []} -> {Host, 443, https}; - {p1_tls, [Port]} -> + {fast_tls, []} -> {Host, 443, https}; + {fast_tls, [Port]} -> {Host, jlib:binary_to_integer(Port), https} end. diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 785855294a4..fa85805d5e3 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -48,8 +48,8 @@ -include("logger.hrl"). -record(state, - {socket :: inet:socket() | p1_tls:tls_socket() | ezlib:zlib_socket(), - sock_mod = gen_tcp :: gen_tcp | p1_tls | ezlib, + {socket :: inet:socket() | fast_tls:tls_socket() | ezlib:zlib_socket(), + sock_mod = gen_tcp :: gen_tcp | fast_tls | ezlib, shaper_state = none :: shaper:shaper(), c2s_pid :: pid(), max_stanza_size = infinity :: non_neg_integer() | infinity, @@ -89,7 +89,7 @@ change_shaper(Pid, Shaper) -> reset_stream(Pid) -> do_call(Pid, reset_stream). --spec starttls(pid(), p1_tls:tls_socket()) -> ok. +-spec starttls(pid(), fast_tls:tls_socket()) -> ok. starttls(Pid, TLSSocket) -> do_call(Pid, {starttls, TLSSocket}). @@ -129,8 +129,8 @@ init([Socket, SockMod, Shaper, MaxStanzaSize]) -> handle_call({starttls, TLSSocket}, _From, State) -> State1 = reset_parser(State), NewState = State1#state{socket = TLSSocket, - sock_mod = p1_tls}, - case p1_tls:recv_data(TLSSocket, <<"">>) of + sock_mod = fast_tls}, + case fast_tls:recv_data(TLSSocket, <<"">>) of {ok, TLSData} -> {reply, ok, process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT}; @@ -182,8 +182,8 @@ handle_info({Tag, _TCPSocket, Data}, when (Tag == tcp) or (Tag == ssl) or (Tag == ejabberd_xml) -> case SockMod of - p1_tls -> - case p1_tls:recv_data(Socket, Data) of + fast_tls -> + case fast_tls:recv_data(Socket, Data) of {ok, TLSData} -> {noreply, process_data(TLSData, State), ?HIBERNATE_TIMEOUT}; diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 2f026b32adc..3d0c4730765 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -214,7 +214,7 @@ check_peer_certificate(SockMod, Sock, Peer) -> end end; VerifyRes -> - {error, p1_tls:get_cert_verify_string(VerifyRes, Cert)} + {error, fast_tls:get_cert_verify_string(VerifyRes, Cert)} end; {error, _Reason} -> {error, <<"Cannot get peer certificate">>}; diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index 16ffd192ee3..887b4a0f33d 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -52,10 +52,10 @@ -type sockmod() :: ejabberd_http_bind | ejabberd_http_ws | - gen_tcp | p1_tls | ezlib. + gen_tcp | fast_tls | ezlib. -type receiver() :: pid () | atom(). -type socket() :: pid() | inet:socket() | - p1_tls:tls_socket() | + fast_tls:tls_socket() | ezlib:zlib_socket() | ejabberd_http_bind:bind_socket(). @@ -145,15 +145,15 @@ connect(Addr, Port, Opts, Timeout) -> end. starttls(SocketData, TLSOpts) -> - {ok, TLSSocket} = p1_tls:tcp_to_tls(SocketData#socket_state.socket, TLSOpts), + {ok, TLSSocket} = fast_tls:tcp_to_tls(SocketData#socket_state.socket, TLSOpts), ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket), - SocketData#socket_state{socket = TLSSocket, sockmod = p1_tls}. + SocketData#socket_state{socket = TLSSocket, sockmod = fast_tls}. starttls(SocketData, TLSOpts, Data) -> - {ok, TLSSocket} = p1_tls:tcp_to_tls(SocketData#socket_state.socket, TLSOpts), + {ok, TLSSocket} = fast_tls:tcp_to_tls(SocketData#socket_state.socket, TLSOpts), ejabberd_receiver:starttls(SocketData#socket_state.receiver, TLSSocket), send(SocketData, Data), - SocketData#socket_state{socket = TLSSocket, sockmod = p1_tls}. + SocketData#socket_state{socket = TLSSocket, sockmod = fast_tls}. compress(SocketData) -> compress(SocketData, undefined). @@ -216,10 +216,10 @@ get_sockmod(SocketData) -> SocketData#socket_state.sockmod. get_peer_certificate(SocketData) -> - p1_tls:get_peer_certificate(SocketData#socket_state.socket). + fast_tls:get_peer_certificate(SocketData#socket_state.socket). get_verify_result(SocketData) -> - p1_tls:get_verify_result(SocketData#socket_state.socket). + fast_tls:get_verify_result(SocketData#socket_state.socket). close(SocketData) -> ejabberd_receiver:close(SocketData#socket_state.receiver). diff --git a/src/ejabberd_websocket.erl b/src/ejabberd_websocket.erl index d9a1bafc7ed..0cdd9bac593 100644 --- a/src/ejabberd_websocket.erl +++ b/src/ejabberd_websocket.erl @@ -373,10 +373,10 @@ process_frame(#frame_info{unprocessed = process_frame(FrameInfo#frame_info{unprocessed = <<>>}, <>). -handle_data(tcp, FrameInfo, Data, Socket, WsHandleLoopPid, p1_tls) -> - case p1_tls:recv_data(Socket, Data) of +handle_data(tcp, FrameInfo, Data, Socket, WsHandleLoopPid, fast_tls) -> + case fast_tls:recv_data(Socket, Data) of {ok, NewData} -> - handle_data_int(FrameInfo, NewData, Socket, WsHandleLoopPid, p1_tls); + handle_data_int(FrameInfo, NewData, Socket, WsHandleLoopPid, fast_tls); {error, Error} -> {error, Error} end; From 5539db37b6a6a38a88aa0d69b19c88d25d6b4850 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 16:26:15 +0100 Subject: [PATCH 547/695] Remove reference to p1_logger --- rebar.config | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index f3d52f9e40b..09fb78680c1 100644 --- a/rebar.config +++ b/rebar.config @@ -35,8 +35,7 @@ {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}}]}. {if_var_true, latest_deps, - {floating_deps, [p1_logger, - cache_tab, + {floating_deps, [cache_tab, fast_tls, stringprep, p1_xml, From 315fc9493eb1f7b2374c6fde68391e8abaf451f9 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 3 Feb 2016 17:45:27 +0100 Subject: [PATCH 548/695] Handle spaces in vsn attribute of app file when installing deps (#940) --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 08cd83791fe..1b7e5043cde 100644 --- a/Makefile.in +++ b/Makefile.in @@ -137,7 +137,7 @@ MAIN_FILES=$(filter-out %/configure.beam,$(call FILES_WILDCARD,ebin/*.beam ebin/ MAIN_DIRS=$(sort $(dir $(MAIN_FILES)) priv/bin priv/sql) define DEP_VERSION_template -DEP_$(1)_VERSION:=$(shell $(SED) -e '/vsn/!d;s/.*,"/$(1)-/;s/".*//' $(2) 2>/dev/null) +DEP_$(1)_VERSION:=$(shell $(SED) -e '/vsn/!d;s/.*, *"/$(1)-/;s/".*//' $(2) 2>/dev/null) endef $(foreach DEP,$(DEPS),$(eval $(call DEP_VERSION_template,$(DEP),deps/$(DEP)/ebin/$(DEP).app))) From dfc29ea03ca91e1eb5387d93612e2ac4b4b496da Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 19:03:17 +0100 Subject: [PATCH 549/695] Switch to Fast XML module --- include/jlib.hrl | 4 +- mix.exs | 6 +- mix.lock | 2 +- rebar.config | 6 +- src/adhoc.erl | 8 +- src/cyrsasl.erl | 4 +- src/cyrsasl_digest.erl | 8 +- src/ejabberd_app.erl | 2 +- src/ejabberd_c2s.erl | 114 +++++++++++++------------- src/ejabberd_captcha.erl | 2 +- src/ejabberd_commands_doc.erl | 2 +- src/ejabberd_http.erl | 4 +- src/ejabberd_http_bind.erl | 52 ++++++------ src/ejabberd_http_ws.erl | 20 ++--- src/ejabberd_local.erl | 2 +- src/ejabberd_piefxis.erl | 30 +++---- src/ejabberd_receiver.erl | 12 +-- src/ejabberd_router.erl | 2 +- src/ejabberd_s2s.erl | 2 +- src/ejabberd_s2s_in.erl | 44 +++++------ src/ejabberd_s2s_out.erl | 64 +++++++-------- src/ejabberd_service.erl | 20 ++--- src/ejabberd_sm.erl | 10 +-- src/ejabberd_system_monitor.erl | 2 +- src/ejabberd_web_admin.erl | 6 +- src/ejabberd_xmlrpc.erl | 6 +- src/jd2ejd.erl | 14 ++-- src/jlib.erl | 54 ++++++------- src/mod_admin_extra.erl | 16 ++-- src/mod_announce.erl | 16 ++-- src/mod_blocking.erl | 4 +- src/mod_caps.erl | 40 +++++----- src/mod_carboncopy.erl | 12 +-- src/mod_client_state.erl | 2 +- src/mod_configure.erl | 6 +- src/mod_configure2.erl | 4 +- src/mod_disco.erl | 8 +- src/mod_echo.erl | 2 +- src/mod_http_upload.erl | 10 +-- src/mod_irc.erl | 20 ++--- src/mod_irc_connection.erl | 36 ++++----- src/mod_mam.erl | 66 ++++++++-------- src/mod_muc.erl | 26 +++--- src/mod_muc_log.erl | 16 ++-- src/mod_muc_room.erl | 132 +++++++++++++++---------------- src/mod_multicast.erl | 40 +++++----- src/mod_offline.erl | 50 ++++++------ src/mod_pres_counter.erl | 2 +- src/mod_privacy.erl | 22 +++--- src/mod_private.erl | 14 ++-- src/mod_proxy65_service.erl | 6 +- src/mod_pubsub.erl | 76 +++++++++--------- src/mod_register.erl | 16 ++-- src/mod_roster.erl | 12 +-- src/mod_shared_roster.erl | 4 +- src/mod_stats.erl | 4 +- src/mod_vcard.erl | 82 +++++++++---------- src/mod_vcard_ldap.erl | 4 +- src/mod_vcard_xupdate.erl | 4 +- src/node_flat_odbc.erl | 4 +- src/prosody2ejabberd.erl | 8 +- src/pubsub_subscription.erl | 2 +- src/pubsub_subscription_odbc.erl | 2 +- 63 files changed, 635 insertions(+), 635 deletions(-) diff --git a/include/jlib.hrl b/include/jlib.hrl index f09e392fbf1..50a031334d0 100644 --- a/include/jlib.hrl +++ b/include/jlib.hrl @@ -20,9 +20,9 @@ -include("ns.hrl"). -ifdef(NO_EXT_LIB). --include("xml.hrl"). +-include("fxml.hrl"). -else. --include_lib("p1_xml/include/xml.hrl"). +-include_lib("fast_xml/include/fxml.hrl"). -endif. -define(STANZA_ERROR(Code, Type, Condition), diff --git a/mix.exs b/mix.exs index e9545b1786e..cdba398dd47 100644 --- a/mix.exs +++ b/mix.exs @@ -25,7 +25,7 @@ defmodule Ejabberd.Mixfile do [mod: {:ejabberd_app, []}, applications: [:ssl], included_applications: [:lager, :mnesia, :p1_utils, :cache_tab, - :fast_tls, :stringprep, :p1_xml, + :fast_tls, :stringprep, :fast_xml, :stun, :fast_yaml, :ezlib, :iconv, :esip, :jiffy, :p1_oauth2, :p1_xmlrpc, :eredis, :p1_mysql, :p1_pgsql, :sqlite3]] @@ -39,12 +39,12 @@ defmodule Ejabberd.Mixfile do defp deps do [{:lager, "~> 3.0"}, - {:p1_utils, "~> 1.0", override: true}, + {:p1_utils, "~> 1.0"}, {:cache_tab, "~> 1.0"}, {:stringprep, "~> 1.0"}, {:fast_yaml, "~> 1.0"}, {:fast_tls, "~> 1.0"}, - {:p1_xml, git: "https://github.com/processone/xml", tag: "1.1.2"}, + {:fast_xml, "~> 1.1"}, {:stun, "~> 1.0"}, {:esip, "~> 1.0"}, {:jiffy, "~> 0.14.7"}, diff --git a/mix.lock b/mix.lock index d905ac77e8a..c0b3d3fbd14 100644 --- a/mix.lock +++ b/mix.lock @@ -6,6 +6,7 @@ "exrm": {:hex, :exrm, "1.0.0-rc7"}, "ezlib": {:hex, :ezlib, "1.0.1"}, "fast_tls": {:hex, :fast_tls, "1.0.1"}, + "fast_xml": {:hex, :fast_xml, "1.1.3"}, "fast_yaml": {:hex, :fast_yaml, "1.0.2"}, "getopt": {:hex, :getopt, "0.8.2"}, "goldrush": {:hex, :goldrush, "0.1.7"}, @@ -16,7 +17,6 @@ "p1_oauth2": {:hex, :p1_oauth2, "0.6.1"}, "p1_pgsql": {:hex, :p1_pgsql, "1.0.1"}, "p1_utils": {:hex, :p1_utils, "1.0.3"}, - "p1_xml": {:git, "https://github.com/processone/xml", "79c6d54e56bf991f1ec70ceb5e255afcb8dbf53f", [tag: "1.1.2"]}, "p1_xmlrpc": {:hex, :p1_xmlrpc, "1.15.1"}, "providers": {:hex, :providers, "1.4.1"}, "relx": {:hex, :relx, "3.5.0"}, diff --git a/rebar.config b/rebar.config index 09fb78680c1..19122c308f7 100644 --- a/rebar.config +++ b/rebar.config @@ -12,7 +12,7 @@ {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.2"}}}, {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.1"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.2"}}}, - {p1_xml, ".*", {git, "https://github.com/processone/xml", {tag, "1.1.2"}}}, + {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.3"}}}, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.1"}}}, {esip, ".*", {git, "https://github.com/processone/esip", "1.0.2"}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.2"}}}, @@ -38,7 +38,7 @@ {floating_deps, [cache_tab, fast_tls, stringprep, - p1_xml, + fast_xml, esip, luerl, stun, @@ -97,7 +97,7 @@ {"stringprep", []}, {"fast_yaml", []}, {"esip", []}, - {"p1_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, + {"fast_xml", [{if_var_true, full_xml, "--enable-full-xml"}]}, {if_var_true, pam, {"p1_pam", []}}, {if_var_true, zlib, {"ezlib", []}}, {if_var_true, iconv, {"iconv", []}}]}. diff --git a/src/adhoc.erl b/src/adhoc.erl index d252a6cbb24..788bf65ab4d 100644 --- a/src/adhoc.erl +++ b/src/adhoc.erl @@ -51,9 +51,9 @@ parse_request(#iq{type = set, lang = Lang, sub_el = SubEl, xmlns = ?NS_COMMANDS}) -> ?DEBUG("entering parse_request...", []), - Node = xml:get_tag_attr_s(<<"node">>, SubEl), - SessionID = xml:get_tag_attr_s(<<"sessionid">>, SubEl), - Action = xml:get_tag_attr_s(<<"action">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), + SessionID = fxml:get_tag_attr_s(<<"sessionid">>, SubEl), + Action = fxml:get_tag_attr_s(<<"action">>, SubEl), XData = find_xdata_el(SubEl), #xmlel{children = AllEls} = SubEl, Others = case XData of @@ -76,7 +76,7 @@ find_xdata_el(#xmlel{children = SubEls}) -> find_xdata_el1([]) -> false; find_xdata_el1([El | Els]) when is_record(El, xmlel) -> - case xml:get_tag_attr_s(<<"xmlns">>, El) of + case fxml:get_tag_attr_s(<<"xmlns">>, El) of ?NS_XDATA -> El; _ -> find_xdata_el1(Els) end; diff --git a/src/cyrsasl.erl b/src/cyrsasl.erl index 5d2d89d67c1..cc03a49ce2b 100644 --- a/src/cyrsasl.erl +++ b/src/cyrsasl.erl @@ -111,12 +111,12 @@ register_mechanism(Mechanism, Module, PasswordType) -> %%-include("ejabberd.hrl"). %%-include("jlib.hrl"). %%check_authzid(_State, Props) -> -%% AuthzId = xml:get_attr_s(authzid, Props), +%% AuthzId = fxml:get_attr_s(authzid, Props), %% case jid:from_string(AuthzId) of %% error -> %% {error, "invalid-authzid"}; %% JID -> -%% LUser = jid:nodeprep(xml:get_attr_s(username, Props)), +%% LUser = jid:nodeprep(fxml:get_attr_s(username, Props)), %% {U, S, R} = jid:tolower(JID), %% case R of %% "" -> diff --git a/src/cyrsasl_digest.erl b/src/cyrsasl_digest.erl index 8ccd90952ba..976e49e8569 100644 --- a/src/cyrsasl_digest.erl +++ b/src/cyrsasl_digest.erl @@ -83,9 +83,9 @@ mech_step(#state{step = 3, nonce = Nonce} = State, bad -> {error, <<"bad-protocol">>}; KeyVals -> DigestURI = proplists:get_value(<<"digest-uri">>, KeyVals, <<>>), - %DigestURI = xml:get_attr_s(<<"digest-uri">>, KeyVals), + %DigestURI = fxml:get_attr_s(<<"digest-uri">>, KeyVals), UserName = proplists:get_value(<<"username">>, KeyVals, <<>>), - %UserName = xml:get_attr_s(<<"username">>, KeyVals), + %UserName = fxml:get_attr_s(<<"username">>, KeyVals), case is_digesturi_valid(DigestURI, State#state.host, State#state.hostfqdn) of @@ -97,13 +97,13 @@ mech_step(#state{step = 3, nonce = Nonce} = State, {error, <<"not-authorized">>, UserName}; true -> AuthzId = proplists:get_value(<<"authzid">>, KeyVals, <<>>), - %AuthzId = xml:get_attr_s(<<"authzid">>, KeyVals), + %AuthzId = fxml:get_attr_s(<<"authzid">>, KeyVals), case (State#state.get_password)(UserName) of {false, _} -> {error, <<"not-authorized">>, UserName}; {Passwd, AuthModule} -> case (State#state.check_password)(UserName, <<"">>, proplists:get_value(<<"response">>, KeyVals, <<>>), - %xml:get_attr_s(<<"response">>, KeyVals), + %fxml:get_attr_s(<<"response">>, KeyVals), fun (PW) -> response(KeyVals, UserName, diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index bc68a98849f..66de3ceb714 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -254,7 +254,7 @@ start_apps() -> ejabberd:start_app(ssl), ejabberd:start_app(fast_yaml), ejabberd:start_app(fast_tls), - ejabberd:start_app(p1_xml), + ejabberd:start_app(fast_xml), ejabberd:start_app(stringprep), ejabberd:start_app(ezlib), ejabberd:start_app(cache_tab). diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index a1a25aa116d..ad7590ebb11 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -342,15 +342,15 @@ get_subscribed(FsmRef) -> wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> DefaultLang = ?MYLANG, - case xml:get_attr_s(<<"xmlns:stream">>, Attrs) of + case fxml:get_attr_s(<<"xmlns:stream">>, Attrs) of ?NS_STREAM -> Server = case StateData#state.server of <<"">> -> - jid:nameprep(xml:get_attr_s(<<"to">>, Attrs)); + jid:nameprep(fxml:get_attr_s(<<"to">>, Attrs)); S -> S end, - Lang = case xml:get_attr_s(<<"xml:lang">>, Attrs) of + Lang = case fxml:get_attr_s(<<"xml:lang">>, Attrs) of Lang1 when byte_size(Lang1) =< 35 -> %% As stated in BCP47, 4.4.1: %% Protocols or specifications that @@ -367,7 +367,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> case lists:member(Server, ?MYHOSTS) of true when IsBlacklistedIP == false -> change_shaper(StateData, jid:make(<<"">>, Server, <<"">>)), - case xml:get_attr_s(<<"version">>, Attrs) of + case fxml:get_attr_s(<<"version">>, Attrs) of <<"1.0">> -> send_header(StateData, Server, <<"1.0">>, DefaultLang), case StateData#state.authenticated of @@ -724,19 +724,19 @@ wait_for_feature_request({xmlstreamelement, El}, TLSRequired = StateData#state.tls_required, SockMod = (StateData#state.sockmod):get_sockmod(StateData#state.socket), - case {xml:get_attr_s(<<"xmlns">>, Attrs), Name} of + case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of {?NS_SASL, <<"auth">>} when TLSEnabled or not TLSRequired -> - Mech = xml:get_attr_s(<<"mechanism">>, Attrs), - ClientIn = jlib:decode_base64(xml:get_cdata(Els)), + Mech = fxml:get_attr_s(<<"mechanism">>, Attrs), + ClientIn = jlib:decode_base64(fxml:get_cdata(Els)), case cyrsasl:server_start(StateData#state.sasl_state, Mech, ClientIn) of {ok, Props} -> (StateData#state.sockmod):reset_stream(StateData#state.socket), - %U = xml:get_attr_s(username, Props), + %U = fxml:get_attr_s(username, Props), U = proplists:get_value(username, Props, <<>>), - %AuthModule = xml:get_attr_s(auth_module, Props), + %AuthModule = fxml:get_attr_s(auth_module, Props), AuthModule = proplists:get_value(auth_module, Props, undefined), ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", @@ -802,7 +802,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData#state.tls_options)] end, Socket = StateData#state.socket, - BProceed = xml:element_to_binary(#xmlel{name = <<"proceed">>, + BProceed = fxml:element_to_binary(#xmlel{name = <<"proceed">>, attrs = [{<<"xmlns">>, ?NS_TLS}]}), TLSSocket = (StateData#state.sockmod):starttls(Socket, TLSOpts, @@ -814,7 +814,7 @@ wait_for_feature_request({xmlstreamelement, El}, {?NS_COMPRESS, <<"compress">>} when Zlib == true, (SockMod == gen_tcp) or (SockMod == fast_tls) -> - case xml:get_subtag(El, <<"method">>) of + case fxml:get_subtag(El, <<"method">>) of false -> send_element(StateData, #xmlel{name = <<"failure">>, @@ -824,10 +824,10 @@ wait_for_feature_request({xmlstreamelement, El}, attrs = [], children = []}]}), fsm_next_state(wait_for_feature_request, StateData); Method -> - case xml:get_tag_cdata(Method) of + case fxml:get_tag_cdata(Method) of <<"zlib">> -> Socket = StateData#state.socket, - BCompressed = xml:element_to_binary(#xmlel{name = <<"compressed">>, + BCompressed = fxml:element_to_binary(#xmlel{name = <<"compressed">>, attrs = [{<<"xmlns">>, ?NS_COMPRESS}]}), ZlibSocket = (StateData#state.sockmod):compress(Socket, BCompressed), @@ -880,18 +880,18 @@ wait_for_sasl_response({xmlstreamelement, #xmlel{name = Name} = El}, StateData) wait_for_sasl_response({xmlstreamelement, El}, StateData) -> #xmlel{name = Name, attrs = Attrs, children = Els} = El, - case {xml:get_attr_s(<<"xmlns">>, Attrs), Name} of + case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of {?NS_SASL, <<"response">>} -> - ClientIn = jlib:decode_base64(xml:get_cdata(Els)), + ClientIn = jlib:decode_base64(fxml:get_cdata(Els)), case cyrsasl:server_step(StateData#state.sasl_state, ClientIn) of {ok, Props} -> catch (StateData#state.sockmod):reset_stream(StateData#state.socket), -% U = xml:get_attr_s(username, Props), +% U = fxml:get_attr_s(username, Props), U = proplists:get_value(username, Props, <<>>), -% AuthModule = xml:get_attr_s(auth_module, Props), +% AuthModule = fxml:get_attr_s(auth_module, Props), AuthModule = proplists:get_value(auth_module, Props, <<>>), ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", @@ -912,9 +912,9 @@ wait_for_sasl_response({xmlstreamelement, El}, user = U}); {ok, Props, ServerOut} -> (StateData#state.sockmod):reset_stream(StateData#state.socket), -% U = xml:get_attr_s(username, Props), +% U = fxml:get_attr_s(username, Props), U = proplists:get_value(username, Props, <<>>), -% AuthModule = xml:get_attr_s(auth_module, Props), +% AuthModule = fxml:get_attr_s(auth_module, Props), AuthModule = proplists:get_value(auth_module, Props, undefined), ?INFO_MSG("(~w) Accepted authentication for ~s " "by ~p from ~s", @@ -1035,7 +1035,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> #iq{type = set, xmlns = ?NS_BIND, sub_el = SubEl} = IQ -> U = StateData#state.user, - R1 = xml:get_path_s(SubEl, + R1 = fxml:get_path_s(SubEl, [{elem, <<"resource">>}, cdata]), R = case jid:resourceprep(R1) of error -> error; @@ -1207,24 +1207,24 @@ session_established2(El, StateData) -> User = NewStateData#state.user, Server = NewStateData#state.server, FromJID = NewStateData#state.jid, - To = xml:get_attr_s(<<"to">>, Attrs), + To = fxml:get_attr_s(<<"to">>, Attrs), ToJID = case To of <<"">> -> jid:make(User, Server, <<"">>); _ -> jid:from_string(To) end, NewEl1 = jlib:remove_attr(<<"xmlns">>, El), - NewEl = case xml:get_attr_s(<<"xml:lang">>, Attrs) of + NewEl = case fxml:get_attr_s(<<"xml:lang">>, Attrs) of <<"">> -> case NewStateData#state.lang of <<"">> -> NewEl1; Lang -> - xml:replace_tag_attr(<<"xml:lang">>, Lang, NewEl1) + fxml:replace_tag_attr(<<"xml:lang">>, Lang, NewEl1) end; _ -> NewEl1 end, NewState = case ToJID of error -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> NewStateData; <<"result">> -> NewStateData; _ -> @@ -1408,7 +1408,7 @@ handle_info({route, From, To, StateData, [{From, To, Packet}]), - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"probe">> -> LFrom = jid:tolower(From), LBFrom = @@ -1625,7 +1625,7 @@ handle_info({route, From, To, allow -> {true, Attrs, StateData}; deny -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; <<"groupchat">> -> ok; <<"headline">> -> ok; @@ -1844,7 +1844,7 @@ send_element(StateData, El) when StateData#state.xml_socket -> (StateData#state.sockmod):send_xml(StateData#state.socket, {xmlstreamelement, El}); send_element(StateData, El) -> - send_text(StateData, xml:element_to_binary(El)). + send_text(StateData, fxml:element_to_binary(El)). send_stanza(StateData, Stanza) when StateData#state.csi_state == inactive -> csi_filter_stanza(StateData, Stanza); @@ -1924,7 +1924,7 @@ is_auth_packet(El) -> is_stanza(#xmlel{name = Name, attrs = Attrs}) when Name == <<"message">>; Name == <<"presence">>; Name == <<"iq">> -> - case xml:get_attr(<<"xmlns">>, Attrs) of + case fxml:get_attr(<<"xmlns">>, Attrs) of {value, NS} when NS /= <<"jabber:client">>, NS /= <<"jabber:server">> -> false; @@ -1936,7 +1936,7 @@ is_stanza(_El) -> get_auth_tags([#xmlel{name = Name, children = Els} | L], U, P, D, R) -> - CData = xml:get_cdata(Els), + CData = fxml:get_cdata(Els), case Name of <<"username">> -> get_auth_tags(L, CData, P, D, R); <<"password">> -> get_auth_tags(L, U, CData, D, R); @@ -2003,11 +2003,11 @@ process_presence_probe(From, To, StateData) -> %% User updates his presence (non-directed presence packet) presence_update(From, Packet, StateData) -> #xmlel{attrs = Attrs} = Packet, - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"unavailable">> -> - Status = case xml:get_subtag(Packet, <<"status">>) of + Status = case fxml:get_subtag(Packet, <<"status">>) of false -> <<"">>; - StatusTag -> xml:get_tag_cdata(StatusTag) + StatusTag -> fxml:get_tag_cdata(StatusTag) end, Info = [{ip, StateData#state.ip}, {conn, StateData#state.conn}, @@ -2068,7 +2068,7 @@ presence_track(From, To, Packet, StateData) -> LTo = jid:tolower(To), User = StateData#state.user, Server = StateData#state.server, - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"unavailable">> -> A = remove_element(LTo, StateData#state.pres_a), check_privacy_route(From, StateData#state{pres_a = A}, From, To, Packet); @@ -2265,11 +2265,11 @@ update_priority(Priority, Packet, StateData) -> StateData#state.resource, Priority, Packet, Info). get_priority_from_presence(PresencePacket) -> - case xml:get_subtag(PresencePacket, <<"priority">>) of + case fxml:get_subtag(PresencePacket, <<"priority">>) of false -> 0; SubEl -> case catch - jlib:binary_to_integer(xml:get_tag_cdata(SubEl)) + jlib:binary_to_integer(fxml:get_tag_cdata(SubEl)) of P when is_integer(P) -> P; _ -> 0 @@ -2346,21 +2346,21 @@ resend_subscription_requests(#state{user = User, get_showtag(undefined) -> <<"unavailable">>; get_showtag(Presence) -> - case xml:get_path_s(Presence, [{elem, <<"show">>}, cdata]) of + case fxml:get_path_s(Presence, [{elem, <<"show">>}, cdata]) of <<"">> -> <<"available">>; ShowTag -> ShowTag end. get_statustag(undefined) -> <<"">>; get_statustag(Presence) -> - xml:get_path_s(Presence, [{elem, <<"status">>}, cdata]). + fxml:get_path_s(Presence, [{elem, <<"status">>}, cdata]). process_unauthenticated_stanza(StateData, El) -> - NewEl = case xml:get_tag_attr_s(<<"xml:lang">>, El) of + NewEl = case fxml:get_tag_attr_s(<<"xml:lang">>, El) of <<"">> -> case StateData#state.lang of <<"">> -> El; - Lang -> xml:replace_tag_attr(<<"xml:lang">>, Lang, El) + Lang -> fxml:replace_tag_attr(<<"xml:lang">>, Lang, El) end; _ -> El end, @@ -2462,7 +2462,7 @@ is_ip_blacklisted({IP, _Port}, Lang) -> %% Check from attributes %% returns invalid-from|NewElement check_from(El, FromJID) -> - case xml:get_tag_attr(<<"from">>, El) of + case fxml:get_tag_attr(<<"from">>, El) of false -> El; {value, SJID} -> @@ -2573,7 +2573,7 @@ negotiate_stream_mgmt(_El, #state{resource = <<"">>} = StateData) -> send_element(StateData, ?MGMT_UNEXPECTED_REQUEST(?NS_STREAM_MGMT_3)), StateData; negotiate_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of Xmlns when ?IS_SUPPORTED_MGMT_XMLNS(Xmlns) -> case stream_mgmt_enabled(StateData) of true -> @@ -2601,7 +2601,7 @@ negotiate_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) -> end. perform_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of Xmlns when Xmlns == StateData#state.mgmt_xmlns -> case Name of <<"r">> -> @@ -2626,10 +2626,10 @@ perform_stream_mgmt(#xmlel{name = Name, attrs = Attrs}, StateData) -> handle_enable(#state{mgmt_timeout = DefaultTimeout, mgmt_max_timeout = MaxTimeout} = StateData, Attrs) -> - Timeout = case xml:get_attr_s(<<"resume">>, Attrs) of + Timeout = case fxml:get_attr_s(<<"resume">>, Attrs) of ResumeAttr when ResumeAttr == <<"true">>; ResumeAttr == <<"1">> -> - MaxAttr = xml:get_attr_s(<<"max">>, Attrs), + MaxAttr = fxml:get_attr_s(<<"max">>, Attrs), case catch jlib:binary_to_integer(MaxAttr) of Max when is_integer(Max), Max > 0, Max =< MaxTimeout -> Max; @@ -2669,7 +2669,7 @@ handle_r(StateData) -> StateData. handle_a(StateData, Attrs) -> - case catch jlib:binary_to_integer(xml:get_attr_s(<<"h">>, Attrs)) of + case catch jlib:binary_to_integer(fxml:get_attr_s(<<"h">>, Attrs)) of H when is_integer(H), H >= 0 -> check_h_attribute(StateData, H); _ -> @@ -2679,12 +2679,12 @@ handle_a(StateData, Attrs) -> end. handle_resume(StateData, Attrs) -> - R = case xml:get_attr_s(<<"xmlns">>, Attrs) of + R = case fxml:get_attr_s(<<"xmlns">>, Attrs) of Xmlns when ?IS_SUPPORTED_MGMT_XMLNS(Xmlns) -> case stream_mgmt_enabled(StateData) of true -> - case {xml:get_attr(<<"previd">>, Attrs), - catch jlib:binary_to_integer(xml:get_attr_s(<<"h">>, Attrs))} + case {fxml:get_attr(<<"previd">>, Attrs), + catch jlib:binary_to_integer(fxml:get_attr_s(<<"h">>, Attrs))} of {{value, PrevID}, H} when is_integer(H), H >= 0 -> case inherit_session_state(StateData, PrevID) of @@ -2815,9 +2815,9 @@ handle_unacked_stanzas(StateData, F) [N, jid:to_string(StateData#state.jid)]), lists:foreach( fun({_, Time, #xmlel{attrs = Attrs} = El}) -> - From_s = xml:get_attr_s(<<"from">>, Attrs), + From_s = fxml:get_attr_s(<<"from">>, Attrs), From = jid:from_string(From_s), - To_s = xml:get_attr_s(<<"to">>, Attrs), + To_s = fxml:get_attr_s(<<"to">>, Attrs), To = jid:from_string(To_s), F(From, To, El, Time) end, queue:to_list(Queue)) @@ -2867,7 +2867,7 @@ handle_unacked_stanzas(StateData) case is_encapsulated_forward(El) of true -> ?DEBUG("Dropping forwarded message stanza from ~s", - [xml:get_attr_s(<<"from">>, El#xmlel.attrs)]); + [fxml:get_attr_s(<<"from">>, El#xmlel.attrs)]); false -> case ejabberd_hooks:run_fold(message_is_archived, StateData#state.server, @@ -2886,9 +2886,9 @@ handle_unacked_stanzas(_StateData) -> ok. is_encapsulated_forward(#xmlel{name = <<"message">>} = El) -> - SubTag = case {xml:get_subtag(El, <<"sent">>), - xml:get_subtag(El, <<"received">>), - xml:get_subtag(El, <<"result">>)} of + SubTag = case {fxml:get_subtag(El, <<"sent">>), + fxml:get_subtag(El, <<"received">>), + fxml:get_subtag(El, <<"result">>)} of {false, false, false} -> false; {Tag, false, false} -> @@ -2901,7 +2901,7 @@ is_encapsulated_forward(#xmlel{name = <<"message">>} = El) -> if SubTag == false -> false; true -> - case xml:get_subtag(SubTag, <<"forwarded">>) of + case fxml:get_subtag(SubTag, <<"forwarded">>) of false -> false; _ -> @@ -2989,7 +2989,7 @@ csi_filter_stanza(#state{csi_state = CsiState, jid = JID} = StateData, queue -> csi_queue_add(StateData, Stanza); drop -> StateData; send -> - From = xml:get_tag_attr_s(<<"from">>, Stanza), + From = fxml:get_tag_attr_s(<<"from">>, Stanza), StateData1 = csi_queue_send(StateData, From), StateData2 = send_stanza(StateData1#state{csi_state = active}, Stanza), @@ -3000,7 +3000,7 @@ csi_queue_add(#state{csi_queue = Queue} = StateData, Stanza) -> case length(StateData#state.csi_queue) >= csi_max_queue(StateData) of true -> csi_queue_add(csi_queue_flush(StateData), Stanza); false -> - From = xml:get_tag_attr_s(<<"from">>, Stanza), + From = fxml:get_tag_attr_s(<<"from">>, Stanza), NewQueue = lists:keystore(From, 1, Queue, {From, p1_time_compat:timestamp(), Stanza}), StateData#state{csi_queue = NewQueue} end. diff --git a/src/ejabberd_captcha.erl b/src/ejabberd_captcha.erl index cc3e2e9f43b..157700c4761 100644 --- a/src/ejabberd_captcha.erl +++ b/src/ejabberd_captcha.erl @@ -320,7 +320,7 @@ build_captcha_html(Id, Lang) -> -spec process_reply(xmlel()) -> ok | {error, bad_match | not_found | malformed}. process_reply(#xmlel{} = El) -> - case xml:get_subtag(El, <<"x">>) of + case fxml:get_subtag(El, <<"x">>) of false -> {error, malformed}; Xdata -> Fields = jlib:parse_xdata_submit(Xdata), diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index 277ed0c784f..85b1064bd67 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -32,7 +32,7 @@ -include("ejabberd_commands.hrl"). -include("ejabberd.hrl"). --define(RAW(V), if HTMLOutput -> xml:crypt(iolist_to_binary(V)); true -> iolist_to_binary(V) end). +-define(RAW(V), if HTMLOutput -> fxml:crypt(iolist_to_binary(V)); true -> iolist_to_binary(V) end). -define(TAG(N), if HTMLOutput -> [<<"<", ??N, "/>">>]; true -> md_tag(N, <<"">>) end). -define(TAG(N, V), if HTMLOutput -> [<<"<", ??N, ">">>, V, <<"">>]; true -> md_tag(N, V) end). -define(TAG(N, C, V), if HTMLOutput -> [<<"<", ??N, " class='", C, "'>">>, V, <<"">>]; true -> md_tag(N, V) end). diff --git a/src/ejabberd_http.erl b/src/ejabberd_http.erl index 6c5a37212ed..d8d1ddd44d7 100644 --- a/src/ejabberd_http.erl +++ b/src/ejabberd_http.erl @@ -532,10 +532,10 @@ make_xhtml_output(State, Status, Headers, XHTML) -> Data = case lists:member(html, Headers) of true -> iolist_to_binary([?HTML_DOCTYPE, - xml:element_to_binary(XHTML)]); + fxml:element_to_binary(XHTML)]); _ -> iolist_to_binary([?XHTML_DOCTYPE, - xml:element_to_binary(XHTML)]) + fxml:element_to_binary(XHTML)]) end, Headers1 = case lists:keysearch(<<"Content-Type">>, 1, Headers) diff --git a/src/ejabberd_http_bind.erl b/src/ejabberd_http_bind.erl index c4cfdddd9a2..ea8cd792f1e 100644 --- a/src/ejabberd_http_bind.erl +++ b/src/ejabberd_http_bind.erl @@ -224,7 +224,7 @@ process_request(Data, IP, HOpts) -> of %% No existing session: {ok, {<<"">>, Rid, Attrs, Payload}} -> - case xml:get_attr_s(<<"to">>, Attrs) of + case fxml:get_attr_s(<<"to">>, Attrs) of <<"">> -> ?DEBUG("Session not created (Improper addressing)", []), {200, ?HEADER, @@ -248,13 +248,13 @@ process_request(Data, IP, HOpts) -> end; %% Existing session {ok, {Sid, Rid, Attrs, Payload1}} -> - StreamStart = case xml:get_attr_s(<<"xmpp:restart">>, + StreamStart = case fxml:get_attr_s(<<"xmpp:restart">>, Attrs) of <<"true">> -> true; _ -> false end, - Payload2 = case xml:get_attr_s(<<"type">>, Attrs) of + Payload2 = case fxml:get_attr_s(<<"type">>, Attrs) of <<"terminate">> -> Payload1 ++ [{xmlstreamend, <<"stream:stream">>}]; _ -> Payload1 @@ -280,7 +280,7 @@ process_request(Data, IP, HOpts) -> handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, Payload, PayloadSize, IP) -> ?DEBUG("got pid: ~p", [Pid]), - Wait = case str:to_integer(xml:get_attr_s(<<"wait">>, + Wait = case str:to_integer(fxml:get_attr_s(<<"wait">>, Attrs)) of {error, _} -> ?MAX_WAIT; @@ -289,7 +289,7 @@ handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, true -> CWait end end, - Hold = case str:to_integer(xml:get_attr_s(<<"hold">>, + Hold = case str:to_integer(fxml:get_attr_s(<<"hold">>, Attrs)) of {error, _} -> (?MAX_REQUESTS) - 1; @@ -299,7 +299,7 @@ handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, end end, Pdelay = case - str:to_integer(xml:get_attr_s(<<"process-delay">>, + str:to_integer(fxml:get_attr_s(<<"process-delay">>, Attrs)) of {error, _} -> ?PROCESS_DELAY_DEFAULT; @@ -312,12 +312,12 @@ handle_session_start(Pid, XmppDomain, Sid, Rid, Attrs, ?PROCESS_DELAY_MIN]) end, Version = case catch - list_to_float(binary_to_list(xml:get_attr_s(<<"ver">>, Attrs))) + list_to_float(binary_to_list(fxml:get_attr_s(<<"ver">>, Attrs))) of {'EXIT', _} -> 0.0; V -> V end, - XmppVersion = xml:get_attr_s(<<"xmpp:version">>, Attrs), + XmppVersion = fxml:get_attr_s(<<"xmpp:version">>, Attrs), ?DEBUG("Create session: ~p", [Sid]), mnesia:dirty_write( #http_bind{id = Sid, @@ -589,8 +589,8 @@ process_http_put(#http_put{rid = Rid, attrs = Attrs, Request, StateName, StateData, RidAllow) -> ?DEBUG("Actually processing request: ~p", [Request]), - Key = xml:get_attr_s(<<"key">>, Attrs), - NewKey = xml:get_attr_s(<<"newkey">>, Attrs), + Key = fxml:get_attr_s(<<"key">>, Attrs), + NewKey = fxml:get_attr_s(<<"newkey">>, Attrs), KeyAllow = case RidAllow of repeat -> true; false -> false; @@ -801,7 +801,7 @@ handle_http_put_error(Reason, case Reason of not_exists -> {200, ?HEADER, - xml:element_to_binary(#xmlel{name = <<"body">>, + fxml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"type">>, <<"terminate">>}, @@ -810,7 +810,7 @@ handle_http_put_error(Reason, children = []})}; bad_key -> {200, ?HEADER, - xml:element_to_binary(#xmlel{name = <<"body">>, + fxml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"type">>, <<"terminate">>}, @@ -819,7 +819,7 @@ handle_http_put_error(Reason, children = []})}; polling_too_frequently -> {200, ?HEADER, - xml:element_to_binary(#xmlel{name = <<"body">>, + fxml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"type">>, <<"terminate">>}, @@ -855,7 +855,7 @@ rid_allow(OldRid, NewRid, Attrs, Hold, MaxPause) -> %% We did not miss any packet, we can process it immediately: NewRid == OldRid + 1 -> case catch - jlib:binary_to_integer(xml:get_attr_s(<<"pause">>, + jlib:binary_to_integer(fxml:get_attr_s(<<"pause">>, Attrs)) of {'EXIT', _} -> {true, 0}; @@ -929,9 +929,9 @@ prepare_outpacket_response(#http_bind{id = Sid, _Rid, OutPacket, true) -> case OutPacket of [{xmlstreamstart, _, OutAttrs} | Els] -> - AuthID = xml:get_attr_s(<<"id">>, OutAttrs), - From = xml:get_attr_s(<<"from">>, OutAttrs), - Version = xml:get_attr_s(<<"version">>, OutAttrs), + AuthID = fxml:get_attr_s(<<"id">>, OutAttrs), + From = fxml:get_attr_s(<<"from">>, OutAttrs), + Version = fxml:get_attr_s(<<"version">>, OutAttrs), OutEls = case Els of [] -> []; [{xmlstreamelement, @@ -968,7 +968,7 @@ prepare_outpacket_response(#http_bind{id = Sid, MaxInactivity = get_max_inactivity(To, ?MAX_INACTIVITY), MaxPause = get_max_pause(To), {200, ?HEADER, - xml:element_to_binary(#xmlel{name = <<"body">>, + fxml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}, {<<"sid">>, Sid}, @@ -1032,7 +1032,7 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> TypedEls = lists:foldl(fun ({xmlstreamelement, El}, Acc) -> Acc ++ - [xml:element_to_binary(check_default_xmlns(El))]; + [fxml:element_to_binary(check_default_xmlns(El))]; ({xmlstreamraw, R}, Acc) -> Acc ++ [R] end, @@ -1067,7 +1067,7 @@ send_outpacket(#http_bind{pid = FsmRef}, OutPacket) -> || {xmlstreamelement, OEl} <- StreamTail] end, {200, ?HEADER, - xml:element_to_binary(#xmlel{name = <<"body">>, + fxml:element_to_binary(#xmlel{name = <<"body">>, attrs = [{<<"xmlns">>, ?NS_HTTP_BIND}], @@ -1114,14 +1114,14 @@ parse_request(Data, PayloadSize, MaxStanzaSize) -> ?DEBUG("--- incoming data --- ~n~s~n --- END " "--- ", [Data]), - case xml_stream:parse_element(Data) of + case fxml_stream:parse_element(Data) of #xmlel{name = <<"body">>, attrs = Attrs, children = Els} -> - Xmlns = xml:get_attr_s(<<"xmlns">>, Attrs), + Xmlns = fxml:get_attr_s(<<"xmlns">>, Attrs), if Xmlns /= (?NS_HTTP_BIND) -> {error, bad_request}; true -> case catch - jlib:binary_to_integer(xml:get_attr_s(<<"rid">>, + jlib:binary_to_integer(fxml:get_attr_s(<<"rid">>, Attrs)) of {'EXIT', _} -> {error, bad_request}; @@ -1133,7 +1133,7 @@ parse_request(Data, PayloadSize, MaxStanzaSize) -> end end, Els), - Sid = xml:get_attr_s(<<"sid">>, Attrs), + Sid = fxml:get_attr_s(<<"sid">>, Attrs), if PayloadSize =< MaxStanzaSize -> {ok, {Sid, Rid, Attrs, FixedEls}}; true -> {size_limit, Sid} @@ -1165,7 +1165,7 @@ set_inactivity_timer(_Pause, MaxInactivity) -> elements_to_string([]) -> []; elements_to_string([El | Els]) -> - [xml:element_to_binary(El) | elements_to_string(Els)]. + [fxml:element_to_binary(El) | elements_to_string(Els)]. %% @spec (To, Default::integer()) -> integer() %% where To = [] | {Host::string(), Version::string()} @@ -1188,7 +1188,7 @@ get_max_pause(_) -> ?MAX_PAUSE. check_default_xmlns(#xmlel{name = Name, attrs = Attrs, children = Els} = El) -> - case xml:get_tag_attr_s(<<"xmlns">>, El) of + case fxml:get_tag_attr_s(<<"xmlns">>, El) of <<"">> -> #xmlel{name = Name, attrs = [{<<"xmlns">>, ?NS_CLIENT} | Attrs], diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl index 3b50e44a342..e66cf33a5c0 100644 --- a/src/ejabberd_http_ws.erl +++ b/src/ejabberd_http_ws.erl @@ -171,11 +171,11 @@ handle_sync_event({send_xml, Packet}, _From, StateName, {true, {xmlstreamelement, #xmlel{name=Name2} = El2}} -> El3 = case Name2 of <<"stream:", _/binary>> -> - xml:replace_tag_attr(<<"xmlns:stream">>, ?NS_STREAM, El2); + fxml:replace_tag_attr(<<"xmlns:stream">>, ?NS_STREAM, El2); _ -> - case xml:get_tag_attr_s(<<"xmlns">>, El2) of + case fxml:get_tag_attr_s(<<"xmlns">>, El2) of <<"">> -> - xml:replace_tag_attr(<<"xmlns">>, <<"jabber:client">>, El2); + fxml:replace_tag_attr(<<"xmlns">>, <<"jabber:client">>, El2); _ -> El2 end @@ -186,12 +186,12 @@ handle_sync_event({send_xml, Packet}, _From, StateName, end, case Packet2 of {xmlstreamstart, Name, Attrs3} -> - B = xml:element_to_binary(#xmlel{name = Name, attrs = Attrs3}), + B = fxml:element_to_binary(#xmlel{name = Name, attrs = Attrs3}), WsPid ! {send, <<(binary:part(B, 0, byte_size(B)-2))/binary, ">">>}; {xmlstreamend, Name} -> WsPid ! {send, <<"">>}; {xmlstreamelement, El} -> - WsPid ! {send, xml:element_to_binary(El)}; + WsPid ! {send, fxml:element_to_binary(El)}; {xmlstreamraw, Bin} -> WsPid ! {send, Bin}; {xmlstreamcdata, Bin2} -> @@ -210,7 +210,7 @@ handle_sync_event(close, _From, StateName, #state{ws = {_, WsPid}, rfc_compilant when StateName /= stream_end_sent -> Close = #xmlel{name = <<"close">>, attrs = [{<<"xmlns">>, <<"urn:ietf:params:xml:ns:xmpp-framing">>}]}, - WsPid ! {send, xml:element_to_binary(Close)}, + WsPid ! {send, fxml:element_to_binary(Close)}, {stop, normal, StateData}; handle_sync_event(close, _From, _StateName, StateData) -> {stop, normal, StateData}. @@ -316,9 +316,9 @@ get_human_html_xmlel() -> parse(#state{rfc_compilant = C} = State, Data) -> case C of undefined -> - P = xml_stream:new(self()), - P2 = xml_stream:parse(P, Data), - xml_stream:close(P2), + P = fxml_stream:new(self()), + P2 = fxml_stream:parse(P, Data), + fxml_stream:close(P2), case parsed_items([]) of error -> {State#state{rfc_compilant = true}, <<"parse error">>}; @@ -330,7 +330,7 @@ parse(#state{rfc_compilant = C} = State, Data) -> parse(State#state{rfc_compilant = false}, Data) end; true -> - El = xml_stream:parse_element(Data), + El = fxml_stream:parse_element(Data), case El of #xmlel{name = <<"open">>, attrs = Attrs} -> Attrs2 = [{<<"xmlns:stream">>, ?NS_STREAM}, {<<"xmlns">>, <<"jabber:client">>} | diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 66f530c8f4c..1b7f93c77f1 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -272,7 +272,7 @@ do_route(From, To, Packet) -> end; true -> #xmlel{attrs = Attrs} = Packet, - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; <<"result">> -> ok; _ -> diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 50c8e323c59..028a8a8b3c0 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -64,7 +64,7 @@ -define(NS_PIEFXIS, <<"http://www.xmpp.org/extensions/xep-0227.html#ns">>). -define(NS_XI, <<"http://www.w3.org/2001/XInclude">>). --record(state, {xml_stream_state :: xml_stream:xml_stream_state(), +-record(state, {xml_stream_state :: fxml_stream:xml_stream_state(), user = <<"">> :: binary(), server = <<"">> :: binary(), fd :: file:io_device(), @@ -85,7 +85,7 @@ import_file(FileName, State) -> case file:open(FileName, [read, binary]) of {ok, Fd} -> Dir = filename:dirname(FileName), - XMLStreamState = xml_stream:new(self(), infinity), + XMLStreamState = fxml_stream:new(self(), infinity), Res = process(State#state{xml_stream_state = XMLStreamState, fd = Fd, dir = Dir}), @@ -257,7 +257,7 @@ export_user(User, Server, Fd) -> get_privacy(User, Server) ++ get_roster(User, Server) ++ get_private(User, Server), - print(Fd, xml:element_to_binary( + print(Fd, fxml:element_to_binary( #xmlel{name = <<"user">>, attrs = [{<<"name">>, User}, {<<"password">>, Pass}], @@ -387,17 +387,17 @@ get_private(User, Server) -> process(#state{xml_stream_state = XMLStreamState, fd = Fd} = State) -> case file:read(Fd, ?CHUNK_SIZE) of {ok, Data} -> - NewXMLStreamState = xml_stream:parse(XMLStreamState, Data), + NewXMLStreamState = fxml_stream:parse(XMLStreamState, Data), case process_els(State#state{xml_stream_state = NewXMLStreamState}) of {ok, NewState} -> process(NewState); Err -> - xml_stream:close(NewXMLStreamState), + fxml_stream:close(NewXMLStreamState), Err end; eof -> - xml_stream:close(XMLStreamState), + fxml_stream:close(XMLStreamState), ok end. @@ -415,7 +415,7 @@ process_els(State) -> end. process_el({xmlstreamstart, <<"server-data">>, Attrs}, State) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_PIEFXIS -> {ok, State}; ?NS_PIE -> @@ -430,7 +430,7 @@ process_el({xmlstreamcdata, _}, State) -> process_el({xmlstreamelement, #xmlel{name = <<"xi:include">>, attrs = Attrs}}, #state{dir = Dir, user = <<"">>} = State) -> - FileName = xml:get_attr_s(<<"href">>, Attrs), + FileName = fxml:get_attr_s(<<"href">>, Attrs), case import_file(filename:join([Dir, FileName]), State) of ok -> {ok, State}; @@ -443,7 +443,7 @@ process_el({xmlstreamstart, <<"host">>, Attrs}, State) -> process_el({xmlstreamelement, #xmlel{name = <<"host">>, attrs = Attrs, children = Els}}, State) -> - JIDS = xml:get_attr_s(<<"jid">>, Attrs), + JIDS = fxml:get_attr_s(<<"jid">>, Attrs), case jid:from_string(JIDS) of #jid{lserver = S} -> case lists:member(S, ?MYHOSTS) of @@ -486,8 +486,8 @@ process_users([], State) -> process_user(#xmlel{name = <<"user">>, attrs = Attrs, children = Els}, #state{server = LServer} = State) -> - Name = xml:get_attr_s(<<"name">>, Attrs), - Password = xml:get_attr_s(<<"password">>, Attrs), + Name = fxml:get_attr_s(<<"name">>, Attrs), + Password = fxml:get_attr_s(<<"password">>, Attrs), PasswordFormat = ejabberd_config:get_option({auth_password_format, LServer}, fun(X) -> X end, plain), Pass = case PasswordFormat of scram -> @@ -525,7 +525,7 @@ process_user_els([], State) -> process_user_el(#xmlel{name = Name, attrs = Attrs, children = Els} = El, State) -> - case {Name, xml:get_attr_s(<<"xmlns">>, Attrs)} of + case {Name, fxml:get_attr_s(<<"xmlns">>, Attrs)} of {<<"query">>, ?NS_ROSTER} -> process_roster(El, State); {<<"query">>, ?NS_PRIVACY} -> @@ -584,7 +584,7 @@ process_privacy(El, State = #state{user = U, server = S}) -> [], JID, JID, #iq{type = set, sub_el = El}) of {error, Error} = Err -> #xmlel{children = Els} = El, - Name = case xml:remove_cdata(Els) of + Name = case fxml:remove_cdata(Els) of [#xmlel{name = N}] -> N; _ -> undefined end, @@ -628,7 +628,7 @@ process_vcard(El, State = #state{user = U, server = S}) -> %% @spec (Dir::string(), Host::string()) -> ok process_offline_msg(El, State = #state{user = U, server = S}) -> - FromS = xml:get_attr_s(<<"from">>, El#xmlel.attrs), + FromS = fxml:get_attr_s(<<"from">>, El#xmlel.attrs), case jid:from_string(FromS) of #jid{} = From -> To = jid:make(U, S, <<>>), @@ -645,7 +645,7 @@ process_offline_msg(El, State = #state{user = U, server = S}) -> %% @spec (Dir::string(), Fn::string(), Host::string()) -> ok process_presence(El, #state{user = U, server = S} = State) -> - FromS = xml:get_attr_s(<<"from">>, El#xmlel.attrs), + FromS = fxml:get_attr_s(<<"from">>, El#xmlel.attrs), case jid:from_string(FromS) of #jid{} = From -> To = jid:make(U, S, <<>>), diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index fa85805d5e3..6189c433297 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -53,7 +53,7 @@ shaper_state = none :: shaper:shaper(), c2s_pid :: pid(), max_stanza_size = infinity :: non_neg_integer() | infinity, - xml_stream_state :: xml_stream:xml_stream_state(), + xml_stream_state :: fxml_stream:xml_stream_state(), timeout = infinity:: timeout()}). -define(HIBERNATE_TIMEOUT, 90000). @@ -160,7 +160,7 @@ handle_call(reset_stream, _From, State) -> Reply = ok, {reply, Reply, NewState, ?HIBERNATE_TIMEOUT}; handle_call({become_controller, C2SPid}, _From, State) -> - XMLStreamState = xml_stream:new(C2SPid, State#state.max_stanza_size), + XMLStreamState = fxml_stream:new(C2SPid, State#state.max_stanza_size), NewState = State#state{c2s_pid = C2SPid, xml_stream_state = XMLStreamState}, activate_socket(NewState), @@ -284,7 +284,7 @@ process_data(Data, undefined -> XMLStreamState; _ -> - xml_stream:parse(XMLStreamState, Data) + fxml_stream:parse(XMLStreamState, Data) end, {NewShaperState, Pause} = shaper:update(ShaperState, byte_size(Data)), if @@ -309,7 +309,7 @@ element_wrapper(Element) -> Element. close_stream(undefined) -> ok; close_stream(XMLStreamState) -> - xml_stream:close(XMLStreamState). + fxml_stream:close(XMLStreamState). reset_parser(#state{xml_stream_state = undefined} = State) -> State; @@ -317,14 +317,14 @@ reset_parser(#state{c2s_pid = C2SPid, max_stanza_size = MaxStanzaSize, xml_stream_state = XMLStreamState} = State) -> - NewStreamState = try xml_stream:reset(XMLStreamState) + NewStreamState = try fxml_stream:reset(XMLStreamState) catch error:_ -> close_stream(XMLStreamState), case C2SPid of undefined -> undefined; _ -> - xml_stream:new(C2SPid, MaxStanzaSize) + fxml_stream:new(C2SPid, MaxStanzaSize) end end, State#state{xml_stream_state = NewStreamState}. diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index 5ca1262e675..da1bd3e0fc0 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -86,7 +86,7 @@ route(From, To, Packet) -> route_error(From, To, ErrPacket, OrigPacket) -> #xmlel{attrs = Attrs} = OrigPacket, - case <<"error">> == xml:get_attr_s(<<"type">>, Attrs) of + case <<"error">> == fxml:get_attr_s(<<"type">>, Attrs) of false -> route(From, To, ErrPacket); true -> ok end. diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 3d0c4730765..0eab46337ef 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -308,7 +308,7 @@ do_route(From, To, Packet) -> #xmlel{name = Name, attrs = NewAttrs, children = Els}), ok; {aborted, _Reason} -> - case xml:get_tag_attr_s(<<"type">>, Packet) of + case fxml:get_tag_attr_s(<<"type">>, Packet) of <<"error">> -> ok; <<"result">> -> ok; _ -> diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index 29dd5e9dfdd..c8d3cd04e97 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -85,16 +85,16 @@ -define(STREAM_TRAILER, <<"">>). -define(INVALID_NAMESPACE_ERR, - xml:element_to_binary(?SERR_INVALID_NAMESPACE)). + fxml:element_to_binary(?SERR_INVALID_NAMESPACE)). -define(HOST_UNKNOWN_ERR, - xml:element_to_binary(?SERR_HOST_UNKNOWN)). + fxml:element_to_binary(?SERR_HOST_UNKNOWN)). -define(INVALID_FROM_ERR, - xml:element_to_binary(?SERR_INVALID_FROM)). + fxml:element_to_binary(?SERR_INVALID_FROM)). -define(INVALID_XML_ERR, - xml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). + fxml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). start(SockData, Opts) -> supervisor:start_child(ejabberd_s2s_in_sup, @@ -188,10 +188,10 @@ init([{SockMod, Socket}, Opts]) -> wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> - case {xml:get_attr_s(<<"xmlns">>, Attrs), - xml:get_attr_s(<<"xmlns:db">>, Attrs), - xml:get_attr_s(<<"to">>, Attrs), - xml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} + case {fxml:get_attr_s(<<"xmlns">>, Attrs), + fxml:get_attr_s(<<"xmlns:db">>, Attrs), + fxml:get_attr_s(<<"to">>, Attrs), + fxml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} of {<<"jabber:server">>, _, Server, true} when StateData#state.tls and @@ -199,7 +199,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, send_text(StateData, ?STREAM_HEADER(<<" version='1.0'">>)), Auth = if StateData#state.tls_enabled -> - case jid:nameprep(xml:get_attr_s(<<"from">>, Attrs)) of + case jid:nameprep(fxml:get_attr_s(<<"from">>, Attrs)) of From when From /= <<"">>, From /= error -> {Result, Message} = ejabberd_s2s:check_peer_certificate(StateData#state.sockmod, @@ -234,7 +234,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, ?INFO_MSG("Closing s2s connection: ~s <--> ~s (~s)", [StateData#state.server, RemoteServer, CertError]), send_text(StateData, - <<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, + <<(fxml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, CertError)))/binary, (?STREAM_TRAILER)/binary>>), {stop, normal, StateData}; @@ -306,7 +306,7 @@ wait_for_feature_request({xmlstreamelement, El}, TLSEnabled = StateData#state.tls_enabled, SockMod = (StateData#state.sockmod):get_sockmod(StateData#state.socket), - case {xml:get_attr_s(<<"xmlns">>, Attrs), Name} of + case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of {?NS_TLS, <<"starttls">>} when TLS == true, TLSEnabled == false, SockMod == gen_tcp -> @@ -331,7 +331,7 @@ wait_for_feature_request({xmlstreamelement, El}, end, TLSSocket = (StateData#state.sockmod):starttls(Socket, TLSOpts, - xml:element_to_binary(#xmlel{name + fxml:element_to_binary(#xmlel{name = <<"proceed">>, attrs @@ -345,7 +345,7 @@ wait_for_feature_request({xmlstreamelement, El}, StateData#state{socket = TLSSocket, streamid = new_id(), tls_enabled = true, tls_options = TLSOpts}}; {?NS_SASL, <<"auth">>} when TLSEnabled -> - Mech = xml:get_attr_s(<<"mechanism">>, Attrs), + Mech = fxml:get_attr_s(<<"mechanism">>, Attrs), case Mech of <<"EXTERNAL">> when StateData#state.auth_domain /= <<"">> -> AuthDomain = StateData#state.auth_domain, @@ -447,9 +447,9 @@ stream_established({xmlstreamelement, El}, StateData) -> _ -> NewEl = jlib:remove_attr(<<"xmlns">>, El), #xmlel{name = Name, attrs = Attrs} = NewEl, - From_s = xml:get_attr_s(<<"from">>, Attrs), + From_s = fxml:get_attr_s(<<"from">>, Attrs), From = jid:from_string(From_s), - To_s = xml:get_attr_s(<<"to">>, Attrs), + To_s = fxml:get_attr_s(<<"to">>, Attrs), To = jid:from_string(To_s), if (To /= error) and (From /= error) -> LFrom = From#jid.lserver, @@ -626,7 +626,7 @@ send_text(StateData, Text) -> Text). send_element(StateData, El) -> - send_text(StateData, xml:element_to_binary(El)). + send_text(StateData, fxml:element_to_binary(El)). change_shaper(StateData, Host, JID) -> Shaper = acl:match_rule(Host, StateData#state.shaper, @@ -643,15 +643,15 @@ cancel_timer(Timer) -> is_key_packet(#xmlel{name = Name, attrs = Attrs, children = Els}) when Name == <<"db:result">> -> - {key, xml:get_attr_s(<<"to">>, Attrs), - xml:get_attr_s(<<"from">>, Attrs), - xml:get_attr_s(<<"id">>, Attrs), xml:get_cdata(Els)}; + {key, fxml:get_attr_s(<<"to">>, Attrs), + fxml:get_attr_s(<<"from">>, Attrs), + fxml:get_attr_s(<<"id">>, Attrs), fxml:get_cdata(Els)}; is_key_packet(#xmlel{name = Name, attrs = Attrs, children = Els}) when Name == <<"db:verify">> -> - {verify, xml:get_attr_s(<<"to">>, Attrs), - xml:get_attr_s(<<"from">>, Attrs), - xml:get_attr_s(<<"id">>, Attrs), xml:get_cdata(Els)}; + {verify, fxml:get_attr_s(<<"to">>, Attrs), + fxml:get_attr_s(<<"from">>, Attrs), + fxml:get_attr_s(<<"id">>, Attrs), fxml:get_cdata(Els)}; is_key_packet(_) -> false. fsm_limit_opts(Opts) -> diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl index 69618573939..594fbb2c795 100644 --- a/src/ejabberd_s2s_out.erl +++ b/src/ejabberd_s2s_out.erl @@ -105,13 +105,13 @@ -define(STREAM_TRAILER, <<"">>). -define(INVALID_NAMESPACE_ERR, - xml:element_to_binary(?SERR_INVALID_NAMESPACE)). + fxml:element_to_binary(?SERR_INVALID_NAMESPACE)). -define(HOST_UNKNOWN_ERR, - xml:element_to_binary(?SERR_HOST_UNKNOWN)). + fxml:element_to_binary(?SERR_HOST_UNKNOWN)). -define(INVALID_XML_ERR, - xml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). + fxml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). -define(SOCKET_DEFAULT_RESULT, {error, badarg}). @@ -323,15 +323,15 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, true -> {no_verify, <<"Not verified">>, StateData} end, - RemoteStreamID = xml:get_attr_s(<<"id">>, Attrs), + RemoteStreamID = fxml:get_attr_s(<<"id">>, Attrs), NewStateData = StateData0#state{remote_streamid = RemoteStreamID}, - case {xml:get_attr_s(<<"xmlns">>, Attrs), - xml:get_attr_s(<<"xmlns:db">>, Attrs), - xml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} + case {fxml:get_attr_s(<<"xmlns">>, Attrs), + fxml:get_attr_s(<<"xmlns:db">>, Attrs), + fxml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} of _ when CertCheckRes == error -> send_text(NewStateData, - <<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, + <<(fxml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, CertCheckMsg)))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (~s)", @@ -495,7 +495,7 @@ wait_for_features({xmlstreamelement, El}, StateData) -> STLSReq} = Acc) -> case - xml:get_attr_s(<<"xmlns">>, + fxml:get_attr_s(<<"xmlns">>, Attrs1) of ?NS_SASL -> @@ -508,7 +508,7 @@ wait_for_features({xmlstreamelement, El}, StateData) -> = Els2}) -> case - xml:get_cdata(Els2) + fxml:get_cdata(Els2) of <<"EXTERNAL">> -> true; @@ -533,13 +533,13 @@ wait_for_features({xmlstreamelement, El}, StateData) -> _STLSReq} = Acc) -> case - xml:get_attr_s(<<"xmlns">>, + fxml:get_attr_s(<<"xmlns">>, Attrs1) of ?NS_TLS -> Req = case - xml:get_subtag(El1, + fxml:get_subtag(El1, <<"required">>) of #xmlel{} -> @@ -610,7 +610,7 @@ wait_for_features({xmlstreamelement, El}, StateData) -> end; _ -> send_text(StateData, - <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, + <<(fxml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", @@ -637,7 +637,7 @@ wait_for_auth_result({xmlstreamelement, El}, StateData) -> case El of #xmlel{name = <<"success">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_SASL -> ?DEBUG("auth: ~p", [{StateData#state.myname, StateData#state.server}]), @@ -653,7 +653,7 @@ wait_for_auth_result({xmlstreamelement, El}, ?FSMTIMEOUT}; _ -> send_text(StateData, - <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, + <<(fxml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", @@ -661,7 +661,7 @@ wait_for_auth_result({xmlstreamelement, El}, {stop, normal, StateData} end; #xmlel{name = <<"failure">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_SASL -> ?DEBUG("restarted: ~p", [{StateData#state.myname, StateData#state.server}]), @@ -670,7 +670,7 @@ wait_for_auth_result({xmlstreamelement, El}, StateData#state{socket = undefined}, ?FSMTIMEOUT}; _ -> send_text(StateData, - <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, + <<(fxml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", @@ -679,7 +679,7 @@ wait_for_auth_result({xmlstreamelement, El}, end; _ -> send_text(StateData, - <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, + <<(fxml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", @@ -707,7 +707,7 @@ wait_for_starttls_proceed({xmlstreamelement, El}, StateData) -> case El of #xmlel{name = <<"proceed">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_TLS -> ?DEBUG("starttls: ~p", [{StateData#state.myname, StateData#state.server}]), @@ -737,7 +737,7 @@ wait_for_starttls_proceed({xmlstreamelement, El}, ?FSMTIMEOUT}; _ -> send_text(StateData, - <<(xml:element_to_binary(?SERR_BAD_FORMAT))/binary, + <<(fxml:element_to_binary(?SERR_BAD_FORMAT))/binary, (?STREAM_TRAILER)/binary>>), ?INFO_MSG("Closing s2s connection: ~s -> ~s (bad " "format)", @@ -985,7 +985,7 @@ send_text(StateData, Text) -> ejabberd_socket:send(StateData#state.socket, Text). send_element(StateData, El) -> - send_text(StateData, xml:element_to_binary(El)). + send_text(StateData, fxml:element_to_binary(El)). send_queue(StateData, Q) -> case queue:out(Q) of @@ -997,14 +997,14 @@ send_queue(StateData, Q) -> %% Bounce a single message (xmlelement) bounce_element(El, Error) -> #xmlel{attrs = Attrs} = El, - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; <<"result">> -> ok; _ -> Err = jlib:make_error_reply(El, Error), - From = jid:from_string(xml:get_tag_attr_s(<<"from">>, + From = jid:from_string(fxml:get_tag_attr_s(<<"from">>, El)), - To = jid:from_string(xml:get_tag_attr_s(<<"to">>, + To = jid:from_string(fxml:get_tag_attr_s(<<"to">>, El)), ejabberd_router:route(To, From, Err) end. @@ -1070,16 +1070,16 @@ send_db_request(StateData) -> is_verify_res(#xmlel{name = Name, attrs = Attrs}) when Name == <<"db:result">> -> - {result, xml:get_attr_s(<<"to">>, Attrs), - xml:get_attr_s(<<"from">>, Attrs), - xml:get_attr_s(<<"id">>, Attrs), - xml:get_attr_s(<<"type">>, Attrs)}; + {result, fxml:get_attr_s(<<"to">>, Attrs), + fxml:get_attr_s(<<"from">>, Attrs), + fxml:get_attr_s(<<"id">>, Attrs), + fxml:get_attr_s(<<"type">>, Attrs)}; is_verify_res(#xmlel{name = Name, attrs = Attrs}) when Name == <<"db:verify">> -> - {verify, xml:get_attr_s(<<"to">>, Attrs), - xml:get_attr_s(<<"from">>, Attrs), - xml:get_attr_s(<<"id">>, Attrs), - xml:get_attr_s(<<"type">>, Attrs)}; + {verify, fxml:get_attr_s(<<"to">>, Attrs), + fxml:get_attr_s(<<"from">>, Attrs), + fxml:get_attr_s(<<"id">>, Attrs), + fxml:get_attr_s(<<"type">>, Attrs)}; is_verify_res(_) -> false. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index a9b771b8988..e5508a19080 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -91,10 +91,10 @@ "m:error>">>). -define(INVALID_XML_ERR, - xml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). + fxml:element_to_binary(?SERR_XML_NOT_WELL_FORMED)). -define(INVALID_NS_ERR, - xml:element_to_binary(?SERR_INVALID_NAMESPACE)). + fxml:element_to_binary(?SERR_INVALID_NAMESPACE)). %%%---------------------------------------------------------------------- %%% API @@ -166,9 +166,9 @@ init([{SockMod, Socket}, Opts]) -> wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of <<"jabber:component:accept">> -> - To = xml:get_attr_s(<<"to">>, Attrs), + To = fxml:get_attr_s(<<"to">>, Attrs), Host = jid:nameprep(To), if Host == error -> Header = io_lib:format(?STREAM_HEADER, @@ -180,7 +180,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, {stop, normal, StateData}; true -> Header = io_lib:format(?STREAM_HEADER, - [StateData#state.streamid, xml:crypt(To)]), + [StateData#state.streamid, fxml:crypt(To)]), send_text(StateData, Header), HostOpts = case dict:is_key(Host, StateData#state.host_opts) of true -> @@ -212,7 +212,7 @@ wait_for_stream(closed, StateData) -> wait_for_handshake({xmlstreamelement, El}, StateData) -> #xmlel{name = Name, children = Els} = El, - case {Name, xml:get_cdata(Els)} of + case {Name, fxml:get_cdata(Els)} of {<<"handshake">>, Digest} -> case dict:find(StateData#state.host, StateData#state.host_opts) of {ok, Password} -> @@ -250,7 +250,7 @@ wait_for_handshake(closed, StateData) -> stream_established({xmlstreamelement, El}, StateData) -> NewEl = jlib:remove_attr(<<"xmlns">>, El), #xmlel{name = Name, attrs = Attrs} = NewEl, - From = xml:get_attr_s(<<"from">>, Attrs), + From = fxml:get_attr_s(<<"from">>, Attrs), FromJID = case StateData#state.check_from of %% If the admin does not want to check the from field %% when accept packets from any address. @@ -269,7 +269,7 @@ stream_established({xmlstreamelement, El}, StateData) -> _ -> error end end, - To = xml:get_attr_s(<<"to">>, Attrs), + To = fxml:get_attr_s(<<"to">>, Attrs), ToJID = case To of <<"">> -> error; _ -> jid:from_string(To) @@ -356,7 +356,7 @@ handle_info({route, From, To, Packet}, StateName, Attrs2 = jlib:replace_from_to_attrs(jid:to_string(From), jid:to_string(To), Attrs), - Text = xml:element_to_binary(#xmlel{name = Name, + Text = fxml:element_to_binary(#xmlel{name = Name, attrs = Attrs2, children = Els}), send_text(StateData, Text); deny -> @@ -402,7 +402,7 @@ send_text(StateData, Text) -> Text). send_element(StateData, El) -> - send_text(StateData, xml:element_to_binary(El)). + send_text(StateData, fxml:element_to_binary(El)). new_id() -> randoms:get_string(). diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 3045a417b1c..a3442a9d2f2 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -419,10 +419,10 @@ do_route(From, To, #xmlel{} = Packet) -> <<"">> -> case Name of <<"presence">> -> - {Pass, _Subsc} = case xml:get_attr_s(<<"type">>, Attrs) + {Pass, _Subsc} = case fxml:get_attr_s(<<"type">>, Attrs) of <<"subscribe">> -> - Reason = xml:get_path_s(Packet, + Reason = fxml:get_path_s(Packet, [{elem, <<"status">>}, cdata]), @@ -483,7 +483,7 @@ do_route(From, To, #xmlel{} = Packet) -> true -> ok end; <<"message">> -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"chat">> -> route_message(From, To, Packet, chat); <<"headline">> -> route_message(From, To, Packet, headline); <<"error">> -> ok; @@ -503,7 +503,7 @@ do_route(From, To, #xmlel{} = Packet) -> [] -> case Name of <<"message">> -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"chat">> -> route_message(From, To, Packet, chat); <<"normal">> -> route_message(From, To, Packet, normal); <<"">> -> route_message(From, To, Packet, normal); @@ -514,7 +514,7 @@ do_route(From, To, #xmlel{} = Packet) -> ejabberd_router:route(To, From, Err) end; <<"iq">> -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; <<"result">> -> ok; _ -> diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index 9a0213c1db2..3ea6360339a 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -71,7 +71,7 @@ process_command(From, To, Packet) -> jid:tolower(jid:remove_resource(From)), case lists:member(LFrom, get_admin_jids()) of true -> - Body = xml:get_path_s(Packet, + Body = fxml:get_path_s(Packet, [{elem, <<"body">>}, cdata]), spawn(fun () -> process_flag(priority, high), diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index d711f2fc39e..efdb9236177 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -2722,14 +2722,14 @@ pretty_print_xml(#xmlel{name = Name, attrs = Attrs, [{Attr, Val} | RestAttrs] -> AttrPrefix = [Prefix, str:copies(<<" ">>, byte_size(Name) + 2)], - [$\s, Attr, $=, $', xml:crypt(Val) | [$', + [$\s, Attr, $=, $', fxml:crypt(Val) | [$', lists:map(fun ({Attr1, Val1}) -> [$\n, AttrPrefix, Attr1, $=, $', - xml:crypt(Val1), + fxml:crypt(Val1), $'] end, RestAttrs)]] @@ -2741,7 +2741,7 @@ pretty_print_xml(#xmlel{name = Name, attrs = Attrs, end, Els), if OnlyCData -> - [$>, xml:get_cdata(Els), $<, $/, Name, $>, $\n]; + [$>, fxml:get_cdata(Els), $<, $/, Name, $>, $\n]; true -> [$>, $\n, lists:map(fun (E) -> diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 6b25adc4c0d..3078b64ea1c 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -228,13 +228,13 @@ process(_, #request{method = 'POST', data = Data, opts = Opts}) -> end, GetAuth = true, State = #state{access_commands = AccessCommands, get_auth = GetAuth}, - case xml_stream:parse_element(Data) of + case fxml_stream:parse_element(Data) of {error, _} -> {400, [], #xmlel{name = <<"h1">>, attrs = [], children = [{xmlcdata, <<"Malformed XML">>}]}}; El -> - case p1_xmlrpc:decode(El) of + case fxmlrpc:decode(El) of {error, _} = Err -> ?ERROR_MSG("XML-RPC request ~s failed with reason: ~p", [Data, Err]), @@ -244,7 +244,7 @@ process(_, #request{method = 'POST', data = Data, opts = Opts}) -> {ok, RPC} -> ?DEBUG("got XML-RPC request: ~p", [RPC]), {false, Result} = handler(State, RPC), - XML = xml:element_to_binary(p1_xmlrpc:encode(Result)), + XML = fxml:element_to_binary(fxmlrpc:encode(Result)), {200, [{<<"Content-Type">>, <<"text/xml">>}], <<"", XML/binary>>} end diff --git a/src/jd2ejd.erl b/src/jd2ejd.erl index cda8d11ce89..099387c9a5a 100644 --- a/src/jd2ejd.erl +++ b/src/jd2ejd.erl @@ -48,7 +48,7 @@ import_file(File) -> true -> case file:read_file(File) of {ok, Text} -> - case xml_stream:parse_element(Text) of + case fxml_stream:parse_element(Text) of El when is_record(El, xmlel) -> case catch process_xdb(User, Server, El) of {'EXIT', Reason} -> @@ -113,16 +113,16 @@ process_xdb(User, Server, xdb_data(_User, _Server, {xmlcdata, _CData}) -> ok; xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> From = jid:make(User, Server, <<"">>), - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_AUTH -> - Password = xml:get_tag_cdata(El), + Password = fxml:get_tag_cdata(El), ejabberd_auth:set_password(User, Server, Password), ok; ?NS_ROSTER -> catch mod_roster:set_items(User, Server, El), ok; ?NS_LAST -> - TimeStamp = xml:get_attr_s(<<"last">>, Attrs), - Status = xml:get_tag_cdata(El), + TimeStamp = fxml:get_attr_s(<<"last">>, Attrs), + Status = fxml:get_tag_cdata(El), catch mod_last:store_last_info(User, Server, jlib:binary_to_integer(TimeStamp), Status), @@ -136,7 +136,7 @@ xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> <<"jabber:x:offline">> -> process_offline(Server, From, El), ok; XMLNS -> - case xml:get_attr_s(<<"j_private_flag">>, Attrs) of + case fxml:get_attr_s(<<"j_private_flag">>, Attrs) of <<"1">> -> catch mod_private:process_sm_iq(From, jid:make(<<"">>, Server, @@ -160,7 +160,7 @@ xdb_data(User, Server, #xmlel{attrs = Attrs} = El) -> process_offline(Server, To, #xmlel{children = Els}) -> LServer = jid:nameprep(Server), lists:foreach(fun (#xmlel{attrs = Attrs} = El) -> - FromS = xml:get_attr_s(<<"from">>, Attrs), + FromS = fxml:get_attr_s(<<"from">>, Attrs), From = case FromS of <<"">> -> jid:make(<<"">>, Server, <<"">>); diff --git a/src/jlib.erl b/src/jlib.erl index 61aaf690e17..8eaebbc8061 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -92,8 +92,8 @@ make_result_iq_reply(#xmlel{name = Name, attrs = Attrs, -spec make_result_iq_reply_attrs([attr()]) -> [attr()]. make_result_iq_reply_attrs(Attrs) -> - To = xml:get_attr(<<"to">>, Attrs), - From = xml:get_attr(<<"from">>, Attrs), + To = fxml:get_attr(<<"to">>, Attrs), + From = fxml:get_attr(<<"from">>, Attrs), Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = case To of @@ -133,8 +133,8 @@ make_error_reply(#xmlel{name = Name, attrs = Attrs, -spec make_error_reply_attrs([attr()]) -> [attr()]. make_error_reply_attrs(Attrs) -> - To = xml:get_attr(<<"to">>, Attrs), - From = xml:get_attr(<<"from">>, Attrs), + To = fxml:get_attr(<<"to">>, Attrs), + From = fxml:get_attr(<<"from">>, Attrs), Attrs1 = lists:keydelete(<<"to">>, 1, Attrs), Attrs2 = lists:keydelete(<<"from">>, 1, Attrs1), Attrs3 = case To of @@ -159,7 +159,7 @@ make_error_element(Code, Desc) -> make_correct_from_to_attrs(From, To, Attrs) -> Attrs1 = lists:keydelete(<<"from">>, 1, Attrs), - Attrs2 = case xml:get_attr(<<"to">>, Attrs) of + Attrs2 = case fxml:get_attr(<<"to">>, Attrs) of {value, _} -> Attrs1; _ -> [{<<"to">>, To} | Attrs1] end, @@ -299,8 +299,8 @@ jid_replace_resource(JID, Resource) -> -spec get_iq_namespace(xmlel()) -> binary(). get_iq_namespace(#xmlel{name = <<"iq">>, children = Els}) -> - case xml:remove_cdata(Els) of - [#xmlel{attrs = Attrs}] -> xml:get_attr_s(<<"xmlns">>, Attrs); + case fxml:remove_cdata(Els) of + [#xmlel{attrs = Attrs}] -> fxml:get_attr_s(<<"xmlns">>, Attrs); _ -> <<"">> end; get_iq_namespace(_) -> <<"">>. @@ -326,9 +326,9 @@ iq_query_or_response_info(El) -> iq_info_internal(El, any). iq_info_internal(#xmlel{name = <<"iq">>, attrs = Attrs, children = Els}, Filter) -> - ID = xml:get_attr_s(<<"id">>, Attrs), - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), - {Type, Class} = case xml:get_attr_s(<<"type">>, Attrs) of + ID = fxml:get_attr_s(<<"id">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), + {Type, Class} = case fxml:get_attr_s(<<"type">>, Attrs) of <<"set">> -> {set, request}; <<"get">> -> {get, request}; <<"result">> -> {result, reply}; @@ -336,15 +336,15 @@ iq_info_internal(#xmlel{name = <<"iq">>, attrs = Attrs, children = Els}, Filter) _ -> {invalid, invalid} end, if Type == invalid -> invalid; Class == request; Filter == any -> - FilteredEls = xml:remove_cdata(Els), + FilteredEls = fxml:remove_cdata(Els), {XMLNS, SubEl} = case {Class, FilteredEls} of {request, [#xmlel{attrs = Attrs2}]} -> - {xml:get_attr_s(<<"xmlns">>, Attrs2), hd(FilteredEls)}; + {fxml:get_attr_s(<<"xmlns">>, Attrs2), hd(FilteredEls)}; {reply, _} -> NonErrorEls = [El || #xmlel{name = SubName} = El <- FilteredEls, SubName /= <<"error">>], {case NonErrorEls of - [NonErrorEl] -> xml:get_tag_attr_s(<<"xmlns">>, NonErrorEl); + [NonErrorEl] -> fxml:get_tag_attr_s(<<"xmlns">>, NonErrorEl); _ -> <<"">> end, FilteredEls}; @@ -399,7 +399,7 @@ iq_to_xml(#iq{id = ID, type = Type, sub_el = SubEl}) -> ). parse_xdata_submit(#xmlel{attrs = Attrs, children = Els}) -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"submit">> -> lists:reverse(parse_xdata_fields(Els, [])); <<"form">> -> %% This is a workaround to accept Psi's wrong forms @@ -418,7 +418,7 @@ parse_xdata_submit(#xmlel{attrs = Attrs, children = Els}) -> parse_xdata_fields([], Res) -> Res; parse_xdata_fields([#xmlel{name = <<"field">>, attrs = Attrs, children = SubEls} | Els], Res) -> - case xml:get_attr_s(<<"var">>, Attrs) of + case fxml:get_attr_s(<<"var">>, Attrs) of <<>> -> parse_xdata_fields(Els, Res); Var -> @@ -437,7 +437,7 @@ parse_xdata_fields([_ | Els], Res) -> parse_xdata_values([], Res) -> Res; parse_xdata_values([#xmlel{name = <<"value">>, children = SubEls} | Els], Res) -> - Val = xml:get_cdata(SubEls), + Val = fxml:get_cdata(SubEls), parse_xdata_values(Els, [Val | Res]); parse_xdata_values([_ | Els], Res) -> parse_xdata_values(Els, Res). @@ -446,7 +446,7 @@ parse_xdata_values([_ | Els], Res) -> rsm_decode(#iq{sub_el = SubEl}) -> rsm_decode(SubEl); rsm_decode(#xmlel{} = SubEl) -> - case xml:get_subtag(SubEl, <<"set">>) of + case fxml:get_subtag(SubEl, <<"set">>) of false -> none; #xmlel{name = <<"set">>, children = SubEls} -> lists:foldl(fun rsm_parse_element/2, #rsm_in{}, SubEls) @@ -455,26 +455,26 @@ rsm_decode(#xmlel{} = SubEl) -> rsm_parse_element(#xmlel{name = <<"max">>, attrs = []} = Elem, RsmIn) -> - CountStr = xml:get_tag_cdata(Elem), + CountStr = fxml:get_tag_cdata(Elem), {Count, _} = str:to_integer(CountStr), RsmIn#rsm_in{max = Count}; rsm_parse_element(#xmlel{name = <<"before">>, attrs = []} = Elem, RsmIn) -> - UID = xml:get_tag_cdata(Elem), + UID = fxml:get_tag_cdata(Elem), RsmIn#rsm_in{direction = before, id = UID}; rsm_parse_element(#xmlel{name = <<"after">>, attrs = []} = Elem, RsmIn) -> - UID = xml:get_tag_cdata(Elem), + UID = fxml:get_tag_cdata(Elem), RsmIn#rsm_in{direction = aft, id = UID}; rsm_parse_element(#xmlel{name = <<"index">>, attrs = []} = Elem, RsmIn) -> - IndexStr = xml:get_tag_cdata(Elem), + IndexStr = fxml:get_tag_cdata(Elem), {Index, _} = str:to_integer(IndexStr), RsmIn#rsm_in{index = Index}; rsm_parse_element(_, RsmIn) -> RsmIn. @@ -535,7 +535,7 @@ is_standalone_chat_state(#xmlel{name = <<"message">>} = El) -> <<"paused">>], Stripped = lists:foldl(fun(ChatState, AccEl) -> - xml:remove_subtags(AccEl, ChatState, + fxml:remove_subtags(AccEl, ChatState, {<<"xmlns">>, ?NS_CHATSTATES}) end, El, ChatStates), case Stripped of @@ -558,15 +558,15 @@ add_delay_info(El, From, Time) -> binary()) -> xmlel(). add_delay_info(El, From, Time, Desc) -> - case xml:get_subtag_with_xmlns(El, <<"delay">>, ?NS_DELAY) of + case fxml:get_subtag_with_xmlns(El, <<"delay">>, ?NS_DELAY) of false -> %% Add new tag DelayTag = create_delay_tag(Time, From, Desc), - xml:append_subtags(El, [DelayTag]); + fxml:append_subtags(El, [DelayTag]); DelayTag -> %% Update existing tag NewDelayTag = - case {xml:get_tag_cdata(DelayTag), Desc} of + case {fxml:get_tag_cdata(DelayTag), Desc} of {<<"">>, <<"">>} -> DelayTag; {OldDesc, <<"">>} -> @@ -582,8 +582,8 @@ add_delay_info(El, From, Time, Desc) -> DelayTag#xmlel{children = [{xmlcdata, OldDesc}]} end end, - NewEl = xml:remove_subtags(El, <<"delay">>, {<<"xmlns">>, ?NS_DELAY}), - xml:append_subtags(NewEl, [NewDelayTag]) + NewEl = fxml:remove_subtags(El, <<"delay">>, {<<"xmlns">>, ?NS_DELAY}), + fxml:append_subtags(NewEl, [NewDelayTag]) end. -spec create_delay_tag(erlang:timestamp(), jid() | ljid() | binary(), binary()) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index dae775e4712..dc6595615e1 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -912,7 +912,7 @@ get_vcard_content(User, Server, Data) -> [_|_] -> case get_vcard(Data, A1) of [false] -> throw(error_no_value_found_in_vcard); - ElemList -> ?DEBUG("ELS ~p", [ElemList]), [xml:get_tag_cdata(Elem) || Elem <- ElemList] + ElemList -> ?DEBUG("ELS ~p", [ElemList]), [fxml:get_tag_cdata(Elem) || Elem <- ElemList] end; [] -> throw(error_no_vcard_found) @@ -933,7 +933,7 @@ get_vcard([Data], A1) -> get_subtag(A1, Data). get_subtag(Xmlelement, Name) -> - [xml:get_subtag(Xmlelement, Name)]. + [fxml:get_subtag(Xmlelement, Name)]. set_vcard_content(User, Server, Data, SomeContent) -> ContentList = case SomeContent of @@ -963,7 +963,7 @@ set_vcard_content(User, Server, Data, SomeContent) -> take_vcard_tel(TelType, [{xmlel, <<"TEL">>, _, SubEls}=OldEl | OldEls], NewEls, Taken) -> {Taken2, NewEls2} = case lists:keymember(TelType, 2, SubEls) of - true -> {xml:get_subtag(OldEl, <<"NUMBER">>), NewEls}; + true -> {fxml:get_subtag(OldEl, <<"NUMBER">>), NewEls}; false -> {Taken, [OldEl | NewEls]} end, take_vcard_tel(TelType, OldEls, NewEls2, Taken2); @@ -1206,10 +1206,10 @@ private_get(Username, Host, Element, Ns) -> [{xmlel, <<"query">>, [{<<"xmlns">>, ?NS_PRIVATE}], [SubEl]}] = ResIq#iq.sub_el, - binary_to_list(xml:element_to_binary(SubEl)). + binary_to_list(fxml:element_to_binary(SubEl)). private_set(Username, Host, ElementString) -> - case xml_stream:parse_element(ElementString) of + case fxml_stream:parse_element(ElementString) of {error, Error} -> io:format("Error found parsing the element:~n ~p~nError: ~p~n", [ElementString, Error]), @@ -1333,7 +1333,7 @@ build_packet(Type, Subject, Body) -> }. send_stanza(FromString, ToString, Stanza) -> - case xml_stream:parse_element(Stanza) of + case fxml_stream:parse_element(Stanza) of {error, Error} -> {error, Error}; XmlEl -> @@ -1344,7 +1344,7 @@ send_stanza(FromString, ToString, Stanza) -> end. send_stanza_c2s(Username, Host, Resource, Stanza) -> - case {xml_stream:parse_element(Stanza), + case {fxml_stream:parse_element(Stanza), ejabberd_sm:get_session_pid(Username, Host, Resource)} of {{error, Error}, _} -> @@ -1358,7 +1358,7 @@ send_stanza_c2s(Username, Host, Resource, Stanza) -> privacy_set(Username, Host, QueryS) -> From = jid:make(Username, Host, <<"">>), To = jid:make(<<"">>, Host, <<"">>), - QueryEl = xml_stream:parse_element(QueryS), + QueryEl = fxml_stream:parse_element(QueryS), StanzaEl = {xmlel, <<"iq">>, [{<<"type">>, <<"set">>}], [QueryEl]}, IQ = jlib:iq_query_info(StanzaEl), ejabberd_hooks:run_fold( diff --git a/src/mod_announce.erl b/src/mod_announce.erl index 3d0924a6d08..d30cf57f244 100644 --- a/src/mod_announce.erl +++ b/src/mod_announce.erl @@ -845,7 +845,7 @@ announce_motd_update(LServer, Packet) -> packet = Packet}, motd_schema())}; odbc -> - XML = ejabberd_odbc:escape(xml:element_to_binary(Packet)), + XML = ejabberd_odbc:escape(fxml:element_to_binary(Packet)), F = fun() -> odbc_queries:update_t( <<"motd">>, @@ -953,7 +953,7 @@ send_motd(#jid{luser = LUser, lserver = LServer} = JID, odbc) when LUser /= <<>> case catch ejabberd_odbc:sql_query( LServer, [<<"select xml from motd where username='';">>]) of {selected, [<<"xml">>], [[XML]]} -> - case xml_stream:parse_element(XML) of + case fxml_stream:parse_element(XML) of {error, _} -> ok; Packet -> @@ -986,8 +986,8 @@ send_motd(_, odbc) -> get_stored_motd(LServer) -> case get_stored_motd_packet(LServer, gen_mod:db_type(LServer, ?MODULE)) of {ok, Packet} -> - {xml:get_subtag_cdata(Packet, <<"subject">>), - xml:get_subtag_cdata(Packet, <<"body">>)}; + {fxml:get_subtag_cdata(Packet, <<"subject">>), + fxml:get_subtag_cdata(Packet, <<"body">>)}; error -> {<<>>, <<>>} end. @@ -1010,7 +1010,7 @@ get_stored_motd_packet(LServer, odbc) -> case catch ejabberd_odbc:sql_query( LServer, [<<"select xml from motd where username='';">>]) of {selected, [<<"xml">>], [[XML]]} -> - case xml_stream:parse_element(XML) of + case fxml_stream:parse_element(XML) of {error, _} -> error; Packet -> @@ -1067,7 +1067,7 @@ update_motd_table() -> fun(#motd{server = S}) -> S end, fun(#motd{server = S, packet = P} = R) -> NewS = iolist_to_binary(S), - NewP = xml:to_xmlel(P), + NewP = fxml:to_xmlel(P), R#motd{server = NewS, packet = NewP} end); _ -> @@ -1105,7 +1105,7 @@ export(_Server) -> when LServer == Host -> [[<<"delete from motd where username='';">>], [<<"insert into motd(username, xml) values ('', '">>, - ejabberd_odbc:escape(xml:element_to_binary(El)), + ejabberd_odbc:escape(fxml:element_to_binary(El)), <<"');">>]]; (_Host, _R) -> [] @@ -1124,7 +1124,7 @@ export(_Server) -> import(LServer) -> [{<<"select xml from motd where username='';">>, fun([XML]) -> - El = xml_stream:parse_element(XML), + El = fxml_stream:parse_element(XML), #motd{server = LServer, packet = El} end}, {<<"select username from motd where xml='';">>, diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 4f9c82734d0..981c5735f92 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -76,7 +76,7 @@ process_iq_set(_, From, _To, sub_el = #xmlel{name = SubElName, children = SubEls}}) -> #jid{luser = LUser, lserver = LServer} = From, - Res = case {SubElName, xml:remove_cdata(SubEls)} of + Res = case {SubElName, fxml:remove_cdata(SubEls)} of {<<"block">>, []} -> {error, ?ERR_BAD_REQUEST}; {<<"block">>, Els} -> JIDs = parse_blocklist_items(Els, []), @@ -116,7 +116,7 @@ parse_blocklist_items([#xmlel{name = <<"item">>, attrs = Attrs} | Els], JIDs) -> - case xml:get_attr(<<"jid">>, Attrs) of + case fxml:get_attr(<<"jid">>, Attrs) of {value, JID1} -> JID = jid:tolower(jid:from_string(JID1)), parse_blocklist_items(Els, [JID | JIDs]); diff --git a/src/mod_caps.erl b/src/mod_caps.erl index 7d764c4bf5b..0646d381241 100644 --- a/src/mod_caps.erl +++ b/src/mod_caps.erl @@ -120,12 +120,12 @@ read_caps(Els) -> read_caps(Els, nothing). read_caps([#xmlel{name = <<"c">>, attrs = Attrs} | Tail], Result) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_CAPS -> - Node = xml:get_attr_s(<<"node">>, Attrs), - Version = xml:get_attr_s(<<"ver">>, Attrs), - Hash = xml:get_attr_s(<<"hash">>, Attrs), - Exts = str:tokens(xml:get_attr_s(<<"ext">>, Attrs), + Node = fxml:get_attr_s(<<"node">>, Attrs), + Version = fxml:get_attr_s(<<"ver">>, Attrs), + Hash = fxml:get_attr_s(<<"hash">>, Attrs), + Exts = str:tokens(fxml:get_attr_s(<<"ext">>, Attrs), <<" ">>), read_caps(Tail, #caps{node = Node, hash = Hash, version = Version, @@ -135,7 +135,7 @@ read_caps([#xmlel{name = <<"c">>, attrs = Attrs} read_caps([#xmlel{name = <<"x">>, attrs = Attrs} | Tail], Result) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC_USER -> nothing; _ -> read_caps(Tail, Result) end; @@ -149,7 +149,7 @@ user_send_packet(#xmlel{name = <<"presence">>, attrs = Attrs, #jid{luser = User, lserver = Server} = From, #jid{luser = User, lserver = Server, lresource = <<"">>}) -> - Type = xml:get_attr_s(<<"type">>, Attrs), + Type = fxml:get_attr_s(<<"type">>, Attrs), if Type == <<"">>; Type == <<"available">> -> case read_caps(Els) of nothing -> ok; @@ -167,7 +167,7 @@ user_receive_packet(#xmlel{name = <<"presence">>, attrs = Attrs, _C2SState, #jid{lserver = Server}, From, _To) -> - Type = xml:get_attr_s(<<"type">>, Attrs), + Type = fxml:get_attr_s(<<"type">>, Attrs), IsRemote = not lists:member(From#jid.lserver, ?MYHOSTS), if IsRemote and ((Type == <<"">>) or (Type == <<"available">>)) -> @@ -227,7 +227,7 @@ disco_info(Acc, Host, Module, Node, Lang) -> c2s_presence_in(C2SState, {From, To, {_, _, Attrs, Els}}) -> - Type = xml:get_attr_s(<<"type">>, Attrs), + Type = fxml:get_attr_s(<<"type">>, Attrs), Subscription = ejabberd_c2s:get_subscription(From, C2SState), Insert = ((Type == <<"">>) or (Type == <<"available">>)) @@ -434,7 +434,7 @@ feature_response(#iq{type = result, Features = lists:flatmap(fun (#xmlel{name = <<"feature">>, attrs = FAttrs}) -> - [xml:get_attr_s(<<"var">>, FAttrs)]; + [fxml:get_attr_s(<<"var">>, FAttrs)]; (_) -> [] end, Els), @@ -567,7 +567,7 @@ concat_features(Els) -> lists:usort(lists:flatmap(fun (#xmlel{name = <<"feature">>, attrs = Attrs}) -> - [[xml:get_attr_s(<<"var">>, Attrs), $<]]; + [[fxml:get_attr_s(<<"var">>, Attrs), $<]]; (_) -> [] end, Els)). @@ -576,11 +576,11 @@ concat_identities(Els) -> lists:sort(lists:flatmap(fun (#xmlel{name = <<"identity">>, attrs = Attrs}) -> - [[xml:get_attr_s(<<"category">>, Attrs), - $/, xml:get_attr_s(<<"type">>, Attrs), + [[fxml:get_attr_s(<<"category">>, Attrs), + $/, fxml:get_attr_s(<<"type">>, Attrs), $/, - xml:get_attr_s(<<"xml:lang">>, Attrs), - $/, xml:get_attr_s(<<"name">>, Attrs), + fxml:get_attr_s(<<"xml:lang">>, Attrs), + $/, fxml:get_attr_s(<<"name">>, Attrs), $<]]; (_) -> [] end, @@ -589,8 +589,8 @@ concat_identities(Els) -> concat_info(Els) -> lists:sort(lists:flatmap(fun (#xmlel{name = <<"x">>, attrs = Attrs, children = Fields}) -> - case {xml:get_attr_s(<<"xmlns">>, Attrs), - xml:get_attr_s(<<"type">>, Attrs)} + case {fxml:get_attr_s(<<"xmlns">>, Attrs), + fxml:get_attr_s(<<"type">>, Attrs)} of {?NS_XDATA, <<"result">>} -> [concat_xdata_fields(Fields)]; @@ -606,10 +606,10 @@ concat_xdata_fields(Fields) -> attrs = Attrs, children = Els} = El, [FormType, VarFields] = Acc) -> - case xml:get_attr_s(<<"var">>, Attrs) of + case fxml:get_attr_s(<<"var">>, Attrs) of <<"">> -> Acc; <<"FORM_TYPE">> -> - [xml:get_subtag_cdata(El, + [fxml:get_subtag_cdata(El, <<"value">>), VarFields]; Var -> @@ -622,7 +622,7 @@ concat_xdata_fields(Fields) -> children = VEls}) -> - [[xml:get_cdata(VEls), + [[fxml:get_cdata(VEls), $<]]; (_) -> [] diff --git a/src/mod_carboncopy.erl b/src/mod_carboncopy.erl index a4ca45ddfb6..81cf78a9d98 100644 --- a/src/mod_carboncopy.erl +++ b/src/mod_carboncopy.erl @@ -55,9 +55,9 @@ is_carbon_copy(Packet) -> is_carbon_copy(Packet, <<"received">>). is_carbon_copy(Packet, Direction) -> - case xml:get_subtag(Packet, Direction) of + case fxml:get_subtag(Packet, Direction) of #xmlel{name = Direction, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_CARBONS_2 -> true; ?NS_CARBONS_1 -> true; _ -> false @@ -137,8 +137,8 @@ user_receive_packet(Packet, _C2SState, JID, _From, To) -> % - we also replicate "read" notifications check_and_forward(JID, To, Packet, Direction)-> case is_chat_message(Packet) andalso - xml:get_subtag(Packet, <<"private">>) == false andalso - xml:get_subtag(Packet, <<"no-copy">>) == false of + fxml:get_subtag(Packet, <<"private">>) == false andalso + fxml:get_subtag(Packet, <<"no-copy">>) == false of true -> case is_carbon_copy(Packet) of false -> @@ -268,7 +268,7 @@ complete_packet(_From, #xmlel{name = <<"message">>, attrs=OrigAttrs} = Packet, r Packet#xmlel{attrs = Attrs}. message_type(#xmlel{attrs = Attrs}) -> - case xml:get_attr(<<"type">>, Attrs) of + case fxml:get_attr(<<"type">>, Attrs) of {value, Type} -> Type; false -> <<"normal">> end. @@ -282,7 +282,7 @@ is_chat_message(#xmlel{name = <<"message">>} = Packet) -> is_chat_message(_Packet) -> false. has_non_empty_body(Packet) -> - xml:get_subtag_cdata(Packet, <<"body">>) =/= <<"">>. + fxml:get_subtag_cdata(Packet, <<"body">>) =/= <<"">>. %% list {resource, cc_version} with carbons enabled for given user and host list(User, Server) -> diff --git a/src/mod_client_state.erl b/src/mod_client_state.erl index 3c046d77621..dfbfc028e40 100644 --- a/src/mod_client_state.erl +++ b/src/mod_client_state.erl @@ -80,7 +80,7 @@ add_stream_feature(Features, _Host) -> [Feature | Features]. filter_presence(_Action, #xmlel{name = <<"presence">>, attrs = Attrs}) -> - case xml:get_attr(<<"type">>, Attrs) of + case fxml:get_attr(<<"type">>, Attrs) of {value, Type} when Type /= <<"unavailable">> -> ?DEBUG("Got important presence stanza", []), {stop, send}; diff --git a/src/mod_configure.erl b/src/mod_configure.erl index 0c7e752687a..5e011704779 100644 --- a/src/mod_configure.erl +++ b/src/mod_configure.erl @@ -350,7 +350,7 @@ adhoc_local_items(Acc, From, Nodes = recursively_get_local_items(PermLev, LServer, <<"">>, Server, Lang), Nodes1 = lists:filter(fun (N) -> - Nd = xml:get_tag_attr_s(<<"node">>, N), + Nd = fxml:get_tag_attr_s(<<"node">>, N), F = get_local_features([], From, To, Nd, Lang), case F of @@ -379,9 +379,9 @@ recursively_get_local_items(PermLev, LServer, Node, {error, _Error} -> [] end, Nodes = lists:flatten(lists:map(fun (N) -> - S = xml:get_tag_attr_s(<<"jid">>, + S = fxml:get_tag_attr_s(<<"jid">>, N), - Nd = xml:get_tag_attr_s(<<"node">>, + Nd = fxml:get_tag_attr_s(<<"node">>, N), if (S /= Server) or (Nd == <<"">>) -> diff --git a/src/mod_configure2.erl b/src/mod_configure2.erl index 3e00a9cf73d..0acd4a78c61 100644 --- a/src/mod_configure2.erl +++ b/src/mod_configure2.erl @@ -65,7 +65,7 @@ process_local_iq(From, To, set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}; - %%case xml:get_tag_attr_s("type", SubEl) of + %%case fxml:get_tag_attr_s("type", SubEl) of %% "cancel" -> %% IQ#iq{type = result, %% sub_el = [{xmlelement, "query", @@ -79,7 +79,7 @@ process_local_iq(From, To, %% _ -> %% Node = %% string:tokens( - %% xml:get_tag_attr_s("node", SubEl), + %% fxml:get_tag_attr_s("node", SubEl), %% "/"), %% case set_form(Node, Lang, XData) of %% {result, Res} -> diff --git a/src/mod_disco.erl b/src/mod_disco.erl index 6e0b9c929c5..fc3397e17e6 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -152,7 +152,7 @@ process_local_iq_items(From, To, set -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), Host = To#jid.lserver, case ejabberd_hooks:run_fold(disco_local_items, Host, empty, [From, To, Node, Lang]) @@ -180,7 +180,7 @@ process_local_iq_info(From, To, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> Host = To#jid.lserver, - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), Identity = ejabberd_hooks:run_fold(disco_local_identity, Host, [], [From, To, Node, Lang]), Info = ejabberd_hooks:run_fold(disco_info, Host, [], @@ -305,7 +305,7 @@ process_sm_iq_items(From, To, case is_presence_subscribed(From, To) of true -> Host = To#jid.lserver, - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), case ejabberd_hooks:run_fold(disco_sm_items, Host, empty, [From, To, Node, Lang]) of @@ -378,7 +378,7 @@ process_sm_iq_info(From, To, case is_presence_subscribed(From, To) of true -> Host = To#jid.lserver, - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), Identity = ejabberd_hooks:run_fold(disco_sm_identity, Host, [], [From, To, Node, Lang]), diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 3f91f1d036d..8e7394cb489 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -182,7 +182,7 @@ do_client_version(enabled, From, To) -> Els = receive {route, To, From2, IQ} -> #xmlel{name = <<"query">>, children = List} = - xml:get_subtag(IQ, <<"query">>), + fxml:get_subtag(IQ, <<"query">>), List after 5000 -> % Timeout in miliseconds: 5 seconds [] diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 36d3626be51..5d21b497089 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -572,12 +572,12 @@ process_iq(_From, invalid, _State) -> -> {ok, binary(), pos_integer(), binary()} | {error, xmlel()}. parse_request(#xmlel{name = <<"request">>, attrs = Attrs} = Request, Lang) -> - case xml:get_attr(<<"xmlns">>, Attrs) of + case fxml:get_attr(<<"xmlns">>, Attrs) of {value, XMLNS} when XMLNS == ?NS_HTTP_UPLOAD; XMLNS == ?NS_HTTP_UPLOAD_OLD -> - case {xml:get_subtag_cdata(Request, <<"filename">>), - xml:get_subtag_cdata(Request, <<"size">>), - xml:get_subtag_cdata(Request, <<"content-type">>)} of + case {fxml:get_subtag_cdata(Request, <<"filename">>), + fxml:get_subtag_cdata(Request, <<"size">>), + fxml:get_subtag_cdata(Request, <<"content-type">>)} of {File, SizeStr, ContentType} when byte_size(File) > 0 -> case catch jlib:binary_to_integer(SizeStr) of Size when is_integer(Size), Size > 0 -> @@ -796,7 +796,7 @@ store_file(Path, Data, FileMode, DirMode, GetPrefix, Slot, Thumbnail) -> {ok, [{<<"Content-Type">>, <<"text/xml; charset=utf-8">>}], - xml:element_to_binary(ThumbEl)}; + fxml:element_to_binary(ThumbEl)}; pass -> ok end; diff --git a/src/mod_irc.erl b/src/mod_irc.erl index 25b3245de03..b7300e28b36 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -216,7 +216,7 @@ do_route(Host, ServerHost, Access, From, To, Packet) -> allow -> do_route1(Host, ServerHost, From, To, Packet); _ -> #xmlel{attrs = Attrs} = Packet, - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Access denied by service policy">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), @@ -234,7 +234,7 @@ do_route1(Host, ServerHost, From, To, Packet) -> #iq{type = get, xmlns = (?NS_DISCO_INFO) = XMLNS, sub_el = SubEl, lang = Lang} = IQ -> - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), Info = ejabberd_hooks:run_fold(disco_info, ServerHost, [], [ServerHost, ?MODULE, @@ -262,7 +262,7 @@ do_route1(Host, ServerHost, From, To, Packet) -> #iq{type = get, xmlns = (?NS_DISCO_ITEMS) = XMLNS, sub_el = SubEl, lang = Lang} = IQ -> - Node = xml:get_tag_attr_s(<<"node">>, SubEl), + Node = fxml:get_tag_attr_s(<<"node">>, SubEl), case Node of <<>> -> ResIQ = IQ#iq{type = result, @@ -516,7 +516,7 @@ find_xdata_el1([]) -> false; find_xdata_el1([#xmlel{name = Name, attrs = Attrs, children = SubEls} | Els]) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> #xmlel{name = Name, attrs = Attrs, children = SubEls}; _ -> find_xdata_el1(Els) @@ -535,7 +535,7 @@ process_irc_register(ServerHost, Host, From, _To, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ACCEPTABLE]}; #xmlel{attrs = Attrs} -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"cancel">> -> IQ#iq{type = result, sub_el = @@ -549,7 +549,7 @@ process_irc_register(ServerHost, Host, From, _To, IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}; _ -> - Node = str:tokens(xml:get_tag_attr_s(<<"node">>, + Node = str:tokens(fxml:get_tag_attr_s(<<"node">>, SubEl), <<"/">>), case set_form(ServerHost, Host, From, Node, Lang, @@ -571,7 +571,7 @@ process_irc_register(ServerHost, Host, From, _To, end end; get -> - Node = str:tokens(xml:get_tag_attr_s(<<"node">>, SubEl), + Node = str:tokens(fxml:get_tag_attr_s(<<"node">>, SubEl), <<"/">>), case get_form(ServerHost, Host, From, Node, Lang) of {result, Res} -> @@ -1368,7 +1368,7 @@ mod_opt_type(_) -> [access, db_type, default_encoding, host]. extract_ident(Packet) -> - case xml:get_subtag(Packet, <<"headers">>) of + case fxml:get_subtag(Packet, <<"headers">>) of {xmlel, _Name, _Attrs, Headers} -> extract_header(<<"X-Irc-Ident">>, Headers); _ -> @@ -1376,7 +1376,7 @@ extract_ident(Packet) -> end. extract_ip_address(Packet) -> - case xml:get_subtag(Packet, <<"headers">>) of + case fxml:get_subtag(Packet, <<"headers">>) of {xmlel, _Name, _Attrs, Headers} -> extract_header(<<"X-Forwarded-For">>, Headers); _ -> @@ -1384,7 +1384,7 @@ extract_ip_address(Packet) -> end. extract_header(HeaderName, [{xmlel, _Name, _Attrs, [{xmlcdata, Value}]} | Tail]) -> - case xml:get_attr(<<"name">>, _Attrs) of + case fxml:get_attr(<<"name">>, _Attrs) of {value, HeaderName} -> binary_to_list(Value); _ -> diff --git a/src/mod_irc_connection.erl b/src/mod_irc_connection.erl index ae709dc27b5..098c8c28617 100644 --- a/src/mod_irc_connection.erl +++ b/src/mod_irc_connection.erl @@ -233,7 +233,7 @@ get_password_from_presence(#xmlel{name = <<"presence">>, case lists:filter(fun (El) -> case El of #xmlel{name = <<"x">>, attrs = Attrs} -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC -> true; _ -> false end; @@ -243,9 +243,9 @@ get_password_from_presence(#xmlel{name = <<"presence">>, Els) of [ElXMUC | _] -> - case xml:get_subtag(ElXMUC, <<"password">>) of + case fxml:get_subtag(ElXMUC, <<"password">>) of #xmlel{name = <<"password">>} = PasswordTag -> - {true, xml:get_tag_cdata(PasswordTag)}; + {true, fxml:get_tag_cdata(PasswordTag)}; _ -> false end; _ -> false @@ -261,7 +261,7 @@ handle_info({route_chan, Channel, Resource, #xmlel{name = <<"presence">>, attrs = Attrs} = Presence}, StateName, StateData) -> - NewStateData = case xml:get_attr_s(<<"type">>, Attrs) of + NewStateData = case fxml:get_attr_s(<<"type">>, Attrs) of <<"unavailable">> -> send_stanza_unavailable(Channel, StateData), S1 = (?SEND((io_lib:format("PART #~s\r\n", @@ -312,9 +312,9 @@ handle_info({route_chan, Channel, Resource, handle_info({route_chan, Channel, Resource, #xmlel{name = <<"message">>, attrs = Attrs} = El}, StateName, StateData) -> - NewStateData = case xml:get_attr_s(<<"type">>, Attrs) of + NewStateData = case fxml:get_attr_s(<<"type">>, Attrs) of <<"groupchat">> -> - case xml:get_path_s(El, [{elem, <<"subject">>}, cdata]) + case fxml:get_path_s(El, [{elem, <<"subject">>}, cdata]) of <<"">> -> ejabberd_router:route( @@ -325,7 +325,7 @@ handle_info({route_chan, Channel, Resource, StateData#state.host, StateData#state.nick), StateData#state.user, El), - Body = xml:get_path_s(El, + Body = fxml:get_path_s(El, [{elem, <<"body">>}, cdata]), case Body of @@ -386,7 +386,7 @@ handle_info({route_chan, Channel, Resource, when Type == <<"chat">>; Type == <<"">>; Type == <<"normal">> -> - Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]), + Body = fxml:get_path_s(El, [{elem, <<"body">>}, cdata]), case Body of <<"/quote ", Rest/binary>> -> ?SEND(<>); @@ -481,9 +481,9 @@ handle_info({route_chan, _Channel, _Resource, _Packet}, handle_info({route_nick, Nick, #xmlel{name = <<"message">>, attrs = Attrs} = El}, StateName, StateData) -> - NewStateData = case xml:get_attr_s(<<"type">>, Attrs) of + NewStateData = case fxml:get_attr_s(<<"type">>, Attrs) of <<"chat">> -> - Body = xml:get_path_s(El, [{elem, <<"body">>}, cdata]), + Body = fxml:get_path_s(El, [{elem, <<"body">>}, cdata]), case Body of <<"/quote ", Rest/binary>> -> ?SEND(<>); @@ -778,13 +778,13 @@ bounce_messages(Reason) -> receive {send_element, El} -> #xmlel{attrs = Attrs} = El, - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; _ -> Err = jlib:make_error_reply(El, <<"502">>, Reason), - From = jid:from_string(xml:get_attr_s(<<"from">>, + From = jid:from_string(fxml:get_attr_s(<<"from">>, Attrs)), - To = jid:from_string(xml:get_attr_s(<<"to">>, + To = jid:from_string(fxml:get_attr_s(<<"to">>, Attrs)), ejabberd_router:route(To, From, Err) end, @@ -1535,14 +1535,14 @@ iq_admin(StateData, Channel, From, To, end. process_iq_admin(StateData, Channel, set, SubEl) -> - case xml:get_subtag(SubEl, <<"item">>) of + case fxml:get_subtag(SubEl, <<"item">>) of false -> {error, ?ERR_BAD_REQUEST}; ItemEl -> - Nick = xml:get_tag_attr_s(<<"nick">>, ItemEl), - Affiliation = xml:get_tag_attr_s(<<"affiliation">>, + Nick = fxml:get_tag_attr_s(<<"nick">>, ItemEl), + Affiliation = fxml:get_tag_attr_s(<<"affiliation">>, ItemEl), - Role = xml:get_tag_attr_s(<<"role">>, ItemEl), - Reason = xml:get_path_s(ItemEl, + Role = fxml:get_tag_attr_s(<<"role">>, ItemEl), + Reason = fxml:get_path_s(ItemEl, [{elem, <<"reason">>}, cdata]), process_admin(StateData, Channel, Nick, Affiliation, Role, Reason) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index d6e4e93685e..62f333555b2 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -287,7 +287,7 @@ muc_process_iq(#iq{type = set, sub_el = #xmlel{name = <<"query">>, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of NS when NS == ?NS_MAM_0; NS == ?NS_MAM_1 -> muc_process_iq(IQ, MUCState, From, To, get_xdata_fields(SubEl)); _ -> @@ -297,7 +297,7 @@ muc_process_iq(#iq{type = get, sub_el = #xmlel{name = <<"query">>, attrs = Attrs} = SubEl} = IQ, MUCState, From, To) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MAM_TMP -> muc_process_iq(IQ, MUCState, From, To, parse_query_v0_2(SubEl)); NS when NS == ?NS_MAM_0; NS == ?NS_MAM_1 -> @@ -310,8 +310,8 @@ muc_process_iq(IQ, _MUCState, _From, _To) -> IQ. get_xdata_fields(SubEl) -> - case {xml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), - xml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of + case {fxml:get_subtag_with_xmlns(SubEl, <<"x">>, ?NS_XDATA), + fxml:get_subtag_with_xmlns(SubEl, <<"set">>, ?NS_RSM)} of {#xmlel{} = XData, false} -> jlib:parse_xdata_submit(XData); {#xmlel{} = XData, #xmlel{}} -> @@ -407,7 +407,7 @@ delete_old_messages(_TimeStamp, _Type, _Host, _DBType) -> %%%=================================================================== process_iq(LServer, #iq{sub_el = #xmlel{attrs = Attrs}} = IQ) -> - NS = case xml:get_attr_s(<<"xmlns">>, Attrs) of + NS = case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MAM_0 -> ?NS_MAM_0; _ -> @@ -448,7 +448,7 @@ process_iq(LServer, #iq{sub_el = #xmlel{attrs = Attrs}} = IQ) -> process_iq(#jid{luser = LUser, lserver = LServer}, #jid{lserver = LServer}, #iq{type = set, sub_el = #xmlel{name = <<"prefs">>} = SubEl} = IQ) -> - try {case xml:get_tag_attr_s(<<"default">>, SubEl) of + try {case fxml:get_tag_attr_s(<<"default">>, SubEl) of <<"always">> -> always; <<"never">> -> never; <<"roster">> -> roster @@ -524,7 +524,7 @@ process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) -> {_Start, _End, _With, #rsm_in{index = Index}} when is_integer(Index) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_FEATURE_NOT_IMPLEMENTED]}; {Start, End, With, RSM} -> - NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), + NS = fxml:get_tag_attr_s(<<"xmlns">>, SubEl), select_and_send(LServer, From, To, Start, End, With, limit_max(RSM, NS), IQ, MsgType) end. @@ -548,13 +548,13 @@ muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ, parse_query_v0_2(Query) -> lists:flatmap( fun (#xmlel{name = <<"start">>} = El) -> - [{<<"start">>, [xml:get_tag_cdata(El)]}]; + [{<<"start">>, [fxml:get_tag_cdata(El)]}]; (#xmlel{name = <<"end">>} = El) -> - [{<<"end">>, [xml:get_tag_cdata(El)]}]; + [{<<"end">>, [fxml:get_tag_cdata(El)]}]; (#xmlel{name = <<"with">>} = El) -> - [{<<"with">>, [xml:get_tag_cdata(El)]}]; + [{<<"with">>, [fxml:get_tag_cdata(El)]}]; (#xmlel{name = <<"withtext">>} = El) -> - [{<<"withtext">>, [xml:get_tag_cdata(El)]}]; + [{<<"withtext">>, [fxml:get_tag_cdata(El)]}]; (#xmlel{name = <<"set">>}) -> [{<<"set">>, Query}]; (_) -> @@ -562,7 +562,7 @@ parse_query_v0_2(Query) -> end, Query#xmlel.children). should_archive(#xmlel{name = <<"message">>} = Pkt, LServer) -> - case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of + case fxml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of <<"error">> -> false; <<"groupchat">> -> @@ -578,7 +578,7 @@ should_archive(#xmlel{name = <<"message">>} = Pkt, LServer) -> no_store -> false; none -> - case xml:get_subtag_cdata(Pkt, <<"body">>) of + case fxml:get_subtag_cdata(Pkt, <<"body">>) of <<>> -> %% Empty body false; @@ -596,7 +596,7 @@ strip_my_archived_tag(Pkt, LServer) -> fun(#xmlel{name = Tag, attrs = Attrs}) when Tag == <<"archived">>; Tag == <<"stanza-id">> -> case catch jid:nameprep( - xml:get_attr_s( + fxml:get_attr_s( <<"by">>, Attrs)) of LServer -> false; @@ -612,9 +612,9 @@ strip_x_jid_tags(Pkt) -> NewEls = lists:filter( fun(#xmlel{name = <<"x">>} = XEl) -> not lists:any(fun(ItemEl) -> - xml:get_tag_attr(<<"jid">>, ItemEl) + fxml:get_tag_attr(<<"jid">>, ItemEl) /= false - end, xml:get_subtags(XEl, <<"item">>)); + end, fxml:get_subtags(XEl, <<"item">>)); (_) -> true end, Pkt#xmlel.children), @@ -650,7 +650,7 @@ should_archive_peer(C2SState, end. should_archive_muc(Pkt) -> - case xml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of + case fxml:get_attr_s(<<"type">>, Pkt#xmlel.attrs) of <<"groupchat">> -> case check_store_hint(Pkt) of store -> @@ -658,9 +658,9 @@ should_archive_muc(Pkt) -> no_store -> false; none -> - case xml:get_subtag_cdata(Pkt, <<"body">>) of + case fxml:get_subtag_cdata(Pkt, <<"body">>) of <<>> -> - case xml:get_subtag_cdata(Pkt, <<"subject">>) of + case fxml:get_subtag_cdata(Pkt, <<"subject">>) of <<>> -> false; _ -> @@ -688,23 +688,23 @@ check_store_hint(Pkt) -> end. has_store_hint(Message) -> - xml:get_subtag_with_xmlns(Message, <<"store">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Message, <<"store">>, ?NS_HINTS) /= false. has_no_store_hint(Message) -> - xml:get_subtag_with_xmlns(Message, <<"no-store">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Message, <<"no-store">>, ?NS_HINTS) /= false orelse - xml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Message, <<"no-storage">>, ?NS_HINTS) /= false orelse - xml:get_subtag_with_xmlns(Message, <<"no-permanent-store">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Message, <<"no-permanent-store">>, ?NS_HINTS) /= false orelse - xml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Message, <<"no-permanent-storage">>, ?NS_HINTS) /= false. is_resent(Pkt, LServer) -> - case xml:get_subtag_with_xmlns(Pkt, <<"stanza-id">>, ?NS_SID_0) of + case fxml:get_subtag_with_xmlns(Pkt, <<"stanza-id">>, ?NS_SID_0) of #xmlel{attrs = Attrs} -> - case xml:get_attr(<<"by">>, Attrs) of + case fxml:get_attr(<<"by">>, Attrs) of {value, LServer} -> true; _ -> @@ -766,8 +766,8 @@ store(Pkt, LServer, {LUser, LHost}, Type, Peer, Nick, _Dir, odbc) -> jid:remove_resource(Peer))), LPeer = jid:to_string( jid:tolower(Peer)), - XML = xml:element_to_binary(Pkt), - Body = xml:get_subtag_cdata(Pkt, <<"body">>), + XML = fxml:element_to_binary(Pkt), + Body = fxml:get_subtag_cdata(Pkt, <<"body">>), case ejabberd_odbc:sql_query( LServer, [<<"insert into archive (username, timestamp, " @@ -1005,7 +1005,7 @@ select(LServer, #jid{luser = LUser} = JidRequestor, {lists:flatmap( fun([TS, XML, PeerBin, Kind, Nick]) -> try - #xmlel{} = El = xml_stream:parse_element(XML), + #xmlel{} = El = fxml_stream:parse_element(XML), Now = usec_to_now(jlib:binary_to_integer(TS)), PeerJid = jid:tolower(jid:from_string(PeerBin)), T = case Kind of @@ -1039,7 +1039,7 @@ msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, Peer, MsgType, Nick), Pkt3 = #xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}], - children = [xml:replace_tag_attr( + children = [fxml:replace_tag_attr( <<"xmlns">>, <<"jabber:client">>, Pkt2)]}, jlib:add_delay_info(Pkt3, LServer, TS). @@ -1095,8 +1095,8 @@ is_bare_copy(#jid{luser = U, lserver = S, lresource = R}, To) -> end. send(From, To, Msgs, RSM, Count, IsComplete, #iq{sub_el = SubEl} = IQ) -> - QID = xml:get_tag_attr_s(<<"queryid">>, SubEl), - NS = xml:get_tag_attr_s(<<"xmlns">>, SubEl), + QID = fxml:get_tag_attr_s(<<"queryid">>, SubEl), + NS = fxml:get_tag_attr_s(<<"xmlns">>, SubEl), QIDAttr = if QID /= <<>> -> [{<<"queryid">>, QID}]; true -> @@ -1336,7 +1336,7 @@ datetime_to_now(DateTime, USecs) -> get_jids(Els) -> lists:flatmap( fun(#xmlel{name = <<"jid">>} = El) -> - J = jid:from_string(xml:get_tag_cdata(El)), + J = jid:from_string(fxml:get_tag_cdata(El)), [jid:tolower(jid:remove_resource(J)), jid:tolower(J)]; (_) -> diff --git a/src/mod_muc.erl b/src/mod_muc.erl index a64a0032657..f7c6d26de36 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -222,7 +222,7 @@ remove_room_mam(LServer, Host, Name) -> process_iq_disco_items(Host, From, To, #iq{lang = Lang} = IQ) -> Rsm = jlib:rsm_decode(IQ), - DiscoNode = xml:get_tag_attr_s(<<"node">>, IQ#iq.sub_el), + DiscoNode = fxml:get_tag_attr_s(<<"node">>, IQ#iq.sub_el), Res = IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, @@ -451,7 +451,7 @@ do_route(Host, ServerHost, Access, HistorySize, RoomShaper, From, To, Packet, DefRoomOpts); _ -> #xmlel{attrs = Attrs} = Packet, - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Access denied by service policy">>, Err = jlib:make_error_reply(Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), @@ -557,18 +557,18 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, _ -> ok end; <<"message">> -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; _ -> case acl:match_rule(ServerHost, AccessAdmin, From) of allow -> - Msg = xml:get_path_s(Packet, + Msg = fxml:get_path_s(Packet, [{elem, <<"body">>}, cdata]), broadcast_service_message(Host, Msg); _ -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Only service administrators are allowed " "to send service messages">>, @@ -581,7 +581,7 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, <<"presence">> -> ok end; _ -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; <<"result">> -> ok; _ -> @@ -593,7 +593,7 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, _ -> case mnesia:dirty_read(muc_online_room, {Room, Host}) of [] -> - Type = xml:get_attr_s(<<"type">>, Attrs), + Type = fxml:get_attr_s(<<"type">>, Attrs), case {Name, Type} of {<<"presence">>, <<"">>} -> case check_user_can_create_room(ServerHost, @@ -606,14 +606,14 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, mod_muc_room:route(Pid, From, Nick, Packet), ok; false -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Room creation is denied by service policy">>, Err = jlib:make_error_reply( Packet, ?ERRT_FORBIDDEN(Lang, ErrText)), ejabberd_router:route(To, From, Err) end; _ -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"Conference room does not exist">>, Err = jlib:make_error_reply(Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)), @@ -1056,12 +1056,12 @@ iq_set_register_info(ServerHost, Host, From, Nick, process_iq_register_set(ServerHost, Host, From, SubEl, Lang) -> #xmlel{children = Els} = SubEl, - case xml:get_subtag(SubEl, <<"remove">>) of + case fxml:get_subtag(SubEl, <<"remove">>) of false -> - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [#xmlel{name = <<"x">>} = XEl] -> - case {xml:get_tag_attr_s(<<"xmlns">>, XEl), - xml:get_tag_attr_s(<<"type">>, XEl)} + case {fxml:get_tag_attr_s(<<"xmlns">>, XEl), + fxml:get_tag_attr_s(<<"type">>, XEl)} of {?NS_XDATA, <<"cancel">>} -> {result, []}; {?NS_XDATA, <<"submit">>} -> diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl index 4d8e3965cbf..1f32f6f9b4a 100644 --- a/src/mod_muc_log.erl +++ b/src/mod_muc_log.erl @@ -193,15 +193,15 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}. add_to_log2(text, {Nick, Packet}, Room, Opts, State) -> case has_no_permanent_store_hint(Packet) of false -> - case {xml:get_subtag(Packet, <<"subject">>), - xml:get_subtag(Packet, <<"body">>)} + case {fxml:get_subtag(Packet, <<"subject">>), + fxml:get_subtag(Packet, <<"body">>)} of {false, false} -> ok; {false, SubEl} -> - Message = {body, xml:get_tag_cdata(SubEl)}, + Message = {body, fxml:get_tag_cdata(SubEl)}, add_message_to_log(Nick, Message, Room, Opts, State); {SubEl, _} -> - Message = {subject, xml:get_tag_cdata(SubEl)}, + Message = {subject, fxml:get_tag_cdata(SubEl)}, add_message_to_log(Nick, Message, Room, Opts, State) end; true -> ok @@ -1201,13 +1201,13 @@ fjoin(FileList) -> list_to_binary(filename:join([binary_to_list(File) || File <- FileList])). has_no_permanent_store_hint(Packet) -> - xml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) =/= false orelse - xml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) =/= false orelse - xml:get_subtag_with_xmlns(Packet, <<"no-permanent-store">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Packet, <<"no-permanent-store">>, ?NS_HINTS) =/= false orelse - xml:get_subtag_with_xmlns(Packet, <<"no-permanent-storage">>, ?NS_HINTS) + fxml:get_subtag_with_xmlns(Packet, <<"no-permanent-storage">>, ?NS_HINTS) =/= false. mod_opt_type(access_log) -> diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 3306e48a421..3c5776de1ae 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -143,12 +143,12 @@ normal_state({route, From, <<"">>, children = Els} = Packet}, StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), case is_user_online(From, StateData) orelse is_user_allowed_message_nonparticipant(From, StateData) of true -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"groupchat">> -> Activity = get_user_activity(From, StateData), Now = p1_time_compat:system_time(micro_seconds), @@ -394,7 +394,7 @@ normal_state({route, From, <<"">>, {next_state, normal_state, StateData} end; _ -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; _ -> handle_roommessage_from_nonparticipant(Packet, Lang, @@ -432,7 +432,7 @@ normal_state({route, From, <<"">>, ?NS_MUC_OWNER -> process_iq_owner(From, Type, Lang, SubEl, StateData); ?NS_DISCO_INFO -> - case xml:get_attr(<<"node">>, Attrs) of + case fxml:get_attr(<<"node">>, Attrs) of false -> process_iq_disco_info(From, Type, Lang, StateData); {value, _} -> {error, ?ERR_SERVICE_UNAVAILABLE} end; @@ -509,8 +509,8 @@ normal_state({route, From, Nick, normal_state({route, From, ToNick, #xmlel{name = <<"message">>, attrs = Attrs} = Packet}, StateData) -> - Type = xml:get_attr_s(<<"type">>, Attrs), - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Type = fxml:get_attr_s(<<"type">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), case decide_fate_message(Type, Packet, From, StateData) of {expulse_sender, Reason} -> @@ -568,7 +568,7 @@ normal_state({route, From, ToNick, FromNick), X = #xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_MUC_USER}]}, - PrivMsg = xml:append_subtags(Packet, [X]), + PrivMsg = fxml:append_subtags(Packet, [X]), [ejabberd_router:route(FromNickJID, ToJID, PrivMsg) || ToJID <- ToJIDs]; true -> @@ -607,8 +607,8 @@ normal_state({route, From, ToNick, normal_state({route, From, ToNick, #xmlel{name = <<"iq">>, attrs = Attrs} = Packet}, StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), - StanzaId = xml:get_attr_s(<<"id">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), + StanzaId = fxml:get_attr_s(<<"id">>, Attrs), case {(StateData#state.config)#config.allow_query_users, is_user_online_iq(StanzaId, From, StateData)} of @@ -884,7 +884,7 @@ route(Pid, From, ToNick, Packet) -> process_groupchat_message(From, #xmlel{name = <<"message">>, attrs = Attrs} = Packet, StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), case is_user_online(From, StateData) orelse is_user_allowed_message_nonparticipant(From, StateData) of @@ -936,7 +936,7 @@ process_groupchat_message(From, drop -> {next_state, normal_state, StateData}; NewPacket1 -> - NewPacket = xml:remove_subtags(NewPacket1, <<"nick">>, {<<"xmlns">>, ?NS_NICK}), + NewPacket = fxml:remove_subtags(NewPacket1, <<"nick">>, {<<"xmlns">>, ?NS_NICK}), send_multiple(jid:replace_resource(StateData#state.jid, FromNick), StateData#state.server_host, @@ -1016,7 +1016,7 @@ get_participant_data(From, StateData) -> process_presence(From, Nick, #xmlel{name = <<"presence">>, attrs = Attrs0} = Packet0, StateData) -> - Type0 = xml:get_attr_s(<<"type">>, Attrs0), + Type0 = fxml:get_attr_s(<<"type">>, Attrs0), IsOnline = is_user_online(From, StateData), if Type0 == <<"">>; IsOnline and ((Type0 == <<"unavailable">>) or (Type0 == <<"error">>)) -> @@ -1029,8 +1029,8 @@ process_presence(From, Nick, drop -> {next_state, normal_state, StateData}; #xmlel{attrs = Attrs} = Packet -> - Type = xml:get_attr_s(<<"type">>, Attrs), - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Type = fxml:get_attr_s(<<"type">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), StateData1 = case Type of <<"unavailable">> -> NewPacket = case @@ -1047,12 +1047,12 @@ process_presence(From, Nick, {ok, [_, _ | _]} -> ok; _ -> send_new_presence(From, NewState, StateData) end, - Reason = case xml:get_subtag(NewPacket, + Reason = case fxml:get_subtag(NewPacket, <<"status">>) of false -> <<"">>; Status_el -> - xml:get_tag_cdata(Status_el) + fxml:get_tag_cdata(Status_el) end, remove_online_user(From, NewState, Reason); <<"error">> -> @@ -1087,7 +1087,7 @@ process_presence(From, Nick, From, Err), StateData; {true, _, _} -> - Lang = xml:get_attr_s(<<"xml:lang">>, + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), ErrText = <<"That nickname is already in use by another " @@ -1304,7 +1304,7 @@ get_error_condition(Packet) -> end. get_error_condition2(Packet) -> - #xmlel{children = EEls} = xml:get_subtag(Packet, + #xmlel{children = EEls} = fxml:get_subtag(Packet, <<"error">>), [Condition] = [Name || #xmlel{name = Name, @@ -1655,7 +1655,7 @@ filter_presence(#xmlel{name = <<"presence">>, case El of {xmlcdata, _} -> false; #xmlel{attrs = Attrs1} -> - XMLNS = xml:get_attr_s(<<"xmlns">>, + XMLNS = fxml:get_attr_s(<<"xmlns">>, Attrs1), NS_MUC = ?NS_MUC, Size = byte_size(NS_MUC), @@ -1743,11 +1743,11 @@ higher_presence(Pres1, Pres2) -> Pri1 > Pri2. get_priority_from_presence(PresencePacket) -> - case xml:get_subtag(PresencePacket, <<"priority">>) of + case fxml:get_subtag(PresencePacket, <<"priority">>) of false -> 0; SubEl -> case catch - jlib:binary_to_integer(xml:get_tag_cdata(SubEl)) + jlib:binary_to_integer(fxml:get_tag_cdata(SubEl)) of P when is_integer(P) -> P; _ -> 0 @@ -1781,7 +1781,7 @@ nick_collision(User, Nick, StateData) -> add_new_user(From, Nick, #xmlel{attrs = Attrs, children = Els} = Packet, StateData) -> - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), MaxUsers = get_max_users(StateData), MaxAdminUsers = MaxUsers + get_max_users_admin_threshold(StateData), @@ -1879,7 +1879,7 @@ add_new_user(From, Nick, From, Err), StateData; captcha_required -> - SID = xml:get_attr_s(<<"id">>, Attrs), + SID = fxml:get_attr_s(<<"id">>, Attrs), RoomJID = StateData#state.jid, To = jid:replace_resource(RoomJID, Nick), Limiter = {From#jid.luser, From#jid.lserver}, @@ -1979,11 +1979,11 @@ check_captcha(Affiliation, From, StateData) -> extract_password([]) -> false; extract_password([#xmlel{attrs = Attrs} = El | Els]) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC -> - case xml:get_subtag(El, <<"password">>) of + case fxml:get_subtag(El, <<"password">>) of false -> false; - SubEl -> xml:get_tag_cdata(SubEl) + SubEl -> fxml:get_tag_cdata(SubEl) end; _ -> extract_password(Els) end; @@ -2057,9 +2057,9 @@ calc_shift(MaxSize, Size, Shift, [S | TSizes]) -> extract_history([], _Type) -> false; extract_history([#xmlel{attrs = Attrs} = El | Els], Type) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC -> - AttrVal = xml:get_path_s(El, + AttrVal = fxml:get_path_s(El, [{elem, <<"history">>}, {attr, Type}]), case Type of <<"since">> -> @@ -2232,7 +2232,7 @@ send_new_presence1(NJID, Reason, StateData, OldStateData) -> end; false -> Status3 end, - Packet = xml:append_subtags(Presence, + Packet = fxml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, @@ -2295,7 +2295,7 @@ send_existing_presences1(ToJID, StateData) -> {<<"role">>, role_to_list(FromRole)}] end, - Packet = xml:append_subtags(Presence, + Packet = fxml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = @@ -2426,7 +2426,7 @@ send_nick_changing(JID, OldNick, StateData, <<"303">>}], children = []}|Status110]}]}, - Packet2 = xml:append_subtags(Presence, + Packet2 = fxml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, @@ -2480,7 +2480,7 @@ lqueue_to_list(#lqueue{queue = Q1}) -> add_message_to_history(FromNick, FromJID, Packet, StateData) -> - HaveSubject = case xml:get_subtag(Packet, <<"subject">>) + HaveSubject = case fxml:get_subtag(Packet, <<"subject">>) of false -> false; _ -> true @@ -2497,7 +2497,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) -> Addresses = #xmlel{name = <<"addresses">>, attrs = [{<<"xmlns">>, ?NS_ADDRESS}], children = [Address]}, - xml:append_subtags(Packet, [Addresses]) + fxml:append_subtags(Packet, [Addresses]) end, TSPacket = jlib:add_delay_info(AddrPacket, StateData#state.jid, TimeStamp), SPacket = @@ -2536,9 +2536,9 @@ send_subject(JID, #state{subject_author = Nick} = StateData) -> Packet). check_subject(Packet) -> - case xml:get_subtag(Packet, <<"subject">>) of + case fxml:get_subtag(Packet, <<"subject">>) of false -> false; - SubjEl -> xml:get_tag_cdata(SubjEl) + SubjEl -> fxml:get_tag_cdata(SubjEl) end. can_change_subject(Role, StateData) -> @@ -2555,14 +2555,14 @@ process_iq_admin(From, set, Lang, SubEl, StateData) -> #xmlel{children = Items} = SubEl, process_admin_items_set(From, Items, Lang, StateData); process_iq_admin(From, get, Lang, SubEl, StateData) -> - case xml:get_subtag(SubEl, <<"item">>) of + case fxml:get_subtag(SubEl, <<"item">>) of false -> {error, ?ERR_BAD_REQUEST}; Item -> FAffiliation = get_affiliation(From, StateData), FRole = get_role(From, StateData), - case xml:get_tag_attr(<<"role">>, Item) of + case fxml:get_tag_attr(<<"role">>, Item) of false -> - case xml:get_tag_attr(<<"affiliation">>, Item) of + case fxml:get_tag_attr(<<"affiliation">>, Item) of false -> {error, ?ERR_BAD_REQUEST}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of @@ -2754,7 +2754,7 @@ find_changed_items(UJID, UAffiliation, URole, [#xmlel{name = <<"item">>, attrs = Attrs} = Item | Items], Lang, StateData, Res) -> - TJID = case xml:get_attr(<<"jid">>, Attrs) of + TJID = case fxml:get_attr(<<"jid">>, Attrs) of {value, S} -> case jid:from_string(S) of error -> @@ -2767,7 +2767,7 @@ find_changed_items(UJID, UAffiliation, URole, J -> {value, [J]} end; _ -> - case xml:get_attr(<<"nick">>, Attrs) of + case fxml:get_attr(<<"nick">>, Attrs) of {value, N} -> case find_jids_by_nick(N, StateData) of false -> @@ -2787,9 +2787,9 @@ find_changed_items(UJID, UAffiliation, URole, {value, [JID | _] = JIDs} -> TAffiliation = get_affiliation(JID, StateData), TRole = get_role(JID, StateData), - case xml:get_attr(<<"role">>, Attrs) of + case fxml:get_attr(<<"role">>, Attrs) of false -> - case xml:get_attr(<<"affiliation">>, Attrs) of + case fxml:get_attr(<<"affiliation">>, Attrs) of false -> {error, ?ERR_BAD_REQUEST}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of @@ -2830,7 +2830,7 @@ find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, Res); true -> - Reason = xml:get_path_s(Item, + Reason = fxml:get_path_s(Item, [{elem, <<"reason">>}, cdata]), MoreRes = [{jid:remove_resource(Jidx), @@ -2877,7 +2877,7 @@ find_changed_items(UJID, UAffiliation, URole, find_changed_items(UJID, UAffiliation, URole, Items, Lang, StateData, Res); true -> - Reason = xml:get_path_s(Item, + Reason = fxml:get_path_s(Item, [{elem, <<"reason">>}, cdata]), MoreRes = [{Jidx, role, SRole, Reason} @@ -3129,10 +3129,10 @@ process_iq_owner(From, set, Lang, SubEl, StateData) -> case FAffiliation of owner -> #xmlel{children = Els} = SubEl, - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [#xmlel{name = <<"x">>} = XEl] -> - case {xml:get_tag_attr_s(<<"xmlns">>, XEl), - xml:get_tag_attr_s(<<"type">>, XEl)} + case {fxml:get_tag_attr_s(<<"xmlns">>, XEl), + fxml:get_tag_attr_s(<<"type">>, XEl)} of {?NS_XDATA, <<"cancel">>} -> {result, [], StateData}; {?NS_XDATA, <<"submit">>} -> @@ -3166,10 +3166,10 @@ process_iq_owner(From, get, Lang, SubEl, StateData) -> case FAffiliation of owner -> #xmlel{children = Els} = SubEl, - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [] -> get_config(Lang, StateData, From); [Item] -> - case xml:get_tag_attr(<<"affiliation">>, Item) of + case fxml:get_tag_attr(<<"affiliation">>, Item) of false -> {error, ?ERR_BAD_REQUEST}; {value, StrAffiliation} -> case catch list_to_affiliation(StrAffiliation) of @@ -4225,7 +4225,7 @@ process_iq_captcha(_From, set, _Lang, SubEl, process_iq_vcard(_From, get, _Lang, _SubEl, StateData) -> #state{config = #config{vcard = VCardRaw}} = StateData, - case xml_stream:parse_element(VCardRaw) of + case fxml_stream:parse_element(VCardRaw) of #xmlel{children = VCardEls} -> {result, VCardEls, StateData}; {error, _} -> @@ -4234,7 +4234,7 @@ process_iq_vcard(_From, get, _Lang, _SubEl, StateData) -> process_iq_vcard(From, set, Lang, SubEl, StateData) -> case get_affiliation(From, StateData) of owner -> - VCardRaw = xml:element_to_binary(SubEl), + VCardRaw = fxml:element_to_binary(SubEl), Config = StateData#state.config, NewConfig = Config#config{vcard = VCardRaw}, change_config(NewConfig, StateData); @@ -4293,7 +4293,7 @@ is_voice_request(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>, attrs = Attrs} = El, false) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> case jlib:parse_xdata_submit(El) of [_ | _] = Fields -> @@ -4376,7 +4376,7 @@ is_voice_approvement(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>, attrs = Attrs} = El, false) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> case jlib:parse_xdata_submit(El) of [_ | _] = Fs -> @@ -4430,9 +4430,9 @@ is_invitation(Els) -> lists:foldl(fun (#xmlel{name = <<"x">>, attrs = Attrs} = El, false) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_MUC_USER -> - case xml:get_subtag(El, <<"invite">>) of + case fxml:get_subtag(El, <<"invite">>) of false -> false; _ -> true end; @@ -4448,20 +4448,20 @@ check_invitation(From, Els, Lang, StateData) -> (StateData#state.config)#config.allow_user_invites orelse FAffiliation == admin orelse FAffiliation == owner, - InviteEl = case xml:remove_cdata(Els) of + InviteEl = case fxml:remove_cdata(Els) of [#xmlel{name = <<"x">>, children = Els1} = XEl] -> - case xml:get_tag_attr_s(<<"xmlns">>, XEl) of + case fxml:get_tag_attr_s(<<"xmlns">>, XEl) of ?NS_MUC_USER -> ok; _ -> throw({error, ?ERR_BAD_REQUEST}) end, - case xml:remove_cdata(Els1) of + case fxml:remove_cdata(Els1) of [#xmlel{name = <<"invite">>} = InviteEl1] -> InviteEl1; _ -> throw({error, ?ERR_BAD_REQUEST}) end; _ -> throw({error, ?ERR_BAD_REQUEST}) end, JID = case - jid:from_string(xml:get_tag_attr_s(<<"to">>, + jid:from_string(fxml:get_tag_attr_s(<<"to">>, InviteEl)) of error -> throw({error, ?ERR_JID_MALFORMED}); @@ -4470,9 +4470,9 @@ check_invitation(From, Els, Lang, StateData) -> case CanInvite of false -> throw({error, ?ERR_NOT_ALLOWED}); true -> - Reason = xml:get_path_s(InviteEl, + Reason = fxml:get_path_s(InviteEl, [{elem, <<"reason">>}, cdata]), - ContinueEl = case xml:get_path_s(InviteEl, + ContinueEl = case fxml:get_path_s(InviteEl, [{elem, <<"continue">>}]) of <<>> -> []; @@ -4562,10 +4562,10 @@ handle_roommessage_from_nonparticipant(Packet, Lang, %% because it crashes when the packet is not a decline message. check_decline_invitation(Packet) -> #xmlel{name = <<"message">>} = Packet, - XEl = xml:get_subtag(Packet, <<"x">>), - (?NS_MUC_USER) = xml:get_tag_attr_s(<<"xmlns">>, XEl), - DEl = xml:get_subtag(XEl, <<"decline">>), - ToString = xml:get_tag_attr_s(<<"to">>, DEl), + XEl = fxml:get_subtag(Packet, <<"x">>), + (?NS_MUC_USER) = fxml:get_tag_attr_s(<<"xmlns">>, XEl), + DEl = fxml:get_subtag(XEl, <<"decline">>), + ToString = fxml:get_tag_attr_s(<<"to">>, DEl), ToJID = jid:from_string(ToString), {true, {Packet, XEl, DEl, ToJID}}. @@ -4652,7 +4652,7 @@ tab_count_user(JID) -> end. element_size(El) -> - byte_size(xml:element_to_binary(El)). + byte_size(fxml:element_to_binary(El)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Multicast diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 96ebcb6f2ac..5c662a868d7 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -233,7 +233,7 @@ handle_iq(From, To, #xmlel{attrs = Attrs} = Packet, State) -> ejabberd_router:route(To, From, Err); reply -> LServiceS = jts(To), - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"result">> -> process_iqreply_result(From, LServiceS, Packet, State); <<"error">> -> @@ -436,17 +436,17 @@ check_access(LServerS, Access, From) -> %%%------------------------- strip_addresses_element(Packet) -> - case xml:get_subtag(Packet, <<"addresses">>) of + case fxml:get_subtag(Packet, <<"addresses">>) of #xmlel{name = <<"addresses">>, attrs = AAttrs, children = Addresses} -> - case xml:get_attr_s(<<"xmlns">>, AAttrs) of + case fxml:get_attr_s(<<"xmlns">>, AAttrs) of ?NS_ADDRESS -> #xmlel{name = Name, attrs = Attrs, children = Els} = Packet, Els_stripped = lists:keydelete(<<"addresses">>, 2, Els), Packet_stripped = #xmlel{name = Name, attrs = Attrs, children = Els_stripped}, - {ok, Packet_stripped, AAttrs, xml:remove_cdata(Addresses)}; + {ok, Packet_stripped, AAttrs, fxml:remove_cdata(Addresses)}; _ -> throw(ewxmlns) end; _ -> throw(eadsele) @@ -460,10 +460,10 @@ split_addresses_todeliver(Addresses) -> lists:partition(fun (XML) -> case XML of #xmlel{name = <<"address">>, attrs = Attrs} -> - case xml:get_attr_s(<<"delivered">>, Attrs) of + case fxml:get_attr_s(<<"delivered">>, Attrs) of <<"true">> -> false; _ -> - Type = xml:get_attr_s(<<"type">>, + Type = fxml:get_attr_s(<<"type">>, Attrs), case Type of <<"to">> -> true; @@ -499,10 +499,10 @@ check_limit_dests(SLimits, FromJID, Packet, convert_dest_record(XMLs) -> lists:map(fun (XML) -> - case xml:get_tag_attr_s(<<"jid">>, XML) of + case fxml:get_tag_attr_s(<<"jid">>, XML) of <<"">> -> #dest{jid_string = none, full_xml = XML}; JIDS -> - Type = xml:get_tag_attr_s(<<"type">>, XML), + Type = fxml:get_tag_attr_s(<<"type">>, XML), JIDJ = stj(JIDS), #dest{jid_string = JIDS, jid_jid = JIDJ, type = Type, full_xml = XML} @@ -525,7 +525,7 @@ split_dests_jid(Dests) -> Dests). report_not_jid(From, Packet, Dests) -> - Dests2 = [xml:element_to_binary(Dest#dest.full_xml) + Dests2 = [fxml:element_to_binary(Dest#dest.full_xml) || Dest <- Dests], [route_error(From, From, Packet, jid_malformed, <<"This service can not process the address: ", @@ -734,8 +734,8 @@ process_iqreply_error(From, LServiceS, _Packet) -> process_iqreply_result(From, LServiceS, Packet, State) -> #xmlel{name = <<"query">>, attrs = Attrs2, children = Els2} = - xml:get_subtag(Packet, <<"query">>), - case xml:get_attr_s(<<"xmlns">>, Attrs2) of + fxml:get_subtag(Packet, <<"query">>), + case fxml:get_attr_s(<<"xmlns">>, Attrs2) of ?NS_DISCO_INFO -> process_discoinfo_result(From, LServiceS, Els2, State); ?NS_DISCO_ITEMS -> @@ -763,7 +763,7 @@ process_discoinfo_result2(From, FromS, LServiceS, Els, fun(XML) -> case XML of #xmlel{name = <<"feature">>, attrs = Attrs} -> - (?NS_ADDRESS) == xml:get_attr_s(<<"var">>, Attrs); + (?NS_ADDRESS) == fxml:get_attr_s(<<"var">>, Attrs); _ -> false end end, @@ -807,10 +807,10 @@ get_limits_els(Els) -> #xmlel{name = <<"x">>, attrs = Attrs, children = SubEls} -> case ((?NS_XDATA) == - xml:get_attr_s(<<"xmlns">>, Attrs)) + fxml:get_attr_s(<<"xmlns">>, Attrs)) and (<<"result">> == - xml:get_attr_s(<<"type">>, Attrs)) + fxml:get_attr_s(<<"type">>, Attrs)) of true -> get_limits_fields(SubEls) ++ R; false -> R @@ -826,11 +826,11 @@ get_limits_fields(Fields) -> #xmlel{name = <<"field">>, attrs = Attrs} -> (<<"FORM_TYPE">> == - xml:get_attr_s(<<"var">>, + fxml:get_attr_s(<<"var">>, Attrs)) and (<<"hidden">> == - xml:get_attr_s(<<"type">>, + fxml:get_attr_s(<<"type">>, Attrs)); _ -> false end @@ -848,8 +848,8 @@ get_limits_values(Values) -> children = SubEls} -> [#xmlel{name = <<"value">>, children = SubElsV}] = SubEls, - Number = xml:get_cdata(SubElsV), - Name = xml:get_attr_s(<<"var">>, Attrs), + Number = fxml:get_cdata(SubElsV), + Name = fxml:get_attr_s(<<"var">>, Attrs), [{jlib:binary_to_atom(Name), jlib:binary_to_integer(Number)} | R]; @@ -870,7 +870,7 @@ process_discoitems_result(From, LServiceS, Els) -> fun(XML, Res) -> case XML of #xmlel{name = <<"item">>, attrs = Attrs} -> - SJID = xml:get_attr_s(<<"jid">>, Attrs), + SJID = fxml:get_attr_s(<<"jid">>, Attrs), case jid:from_string(SJID) of #jid{luser = <<"">>, lresource = <<"">>} -> @@ -1196,7 +1196,7 @@ to_binary(A) -> list_to_binary(hd(io_lib:format("~p", [A]))). route_error(From, To, Packet, ErrType, ErrText) -> #xmlel{attrs = Attrs} = Packet, - Lang = xml:get_attr_s(<<"xml:lang">>, Attrs), + Lang = fxml:get_attr_s(<<"xml:lang">>, Attrs), Reply = make_reply(ErrType, Lang, ErrText), Err = jlib:make_error_reply(Packet, Reply), ejabberd_router:route(From, To, Err). diff --git a/src/mod_offline.erl b/src/mod_offline.erl index abdbcfdbd04..28a8aa4ffc0 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -227,7 +227,7 @@ store_offline_msg(Host, {User, _Server}, Msgs, Len, MaxOfflineMsgs, odbc) -> M#offline_msg.timestamp, <<"Offline Storage">>), XML = - ejabberd_odbc:escape(xml:element_to_binary(NewPacket)), + ejabberd_odbc:escape(fxml:element_to_binary(NewPacket)), odbc_queries:add_spool_sql(Username, XML) end, Msgs), @@ -286,7 +286,7 @@ get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. need_to_store(LServer, Packet) -> - Type = xml:get_tag_attr_s(<<"type">>, Packet), + Type = fxml:get_tag_attr_s(<<"type">>, Packet), if (Type /= <<"error">>) and (Type /= <<"groupchat">>) and (Type /= <<"headline">>) -> case check_store_hint(Packet) of @@ -302,7 +302,7 @@ need_to_store(LServer, Packet) -> end, unless_chat_state) of false -> - xml:get_subtag(Packet, <<"body">>) /= false; + fxml:get_subtag(Packet, <<"body">>) /= false; unless_chat_state -> not jlib:is_standalone_chat_state(Packet); true -> @@ -346,12 +346,12 @@ check_store_hint(Packet) -> end. has_store_hint(Packet) -> - xml:get_subtag_with_xmlns(Packet, <<"store">>, ?NS_HINTS) =/= false. + fxml:get_subtag_with_xmlns(Packet, <<"store">>, ?NS_HINTS) =/= false. has_no_store_hint(Packet) -> - xml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) =/= false + fxml:get_subtag_with_xmlns(Packet, <<"no-store">>, ?NS_HINTS) =/= false orelse - xml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) =/= false. + fxml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) =/= false. %% Check if the packet has any content about XEP-0022 check_event(From, To, Packet) -> @@ -360,12 +360,12 @@ check_event(From, To, Packet) -> case find_x_event(Els) of false -> true; El -> - case xml:get_subtag(El, <<"id">>) of + case fxml:get_subtag(El, <<"id">>) of false -> - case xml:get_subtag(El, <<"offline">>) of + case fxml:get_subtag(El, <<"offline">>) of false -> true; _ -> - ID = case xml:get_tag_attr_s(<<"id">>, Packet) of + ID = case fxml:get_tag_attr_s(<<"id">>, Packet) of <<"">> -> #xmlel{name = <<"id">>, attrs = [], children = []}; @@ -402,7 +402,7 @@ 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 + case fxml:get_tag_attr_s(<<"xmlns">>, El) of ?NS_EVENT -> El; _ -> find_x_event(Els) end. @@ -411,9 +411,9 @@ 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 + case fxml:get_tag_attr_s(<<"xmlns">>, El) of ?NS_EXPIRE -> - Val = xml:get_tag_attr_s(<<"seconds">>, El), + Val = fxml:get_tag_attr_s(<<"seconds">>, El), case catch jlib:binary_to_integer(Val) of {'EXIT', _} -> never; Int when Int > 0 -> @@ -487,7 +487,7 @@ pop_offline_messages(Ls, LUser, LServer, odbc) -> {atomic, {selected, [<<"username">>, <<"xml">>], Rs}} -> Ls ++ lists:flatmap(fun ([_, XML]) -> - case xml_stream:parse_element(XML) of + case fxml_stream:parse_element(XML) of {error, _Reason} -> []; El -> @@ -635,7 +635,7 @@ update_table() -> iolist_to_binary(S)}, from = jid_to_binary(From), to = jid_to_binary(To), - packet = xml:to_xmlel(El)} + packet = fxml:to_xmlel(El)} end); _ -> ?INFO_MSG("Recreating offline_msg table", []), @@ -650,7 +650,7 @@ discard_warn_sender(Msgs) -> packet = Packet}) -> ErrText = <<"Your contact offline message queue is " "full. The message has been discarded.">>, - Lang = xml:get_tag_attr_s(<<"xml:lang">>, Packet), + Lang = fxml:get_tag_attr_s(<<"xml:lang">>, Packet), Err = jlib:make_error_reply(Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)), @@ -684,7 +684,7 @@ get_offline_els(LUser, LServer, odbc) -> {selected, [<<"xml">>], Rs} -> lists:flatmap( fun([XML]) -> - case xml_stream:parse_element(XML) of + case fxml_stream:parse_element(XML) of #xmlel{} = El -> case offline_msg_to_route(LServer, El) of {route, _, _, NewEl} -> @@ -705,8 +705,8 @@ offline_msg_to_route(LServer, #offline_msg{} = R) -> jlib:add_delay_info(R#offline_msg.packet, LServer, R#offline_msg.timestamp, <<"Offline Storage">>)}; offline_msg_to_route(_LServer, #xmlel{} = El) -> - To = jid:from_string(xml:get_tag_attr_s(<<"to">>, El)), - From = jid:from_string(xml:get_tag_attr_s(<<"from">>, El)), + To = jid:from_string(fxml:get_tag_attr_s(<<"to">>, El)), + From = jid:from_string(fxml:get_tag_attr_s(<<"from">>, El)), if (To /= error) and (From /= error) -> {route, From, To, El}; true -> @@ -734,7 +734,7 @@ read_all_msgs(LUser, LServer, odbc) -> of {selected, [<<"xml">>], Rs} -> lists:flatmap(fun ([XML]) -> - case xml_stream:parse_element(XML) of + case fxml_stream:parse_element(XML) of {error, _Reason} -> []; El -> [El] end @@ -882,7 +882,7 @@ user_queue_parse_query(LUser, LServer, Query, odbc) -> of {selected, [<<"xml">>, <<"seq">>], Rs} -> lists:flatmap(fun ([XML, Seq]) -> - case xml_stream:parse_element(XML) + case fxml_stream:parse_element(XML) of {error, _Reason} -> []; El -> [{El, Seq}] @@ -1114,7 +1114,7 @@ export(_Server) -> Packet1 = jlib:replace_from_to(From, To, Packet), Packet2 = jlib:add_delay_info(Packet1, LServer, TimeStamp, <<"Offline Storage">>), - XML = ejabberd_odbc:escape(xml:element_to_binary(Packet2)), + XML = ejabberd_odbc:escape(fxml:element_to_binary(Packet2)), [[<<"delete from spool where username='">>, Username, <<"';">>], [<<"insert into spool(username, xml) values ('">>, Username, <<"', '">>, XML, <<"');">>]]; @@ -1125,12 +1125,12 @@ export(_Server) -> import(LServer) -> [{<<"select username, xml from spool;">>, fun([LUser, XML]) -> - El = #xmlel{} = xml_stream:parse_element(XML), + El = #xmlel{} = fxml_stream:parse_element(XML), From = #jid{} = jid:from_string( - xml:get_attr_s(<<"from">>, El#xmlel.attrs)), + fxml:get_attr_s(<<"from">>, El#xmlel.attrs)), To = #jid{} = jid:from_string( - xml:get_attr_s(<<"to">>, El#xmlel.attrs)), - Stamp = xml:get_path_s(El, [{elem, <<"delay">>}, + fxml:get_attr_s(<<"to">>, El#xmlel.attrs)), + Stamp = fxml:get_path_s(El, [{elem, <<"delay">>}, {attr, <<"stamp">>}]), TS = case jlib:datetime_string_to_timestamp(Stamp) of {_, _, _} = Now -> diff --git a/src/mod_pres_counter.erl b/src/mod_pres_counter.erl index 34fdcdb75bf..1118b7bbccb 100644 --- a/src/mod_pres_counter.erl +++ b/src/mod_pres_counter.erl @@ -52,7 +52,7 @@ check_packet(_, _User, Server, _PrivacyList, {From, To, #xmlel{name = Name, attrs = Attrs}}, Dir) -> case Name of <<"presence">> -> - IsSubscription = case xml:get_attr_s(<<"type">>, Attrs) + IsSubscription = case fxml:get_attr_s(<<"type">>, Attrs) of <<"subscribe">> -> true; <<"subscribed">> -> true; diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index 62b043db03d..e8e6ee7bea5 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -109,12 +109,12 @@ process_iq_get(_, From, _To, #iq{sub_el = SubEl}, #userlist{name = Active}) -> #jid{luser = LUser, lserver = LServer} = From, #xmlel{children = Els} = SubEl, - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [] -> process_lists_get(LUser, LServer, Active); [#xmlel{name = Name, attrs = Attrs}] -> case Name of <<"list">> -> - ListName = xml:get_attr(<<"name">>, Attrs), + ListName = fxml:get_attr(<<"name">>, Attrs), process_list_get(LUser, LServer, ListName); _ -> {error, ?ERR_BAD_REQUEST} end; @@ -343,14 +343,14 @@ list_to_action(S) -> process_iq_set(_, From, _To, #iq{sub_el = SubEl}) -> #jid{luser = LUser, lserver = LServer} = From, #xmlel{children = Els} = SubEl, - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [#xmlel{name = Name, attrs = Attrs, children = SubEls}] -> - ListName = xml:get_attr(<<"name">>, Attrs), + ListName = fxml:get_attr(<<"name">>, Attrs), case Name of <<"list">> -> process_list_set(LUser, LServer, ListName, - xml:remove_cdata(SubEls)); + fxml:remove_cdata(SubEls)); <<"active">> -> process_active_set(LUser, LServer, ListName); <<"default">> -> @@ -651,10 +651,10 @@ parse_items([#xmlel{name = <<"item">>, attrs = Attrs, children = SubEls} | Els], Res) -> - Type = xml:get_attr(<<"type">>, Attrs), - Value = xml:get_attr(<<"value">>, Attrs), - SAction = xml:get_attr(<<"action">>, Attrs), - SOrder = xml:get_attr(<<"order">>, Attrs), + Type = fxml:get_attr(<<"type">>, Attrs), + Value = fxml:get_attr(<<"value">>, Attrs), + SAction = fxml:get_attr(<<"action">>, Attrs), + SOrder = fxml:get_attr(<<"order">>, Attrs), Action = case catch list_to_action(element(2, SAction)) of {'EXIT', _} -> false; @@ -704,7 +704,7 @@ parse_items([#xmlel{name = <<"item">>, attrs = Attrs, case I2 of false -> false; _ -> - case parse_matches(I2, xml:remove_cdata(SubEls)) of + case parse_matches(I2, fxml:remove_cdata(SubEls)) of false -> false; I3 -> parse_items(Els, [I3 | Res]) end @@ -882,7 +882,7 @@ check_packet(_, User, Server, <<"message">> -> message; <<"iq">> -> iq; <<"presence">> -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of %% notification <<"">> -> presence; <<"unavailable">> -> presence; diff --git a/src/mod_private.erl b/src/mod_private.erl index e074b7185f7..ee3a6c1f332 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -125,7 +125,7 @@ filter_xmlels(Xmlels) -> filter_xmlels(Xmlels, []). filter_xmlels([], Data) -> lists:reverse(Data); filter_xmlels([#xmlel{attrs = Attrs} = Xmlel | Xmlels], Data) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of <<"">> -> []; XmlNS -> filter_xmlels(Xmlels, [{XmlNS, Xmlel} | Data]) end; @@ -154,7 +154,7 @@ set_data(LUser, LServer, {XmlNS, Xmlel}, mnesia) -> set_data(LUser, LServer, {XMLNS, El}, odbc) -> Username = ejabberd_odbc:escape(LUser), LXMLNS = ejabberd_odbc:escape(XMLNS), - SData = ejabberd_odbc:escape(xml:element_to_binary(El)), + SData = ejabberd_odbc:escape(fxml:element_to_binary(El)), odbc_queries:set_private_data(LServer, Username, LXMLNS, SData); set_data(LUser, LServer, {XMLNS, El}, riak) -> @@ -190,7 +190,7 @@ get_data(LUser, LServer, odbc, [{XMLNS, El} | Els], Username, LXMLNS) of {selected, [<<"data">>], [[SData]]} -> - case xml_stream:parse_element(SData) of + case fxml_stream:parse_element(SData) of Data when is_record(Data, xmlel) -> get_data(LUser, LServer, odbc, Els, [Data | Res]) end; @@ -222,7 +222,7 @@ get_all_data(LUser, LServer, odbc) -> {selected, [<<"namespace">>, <<"data">>], Res} -> lists:flatmap( fun([_, SData]) -> - case xml_stream:parse_element(SData) of + case fxml_stream:parse_element(SData) of #xmlel{} = El -> [El]; _ -> @@ -287,7 +287,7 @@ update_table() -> R#private_storage{usns = {iolist_to_binary(U), iolist_to_binary(S), iolist_to_binary(NS)}, - xml = xml:to_xmlel(El)} + xml = fxml:to_xmlel(El)} end); _ -> ?INFO_MSG("Recreating private_storage table", []), @@ -302,7 +302,7 @@ export(_Server) -> Username = ejabberd_odbc:escape(LUser), LXMLNS = ejabberd_odbc:escape(XMLNS), SData = - ejabberd_odbc:escape(xml:element_to_binary(Data)), + ejabberd_odbc:escape(fxml:element_to_binary(Data)), odbc_queries:set_private_data_sql(Username, LXMLNS, SData); (_Host, _R) -> @@ -312,7 +312,7 @@ export(_Server) -> import(LServer) -> [{<<"select username, namespace, data from private_storage;">>, fun([LUser, XMLNS, XML]) -> - El = #xmlel{} = xml_stream:parse_element(XML), + El = #xmlel{} = fxml_stream:parse_element(XML), #private_storage{usns = {LUser, LServer, XMLNS}, xml = El} end}]. diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 97d5b00afbb..3fb86360a11 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -175,11 +175,11 @@ process_iq(InitiatorJID, #state{acl = ACL, serverhost = ServerHost}) -> case acl:match_rule(ServerHost, ACL, InitiatorJID) of allow -> - ActivateEl = xml:get_path_s(SubEl, + ActivateEl = fxml:get_path_s(SubEl, [{elem, <<"activate">>}]), - SID = xml:get_tag_attr_s(<<"sid">>, SubEl), + SID = fxml:get_tag_attr_s(<<"sid">>, SubEl), case catch - jid:from_string(xml:get_tag_cdata(ActivateEl)) + jid:from_string(fxml:get_tag_cdata(ActivateEl)) of TargetJID when is_record(TargetJID, jid), SID /= <<"">>, diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index b6185852b7e..03f3131e5db 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -951,7 +951,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> case jlib:iq_query_info(Packet) of #iq{type = get, xmlns = ?NS_DISCO_INFO, sub_el = SubEl, lang = Lang} = IQ -> #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), + Node = fxml:get_attr_s(<<"node">>, QAttrs), Info = ejabberd_hooks:run_fold(disco_info, ServerHost, [], [ServerHost, ?MODULE, <<>>, <<>>]), @@ -968,7 +968,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> ejabberd_router:route(To, From, Res); #iq{type = get, xmlns = ?NS_DISCO_ITEMS, sub_el = SubEl} = IQ -> #xmlel{attrs = QAttrs} = SubEl, - Node = xml:get_attr_s(<<"node">>, QAttrs), + Node = fxml:get_attr_s(<<"node">>, QAttrs), Res = case iq_disco_items(Host, Node, From, jlib:rsm_decode(IQ)) of {result, IQRes} -> jlib:iq_to_xml(IQ#iq{type = result, @@ -1022,7 +1022,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> ok end; <<"message">> -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; _ -> @@ -1040,7 +1040,7 @@ do_route(ServerHost, Access, Plugins, Host, From, To, Packet) -> ok end; _ -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<"error">> -> ok; <<"result">> -> @@ -1255,16 +1255,16 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) -> iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> #xmlel{children = SubEls} = SubEl, - case xml:remove_cdata(SubEls) of + case fxml:remove_cdata(SubEls) of [#xmlel{name = Name, attrs = Attrs, children = Els} | Rest] -> - Node = xml:get_attr_s(<<"node">>, Attrs), + Node = fxml:get_attr_s(<<"node">>, Attrs), case {IQType, Name} of {set, <<"create">>} -> Config = case Rest of [#xmlel{name = <<"configure">>, children = C}] -> C; _ -> [] end, - Type = case xml:get_attr_s(<<"type">>, Attrs) of + Type = case fxml:get_attr_s(<<"type">>, Attrs) of <<>> -> hd(Plugins); T -> T end, @@ -1276,10 +1276,10 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> create_node(Host, ServerHost, Node, From, Type, Access, Config) end; {set, <<"publish">>} -> - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = Payload}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), + ItemId = fxml:get_attr_s(<<"id">>, ItemAttrs), publish_item(Host, ServerHost, Node, From, ItemId, Payload, Access); [] -> {error, @@ -1289,14 +1289,14 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> extended_error(?ERR_BAD_REQUEST, <<"invalid-payload">>)} end; {set, <<"retract">>} -> - ForceNotify = case xml:get_attr_s(<<"notify">>, Attrs) of + ForceNotify = case fxml:get_attr_s(<<"notify">>, Attrs) of <<"1">> -> true; <<"true">> -> true; _ -> false end, - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [#xmlel{name = <<"item">>, attrs = ItemAttrs}] -> - ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), + ItemId = fxml:get_attr_s(<<"id">>, ItemAttrs), delete_item(Host, Node, From, ItemId, ForceNotify); _ -> {error, @@ -1307,37 +1307,37 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> [#xmlel{name = <<"options">>, children = C}] -> C; _ -> [] end, - JID = xml:get_attr_s(<<"jid">>, Attrs), + JID = fxml:get_attr_s(<<"jid">>, Attrs), subscribe_node(Host, Node, From, JID, Config); {set, <<"unsubscribe">>} -> - JID = xml:get_attr_s(<<"jid">>, Attrs), - SubId = xml:get_attr_s(<<"subid">>, Attrs), + JID = fxml:get_attr_s(<<"jid">>, Attrs), + SubId = fxml:get_attr_s(<<"subid">>, Attrs), unsubscribe_node(Host, Node, From, JID, SubId); {get, <<"items">>} -> - MaxItems = xml:get_attr_s(<<"max_items">>, Attrs), - SubId = xml:get_attr_s(<<"subid">>, Attrs), + MaxItems = fxml:get_attr_s(<<"max_items">>, Attrs), + SubId = fxml:get_attr_s(<<"subid">>, Attrs), ItemIds = lists:foldl(fun (#xmlel{name = <<"item">>, attrs = ItemAttrs}, Acc) -> - case xml:get_attr_s(<<"id">>, ItemAttrs) of + case fxml:get_attr_s(<<"id">>, ItemAttrs) of <<>> -> Acc; ItemId -> [ItemId | Acc] end; (_, Acc) -> Acc end, - [], xml:remove_cdata(Els)), + [], fxml:remove_cdata(Els)), get_items(Host, Node, From, SubId, MaxItems, ItemIds, jlib:rsm_decode(SubEl)); {get, <<"subscriptions">>} -> get_subscriptions(Host, Node, From, Plugins); {get, <<"affiliations">>} -> get_affiliations(Host, Node, From, Plugins); {get, <<"options">>} -> - SubId = xml:get_attr_s(<<"subid">>, Attrs), - JID = xml:get_attr_s(<<"jid">>, Attrs), + SubId = fxml:get_attr_s(<<"subid">>, Attrs), + JID = fxml:get_attr_s(<<"jid">>, Attrs), get_options(Host, Node, JID, SubId, Lang); {set, <<"options">>} -> - SubId = xml:get_attr_s(<<"subid">>, Attrs), - JID = xml:get_attr_s(<<"jid">>, Attrs), + SubId = fxml:get_attr_s(<<"subid">>, Attrs), + JID = fxml:get_attr_s(<<"jid">>, Attrs), set_options(Host, Node, JID, SubId, Els); _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} @@ -1362,10 +1362,10 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> ). iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> #xmlel{children = SubEls} = SubEl, - Action = xml:remove_cdata(SubEls), + Action = fxml:remove_cdata(SubEls), case Action of [#xmlel{name = Name, attrs = Attrs, children = Els}] -> - Node = xml:get_attr_s(<<"node">>, Attrs), + Node = fxml:get_attr_s(<<"node">>, Attrs), case {IQType, Name} of {get, <<"configure">>} -> get_configure(Host, ServerHost, Node, From, Lang); @@ -1380,11 +1380,11 @@ iq_pubsub_owner(Host, ServerHost, From, IQType, SubEl, Lang) -> {get, <<"subscriptions">>} -> get_subscriptions(Host, Node, From); {set, <<"subscriptions">>} -> - set_subscriptions(Host, Node, From, xml:remove_cdata(Els)); + set_subscriptions(Host, Node, From, fxml:remove_cdata(Els)); {get, <<"affiliations">>} -> get_affiliations(Host, Node, From); {set, <<"affiliations">>} -> - set_affiliations(Host, Node, From, xml:remove_cdata(Els)); + set_affiliations(Host, Node, From, fxml:remove_cdata(Els)); _ -> {error, ?ERR_FEATURE_NOT_IMPLEMENTED} end; @@ -1597,9 +1597,9 @@ find_authorization_response(Packet) -> #xmlel{children = Els} = Packet, XData1 = lists:map(fun (#xmlel{name = <<"x">>, attrs = XAttrs} = XEl) -> - case xml:get_attr_s(<<"xmlns">>, XAttrs) of + case fxml:get_attr_s(<<"xmlns">>, XAttrs) of ?NS_XDATA -> - case xml:get_attr_s(<<"type">>, XAttrs) of + case fxml:get_attr_s(<<"type">>, XAttrs) of <<"cancel">> -> none; _ -> jlib:parse_xdata_submit(XEl) end; @@ -1609,7 +1609,7 @@ find_authorization_response(Packet) -> (_) -> none end, - xml:remove_cdata(Els)), + fxml:remove_cdata(Els)), XData = lists:filter(fun (E) -> E /= none end, XData1), case XData of [invalid] -> @@ -1808,7 +1808,7 @@ create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) -> end; create_node(Host, ServerHost, Node, Owner, GivenType, Access, Configuration) -> Type = select_type(ServerHost, Host, Node, GivenType), - ParseOptions = case xml:remove_cdata(Configuration) of + ParseOptions = case fxml:remove_cdata(Configuration) of [] -> {result, node_options(Host, Type)}; [#xmlel{name = <<"x">>} = XEl] -> @@ -2668,8 +2668,8 @@ set_affiliations(Host, Node, From, EntitiesEls) -> (El, Acc) -> case El of #xmlel{name = <<"affiliation">>, attrs = Attrs} -> - JID = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), - Affiliation = string_to_affiliation(xml:get_attr_s(<<"affiliation">>, Attrs)), + JID = jid:from_string(fxml:get_attr_s(<<"jid">>, Attrs)), + Affiliation = string_to_affiliation(fxml:get_attr_s(<<"affiliation">>, Attrs)), if (JID == error) or (Affiliation == false) -> error; true -> [{jid:tolower(JID), Affiliation} | Acc] end @@ -2998,9 +2998,9 @@ set_subscriptions(Host, Node, From, EntitiesEls) -> (El, Acc) -> case El of #xmlel{name = <<"subscription">>, attrs = Attrs} -> - JID = jid:from_string(xml:get_attr_s(<<"jid">>, Attrs)), - Sub = string_to_subscription(xml:get_attr_s(<<"subscription">>, Attrs)), - SubId = xml:get_attr_s(<<"subid">>, Attrs), + JID = jid:from_string(fxml:get_attr_s(<<"jid">>, Attrs)), + Sub = string_to_subscription(fxml:get_attr_s(<<"subscription">>, Attrs)), + SubId = fxml:get_attr_s(<<"subid">>, Attrs), if (JID == error) or (Sub == false) -> error; true -> [{jid:tolower(JID), Sub, SubId} | Acc] end @@ -3786,9 +3786,9 @@ get_configure_xfields(_Type, Options, Lang, Groups) -> %%
  • The specified node does not exist.
  • %% set_configure(Host, Node, From, Els, Lang) -> - case xml:remove_cdata(Els) of + case fxml:remove_cdata(Els) of [#xmlel{name = <<"x">>} = XEl] -> - case {xml:get_tag_attr_s(<<"xmlns">>, XEl), xml:get_tag_attr_s(<<"type">>, XEl)} of + case {fxml:get_tag_attr_s(<<"xmlns">>, XEl), fxml:get_tag_attr_s(<<"type">>, XEl)} of {?NS_XDATA, <<"cancel">>} -> {result, []}; {?NS_XDATA, <<"submit">>} -> diff --git a/src/mod_register.erl b/src/mod_register.erl index c7bfd963b8b..56c5f7205de 100644 --- a/src/mod_register.erl +++ b/src/mod_register.erl @@ -121,9 +121,9 @@ process_iq(From, To, end, case Type of set -> - UTag = xml:get_subtag(SubEl, <<"username">>), - PTag = xml:get_subtag(SubEl, <<"password">>), - RTag = xml:get_subtag(SubEl, <<"remove">>), + UTag = fxml:get_subtag(SubEl, <<"username">>), + PTag = fxml:get_subtag(SubEl, <<"password">>), + RTag = fxml:get_subtag(SubEl, <<"remove">>), Server = To#jid.lserver, Access = gen_mod:get_module_opt(Server, ?MODULE, access, fun(A) when is_atom(A) -> A end, @@ -132,14 +132,14 @@ process_iq(From, To, acl:match_rule(Server, Access, From), if (UTag /= false) and (RTag /= false) and AllowRemove -> - User = xml:get_tag_cdata(UTag), + User = fxml:get_tag_cdata(UTag), case From of #jid{user = User, lserver = Server} -> ejabberd_auth:remove_user(User, Server), IQ#iq{type = result, sub_el = []}; _ -> if PTag /= false -> - Password = xml:get_tag_cdata(PTag), + Password = fxml:get_tag_cdata(PTag), case ejabberd_auth:remove_user(User, Server, Password) of @@ -185,8 +185,8 @@ process_iq(From, To, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]} end; (UTag /= false) and (PTag /= false) -> - User = xml:get_tag_cdata(UTag), - Password = xml:get_tag_cdata(PTag), + User = fxml:get_tag_cdata(UTag), + Password = fxml:get_tag_cdata(PTag), try_register_or_set_password(User, Server, Password, From, IQ, SubEl, Source, Lang, not IsCaptchaEnabled); @@ -599,7 +599,7 @@ write_time({{Y, Mo, D}, {H, Mi, S}}) -> [Y, Mo, D, H, Mi, S]). process_xdata_submit(El) -> - case xml:get_subtag(El, <<"x">>) of + case fxml:get_subtag(El, <<"x">>) of false -> error; Xdata -> Fields = jlib:parse_xdata_submit(Xdata), diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 278e9cb99ef..f68300763a3 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -267,7 +267,7 @@ process_iq_get(From, To, #iq{sub_el = SubEl} = IQ) -> LServer = From#jid.lserver, US = {LUser, LServer}, try {ItemsToSend, VersionToSend} = case - {xml:get_tag_attr(<<"ver">>, SubEl), + {fxml:get_tag_attr(<<"ver">>, SubEl), roster_versioning_enabled(LServer), roster_version_on_db(LServer)} of @@ -516,7 +516,7 @@ process_iq_set(From, To, #iq{sub_el = SubEl, id = Id} = IQ) -> process_item_set(From, To, #xmlel{attrs = Attrs, children = Els}, Managed) -> - JID1 = jid:from_string(xml:get_attr_s(<<"jid">>, + JID1 = jid:from_string(fxml:get_attr_s(<<"jid">>, Attrs)), #jid{user = User, luser = LUser, lserver = LServer} = From, @@ -585,10 +585,10 @@ process_item_els(Item, | Els]) -> case Name of <<"group">> -> - Groups = [xml:get_cdata(SEls) | Item#roster.groups], + Groups = [fxml:get_cdata(SEls) | Item#roster.groups], process_item_els(Item#roster{groups = Groups}, Els); _ -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of <<"">> -> process_item_els(Item, Els); _ -> XEls = [#xmlel{name = Name, attrs = Attrs, @@ -1089,7 +1089,7 @@ del_roster_t(LUser, LServer, LJID, riak) -> process_item_set_t(LUser, LServer, #xmlel{attrs = Attrs, children = Els}) -> - JID1 = jid:from_string(xml:get_attr_s(<<"jid">>, + JID1 = jid:from_string(fxml:get_attr_s(<<"jid">>, Attrs)), case JID1 of error -> ok; @@ -1390,7 +1390,7 @@ update_roster_table() -> groups = [iolist_to_binary(G) || G <- Gs], askmessage = try iolist_to_binary(Ask) catch _:_ -> <<"">> end, - xs = [xml:to_xmlel(X) || X <- Xs]} + xs = [fxml:to_xmlel(X) || X <- Xs]} end); _ -> ?INFO_MSG("Recreating roster table", []), diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index cde0f66b862..1e9e91910b5 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -206,11 +206,11 @@ get_rosteritem_name([ModVcard], U, S) -> get_rosteritem_name_vcard([]) -> <<"">>; get_rosteritem_name_vcard([Vcard]) -> - case xml:get_path_s(Vcard, + case fxml:get_path_s(Vcard, [{elem, <<"NICKNAME">>}, cdata]) of <<"">> -> - xml:get_path_s(Vcard, [{elem, <<"FN">>}, cdata]); + fxml:get_path_s(Vcard, [{elem, <<"FN">>}, cdata]); Nickname -> Nickname end. diff --git a/src/mod_stats.erl b/src/mod_stats.erl index c9f659d3c7c..0328aec3002 100644 --- a/src/mod_stats.erl +++ b/src/mod_stats.erl @@ -57,7 +57,7 @@ process_local_iq(_From, To, IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}; get -> #xmlel{children = Els} = SubEl, - Node = str:tokens(xml:get_tag_attr_s(<<"node">>, SubEl), + Node = str:tokens(fxml:get_tag_attr_s(<<"node">>, SubEl), <<"/">>), Names = get_names(Els, []), case get_local_stats(To#jid.server, Node, Names) of @@ -76,7 +76,7 @@ get_names([], Res) -> Res; get_names([#xmlel{name = <<"stat">>, attrs = Attrs} | Els], Res) -> - Name = xml:get_attr_s(<<"name">>, Attrs), + Name = fxml:get_attr_s(<<"name">>, Attrs), case Name of <<"">> -> get_names(Els, Res); _ -> get_names(Els, [Name | Res]) diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index daeccb352fa..b9b207a7d4f 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -215,7 +215,7 @@ get_vcard(LUser, LServer, odbc) -> Username = ejabberd_odbc:escape(LUser), case catch odbc_queries:get_vcard(LServer, Username) of {selected, [<<"vcard">>], [[SVCARD]]} -> - case xml_stream:parse_element(SVCARD) of + case fxml_stream:parse_element(SVCARD) of {error, _Reason} -> error; VCARD -> [VCARD] end; @@ -233,29 +233,29 @@ get_vcard(LUser, LServer, riak) -> end. set_vcard(User, LServer, VCARD) -> - FN = xml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]), - Family = xml:get_path_s(VCARD, + FN = fxml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]), + Family = fxml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"FAMILY">>}, cdata]), - Given = xml:get_path_s(VCARD, + Given = fxml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"GIVEN">>}, cdata]), - Middle = xml:get_path_s(VCARD, + Middle = fxml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"MIDDLE">>}, cdata]), - Nickname = xml:get_path_s(VCARD, + Nickname = fxml:get_path_s(VCARD, [{elem, <<"NICKNAME">>}, cdata]), - BDay = xml:get_path_s(VCARD, + BDay = fxml:get_path_s(VCARD, [{elem, <<"BDAY">>}, cdata]), - CTRY = xml:get_path_s(VCARD, + CTRY = fxml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"CTRY">>}, cdata]), - Locality = xml:get_path_s(VCARD, + Locality = fxml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"LOCALITY">>}, cdata]), - EMail1 = xml:get_path_s(VCARD, + EMail1 = fxml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, {elem, <<"USERID">>}, cdata]), - EMail2 = xml:get_path_s(VCARD, + EMail2 = fxml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, cdata]), - OrgName = xml:get_path_s(VCARD, + OrgName = fxml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGNAME">>}, cdata]), - OrgUnit = xml:get_path_s(VCARD, + OrgUnit = fxml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGUNIT">>}, cdata]), EMail = case EMail1 of <<"">> -> EMail2; @@ -339,7 +339,7 @@ set_vcard(User, LServer, VCARD) -> Username = ejabberd_odbc:escape(User), LUsername = ejabberd_odbc:escape(LUser), SVCARD = - ejabberd_odbc:escape(xml:element_to_binary(VCARD)), + ejabberd_odbc:escape(fxml:element_to_binary(VCARD)), SFN = ejabberd_odbc:escape(FN), SLFN = ejabberd_odbc:escape(LFN), SFamily = ejabberd_odbc:escape(Family), @@ -587,7 +587,7 @@ find_xdata_el1([]) -> false; find_xdata_el1([#xmlel{name = Name, attrs = Attrs, children = SubEls} | Els]) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> #xmlel{name = Name, attrs = Attrs, children = SubEls}; _ -> find_xdata_el1(Els) @@ -862,27 +862,27 @@ set_vcard_t(R, _) -> US = R#vcard.us, User = US, VCARD = R#vcard.vcard, - FN = xml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]), - Family = xml:get_path_s(VCARD, + FN = fxml:get_path_s(VCARD, [{elem, <<"FN">>}, cdata]), + Family = fxml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"FAMILY">>}, cdata]), - Given = xml:get_path_s(VCARD, + Given = fxml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"GIVEN">>}, cdata]), - Middle = xml:get_path_s(VCARD, + Middle = fxml:get_path_s(VCARD, [{elem, <<"N">>}, {elem, <<"MIDDLE">>}, cdata]), - Nickname = xml:get_path_s(VCARD, + Nickname = fxml:get_path_s(VCARD, [{elem, <<"NICKNAME">>}, cdata]), - BDay = xml:get_path_s(VCARD, + BDay = fxml:get_path_s(VCARD, [{elem, <<"BDAY">>}, cdata]), - CTRY = xml:get_path_s(VCARD, + CTRY = fxml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"CTRY">>}, cdata]), - Locality = xml:get_path_s(VCARD, + Locality = fxml:get_path_s(VCARD, [{elem, <<"ADR">>}, {elem, <<"LOCALITY">>}, cdata]), - EMail = xml:get_path_s(VCARD, + EMail = fxml:get_path_s(VCARD, [{elem, <<"EMAIL">>}, cdata]), - OrgName = xml:get_path_s(VCARD, + OrgName = fxml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGNAME">>}, cdata]), - OrgUnit = xml:get_path_s(VCARD, + OrgUnit = fxml:get_path_s(VCARD, [{elem, <<"ORG">>}, {elem, <<"ORGUNIT">>}, cdata]), {LUser, _LServer} = US, LFN = string2lower(FN), @@ -952,7 +952,7 @@ update_vcard_table() -> fun(#vcard{us = {U, S}, vcard = El} = R) -> R#vcard{us = {iolist_to_binary(U), iolist_to_binary(S)}, - vcard = xml:to_xmlel(El)} + vcard = fxml:to_xmlel(El)} end); _ -> ?INFO_MSG("Recreating vcard table", []), @@ -991,7 +991,7 @@ export(_Server) -> when LServer == Host -> Username = ejabberd_odbc:escape(LUser), SVCARD = - ejabberd_odbc:escape(xml:element_to_binary(VCARD)), + ejabberd_odbc:escape(fxml:element_to_binary(VCARD)), [[<<"delete from vcard where username='">>, Username, <<"';">>], [<<"insert into vcard(username, vcard) values ('">>, Username, <<"', '">>, SVCARD, <<"');">>]]; @@ -1064,7 +1064,7 @@ export(_Server) -> import(LServer) -> [{<<"select username, vcard from vcard;">>, fun([LUser, SVCard]) -> - #xmlel{} = VCARD = xml_stream:parse_element(SVCard), + #xmlel{} = VCARD = fxml_stream:parse_element(SVCard), #vcard{us = {LUser, LServer}, vcard = VCARD} end}, {<<"select username, lusername, fn, lfn, family, lfamily, " @@ -1095,29 +1095,29 @@ import(_LServer, mnesia, #vcard{} = VCard) -> import(_LServer, mnesia, #vcard_search{} = S) -> mnesia:dirty_write(S); import(_LServer, riak, #vcard{us = {LUser, _}, vcard = El} = VCard) -> - FN = xml:get_path_s(El, [{elem, <<"FN">>}, cdata]), - Family = xml:get_path_s(El, + FN = fxml:get_path_s(El, [{elem, <<"FN">>}, cdata]), + Family = fxml:get_path_s(El, [{elem, <<"N">>}, {elem, <<"FAMILY">>}, cdata]), - Given = xml:get_path_s(El, + Given = fxml:get_path_s(El, [{elem, <<"N">>}, {elem, <<"GIVEN">>}, cdata]), - Middle = xml:get_path_s(El, + Middle = fxml:get_path_s(El, [{elem, <<"N">>}, {elem, <<"MIDDLE">>}, cdata]), - Nickname = xml:get_path_s(El, + Nickname = fxml:get_path_s(El, [{elem, <<"NICKNAME">>}, cdata]), - BDay = xml:get_path_s(El, + BDay = fxml:get_path_s(El, [{elem, <<"BDAY">>}, cdata]), - CTRY = xml:get_path_s(El, + CTRY = fxml:get_path_s(El, [{elem, <<"ADR">>}, {elem, <<"CTRY">>}, cdata]), - Locality = xml:get_path_s(El, + Locality = fxml:get_path_s(El, [{elem, <<"ADR">>}, {elem, <<"LOCALITY">>}, cdata]), - EMail1 = xml:get_path_s(El, + EMail1 = fxml:get_path_s(El, [{elem, <<"EMAIL">>}, {elem, <<"USERID">>}, cdata]), - EMail2 = xml:get_path_s(El, + EMail2 = fxml:get_path_s(El, [{elem, <<"EMAIL">>}, cdata]), - OrgName = xml:get_path_s(El, + OrgName = fxml:get_path_s(El, [{elem, <<"ORG">>}, {elem, <<"ORGNAME">>}, cdata]), - OrgUnit = xml:get_path_s(El, + OrgUnit = fxml:get_path_s(El, [{elem, <<"ORG">>}, {elem, <<"ORGUNIT">>}, cdata]), EMail = case EMail1 of <<"">> -> EMail2; diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index b24356d8e59..25239133c1b 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -21,7 +21,7 @@ %%% with this program; if not, write to the Free Software Foundation, Inc., %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% -%%%---------------------------------------------------------------------- +%%%---------------------u------------------------------------------------- -module(mod_vcard_ldap). @@ -723,7 +723,7 @@ find_xdata_el1([]) -> false; find_xdata_el1([#xmlel{name = Name, attrs = Attrs, children = SubEls} | Els]) -> - case xml:get_attr_s(<<"xmlns">>, Attrs) of + case fxml:get_attr_s(<<"xmlns">>, Attrs) of ?NS_XDATA -> #xmlel{name = Name, attrs = Attrs, children = SubEls}; _ -> find_xdata_el1(Els) diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index 96ee09d8730..18fb09a58fb 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -56,7 +56,7 @@ stop(Host) -> update_presence(#xmlel{name = <<"presence">>, attrs = Attrs} = Packet, User, Host) -> - case xml:get_attr_s(<<"type">>, Attrs) of + case fxml:get_attr_s(<<"type">>, Attrs) of <<>> -> presence_with_xupdate(Packet, User, Host); _ -> Packet end; @@ -64,7 +64,7 @@ update_presence(Packet, _User, _Host) -> Packet. vcard_set(LUser, LServer, VCARD) -> US = {LUser, LServer}, - case xml:get_path_s(VCARD, + case fxml:get_path_s(VCARD, [{elem, <<"PHOTO">>}, {elem, <<"BINVAL">>}, cdata]) of <<>> -> remove_xupdate(LUser, LServer); diff --git a/src/node_flat_odbc.erl b/src/node_flat_odbc.erl index 794d3f986bc..e3c57938274 100644 --- a/src/node_flat_odbc.erl +++ b/src/node_flat_odbc.erl @@ -824,7 +824,7 @@ set_item(Item) -> {M, JID} = Item#pubsub_item.modification, P = encode_jid(JID), Payload = Item#pubsub_item.payload, - XML = ejabberd_odbc:escape(str:join([xml:element_to_binary(X) || X<-Payload], <<>>)), + XML = ejabberd_odbc:escape(str:join([fxml:element_to_binary(X) || X<-Payload], <<>>)), S = fun ({T1, T2, T3}) -> str:join([jlib:i2l(T1, 6), jlib:i2l(T2, 6), jlib:i2l(T3, 6)], <<":">>) end, @@ -1041,7 +1041,7 @@ raw_to_item(Nidx, [ItemId, SJID, Creation, Modification, XML]) -> [T1, T2, T3] = str:tokens(Str, <<":">>), {jlib:l2i(T1), jlib:l2i(T2), jlib:l2i(T3)} end, - Payload = case xml_stream:parse_element(XML) of + Payload = case fxml_stream:parse_element(XML) of {error, _Reason} -> []; El -> [El] end, diff --git a/src/prosody2ejabberd.erl b/src/prosody2ejabberd.erl index d16437209c6..204cfec2f3b 100644 --- a/src/prosody2ejabberd.erl +++ b/src/prosody2ejabberd.erl @@ -123,7 +123,7 @@ convert_data(Host, "private", User, [Data]) -> fun({_TagXMLNS, Raw}) -> case deserialize(Raw) of [El] -> - XMLNS = xml:get_tag_attr_s(<<"xmlns">>, El), + XMLNS = fxml:get_tag_attr_s(<<"xmlns">>, El), [{XMLNS, El}]; _ -> [] @@ -301,7 +301,7 @@ convert_privacy_item({_, Item}) -> el_to_offline_msg(LUser, LServer, #xmlel{attrs = Attrs} = El) -> case jlib:datetime_string_to_timestamp( - xml:get_attr_s(<<"stamp">>, Attrs)) of + fxml:get_attr_s(<<"stamp">>, Attrs)) of {_, _, _} = TS -> Attrs1 = lists:filter( fun(<<"stamp">>) -> false; @@ -309,8 +309,8 @@ el_to_offline_msg(LUser, LServer, #xmlel{attrs = Attrs} = El) -> (_) -> true end, Attrs), Packet = El#xmlel{attrs = Attrs1}, - case {jid:from_string(xml:get_attr_s(<<"from">>, Attrs)), - jid:from_string(xml:get_attr_s(<<"to">>, Attrs))} of + case {jid:from_string(fxml:get_attr_s(<<"from">>, Attrs)), + jid:from_string(fxml:get_attr_s(<<"to">>, Attrs))} of {#jid{} = From, #jid{} = To} -> [#offline_msg{ us = {LUser, LServer}, diff --git a/src/pubsub_subscription.erl b/src/pubsub_subscription.erl index 9918a2c3553..22c90414408 100644 --- a/src/pubsub_subscription.erl +++ b/src/pubsub_subscription.erl @@ -126,7 +126,7 @@ get_options_xform(Lang, Options) -> ++ XFields}}. parse_options_xform(XFields) -> - case xml:remove_cdata(XFields) of + case fxml:remove_cdata(XFields) of [#xmlel{name = <<"x">>} = XEl] -> case jlib:parse_xdata_submit(XEl) of XData when is_list(XData) -> diff --git a/src/pubsub_subscription_odbc.erl b/src/pubsub_subscription_odbc.erl index 6791c4ac73a..149308ad091 100644 --- a/src/pubsub_subscription_odbc.erl +++ b/src/pubsub_subscription_odbc.erl @@ -151,7 +151,7 @@ get_options_xform(Lang, Options) -> ++ XFields}}. parse_options_xform(XFields) -> - case xml:remove_cdata(XFields) of + case fxml:remove_cdata(XFields) of [#xmlel{name = <<"x">>} = XEl] -> case jlib:parse_xdata_submit(XEl) of XData when is_list(XData) -> From 89dda473cfc19659205bfbbb64e034fb2307876c Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 3 Feb 2016 19:22:59 +0100 Subject: [PATCH 550/695] Convert tests to Fast XML --- test/suite.erl | 12 ++++++------ test/suite.hrl | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/suite.erl b/test/suite.erl index 74d9b0628cf..e04b9d980e8 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -94,8 +94,8 @@ init_stream(Config) -> ok = send_text(Config, io_lib:format(?STREAM_HEADER, [?config(server, Config)])), {xmlstreamstart, <<"stream:stream">>, Attrs} = recv(), - <<"jabber:client">> = xml:get_attr_s(<<"xmlns">>, Attrs), - <<"1.0">> = xml:get_attr_s(<<"version">>, Attrs), + <<"jabber:client">> = fxml:get_attr_s(<<"xmlns">>, Attrs), + <<"1.0">> = fxml:get_attr_s(<<"version">>, Attrs), #stream_features{sub_els = Fs} = recv(), Mechs = lists:flatmap( fun(#sasl_mechanisms{list = Ms}) -> @@ -182,8 +182,8 @@ wait_auth_SASL_result(Config) -> io_lib:format(?STREAM_HEADER, [?config(server, Config)])), {xmlstreamstart, <<"stream:stream">>, Attrs} = recv(), - <<"jabber:client">> = xml:get_attr_s(<<"xmlns">>, Attrs), - <<"1.0">> = xml:get_attr_s(<<"version">>, Attrs), + <<"jabber:client">> = fxml:get_attr_s(<<"xmlns">>, Attrs), + <<"1.0">> = fxml:get_attr_s(<<"version">>, Attrs), #stream_features{sub_els = Fs} = recv(), lists:foldl( fun(#feature_sm{}, ConfigAcc) -> @@ -255,7 +255,7 @@ send(State, Pkt) -> end, El = xmpp_codec:encode(NewPkt), ct:pal("sent: ~p <-~n~s", [El, xmpp_codec:pp(NewPkt)]), - ok = send_text(State, xml:element_to_binary(El)), + ok = send_text(State, fxml:element_to_binary(El)), NewID. send_recv(State, IQ) -> @@ -271,7 +271,7 @@ sasl_new(<<"DIGEST-MD5">>, User, Server, Password) -> case cyrsasl_digest:parse(ServerIn) of bad -> {error, <<"Invalid SASL challenge">>}; KeyVals -> - Nonce = xml:get_attr_s(<<"nonce">>, KeyVals), + Nonce = fxml:get_attr_s(<<"nonce">>, KeyVals), CNonce = id(), Realm = proplists:get_value(<<"realm">>, KeyVals, Server), DigestURI = <<"xmpp/", Realm/binary>>, diff --git a/test/suite.hrl b/test/suite.hrl index 5463575a829..5638fdb75d6 100644 --- a/test/suite.hrl +++ b/test/suite.hrl @@ -1,5 +1,5 @@ -include_lib("common_test/include/ct.hrl"). --include_lib("p1_xml/include/xml.hrl"). +-include_lib("fast_xml/include/fxml.hrl"). -include("ns.hrl"). -include("ejabberd.hrl"). -include("mod_proxy65.hrl"). From 942072cf9d7bfaab4b35e2414dceb75a671cfe1a Mon Sep 17 00:00:00 2001 From: Pablo Polvorin Date: Thu, 4 Feb 2016 15:45:29 -0300 Subject: [PATCH 551/695] Make hibernate timeouts configurable Two *global* options added: c2s_hibernate and receiver_hibernate. Default if not specified is 90000, the previous hardcoded value. --- src/ejabberd_c2s.erl | 2 +- src/ejabberd_receiver.erl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index ad7590ebb11..19fde38ff1e 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -133,7 +133,7 @@ %% session: -define(C2S_OPEN_TIMEOUT, 60000). --define(C2S_HIBERNATE_TIMEOUT, 90000). +-define(C2S_HIBERNATE_TIMEOUT, ejabberd_config:get_option(c2s_hibernate, fun(X) when is_integer(X); X == hibernate-> X end, 90000)). -define(STREAM_HEADER, <<" X end, 90000)). + -spec start_link(inet:socket(), atom(), shaper:shaper(), non_neg_integer() | infinity) -> ignore | From 30388fa2bf1ba520cf83fb58cda2e9f24e60c028 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Dr=C3=B6ge?= Date: Thu, 4 Feb 2016 21:31:16 +0100 Subject: [PATCH 552/695] Allow to modify host when deleting account or changing password over web --- src/mod_register_web.erl | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index 35f52f3b20c..0bdebaca8bb 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -113,8 +113,8 @@ process([<<"new">>], end; process([<<"delete">>], #request{method = 'POST', q = Q, lang = Lang, - host = Host}) -> - case form_del_post(Q, Host) of + host = _HTTPHost}) -> + case form_del_post(Q) of {atomic, ok} -> Text = (?T(<<"Your Jabber account was successfully " "deleted.">>)), @@ -129,8 +129,8 @@ process([<<"delete">>], %% should include the host where the POST was sent. process([<<"change_password">>], #request{method = 'POST', q = Q, lang = Lang, - host = Host}) -> - case form_changepass_post(Q, Host) of + host = _HTTPHost}) -> + case form_changepass_post(Q) of {atomic, ok} -> Text = (?T(<<"The password of your Jabber account " "was successfully changed.">>)), @@ -361,7 +361,8 @@ form_changepass_get(Host, Lang) -> ?INPUTS(<<"text">>, <<"username">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, - [?CT(<<"Server:">>), ?C(<<" ">>), ?C(Host)]), + [?CT(<<"Server:">>), ?C(<<" ">>), + ?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Old Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"passwordold">>, <<"">>, @@ -386,9 +387,9 @@ form_changepass_get(Host, Lang) -> %%% Formulary change password POST %%%---------------------------------------------------------------------- -form_changepass_post(Q, Host) -> +form_changepass_post(Q) -> case catch get_changepass_parameters(Q) of - [Username, PasswordOld, Password, Password] -> + [Username, Host, PasswordOld, Password, Password] -> try_change_password(Username, Host, PasswordOld, Password); [_Username, _PasswordOld, _Password, _Password2] -> @@ -405,7 +406,7 @@ get_changepass_parameters(Q) -> {value, {_Key, Value}} = lists:keysearch(Key, 1, Q), Value end, - [<<"username">>, <<"passwordold">>, <<"password">>, + [<<"username">>, <<"host">>, <<"passwordold">>, <<"password">>, <<"password2">>]). try_change_password(Username, Host, PasswordOld, @@ -470,7 +471,8 @@ form_del_get(Host, Lang) -> ?INPUTS(<<"text">>, <<"username">>, <<"">>, <<"20">>)]), ?XE(<<"li">>, - [?CT(<<"Server:">>), ?C(<<" ">>), ?C(Host)]), + [?CT(<<"Server:">>), ?C(<<" ">>), + ?INPUTS(<<"text">>, <<"host">>, Host, <<"20">>)]), ?XE(<<"li">>, [?CT(<<"Password:">>), ?C(<<" ">>), ?INPUTS(<<"password">>, <<"password">>, <<"">>, @@ -513,9 +515,9 @@ register_account2(Username, Host, Password) -> %%% Formulary delete POST %%%---------------------------------------------------------------------- -form_del_post(Q, Host) -> +form_del_post(Q) -> case catch get_unregister_parameters(Q) of - [Username, Password] -> + [Username, Host, Password] -> try_unregister_account(Username, Host, Password); _ -> {error, wrong_parameters} end. @@ -529,7 +531,7 @@ get_unregister_parameters(Q) -> {value, {_Key, Value}} = lists:keysearch(Key, 1, Q), Value end, - [<<"username">>, <<"password">>]). + [<<"username">>, <<"host">>, <<"password">>]). try_unregister_account(Username, Host, Password) -> try unregister_account(Username, Host, Password) of From 268f0b30ec4f085179ed7e53659463c241d8e0ee Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Thu, 14 Jan 2016 23:08:31 +0900 Subject: [PATCH 553/695] add room_id_regexp option --- src/mod_muc.erl | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index f7c6d26de36..c887b964d6b 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -597,7 +597,8 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, case {Name, Type} of {<<"presence">>, <<"">>} -> case check_user_can_create_room(ServerHost, - AccessCreate, From, Room) of + AccessCreate, From, Room) and + check_create_roomid(ServerHost, Room) of true -> {ok, Pid} = start_new_room(Host, ServerHost, Access, Room, HistorySize, @@ -628,17 +629,22 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper, end. check_user_can_create_room(ServerHost, AccessCreate, - From, RoomID) -> + From, _RoomID) -> case acl:match_rule(ServerHost, AccessCreate, From) of - allow -> - byte_size(RoomID) =< - gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id, - fun(infinity) -> infinity; - (I) when is_integer(I), I>0 -> I - end, infinity); + allow -> true; _ -> false end. +check_create_roomid(ServerHost, RoomID) -> + Max = gen_mod:get_module_opt(ServerHost, ?MODULE, max_room_id, + fun(infinity) -> infinity; + (I) when is_integer(I), I>0 -> I + end, infinity), + Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, room_id_regexp, + fun iolist_to_binary/1, ""), + (byte_size(RoomID) =< Max) and + (re:run(RoomID, Regexp, [unicode, {capture, none}]) == match). + get_rooms(ServerHost, Host) -> LServer = jid:nameprep(ServerHost), get_rooms(LServer, Host, @@ -1317,6 +1323,8 @@ mod_opt_type(max_room_id) -> fun (infinity) -> infinity; (I) when is_integer(I), I > 0 -> I end; +mod_opt_type(room_id_regexp) -> + fun iolist_to_binary/1; mod_opt_type(max_room_name) -> fun (infinity) -> infinity; (I) when is_integer(I), I > 0 -> I @@ -1342,7 +1350,7 @@ mod_opt_type(user_presence_shaper) -> mod_opt_type(_) -> [access, access_admin, access_create, access_persistent, db_type, default_room_options, history_size, host, - max_room_desc, max_room_id, max_room_name, + max_room_desc, max_room_id, max_room_name, room_id_regexp, max_user_conferences, max_users, max_users_admin_threshold, max_users_presence, min_message_interval, min_presence_interval, From 7435ee464f3918be41f60901bbfdb87a9cc9b249 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 5 Feb 2016 12:08:40 +0100 Subject: [PATCH 554/695] Rename option to regexp_room_id for consistency with other options (#905) --- src/mod_muc.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index c887b964d6b..de795fc0e35 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -640,7 +640,7 @@ check_create_roomid(ServerHost, RoomID) -> fun(infinity) -> infinity; (I) when is_integer(I), I>0 -> I end, infinity), - Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, room_id_regexp, + Regexp = gen_mod:get_module_opt(ServerHost, ?MODULE, regexp_room_id, fun iolist_to_binary/1, ""), (byte_size(RoomID) =< Max) and (re:run(RoomID, Regexp, [unicode, {capture, none}]) == match). @@ -1323,7 +1323,7 @@ mod_opt_type(max_room_id) -> fun (infinity) -> infinity; (I) when is_integer(I), I > 0 -> I end; -mod_opt_type(room_id_regexp) -> +mod_opt_type(regexp_room_id) -> fun iolist_to_binary/1; mod_opt_type(max_room_name) -> fun (infinity) -> infinity; @@ -1350,7 +1350,7 @@ mod_opt_type(user_presence_shaper) -> mod_opt_type(_) -> [access, access_admin, access_create, access_persistent, db_type, default_room_options, history_size, host, - max_room_desc, max_room_id, max_room_name, room_id_regexp, + max_room_desc, max_room_id, max_room_name, regexp_room_id, max_user_conferences, max_users, max_users_admin_threshold, max_users_presence, min_message_interval, min_presence_interval, From f44bf00e0db98b0ad984c69d63b1a566eb4bc3bd Mon Sep 17 00:00:00 2001 From: Nikolaus Polak Date: Sat, 6 Feb 2016 09:25:39 +0100 Subject: [PATCH 555/695] Update German translation --- priv/msgs/de.po | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/priv/msgs/de.po b/priv/msgs/de.po index 4f3d2a370de..09df3e9a977 100644 --- a/priv/msgs/de.po +++ b/priv/msgs/de.po @@ -16,7 +16,7 @@ msgstr "" "X-Additional-Translator: Patrick Dreker\n" "X-Additional-Translator: Torsten Werner\n" "X-Additional-Translator: Marina Hahn\n" -"X-Generator: Poedit 1.8.4\n" +"X-Generator: Poedit 1.8.6\n" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" @@ -72,9 +72,8 @@ msgid "User" msgstr "Benutzer" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Server:" +msgstr "Server" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -84,7 +83,7 @@ msgstr "Passwort" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Akzeptieren" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -156,8 +155,7 @@ msgstr "Virtuelle Hosts" msgid "Users" msgstr "Benutzer" -#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 -#: mod_configure.erl:524 +#: ejabberd_web_admin.erl:955 ejabberd_web_admin.erl:1340 mod_configure.erl:524 msgid "Online Users" msgstr "Angemeldete Benutzer" @@ -251,9 +249,8 @@ msgid "Outgoing s2s Connections:" msgstr "Ausgehende s2s-Verbindungen:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" -msgstr "Ausgehende s2s-Verbindungen:" +msgstr "Eingehende s2s-Verbindungen:" #: ejabberd_web_admin.erl:1595 ejabberd_web_admin.erl:1794 #: ejabberd_web_admin.erl:1804 ejabberd_web_admin.erl:2214 mod_roster.erl:1429 @@ -855,11 +852,11 @@ msgstr "" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Bitte geben Sie die Dateigröße an." #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Bitte geben Sie den Dateinamen an." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" @@ -978,9 +975,8 @@ msgid "Server ~b" msgstr "Server ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Nur Moderatoren dürfen das Thema in diesem Raum ändern" +msgstr "Nur Mitglieder dürfen den Verlauf dieses Raumes abrufen" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -1001,7 +997,7 @@ msgstr "Chaträume" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Leere Räume" #: mod_muc.erl:933 msgid "You need a client that supports x:data to register the nickname" @@ -1011,7 +1007,7 @@ msgstr "" #: mod_muc.erl:943 msgid "Nickname Registration at " -msgstr "Registrieren des Benutzernames auf" +msgstr "Registrieren des Benutzernames auf " #: mod_muc.erl:949 msgid "Enter nickname you want to register" @@ -1045,7 +1041,7 @@ msgstr "Alle Chaträume" #: mod_muc_admin.erl:250 msgid "Permanent rooms" -msgstr "permanente Chaträume" +msgstr "Permanente Chaträume" #: mod_muc_admin.erl:251 msgid "Registered nicknames" @@ -1200,6 +1196,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"Es ist nicht erlaubt Fehlermeldungen an den Raum zu senden. Der Teilnehmer " +"(~s) hat eine Fehlermeldung (~s) gesendet und wurde aus dem Raum entfernt" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1377,20 +1375,19 @@ msgstr "jeden" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Rollen, für die der Status übertragen wird" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "ausschliesslich Moderatoren" +msgstr "Moderator" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Teilnehmer" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Besucher" #: mod_muc_room.erl:3513 msgid "Make room members-only" From a31f59ea31d28e1b00c05e1d6147c76e5b566cf5 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 6 Feb 2016 22:28:55 +0100 Subject: [PATCH 556/695] XEP-0198: Fix session timeout corner case If the "resend_on_timeout" option is set to 'if_offline' and a pending stream management session is terminated because a new session is opened by the same resource (while no other resource is online), resend unacknowledged messages rather than bouncing error messages. --- src/ejabberd_c2s.erl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 19fde38ff1e..8959ae50e57 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -2833,8 +2833,16 @@ handle_unacked_stanzas(StateData) Resend when is_boolean(Resend) -> Resend; if_offline -> - ejabberd_sm:get_user_resources(StateData#state.user, - StateData#state.server) == [] + Resource = StateData#state.resource, + case ejabberd_sm:get_user_resources(StateData#state.user, + StateData#state.server) of + [Resource] -> % Same resource opened new session + true; + [] -> + true; + _ -> + false + end end, ReRoute = case ResendOnTimeout of true -> From 8098f7d9a884ebc01bb160564e58582b9c8e2b2b Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 8 Feb 2016 00:16:02 +0100 Subject: [PATCH 557/695] mod_mam: Don't let outcasts access MUC archive XEP-0313 says: "A MUC archive MUST check that the user requesting the archive has the right to enter it at the time of the query [...]. In the case of open MUC rooms, the MUC archives can generally be accessed by any users [...] who do not have an affiliation of 'outcast'". --- src/mod_mam.erl | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index 62f333555b2..a83c1a64732 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -529,11 +529,8 @@ process_iq(LServer, #jid{luser = LUser} = From, To, IQ, SubEl, Fs, MsgType) -> With, limit_max(RSM, NS), IQ, MsgType) end. -muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ, - #state{config = #config{members_only = MembersOnly}} = MUCState, - From, To, Fs) -> - case not MembersOnly orelse - mod_muc_room:is_occupant_or_admin(From, MUCState) of +muc_process_iq(#iq{lang = Lang, sub_el = SubEl} = IQ, MUCState, From, To, Fs) -> + case may_enter_room(From, MUCState) of true -> LServer = MUCState#state.server_host, Role = mod_muc_room:get_role(From, MUCState), @@ -714,6 +711,12 @@ is_resent(Pkt, LServer) -> false end. +may_enter_room(From, + #state{config = #config{members_only = false}} = MUCState) -> + mod_muc_room:get_affiliation(From, MUCState) /= outcast; +may_enter_room(From, MUCState) -> + mod_muc_room:is_occupant_or_admin(From, MUCState). + store_msg(C2SState, Pkt, LUser, LServer, Peer, Dir) -> Prefs = get_prefs(LUser, LServer), case should_archive_peer(C2SState, Prefs, Peer) of From bf49c292f8374c6b61523deceec655bde705f817 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 8 Feb 2016 00:46:33 +0100 Subject: [PATCH 558/695] Omit redundant check for overcrowded MUC room The send_update_presence/4 function already checked whether the room is overcrowded before calling send_update_presence1/4, so there's no need to have send_new_presence/4 perform the same check. --- src/mod_muc_room.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 3c5776de1ae..1b3b9c2bb71 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2117,7 +2117,7 @@ send_update_presence1(JID, Reason, StateData, OldStateData) -> end end, lists:foreach(fun (J) -> - send_new_presence(J, Reason, StateData, OldStateData) + send_new_presence1(J, Reason, StateData, OldStateData) end, LJIDs). From 0b1620a45c584b126390f8826cb5168f97ad0945 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 8 Feb 2016 10:50:28 +0100 Subject: [PATCH 559/695] Remove compile warnings --- src/ejabberd_oauth.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ejabberd_oauth.erl b/src/ejabberd_oauth.erl index a688bb39ea0..1925a2f78e0 100644 --- a/src/ejabberd_oauth.erl +++ b/src/ejabberd_oauth.erl @@ -149,7 +149,7 @@ authenticate_user({User, Server}, {password, Password} = Ctx) -> authenticate_client(Client, Ctx) -> {ok, {Ctx, {client, Client}}}. -verify_resowner_scope({user, User, Server}, Scope, Ctx) -> +verify_resowner_scope({user, _User, _Server}, Scope, Ctx) -> Cmds = ejabberd_commands:get_commands(), Cmds1 = [sasl_auth | Cmds], RegisteredScope = [atom_to_binary(C, utf8) || C <- Cmds1], @@ -164,7 +164,7 @@ verify_resowner_scope(_, _, _) -> {error, badscope}. -associate_access_code(AccessCode, Context, AppContext) -> +associate_access_code(_AccessCode, _Context, AppContext) -> %put(?ACCESS_CODE_TABLE, AccessCode, Context), {ok, AppContext}. @@ -184,7 +184,7 @@ associate_access_token(AccessToken, Context, AppContext) -> mnesia:dirty_write(R), {ok, AppContext}. -associate_refresh_token(RefreshToken, Context, AppContext) -> +associate_refresh_token(_RefreshToken, _Context, AppContext) -> %put(?REFRESH_TOKEN_TABLE, RefreshToken, Context), {ok, AppContext}. @@ -303,7 +303,7 @@ process(_Handlers, process(_Handlers, #request{method = 'POST', q = Q, lang = _Lang, path = [_, <<"authorization_token">>]}) -> - ResponseType = proplists:get_value(<<"response_type">>, Q, <<"">>), + _ResponseType = proplists:get_value(<<"response_type">>, Q, <<"">>), ClientId = proplists:get_value(<<"client_id">>, Q, <<"">>), RedirectURI = proplists:get_value(<<"redirect_uri">>, Q, <<"">>), SScope = proplists:get_value(<<"scope">>, Q, <<"">>), From ed30bd64cd7f663860ed41e0db1e6a0532b9594a Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 8 Feb 2016 10:54:05 +0100 Subject: [PATCH 560/695] Preparing to release beta package on hex.pm --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index cdba398dd47..e9f19559cdb 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "16.01.0", + version: "16.01.0-beta1", description: description, elixir: "~> 1.1", elixirc_paths: ["lib"], From 3af055fabe55c4d5cdd1ee1ff1d8f30f66b09c36 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 8 Feb 2016 11:34:52 +0100 Subject: [PATCH 561/695] Link to Hex.pm --- README | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README b/README index 44026f67e1e..b0dff0720bb 100644 --- a/README +++ b/README @@ -1,5 +1,7 @@ -ejabberd Community Edition [![Build Status](https://travis-ci.org/processone/ejabberd.svg?branch=master)](https://travis-ci.org/processone/ejabberd) -========================================= +ejabberd Community Edition +========================== + +[![Build Status](https://travis-ci.org/processone/ejabberd.svg?branch=master)](https://travis-ci.org/processone/ejabberd) [![Hex version](https://img.shields.io/hexpm/v/ejabberd.svg "Hex version")](https://hex.pm/packages/ejabberd) ejabberd is a distributed, fault-tolerant technology that allows the creation of large-scale instant messaging applications. The server can reliably support From 6af9aa3de8ad72236d5ecc6da633fec65d700a18 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 8 Feb 2016 11:50:04 +0100 Subject: [PATCH 562/695] Add link to ProcessOne site --- mix.exs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index e9f19559cdb..1f91e146112 100644 --- a/mix.exs +++ b/mix.exs @@ -66,7 +66,8 @@ defmodule Ejabberd.Mixfile do licenses: ["GPLv2"], links: %{"Site" => "https://www.ejabberd.im", "Documentation" => "http://docs.ejabberd.im", - "Source" => "https://github.com/processone/ejabberd"}] + "Source" => "https://github.com/processone/ejabberd", + "ProcessOne" => "http://www.process-one.net/"}] end end From 04a315eb5227e6494fbd33ccca49c4a3ec31ab8a Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 8 Feb 2016 16:16:53 +0100 Subject: [PATCH 563/695] Fix section links to the Guide in the WebAdmin --- src/ejabberd_web_admin.erl | 14 +++++++------- src/mod_shared_roster.erl | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index efdb9236177..8a7be6cce9c 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -735,7 +735,7 @@ process_admin(Host, [{{acl, '$1', '$2'}}]}])), {NumLines, ACLsP} = term_to_paragraph(ACLs, 80), make_xhtml((?H1GL((?T(<<"Access Control Lists">>)), - <<"acl-definition">>, <<"ACL Definition">>)) + <<"acldefinition">>, <<"ACL Definition">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -771,7 +771,7 @@ process_admin(Host, [{{acl, {'$1', Host}, '$2'}, [], [{{acl, '$1', '$2'}}]}])), make_xhtml((?H1GL((?T(<<"Access Control Lists">>)), - <<"acl-definition">>, <<"ACL Definition">>)) + <<"acldefinition">>, <<"ACL Definition">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -837,7 +837,7 @@ process_admin(Host, [{{access, '$1', '$2'}}]}]), {NumLines, AccessP} = term_to_paragraph(lists:keysort(2,Access), 80), make_xhtml((?H1GL((?T(<<"Access Rules">>)), - <<"access-rights">>, <<"Access Rights">>)) + <<"accessrights">>, <<"Access Rights">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -870,7 +870,7 @@ process_admin(Host, [{{access, {'$1', Host}, '$2'}, [], [{{access, '$1', '$2'}}]}]), make_xhtml((?H1GL((?T(<<"Access Rules">>)), - <<"access-rights">>, <<"Access Rights">>)) + <<"accessrights">>, <<"Access Rights">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -929,7 +929,7 @@ process_admin(global, lang = Lang}) -> Res = list_vhosts(Lang, AJID), make_xhtml((?H1GL((?T(<<"Virtual Hosts">>)), - <<"virtual-hosting">>, <<"Virtual Hosting">>)) + <<"virtualhosting">>, <<"Virtual Hosting">>)) ++ Res, global, Lang, AJID); process_admin(Host, @@ -2114,7 +2114,7 @@ get_node(global, Node, [<<"ports">>], Query, Lang) -> []])), H1String = <<(?T(<<"Listened Ports at ">>))/binary, (iolist_to_binary(atom_to_list(Node)))/binary>>, - (?H1GL(H1String, <<"listening-ports">>, <<"Listening Ports">>)) + (?H1GL(H1String, <<"listeningports">>, <<"Listening Ports">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -2142,7 +2142,7 @@ get_node(Host, Node, [<<"modules">>], Query, Lang) NewModules = lists:sort(ejabberd_cluster:call(Node, gen_mod, loaded_modules_with_opts, [Host])), H1String = list_to_binary(io_lib:format(?T(<<"Modules at ~p">>), [Node])), - (?H1GL(H1String, <<"modules-overview">>, + (?H1GL(H1String, <<"modulesoverview">>, <<"Modules Overview">>)) ++ case Res of diff --git a/src/mod_shared_roster.erl b/src/mod_shared_roster.erl index 1e9e91910b5..212a7d47f3c 100644 --- a/src/mod_shared_roster.erl +++ b/src/mod_shared_roster.erl @@ -1160,7 +1160,7 @@ list_shared_roster_groups(Host, Query, Lang) -> [?INPUTT(<<"submit">>, <<"addnew">>, <<"Add New">>)])])]))])), (?H1GL((?T(<<"Shared Roster Groups">>)), - <<"modsharedroster">>, <<"mod_shared_roster">>)) + <<"mod_shared_roster">>, <<"mod_shared_roster">>)) ++ case Res of ok -> [?XREST(<<"Submitted">>)]; @@ -1254,7 +1254,7 @@ shared_roster_group(Host, Group, Query, Lang) -> <<"20">>, list_to_binary(FDisplayedGroups))])])])])), (?H1GL((?T(<<"Shared Roster Groups">>)), - <<"modsharedroster">>, <<"mod_shared_roster">>)) + <<"mod_shared_roster">>, <<"mod_shared_roster">>)) ++ [?XC(<<"h2">>, <<(?T(<<"Group ">>))/binary, Group/binary>>)] ++ case Res of From 10ed4a1c8514ab0850968329fe4c8b3d4c5070c4 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 8 Feb 2016 20:10:20 +0100 Subject: [PATCH 564/695] Add most status codes only to initial MUC presence --- src/mod_muc_room.erl | 101 +++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 1b3b9c2bb71..17b88bc5b65 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -1856,7 +1856,7 @@ add_new_user(From, Nick, add_online_user(From, Nick, Role, StateData)), send_existing_presences(From, NewState), - send_new_presence(From, NewState, StateData), + send_initial_presence(From, NewState, StateData), Shift = count_stanza_shift(Nick, Els, NewState), case send_history(From, Shift, NewState) of true -> ok; @@ -2090,6 +2090,9 @@ presence_broadcast_allowed(JID, StateData) -> Role = get_role(JID, StateData), lists:member(Role, (StateData#state.config)#config.presence_broadcast). +send_initial_presence(NJID, StateData, OldStateData) -> + send_new_presence1(NJID, <<"">>, true, StateData, OldStateData). + send_update_presence(JID, StateData, OldStateData) -> send_update_presence(JID, <<"">>, StateData, OldStateData). @@ -2117,20 +2120,25 @@ send_update_presence1(JID, Reason, StateData, OldStateData) -> end end, lists:foreach(fun (J) -> - send_new_presence1(J, Reason, StateData, OldStateData) + send_new_presence1(J, Reason, false, StateData, + OldStateData) end, LJIDs). send_new_presence(NJID, StateData, OldStateData) -> - send_new_presence(NJID, <<"">>, StateData, OldStateData). + send_new_presence(NJID, <<"">>, false, StateData, OldStateData). send_new_presence(NJID, Reason, StateData, OldStateData) -> + send_new_presence(NJID, Reason, false, StateData, OldStateData). + +send_new_presence(NJID, Reason, IsInitialPresence, StateData, OldStateData) -> case is_room_overcrowded(StateData) of true -> ok; - false -> send_new_presence1(NJID, Reason, StateData, OldStateData) + false -> send_new_presence1(NJID, Reason, IsInitialPresence, StateData, + OldStateData) end. -send_new_presence1(NJID, Reason, StateData, OldStateData) -> +send_new_presence1(NJID, Reason, IsInitialPresence, StateData, OldStateData) -> LNJID = jid:tolower(NJID), #user{nick = Nick} = (?DICT):fetch(LNJID, StateData#state.users), LJID = find_jid_by_nick(Nick, StateData), @@ -2187,51 +2195,8 @@ send_new_presence1(NJID, Reason, StateData, OldStateData) -> children = [{xmlcdata, Reason}]}] end, - Status = case StateData#state.just_created of - true -> - [#xmlel{name = <<"status">>, - attrs = - [{<<"code">>, <<"201">>}], - children = []}]; - false -> [] - end, - Status2 = case - (StateData#state.config)#config.anonymous - == false - andalso NJID == Info#user.jid - of - true -> - [#xmlel{name = <<"status">>, - attrs = - [{<<"code">>, <<"100">>}], - children = []} - | Status]; - false -> Status - end, - Status3 = case NJID == Info#user.jid of - true -> - [#xmlel{name = <<"status">>, - attrs = - [{<<"code">>, <<"110">>}], - children = []} - | Status2]; - false -> Status2 - end, - Status4 = case (StateData#state.config)#config.logging == true - andalso NJID == Info#user.jid of - true -> - case (?DICT):find(jid:tolower(LJID), - OldStateData#state.users) of - {ok, _} -> Status3; - _ -> - [#xmlel{name = <<"status">>, - attrs = - [{<<"code">>, <<"170">>}], - children = []} - | Status3] - end; - false -> Status3 - end, + StatusEls = status_els(IsInitialPresence, NJID, Info, + StateData), Packet = fxml:append_subtags(Presence, [#xmlel{name = <<"x">>, attrs = @@ -2246,7 +2211,7 @@ send_new_presence1(NJID, Reason, StateData, OldStateData) -> children = ItemEls} - | Status4]}]), + | StatusEls]}]), ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), Info#user.jid, Packet) @@ -2456,6 +2421,40 @@ send_nick_changing(JID, OldNick, StateData, end, (?DICT):to_list(StateData#state.users)). +status_els(IsInitialPresence, JID, #user{jid = JID}, StateData) -> + Status = case IsInitialPresence of + true -> + S1 = case StateData#state.just_created of + true -> + [#xmlel{name = <<"status">>, + attrs = [{<<"code">>, <<"201">>}], + children = []}]; + false -> [] + end, + S2 = case (StateData#state.config)#config.anonymous of + true -> S1; + false -> + [#xmlel{name = <<"status">>, + attrs = [{<<"code">>, <<"100">>}], + children = []} | S1] + end, + S3 = case (StateData#state.config)#config.logging of + true -> + [#xmlel{name = <<"status">>, + attrs = [{<<"code">>, <<"170">>}], + children = []} | S2]; + false -> S2 + end, + S3; + false -> [] + end, + [#xmlel{name = <<"status">>, + attrs = + [{<<"code">>, + <<"110">>}], + children = []} | Status]; +status_els(_IsInitialPresence, _JID, _Info, _StateData) -> []. + lqueue_new(Max) -> #lqueue{queue = queue:new(), len = 0, max = Max}. From d36c351fc7d54fc5292170a1701097111a4c9f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 9 Feb 2016 13:03:04 +0100 Subject: [PATCH 565/695] Typo in markdown generator --- src/ejabberd_commands_doc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index 85b1064bd67..e9054143bda 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -79,7 +79,7 @@ md_tag(pre, V) -> md_tag(p, V) -> [<<"\n\n">>, V, <<"\n">>]; md_tag(h1, V) -> - [<<"\\nn## ">>, V, <<"\n">>]; + [<<"\n\n## ">>, V, <<"\n">>]; md_tag(h2, V) -> [<<"\n\n### ">>, V, <<"\n">>]; md_tag(strong, V) -> From 30d171e79eed40fb14558e06f05ca37c73d82146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 9 Feb 2016 13:03:33 +0100 Subject: [PATCH 566/695] Start documenting arguments in mod_admin_extra commands --- src/mod_admin_extra.erl | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index dc6595615e1..fcd3c766540 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -101,29 +101,45 @@ get_commands_spec() -> desc = "Recompile and reload Erlang source code file", module = ?MODULE, function = compile, args = [{file, string}], - result = {res, rescode}}, + args_example = ["/home/me/srcs/ejabberd/mod_example.erl"], + args_desc = ["Filename of erlang source file to compile"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = get_cookie, tags = [erlang], desc = "Get the Erlang cookie of this node", module = ?MODULE, function = get_cookie, args = [], - result = {cookie, string}}, + result = {cookie, string}, + result_example = "MWTAVMODFELNLSMYXPPD", + result_desc = "Erlang cookie used for authentication by ejabberd"}, #ejabberd_commands{name = remove_node, tags = [erlang], desc = "Remove an ejabberd node from Mnesia clustering config", module = ?MODULE, function = remove_node, args = [{node, string}], - result = {res, rescode}}, - + args_example = ["ejabberd@server2"], + args_desc = ["Name of erlang node to remove"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = num_active_users, tags = [accounts, stats], desc = "Get number of users active in the last days", policy = admin, module = ?MODULE, function = num_active_users, args = [{host, binary}, {days, integer}], - result = {users, integer}}, + args_example = [<<"myserver.com">>, 3], + args_desc = ["Name of host to check", "Number of days to calculate sum"], + result = {users, integer}, + result_example = 123, + result_desc = "Number of users active on given server in last n days"}, #ejabberd_commands{name = delete_old_users, tags = [accounts, purge], desc = "Delete users that didn't log in last days, or that never logged", module = ?MODULE, function = delete_old_users, args = [{days, integer}], - result = {res, restuple}}, + args_example = [30], + args_desc = ["Last login age in days of accounts that should be removed"], + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = delete_old_users_vhost, tags = [accounts, purge], desc = "Delete users that didn't log in last days in vhost, or that never logged", module = ?MODULE, function = delete_old_users_vhost, From c0da9b43ceb12f95d400fa1ab998258db73600de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 9 Feb 2016 13:18:01 +0100 Subject: [PATCH 567/695] Better presentation of result description in docs --- src/ejabberd_commands_doc.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index e9054143bda..df4ba9df938 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -360,8 +360,9 @@ gen_doc(#ejabberd_commands{name=Name, tags=_Tags, desc=Desc, longdesc=LongDesc, none -> [?RAW(io_lib:format("~p", [Result]))]; _ -> - [?RAW(io_lib:format("~p", [Result])), - ?TAG_R(p, ResultDesc)] + [?TAG(dl, [ + ?TAG(dt, io_lib:format("~p", [Result])), + ?TAG_R(dd, ResultDesc)])] end, [?TAG(h1, [?TAG(strong, atom_to_list(Name)), <<" - ">>, ?RAW(Desc)]), From 583476380ac8c65126c3316fba4e7db2e9c5759b Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 9 Feb 2016 15:33:00 +0100 Subject: [PATCH 568/695] Use muc_online_room record for pattern matching --- src/mod_muc_admin.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index c08757375d3..b8d7c8828ac 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -178,7 +178,8 @@ muc_online_rooms(ServerHost) -> MUCHost = find_host(ServerHost), Rooms = ets:tab2list(muc_online_room), lists:foldl( - fun({_, {Roomname, Host}, _}, Results) -> + fun(Room, Results) -> + {Roomname, Host} = Room#muc_online_room.name_host, case MUCHost of global -> [<> | Results]; From 2bca8d51216490d59f23d9df373687955619cd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 9 Feb 2016 15:49:47 +0100 Subject: [PATCH 569/695] Remove remanants of pre-binary strings --- src/mod_muc_admin.erl | 50 ++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index b8d7c8828ac..b1112791442 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -280,7 +280,7 @@ get_sort_query(Q) -> get_sort_query2(Q) -> {value, {_, String}} = lists:keysearch(<<"sort">>, 1, Q), - Integer = list_to_integer(binary_to_list(String)), + Integer = jlib:binary_to_integer(String), case Integer >= 0 of true -> {ok, {normal, Integer}}; false -> {ok, {reverse, abs(Integer)}} @@ -472,7 +472,7 @@ destroy_room({N, H, SH}) -> %% The file encoding must be UTF-8 destroy_rooms_file(Filename) -> - {ok, F} = file:open(Filename, [read]), + {ok, F} = file:open(Filename, [read, binary]), RJID = read_room(F), Rooms = read_rooms(F, RJID, []), file:close(F), @@ -500,23 +500,16 @@ read_room(F) -> %% This function is quite rudimentary %% and may not be accurate split_roomjid(RoomJID) -> - [Name, Host] = string:tokens(RoomJID, "@"), - [_MUC_service_name | ServerHostList] = string:tokens(Host, "."), - ServerHost = join(ServerHostList, "."), - {list_to_binary(Name), list_to_binary(Host), list_to_binary(ServerHost)}. - -%% This function is copied from string:join/2 in Erlang/OTP R12B-1 -%% Note that string:join/2 is not implemented in Erlang/OTP R11B -join([H|T], Sep) -> - H ++ lists:concat([Sep ++ X || X <- T]). - + [Name, Host] = binary:split(RoomJID, <<"@">>), + [_MUC_service_name, ServerHost] = binary:split(Host, <<".">>), + {Name, Host, ServerHost}. %%---------------------------- %% Create Rooms in File %%---------------------------- create_rooms_file(Filename) -> - {ok, F} = file:open(Filename, [read]), + {ok, F} = file:open(Filename, [read, binary]), RJID = read_room(F), Rooms = read_rooms(F, RJID, []), file:close(F), @@ -693,29 +686,32 @@ send_direct_invitation(RoomName, RoomService, Password, Reason, UsersString) -> RoomJid = jid:make(RoomName, RoomService, <<"">>), RoomString = jid:to_string(RoomJid), XmlEl = build_invitation(Password, Reason, RoomString), - UsersStrings = get_users_to_invite(RoomJid, binary_to_list(UsersString)), - [send_direct_invitation(RoomJid, jid:from_string(list_to_binary(UserStrings)), XmlEl) + UsersStrings = get_users_to_invite(RoomJid, UsersString), + [send_direct_invitation(RoomJid, UserStrings, XmlEl) || UserStrings <- UsersStrings], timer:sleep(1000), ok. get_users_to_invite(RoomJid, UsersString) -> - UsersStrings = string:tokens(UsersString, ":"), + UsersStrings = binary:split(UsersString, <<":">>, [global]), OccupantsTuples = get_room_occupants(RoomJid#jid.luser, RoomJid#jid.lserver), OccupantsJids = [jid:from_string(JidString) || {JidString, _Nick, _} <- OccupantsTuples], - lists:filter( - fun(UserString) -> - UserJid = jid:from_string(list_to_binary(UserString)), - %% [{"badlop@localhost/work","badlop","moderator"}] - lists:all(fun(OccupantJid) -> - UserJid#jid.luser /= OccupantJid#jid.luser - orelse UserJid#jid.lserver /= OccupantJid#jid.lserver - end, - OccupantsJids) - end, - UsersStrings). + lists:filtermap( + fun(UserString) -> + UserJid = jid:from_string(UserString), + Val = lists:all(fun(OccupantJid) -> + UserJid#jid.luser /= OccupantJid#jid.luser + orelse UserJid#jid.lserver /= OccupantJid#jid.lserver + end, + OccupantsJids), + case Val of + true -> {true, UserJid}; + _ -> false + end + end, + UsersStrings). build_invitation(Password, Reason, RoomString) -> PasswordAttrList = case Password of From 4839ba5ae46788757e581b3accca563a7bed8368 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 9 Feb 2016 17:59:54 +0300 Subject: [PATCH 570/695] XEP-0013: Flexible Offline Message Retrieval support --- include/ns.hrl | 1 + src/ejabberd_c2s.erl | 9 +- src/mod_disco.erl | 4 +- src/mod_offline.erl | 362 ++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 353 insertions(+), 23 deletions(-) diff --git a/include/ns.hrl b/include/ns.hrl index 372b68b7c54..6934195d957 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -131,6 +131,7 @@ -define(NS_FEATURE_COMPRESS, <<"http://jabber.org/features/compress">>). -define(NS_FEATURE_MSGOFFLINE, <<"msgoffline">>). +-define(NS_FLEX_OFFLINE, <<"http://jabber.org/protocol/offline">>). -define(NS_COMPRESS, <<"http://jabber.org/protocol/compress">>). -define(NS_CAPS, <<"http://jabber.org/protocol/caps">>). diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 8959ae50e57..b9f9d815d31 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -115,6 +115,7 @@ mgmt_resend, mgmt_stanzas_in = 0, mgmt_stanzas_out = 0, + ask_offline = true, lang = <<"">>}). %-define(DBGFSM, true). @@ -1737,6 +1738,8 @@ handle_info({broadcast, Type, From, Packet}, StateName, StateData) -> From, jid:make(USR), Packet) end, lists:usort(Recipients)), fsm_next_state(StateName, StateData); +handle_info(dont_ask_offline, StateName, StateData) -> + fsm_next_state(StateName, StateData#state{ask_offline = false}); handle_info(Info, StateName, StateData) -> ?ERROR_MSG("Unexpected info: ~p", [Info]), fsm_next_state(StateName, StateData). @@ -2310,7 +2313,7 @@ process_privacy_iq(From, To, ejabberd_router:route(To, From, jlib:iq_to_xml(IQRes)), NewStateData. -resend_offline_messages(StateData) -> +resend_offline_messages(#state{ask_offline = true} = StateData) -> case ejabberd_hooks:run_fold(resend_offline_messages_hook, StateData#state.server, [], [StateData#state.user, StateData#state.server]) @@ -2331,7 +2334,9 @@ resend_offline_messages(StateData) -> end end, Rs) - end. + end; +resend_offline_messages(_StateData) -> + ok. resend_subscription_requests(#state{user = User, server = Server} = StateData) -> diff --git a/src/mod_disco.erl b/src/mod_disco.erl index fc3397e17e6..734e90d367f 100644 --- a/src/mod_disco.erl +++ b/src/mod_disco.erl @@ -382,6 +382,8 @@ process_sm_iq_info(From, To, Identity = ejabberd_hooks:run_fold(disco_sm_identity, Host, [], [From, To, Node, Lang]), + Info = ejabberd_hooks:run_fold(disco_info, Host, [], + [From, To, Node, Lang]), case ejabberd_hooks:run_fold(disco_sm_features, Host, empty, [From, To, Node, Lang]) of @@ -397,7 +399,7 @@ process_sm_iq_info(From, To, [{<<"xmlns">>, ?NS_DISCO_INFO} | ANode], children = - Identity ++ + Identity ++ Info ++ features_to_xml(Features)}]}; {error, Error} -> IQ#iq{type = error, sub_el = [SubEl, Error]} diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 28a8aa4ffc0..5e566011bd9 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -47,6 +47,10 @@ resend_offline_messages/2, pop_offline_messages/3, get_sm_features/5, + get_sm_identity/5, + get_sm_items/5, + get_info/5, + handle_offline_query/3, remove_expired_messages/1, remove_old_messages/2, remove_user/2, @@ -113,6 +117,8 @@ init([Host, Opts]) -> update_table(); _ -> ok end, + IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, + no_queue), ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, store_packet, 50), ejabberd_hooks:add(resend_offline_messages_hook, Host, @@ -125,12 +131,19 @@ init([Host, Opts]) -> ?MODULE, get_sm_features, 50), ejabberd_hooks:add(disco_local_features, Host, ?MODULE, get_sm_features, 50), + ejabberd_hooks:add(disco_sm_identity, Host, + ?MODULE, get_sm_identity, 50), + ejabberd_hooks:add(disco_sm_items, Host, + ?MODULE, get_sm_items, 50), + ejabberd_hooks:add(disco_info, Host, ?MODULE, get_info, 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), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_FLEX_OFFLINE, + ?MODULE, handle_offline_query, IQDisc), AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, fun(A) when is_atom(A) -> A end, @@ -175,12 +188,16 @@ terminate(_Reason, State) -> ?MODULE, remove_user, 50), ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50), ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, get_sm_features, 50), + ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, get_sm_identity, 50), + ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, get_sm_items, 50), + ejabberd_hooks:delete(disco_info, Host, ?MODULE, get_info, 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), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_FLEX_OFFLINE), ok. @@ -276,38 +293,223 @@ get_sm_features(Acc, _From, _To, <<"">>, _Lang) -> {result, I} -> I; _ -> [] end, - {result, Feats ++ [?NS_FEATURE_MSGOFFLINE]}; + {result, Feats ++ [?NS_FEATURE_MSGOFFLINE, ?NS_FLEX_OFFLINE]}; get_sm_features(_Acc, _From, _To, ?NS_FEATURE_MSGOFFLINE, _Lang) -> %% override all lesser features... {result, []}; +get_sm_features(_Acc, #jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}, + ?NS_FLEX_OFFLINE, _Lang) -> + {result, [?NS_FLEX_OFFLINE]}; + get_sm_features(Acc, _From, _To, _Node, _Lang) -> Acc. +get_sm_identity(_Acc, #jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}, + ?NS_FLEX_OFFLINE, _Lang) -> + Identity = #xmlel{name = <<"identity">>, + attrs = [{<<"category">>, <<"automation">>}, + {<<"type">>, <<"message-list">>}]}, + [Identity]; +get_sm_identity(Acc, _From, _To, _Node, _Lang) -> + Acc. + +get_sm_items(_Acc, #jid{luser = U, lserver = S, lresource = R} = JID, + #jid{luser = U, lserver = S}, + ?NS_FLEX_OFFLINE, _Lang) -> + case ejabberd_sm:get_session_pid(U, S, R) of + Pid when is_pid(Pid) -> + Hdrs = read_message_headers(U, S), + BareJID = jid:to_string(jid:remove_resource(JID)), + Pid ! dont_ask_offline, + {result, lists:map( + fun({Node, From, _OfflineMsg}) -> + #xmlel{name = <<"item">>, + attrs = [{<<"jid">>, BareJID}, + {<<"node">>, Node}, + {<<"name">>, From}]} + end, Hdrs)}; + none -> + {result, []} + end; +get_sm_items(Acc, _From, _To, _Node, _Lang) -> + Acc. + +get_info(_Acc, #jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}, + ?NS_FLEX_OFFLINE, _Lang) -> + N = jlib:integer_to_binary(count_offline_messages(U, S)), + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"result">>}], + children = [#xmlel{name = <<"field">>, + attrs = [{<<"var">>, <<"FORM_TYPE">>}, + {<<"type">>, <<"hidden">>}], + children = [#xmlel{name = <<"value">>, + children = [{xmlcdata, + ?NS_FLEX_OFFLINE}]}]}, + #xmlel{name = <<"field">>, + attrs = [{<<"var">>, <<"number_of_messages">>}], + children = [#xmlel{name = <<"value">>, + children = [{xmlcdata, N}]}]}]}]; +get_info(Acc, _From, _To, _Node, _Lang) -> + Acc. + +handle_offline_query(#jid{luser = U, lserver = S} = From, + #jid{luser = U, lserver = S} = _To, + #iq{type = Type, sub_el = SubEl} = IQ) -> + case Type of + get -> + case fxml:get_subtag(SubEl, <<"fetch">>) of + #xmlel{} -> + handle_offline_fetch(From); + false -> + handle_offline_items_view(From, SubEl) + end; + set -> + case fxml:get_subtag(SubEl, <<"purge">>) of + #xmlel{} -> + delete_all_msgs(U, S); + false -> + handle_offline_items_remove(From, SubEl) + end + end, + IQ#iq{type = result, sub_el = []}; +handle_offline_query(_From, _To, #iq{sub_el = SubEl} = IQ) -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_FORBIDDEN]}. + +handle_offline_items_view(JID, #xmlel{children = Items}) -> + {U, S, R} = jid:tolower(JID), + lists:foreach( + fun(Node) -> + case fetch_msg_by_node(JID, Node) of + {ok, OfflineMsg} -> + case offline_msg_to_route(S, OfflineMsg) of + {route, From, To, El} -> + NewEl = set_offline_tag(El, Node), + case ejabberd_sm:get_session_pid(U, S, R) of + Pid when is_pid(Pid) -> + Pid ! {route, From, To, NewEl}; + none -> + ok + end; + error -> + ok + end; + error -> + ok + end + end, get_nodes_from_items(Items, <<"view">>)). + +handle_offline_items_remove(JID, #xmlel{children = Items}) -> + lists:foreach( + fun(Node) -> + remove_msg_by_node(JID, Node) + end, get_nodes_from_items(Items, <<"remove">>)). + +get_nodes_from_items(Items, Action) -> + lists:flatmap( + fun(#xmlel{name = <<"item">>, attrs = Attrs}) -> + case fxml:get_attr_s(<<"action">>, Attrs) of + Action -> + case fxml:get_attr_s(<<"node">>, Attrs) of + <<"">> -> + []; + TS -> + [TS] + end; + _ -> + [] + end; + (_) -> + [] + end, Items). + +set_offline_tag(#xmlel{children = Els} = El, Node) -> + OfflineEl = #xmlel{name = <<"offline">>, + attrs = [{<<"xmlns">>, ?NS_FLEX_OFFLINE}], + children = [#xmlel{name = <<"item">>, + attrs = [{<<"node">>, Node}]}]}, + El#xmlel{children = [OfflineEl|Els]}. + +handle_offline_fetch(#jid{luser = U, lserver = S, lresource = R}) -> + case ejabberd_sm:get_session_pid(U, S, R) of + none -> + ok; + Pid when is_pid(Pid) -> + Pid ! dont_ask_offline, + lists:foreach( + fun({Node, _, Msg}) -> + case offline_msg_to_route(S, Msg) of + {route, From, To, El} -> + NewEl = set_offline_tag(El, Node), + Pid ! {route, From, To, NewEl}; + error -> + ok + end + end, read_message_headers(U, S)) + end. + +fetch_msg_by_node(To, <>) -> + case jid:from_string(From_s) of + From = #jid{} -> + case gen_mod:db_type(To#jid.lserver, ?MODULE) of + odbc -> + read_message(From, To, Seq, odbc); + DBType -> + case binary_to_timestamp(Seq) of + undefined -> ok; + TS -> read_message(From, To, TS, DBType) + end + end; + error -> + ok + end. + +remove_msg_by_node(To, <>) -> + case jid:from_string(From_s) of + From = #jid{} -> + case gen_mod:db_type(To#jid.lserver, ?MODULE) of + odbc -> + remove_message(From, To, Seq, odbc); + DBType -> + case binary_to_timestamp(Seq) of + undefined -> ok; + TS -> remove_message(From, To, TS, DBType) + end + end; + error -> + ok + end. + need_to_store(LServer, Packet) -> Type = fxml:get_tag_attr_s(<<"type">>, Packet), if (Type /= <<"error">>) and (Type /= <<"groupchat">>) and (Type /= <<"headline">>) -> - case check_store_hint(Packet) of - store -> - true; - no_store -> - false; - none -> - case gen_mod:get_module_opt( - LServer, ?MODULE, store_empty_body, - fun(V) when is_boolean(V) -> V; - (unless_chat_state) -> unless_chat_state - end, - unless_chat_state) of - false -> - fxml:get_subtag(Packet, <<"body">>) /= false; - unless_chat_state -> - not jlib:is_standalone_chat_state(Packet); - true -> - true - end + case has_offline_tag(Packet) of + false -> + case check_store_hint(Packet) of + store -> + true; + no_store -> + false; + none -> + case gen_mod:get_module_opt( + LServer, ?MODULE, store_empty_body, + fun(V) when is_boolean(V) -> V; + (unless_chat_state) -> unless_chat_state + end, + unless_chat_state) of + false -> + fxml:get_subtag(Packet, <<"body">>) /= false; + unless_chat_state -> + not jlib:is_standalone_chat_state(Packet); + true -> + true + end + end; + true -> + false end; true -> false @@ -353,6 +555,9 @@ has_no_store_hint(Packet) -> orelse fxml:get_subtag_with_xmlns(Packet, <<"no-storage">>, ?NS_HINTS) =/= false. +has_offline_tag(Packet) -> + fxml:get_subtag_with_xmlns(Packet, <<"offline">>, ?NS_FLEX_OFFLINE) =/= false. + %% Check if the packet has any content about XEP-0022 check_event(From, To, Packet) -> #xmlel{name = Name, attrs = Attrs, children = Els} = @@ -713,6 +918,123 @@ offline_msg_to_route(_LServer, #xmlel{} = El) -> error end. +binary_to_timestamp(TS) -> + case catch jlib:binary_to_integer(TS) of + Int when is_integer(Int) -> + Secs = Int div 1000000, + USec = Int rem 1000000, + MSec = Secs div 1000000, + Sec = Secs rem 1000000, + {MSec, Sec, USec}; + _ -> + undefined + end. + +timestamp_to_binary({MS, S, US}) -> + format_timestamp(integer_to_list((MS * 1000000 + S) * 1000000 + US)). + +format_timestamp(TS) -> + iolist_to_binary(io_lib:format("~20..0s", [TS])). + +offline_msg_to_header(#offline_msg{from = From, timestamp = Int} = Msg) -> + TS = timestamp_to_binary(Int), + From_s = jid:to_string(From), + {<>, From_s, Msg}. + +read_message_headers(LUser, LServer) -> + DBType = gen_mod:db_type(LServer, ?MODULE), + read_message_headers(LUser, LServer, DBType). + +read_message_headers(LUser, LServer, mnesia) -> + Msgs = mnesia:dirty_read({offline_msg, {LUser, LServer}}), + Hdrs = lists:map(fun offline_msg_to_header/1, Msgs), + lists:keysort(1, Hdrs); +read_message_headers(LUser, LServer, riak) -> + case ejabberd_riak:get_by_index( + offline_msg, offline_msg_schema(), + <<"us">>, {LUser, LServer}) of + {ok, Rs} -> + Hdrs = lists:map(fun offline_msg_to_header/1, Rs), + lists:keysort(1, Hdrs); + _Err -> + [] + end; +read_message_headers(LUser, LServer, odbc) -> + Username = ejabberd_odbc:escape(LUser), + case catch ejabberd_odbc:sql_query( + LServer, [<<"select xml, seq from spool where username ='">>, + Username, <<"' order by seq;">>]) of + {selected, [<<"xml">>, <<"seq">>], Rows} -> + Hdrs = lists:flatmap( + fun([XML, Seq]) -> + try + #xmlel{} = El = fxml_stream:parse_element(XML), + From = fxml:get_tag_attr_s(<<"from">>, El), + #jid{} = jid:from_string(From), + TS = format_timestamp(Seq), + [{<>, From, El}] + catch _:_ -> [] + end + end, Rows), + lists:keysort(1, Hdrs); + _Err -> + [] + end. + +read_message(_From, To, TS, mnesia) -> + {U, S, _} = jid:tolower(To), + case mnesia:dirty_match_object( + offline_msg, #offline_msg{us = {U, S}, timestamp = TS, _ = '_'}) of + [Msg|_] -> + {ok, Msg}; + _ -> + error + end; +read_message(_From, _To, TS, riak) -> + case ejabberd_riak:get(offline_msg, offline_msg_schema(), TS) of + {ok, Msg} -> + {ok, Msg}; + _ -> + error + end; +read_message(_From, To, Seq, odbc) -> + {LUser, LServer, _} = jid:tolower(To), + Username = ejabberd_odbc:escape(LUser), + SSeq = ejabberd_odbc:escape(Seq), + case ejabberd_odbc:sql_query( + LServer, + [<<"select xml from spool where username='">>, Username, + <<"' and seq='">>, SSeq, <<"';">>]) of + {selected, [<<"xml">>], [[RawXML]|_]} -> + case fxml_stream:parse_element(RawXML) of + #xmlel{} = El -> {ok, El}; + {error, _} -> error + end; + _ -> + error + end. + +remove_message(_From, To, TS, mnesia) -> + {U, S, _} = jid:tolower(To), + Msgs = mnesia:dirty_match_object( + offline_msg, #offline_msg{us = {U, S}, timestamp = TS, _ = '_'}), + lists:foreach( + fun(Msg) -> + mnesia:dirty_delete_object(Msg) + end, Msgs); +remove_message(_From, _To, TS, riak) -> + ejabberd_riak:delete(offline_msg, TS), + ok; +remove_message(_From, To, Seq, odbc) -> + {LUser, LServer, _} = jid:tolower(To), + Username = ejabberd_odbc:escape(LUser), + SSeq = ejabberd_odbc:escape(Seq), + ejabberd_odbc:sql_query( + LServer, + [<<"delete from spool where username='">>, Username, + <<"' and seq='">>, SSeq, <<"';">>]), + ok. + read_all_msgs(LUser, LServer, mnesia) -> US = {LUser, LServer}, lists:keysort(#offline_msg.timestamp, From d5b3e6af00c2bbbb739901c4e4c73d7c55de3d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 9 Feb 2016 16:33:19 +0100 Subject: [PATCH 571/695] More documentation of arguments in mod_admin_extra --- src/mod_admin_extra.erl | 83 +++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index fcd3c766540..edfe7a5efc1 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -138,68 +138,119 @@ get_commands_spec() -> args = [{days, integer}], args_example = [30], args_desc = ["Last login age in days of accounts that should be removed"], - result_example = 0, - result_desc = "Status code: 0 on success, 1 otherwise"}, + result = {res, restuple}, + result_example = {ok, <<"Deleted 2 users: [\"oldman@myserver.com\", \"test@myserver.com\"]">>}, + result_desc = "Result tuple"}, #ejabberd_commands{name = delete_old_users_vhost, tags = [accounts, purge], desc = "Delete users that didn't log in last days in vhost, or that never logged", module = ?MODULE, function = delete_old_users_vhost, args = [{host, binary}, {days, integer}], - result = {res, restuple}}, - + args_example = [<<"myserver.com">>, 30], + args_desc = ["Server name", + "Last login age in days of accounts that should be removed"], + result = {res, restuple}, + result_example = {ok, <<"Deleted 2 users: [\"oldman@myserver.com\", \"test@myserver.com\"]">>}, + result_desc = "Result tuple"}, #ejabberd_commands{name = check_account, tags = [accounts], desc = "Check if an account exists or not", module = ejabberd_auth, function = is_user_exists, args = [{user, binary}, {host, binary}], - result = {res, rescode}}, + args_example = [<<"peter">>, <<"myserver.com">>], + args_desc = ["User name to check", "Server to check"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = check_password, tags = [accounts], desc = "Check if a password is correct", module = ejabberd_auth, function = check_password, args = [{user, binary}, {host, binary}, {password, binary}], - result = {res, rescode}}, + args_example = [<<"peter">>, <<"myserver.com">>, <<"secret">>], + args_desc = ["User name to check", "Server to check", "Password to check"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = check_password_hash, tags = [accounts], desc = "Check if the password hash is correct", longdesc = "Allowed hash methods: md5, sha.", module = ?MODULE, function = check_password_hash, - args = [{user, binary}, {host, binary}, {passwordhash, string}, {hashmethod, string}], - result = {res, rescode}}, + args = [{user, binary}, {host, binary}, {passwordhash, string}, + {hashmethod, string}], + args_example = [<<"peter">>, <<"myserver.com">>, + <<"5ebe2294ecd0e0f08eab7690d2a6ee69">>, <<"md5">>], + args_desc = ["User name to check", "Server to check", + "Password's hash value", "Name of hash method"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = change_password, tags = [accounts], desc = "Change the password of an account", module = ?MODULE, function = set_password, args = [{user, binary}, {host, binary}, {newpass, binary}], - result = {res, rescode}}, + args_example = [<<"peter">>, <<"myserver.com">>, <<"blank">>], + args_desc = ["User name", "Server name", + "New password for user"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = ban_account, tags = [accounts], desc = "Ban an account: kick sessions and set random password", module = ?MODULE, function = ban_account, args = [{user, binary}, {host, binary}, {reason, binary}], - result = {res, rescode}}, - + args_example = [<<"attacker">>, <<"myserver.com">>, <<"Spaming other users">>], + args_desc = ["User name to ban", "Server name", + "Reason for banning user"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = num_resources, tags = [session], desc = "Get the number of resources of a user", module = ?MODULE, function = num_resources, args = [{user, binary}, {host, binary}], - result = {resources, integer}}, + args_example = [<<"peter">>, <<"myserver.com">>], + args_desc = ["User name", "Server name"], + result = {resources, integer}, + result_example = 5, + result_desc = "Number of active resources for a user"}, #ejabberd_commands{name = resource_num, tags = [session], desc = "Resource string of a session number", module = ?MODULE, function = resource_num, args = [{user, binary}, {host, binary}, {num, integer}], - result = {resource, string}}, + args_example = [<<"peter">>, <<"myserver.com">>, 2], + args_desc = ["User name", "Server name", "ID of resource to return"], + result = {resource, string}, + result_example = <<"Psi">>, + result_desc = "Name of user resource"}, #ejabberd_commands{name = kick_session, tags = [session], desc = "Kick a user session", module = ?MODULE, function = kick_session, args = [{user, binary}, {host, binary}, {resource, binary}, {reason, binary}], - result = {res, rescode}}, + args_example = [<<"peter">>, <<"myserver.com">>, <<"Psi">>, + <<"Stuck connection">>], + args_desc = ["User name", "Server name", "User's resource", + "Reason for closing session"], + result = {res, rescode}, + result_example = 0, + result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = status_num_host, tags = [session, stats], desc = "Number of logged users with this status in host", policy = admin, module = ?MODULE, function = status_num, args = [{host, binary}, {status, binary}], - result = {users, integer}}, + args_example = [<<"myserver.com">>, <<"dnd">>], + args_desc = ["Server name", "Status type to check"], + result = {users, integer}, + result_example = 23, + result_desc = "Number of connected sessions with given status type"}, #ejabberd_commands{name = status_num, tags = [session, stats], desc = "Number of logged users with this status", policy = admin, module = ?MODULE, function = status_num, args = [{status, binary}], - result = {users, integer}}, + args_example = [<<"dnd">>], + args_desc = ["Status type to check"], + result = {users, integer}, + result_example = 23, + result_desc = "Number of connected sessions with given status type"}, #ejabberd_commands{name = status_list_host, tags = [session], desc = "List of users logged in host with their statuses", module = ?MODULE, function = status_list, From 217b6da5fde8d21c36edc2daeb58694f7f705ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 9 Feb 2016 16:44:57 +0100 Subject: [PATCH 572/695] Fix example value for rescode return type --- src/mod_admin_extra.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index edfe7a5efc1..bd5a8489c9a 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -104,7 +104,7 @@ get_commands_spec() -> args_example = ["/home/me/srcs/ejabberd/mod_example.erl"], args_desc = ["Filename of erlang source file to compile"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = get_cookie, tags = [erlang], desc = "Get the Erlang cookie of this node", @@ -120,7 +120,7 @@ get_commands_spec() -> args_example = ["ejabberd@server2"], args_desc = ["Name of erlang node to remove"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = num_active_users, tags = [accounts, stats], desc = "Get number of users active in the last days", @@ -158,7 +158,7 @@ get_commands_spec() -> args_example = [<<"peter">>, <<"myserver.com">>], args_desc = ["User name to check", "Server to check"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = check_password, tags = [accounts], desc = "Check if a password is correct", @@ -167,7 +167,7 @@ get_commands_spec() -> args_example = [<<"peter">>, <<"myserver.com">>, <<"secret">>], args_desc = ["User name to check", "Server to check", "Password to check"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = check_password_hash, tags = [accounts], desc = "Check if the password hash is correct", @@ -180,7 +180,7 @@ get_commands_spec() -> args_desc = ["User name to check", "Server to check", "Password's hash value", "Name of hash method"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = change_password, tags = [accounts], desc = "Change the password of an account", @@ -190,7 +190,7 @@ get_commands_spec() -> args_desc = ["User name", "Server name", "New password for user"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = ban_account, tags = [accounts], desc = "Ban an account: kick sessions and set random password", @@ -200,7 +200,7 @@ get_commands_spec() -> args_desc = ["User name to ban", "Server name", "Reason for banning user"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = num_resources, tags = [session], desc = "Get the number of resources of a user", @@ -229,7 +229,7 @@ get_commands_spec() -> args_desc = ["User name", "Server name", "User's resource", "Reason for closing session"], result = {res, rescode}, - result_example = 0, + result_example = ok, result_desc = "Status code: 0 on success, 1 otherwise"}, #ejabberd_commands{name = status_num_host, tags = [session, stats], desc = "Number of logged users with this status in host", From 1de085ec23337e9ef4e5107d95bdc2cacaaba15b Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 8 Feb 2016 21:35:26 +0100 Subject: [PATCH 573/695] Prepare room JID in create_room command --- src/mod_muc_admin.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index b1112791442..7c6e84c4539 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -396,7 +396,9 @@ prepare_room_info(Room_info) -> %% @spec (Name::binary(), Host::binary(), ServerHost::binary()) -> %% ok | error %% @doc Create a room immediately with the default options. -create_room(Name, Host, ServerHost) -> +create_room(Name1, Host1, ServerHost) -> + Name = jid:nodeprep(Name1), + Host = jid:nodeprep(Host1), %% Get the default room options from the muc configuration DefRoomOpts = gen_mod:get_module_opt(ServerHost, mod_muc, From 02a519a11eac6edb8e0bb6237f617382f556d704 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 8 Feb 2016 21:35:46 +0100 Subject: [PATCH 574/695] Mention new XEP support --- src/mod_offline.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 5e566011bd9..28c2ba39af5 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -27,6 +27,7 @@ -author('alexey@process-one.net'). +-protocol({xep, 13, '1.2'}). -protocol({xep, 22, '1.4'}). -protocol({xep, 23, '1.3'}). -protocol({xep, 160, '1.0'}). From d6323a7b5e1e96c4738d521432ea5667b11b005e Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 10 Feb 2016 16:15:43 +0300 Subject: [PATCH 575/695] Add tests for XEP-0013 --- Makefile.in | 2 +- test/ejabberd_SUITE.erl | 131 +++++++++++++++++++++++++++ tools/xmpp_codec.erl | 196 +++++++++++++++++++++++++++++++++++++++- tools/xmpp_codec.hrl | 9 +- tools/xmpp_codec.spec | 29 ++++++ 5 files changed, 363 insertions(+), 4 deletions(-) diff --git a/Makefile.in b/Makefile.in index 1b7e5043cde..0d9134485d7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -110,7 +110,7 @@ edoc: spec: $(ERL) -noinput +B -pa ebin -pa deps/*/ebin -eval \ - 'case xml_gen:compile("tools/xmpp_codec.spec") of ok -> halt(0); _ -> halt(1) end.' + 'case fxml_gen:compile("tools/xmpp_codec.spec") of ok -> halt(0); _ -> halt(1) end.' JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1)) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 543437e08cf..5054f0984dc 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -214,6 +214,8 @@ db_tests(riak) -> {test_roster_subscribe, [parallel], [roster_subscribe_master, roster_subscribe_slave]}, + {test_flex_offline, [sequence], + [flex_offline_master, flex_offline_slave]}, {test_offline, [sequence], [offline_master, offline_slave]}, {test_muc, [parallel], @@ -245,6 +247,8 @@ db_tests(mnesia) -> {test_roster_subscribe, [parallel], [roster_subscribe_master, roster_subscribe_slave]}, + {test_flex_offline, [sequence], + [flex_offline_master, flex_offline_slave]}, {test_offline, [sequence], [offline_master, offline_slave]}, {test_old_mam, [parallel], @@ -285,6 +289,8 @@ db_tests(_) -> {test_roster_subscribe, [parallel], [roster_subscribe_master, roster_subscribe_slave]}, + {test_flex_offline, [sequence], + [flex_offline_master, flex_offline_slave]}, {test_offline, [sequence], [offline_master, offline_slave]}, {test_old_mam, [parallel], @@ -1433,6 +1439,131 @@ announce_slave(Config) -> send(Config, #message{to = MotdDelJID}), disconnect(Config). +flex_offline_master(Config) -> + Peer = ?config(slave, Config), + LPeer = jlib:jid_remove_resource(Peer), + lists:foreach( + fun(I) -> + Body = jlib:integer_to_binary(I), + send(Config, #message{to = LPeer, + body = [#text{data = Body}], + subject = [#text{data = <<"subject">>}]}) + end, lists:seq(1, 5)), + disconnect(Config). + +flex_offline_slave(Config) -> + MyJID = my_jid(Config), + MyBareJID = jid:remove_resource(MyJID), + Peer = ?config(master, Config), + Peer_s = jid:to_string(Peer), + true = is_feature_advertised(Config, ?NS_FLEX_OFFLINE), + %% Request disco#info + #iq{type = result, + sub_els = [#disco_info{ + node = ?NS_FLEX_OFFLINE, + identities = Ids, + features = Fts, + xdata = [X]}]} = + send_recv(Config, #iq{type = get, + sub_els = [#disco_info{ + node = ?NS_FLEX_OFFLINE}]}), + %% Check if we have correct identities + true = lists:any( + fun(#identity{category = <<"automation">>, + type = <<"message-list">>}) -> true; + (_) -> false + end, Ids), + %% Check if we have needed feature + true = lists:member(?NS_FLEX_OFFLINE, Fts), + %% Check xdata, the 'number_of_messages' should be 5 + #xdata{type = result, + fields = [#xdata_field{type = hidden, + var = <<"FORM_TYPE">>}, + #xdata_field{var = <<"number_of_messages">>, + values = [<<"5">>]}]} = X, + %% Fetch headers, + #iq{type = result, + sub_els = [#disco_items{ + node = ?NS_FLEX_OFFLINE, + items = DiscoItems}]} = + send_recv(Config, #iq{type = get, + sub_els = [#disco_items{ + node = ?NS_FLEX_OFFLINE}]}), + %% Check if headers are correct + Nodes = lists:sort( + lists:map( + fun(#disco_item{jid = J, name = P, node = N}) + when (J == MyBareJID) and (P == Peer_s) -> + N + end, DiscoItems)), + %% Check full fetch + I0 = send(Config, #iq{type = get, sub_els = [#offline{fetch = true}]}), + lists:foreach( + fun({I, N}) -> + Text = jlib:integer_to_binary(I), + ?recv1(#message{body = Body, sub_els = SubEls}), + [#text{data = Text}] = Body, + #offline{items = [#offline_item{node = N}]} = + lists:keyfind(offline, 1, SubEls), + #delay{} = lists:keyfind(delay, 1, SubEls) + end, lists:zip(lists:seq(1, 5), Nodes)), + ?recv1(#iq{type = result, id = I0, sub_els = []}), + %% Fetch 2nd and 4th message + I1 = send(Config, + #iq{type = get, + sub_els = [#offline{ + items = [#offline_item{ + action = view, + node = lists:nth(2, Nodes)}, + #offline_item{ + action = view, + node = lists:nth(4, Nodes)}]}]}), + lists:foreach( + fun({I, N}) -> + Text = jlib:integer_to_binary(I), + ?recv1(#message{body = [#text{data = Text}], sub_els = SubEls}), + #offline{items = [#offline_item{node = N}]} = + lists:keyfind(offline, 1, SubEls) + end, lists:zip([2, 4], [lists:nth(2, Nodes), lists:nth(4, Nodes)])), + ?recv1(#iq{type = result, id = I1, sub_els = []}), + %% Delete 2nd and 4th message + #iq{type = result, sub_els = []} = + send_recv( + Config, + #iq{type = set, + sub_els = [#offline{ + items = [#offline_item{ + action = remove, + node = lists:nth(2, Nodes)}, + #offline_item{ + action = remove, + node = lists:nth(4, Nodes)}]}]}), + %% Check if messages were deleted + #iq{type = result, + sub_els = [#disco_items{ + node = ?NS_FLEX_OFFLINE, + items = RemainedItems}]} = + send_recv(Config, #iq{type = get, + sub_els = [#disco_items{ + node = ?NS_FLEX_OFFLINE}]}), + RemainedNodes = [lists:nth(1, Nodes), + lists:nth(3, Nodes), + lists:nth(5, Nodes)], + RemainedNodes = lists:sort( + lists:map( + fun(#disco_item{node = N}) -> N end, + RemainedItems)), + %% Purge everything left + #iq{type = result, sub_els = []} = + send_recv(Config, #iq{type = set, sub_els = [#offline{purge = true}]}), + %% Check if there is no offline messages + #iq{type = result, + sub_els = [#disco_items{node = ?NS_FLEX_OFFLINE, items = []}]} = + send_recv(Config, #iq{type = get, + sub_els = [#disco_items{ + node = ?NS_FLEX_OFFLINE}]}), + disconnect(Config). + offline_master(Config) -> Peer = ?config(slave, Config), LPeer = jlib:jid_remove_resource(Peer), diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 3adceabc4d4..917418f5548 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -1,4 +1,4 @@ -%% Created automatically by XML generator (xml_gen.erl) +%% Created automatically by XML generator (fxml_gen.erl) %% Source: xmpp_codec.spec -module(xmpp_codec). @@ -15,6 +15,22 @@ decode(_el) -> decode(_el, []). decode({xmlel, _name, _attrs, _} = _el, Opts) -> IgnoreEls = proplists:get_bool(ignore_els, Opts), case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"offline">>, + <<"http://jabber.org/protocol/offline">>} -> + decode_offline(<<"http://jabber.org/protocol/offline">>, + IgnoreEls, _el); + {<<"item">>, + <<"http://jabber.org/protocol/offline">>} -> + decode_offline_item(<<"http://jabber.org/protocol/offline">>, + IgnoreEls, _el); + {<<"fetch">>, + <<"http://jabber.org/protocol/offline">>} -> + decode_offline_fetch(<<"http://jabber.org/protocol/offline">>, + IgnoreEls, _el); + {<<"purge">>, + <<"http://jabber.org/protocol/offline">>} -> + decode_offline_purge(<<"http://jabber.org/protocol/offline">>, + IgnoreEls, _el); {<<"failed">>, <<"urn:xmpp:sm:2">>} -> decode_sm_failed(<<"urn:xmpp:sm:2">>, IgnoreEls, _el); {<<"failed">>, <<"urn:xmpp:sm:3">>} -> @@ -1072,6 +1088,18 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> is_known_tag({xmlel, _name, _attrs, _} = _el) -> case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"offline">>, + <<"http://jabber.org/protocol/offline">>} -> + true; + {<<"item">>, + <<"http://jabber.org/protocol/offline">>} -> + true; + {<<"fetch">>, + <<"http://jabber.org/protocol/offline">>} -> + true; + {<<"purge">>, + <<"http://jabber.org/protocol/offline">>} -> + true; {<<"failed">>, <<"urn:xmpp:sm:2">>} -> true; {<<"failed">>, <<"urn:xmpp:sm:3">>} -> true; {<<"a">>, <<"urn:xmpp:sm:2">>} -> true; @@ -2124,7 +2152,15 @@ encode({sm_resumed, _, _, _} = Resumed) -> encode({sm_r, _} = R) -> encode_sm_r(R, []); encode({sm_a, _, _} = A) -> encode_sm_a(A, []); encode({sm_failed, _, _} = Failed) -> - encode_sm_failed(Failed, []). + encode_sm_failed(Failed, []); +encode({offline_item, _, _} = Item) -> + encode_offline_item(Item, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/offline">>}]); +encode({offline, _, _, _} = Offline) -> + encode_offline(Offline, + [{<<"xmlns">>, + <<"http://jabber.org/protocol/offline">>}]). get_ns({last, _, _}) -> <<"jabber:iq:last">>; get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; @@ -2319,6 +2355,10 @@ get_ns({carbons_sent, _}) -> <<"urn:xmpp:carbons:2">>; get_ns({feature_csi, _}) -> <<"urn:xmpp:csi:0">>; get_ns({csi, active}) -> <<"urn:xmpp:csi:0">>; get_ns({csi, inactive}) -> <<"urn:xmpp:csi:0">>; +get_ns({offline_item, _, _}) -> + <<"http://jabber.org/protocol/offline">>; +get_ns({offline, _, _, _}) -> + <<"http://jabber.org/protocol/offline">>; get_ns(_) -> <<>>. dec_int(Val) -> dec_int(Val, infinity, infinity). @@ -2522,6 +2562,8 @@ pp(sm_resumed, 3) -> [h, previd, xmlns]; pp(sm_r, 1) -> [xmlns]; pp(sm_a, 2) -> [h, xmlns]; pp(sm_failed, 2) -> [reason, xmlns]; +pp(offline_item, 2) -> [node, action]; +pp(offline, 3) -> [items, purge, fetch]; pp(_, _) -> no. enc_bool(false) -> <<"false">>; @@ -2564,6 +2606,156 @@ dec_tzo(Val) -> M = jlib:binary_to_integer(M1), if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end. +decode_offline(__TopXMLNS, __IgnoreEls, + {xmlel, <<"offline">>, _attrs, _els}) -> + {Items, Purge, Fetch} = decode_offline_els(__TopXMLNS, + __IgnoreEls, _els, [], false, + false), + {offline, Items, Purge, Fetch}. + +decode_offline_els(__TopXMLNS, __IgnoreEls, [], Items, + Purge, Fetch) -> + {lists:reverse(Items), Purge, Fetch}; +decode_offline_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"purge">>, _attrs, _} = _el | _els], Items, + Purge, Fetch) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items, + decode_offline_purge(__TopXMLNS, __IgnoreEls, + _el), + Fetch); + true -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items, + Purge, Fetch) + end; +decode_offline_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"fetch">>, _attrs, _} = _el | _els], Items, + Purge, Fetch) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items, + Purge, + decode_offline_fetch(__TopXMLNS, __IgnoreEls, + _el)); + true -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items, + Purge, Fetch) + end; +decode_offline_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"item">>, _attrs, _} = _el | _els], Items, + Purge, Fetch) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, + [decode_offline_item(__TopXMLNS, __IgnoreEls, _el) + | Items], + Purge, Fetch); + true -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items, + Purge, Fetch) + end; +decode_offline_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Items, Purge, Fetch) -> + decode_offline_els(__TopXMLNS, __IgnoreEls, _els, Items, + Purge, Fetch). + +encode_offline({offline, Items, Purge, Fetch}, + _xmlns_attrs) -> + _els = lists:reverse('encode_offline_$items'(Items, + 'encode_offline_$purge'(Purge, + 'encode_offline_$fetch'(Fetch, + [])))), + _attrs = _xmlns_attrs, + {xmlel, <<"offline">>, _attrs, _els}. + +'encode_offline_$items'([], _acc) -> _acc; +'encode_offline_$items'([Items | _els], _acc) -> + 'encode_offline_$items'(_els, + [encode_offline_item(Items, []) | _acc]). + +'encode_offline_$purge'(false, _acc) -> _acc; +'encode_offline_$purge'(Purge, _acc) -> + [encode_offline_purge(Purge, []) | _acc]. + +'encode_offline_$fetch'(false, _acc) -> _acc; +'encode_offline_$fetch'(Fetch, _acc) -> + [encode_offline_fetch(Fetch, []) | _acc]. + +decode_offline_item(__TopXMLNS, __IgnoreEls, + {xmlel, <<"item">>, _attrs, _els}) -> + {Node, Action} = decode_offline_item_attrs(__TopXMLNS, + _attrs, undefined, undefined), + {offline_item, Node, Action}. + +decode_offline_item_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node, Action) -> + decode_offline_item_attrs(__TopXMLNS, _attrs, _val, + Action); +decode_offline_item_attrs(__TopXMLNS, + [{<<"action">>, _val} | _attrs], Node, _Action) -> + decode_offline_item_attrs(__TopXMLNS, _attrs, Node, + _val); +decode_offline_item_attrs(__TopXMLNS, [_ | _attrs], + Node, Action) -> + decode_offline_item_attrs(__TopXMLNS, _attrs, Node, + Action); +decode_offline_item_attrs(__TopXMLNS, [], Node, + Action) -> + {decode_offline_item_attr_node(__TopXMLNS, Node), + decode_offline_item_attr_action(__TopXMLNS, Action)}. + +encode_offline_item({offline_item, Node, Action}, + _xmlns_attrs) -> + _els = [], + _attrs = encode_offline_item_attr_action(Action, + encode_offline_item_attr_node(Node, + _xmlns_attrs)), + {xmlel, <<"item">>, _attrs, _els}. + +decode_offline_item_attr_node(__TopXMLNS, undefined) -> + undefined; +decode_offline_item_attr_node(__TopXMLNS, _val) -> _val. + +encode_offline_item_attr_node(undefined, _acc) -> _acc; +encode_offline_item_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + +decode_offline_item_attr_action(__TopXMLNS, + undefined) -> + undefined; +decode_offline_item_attr_action(__TopXMLNS, _val) -> + case catch dec_enum(_val, [view, remove]) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"action">>, <<"item">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_offline_item_attr_action(undefined, _acc) -> + _acc; +encode_offline_item_attr_action(_val, _acc) -> + [{<<"action">>, enc_enum(_val)} | _acc]. + +decode_offline_fetch(__TopXMLNS, __IgnoreEls, + {xmlel, <<"fetch">>, _attrs, _els}) -> + true. + +encode_offline_fetch(true, _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"fetch">>, _attrs, _els}. + +decode_offline_purge(__TopXMLNS, __IgnoreEls, + {xmlel, <<"purge">>, _attrs, _els}) -> + true. + +encode_offline_purge(true, _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"purge">>, _attrs, _els}. + decode_sm_failed(__TopXMLNS, __IgnoreEls, {xmlel, <<"failed">>, _attrs, _els}) -> Reason = decode_sm_failed_els(__TopXMLNS, __IgnoreEls, diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index 7996f6a1144..1426287bfc5 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -1,4 +1,4 @@ -%% Created automatically by XML generator (xml_gen.erl) +%% Created automatically by XML generator (fxml_gen.erl) %% Source: xmpp_codec.spec -record(chatstate, {type :: active | composing | gone | inactive | paused}). @@ -424,6 +424,13 @@ features = [] :: [binary()], xdata = [] :: [#xdata{}]}). +-record(offline_item, {node :: binary(), + action :: 'remove' | 'view'}). + +-record(offline, {items = [] :: [#offline_item{}], + purge = false :: boolean(), + fetch = false :: boolean()}). + -record(sasl_mechanisms, {list = [] :: [binary()]}). -record(sm_failed, {reason :: atom() | #gone{} | #redirect{}, diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 8d087c8b637..129a4efba9a 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -2398,6 +2398,35 @@ #ref{name = error_unexpected_request, min = 0, max = 1, label = '$reason'}]}). +-xml(offline_purge, + #elem{name = <<"purge">>, + xmlns = <<"http://jabber.org/protocol/offline">>, + result = true}). + +-xml(offline_fetch, + #elem{name = <<"fetch">>, + xmlns = <<"http://jabber.org/protocol/offline">>, + result = true}). + +-xml(offline_item, + #elem{name = <<"item">>, + xmlns = <<"http://jabber.org/protocol/offline">>, + result = {offline_item, '$node', '$action'}, + attrs = [#attr{name = <<"node">>}, + #attr{name = <<"action">>, + dec = {dec_enum, [[view, remove]]}, + enc = {enc_enum, []}}]}). + +-xml(offline, + #elem{name = <<"offline">>, + xmlns = <<"http://jabber.org/protocol/offline">>, + result = {offline, '$items', '$purge', '$fetch'}, + refs = [#ref{name = offline_purge, min = 0, max = 1, + label = '$purge', default = false}, + #ref{name = offline_fetch, min = 0, max = 1, + label = '$fetch', default = false}, + #ref{name = offline_item, min = 0, label = '$items'}]}). + dec_tzo(Val) -> [H1, M1] = str:tokens(Val, <<":">>), H = jlib:binary_to_integer(H1), From 17be70339caaa7e5890380a94594db346b803d9e Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 10 Feb 2016 23:06:31 +0100 Subject: [PATCH 576/695] mod_mam: Send new preferences when they are set If a client updates the archiving preferences, include the new preferences with the IQ result (as mandated by XEP-0313). --- src/mod_mam.erl | 46 ++++++++++++++++++++++++----------------- test/ejabberd_SUITE.erl | 8 +++---- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/mod_mam.erl b/src/mod_mam.erl index e6f5ac4001d..38642c0c6ab 100644 --- a/src/mod_mam.erl +++ b/src/mod_mam.erl @@ -461,11 +461,13 @@ process_iq(#jid{luser = LUser, lserver = LServer}, (_, {A, N}) -> {A, N} end, {[], []}, SubEl#xmlel.children)} of - {Default, {Always, Never}} -> - case write_prefs(LUser, LServer, LServer, Default, - lists:usort(Always), lists:usort(Never)) of + {Default, {Always0, Never0}} -> + Always = lists:usort(Always0), + Never = lists:usort(Never0), + case write_prefs(LUser, LServer, LServer, Default, Always, Never) of ok -> - IQ#iq{type = result, sub_el = []}; + NewPrefs = prefs_el(Default, Always, Never, IQ#iq.xmlns), + IQ#iq{type = result, sub_el = [NewPrefs]}; _Err -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_INTERNAL_SERVER_ERROR]} @@ -477,21 +479,11 @@ process_iq(#jid{luser = LUser, lserver = LServer}, #jid{lserver = LServer}, #iq{type = get, sub_el = #xmlel{name = <<"prefs">>}} = IQ) -> Prefs = get_prefs(LUser, LServer), - Default = jlib:atom_to_binary(Prefs#archive_prefs.default), - JFun = fun(L) -> - [#xmlel{name = <<"jid">>, - children = [{xmlcdata, jid:to_string(J)}]} - || J <- L] - end, - Always = #xmlel{name = <<"always">>, - children = JFun(Prefs#archive_prefs.always)}, - Never = #xmlel{name = <<"never">>, - children = JFun(Prefs#archive_prefs.never)}, - IQ#iq{type = result, - sub_el = [#xmlel{name = <<"prefs">>, - attrs = [{<<"xmlns">>, IQ#iq.xmlns}, - {<<"default">>, Default}], - children = [Always, Never]}]}; + PrefsEl = prefs_el(Prefs#archive_prefs.default, + Prefs#archive_prefs.always, + Prefs#archive_prefs.never, + IQ#iq.xmlns), + IQ#iq{type = result, sub_el = [PrefsEl]}; process_iq(_, _, #iq{sub_el = SubEl} = IQ) -> IQ#iq{type = error, sub_el = [SubEl, ?ERR_NOT_ALLOWED]}. @@ -874,6 +866,22 @@ get_prefs(LUser, LServer, odbc) -> error end. +prefs_el(Default, Always, Never, NS) -> + Default1 = jlib:atom_to_binary(Default), + JFun = fun(L) -> + [#xmlel{name = <<"jid">>, + children = [{xmlcdata, jid:to_string(J)}]} + || J <- L] + end, + Always1 = #xmlel{name = <<"always">>, + children = JFun(Always)}, + Never1 = #xmlel{name = <<"never">>, + children = JFun(Never)}, + #xmlel{name = <<"prefs">>, + attrs = [{<<"xmlns">>, NS}, + {<<"default">>, Default1}], + children = [Always1, Never1]}. + maybe_activate_mam(LUser, LServer) -> ActivateOpt = gen_mod:get_module_opt(LServer, ?MODULE, request_activates_archiving, diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 5054f0984dc..c426213e1e4 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1713,7 +1713,7 @@ mam_master(Config, NS) -> ?recv1(#presence{}), wait_for_slave(Config), ?recv1(#presence{from = Peer}), - #iq{type = result, sub_els = []} = + #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = roster}]} = send_recv(Config, #iq{type = set, sub_els = [#mam_prefs{xmlns = NS, @@ -1747,7 +1747,7 @@ mam_master(Config, NS) -> mam_query_with(Config, Peer, NS), %% mam_query_with(Config, jlib:jid_remove_resource(Peer)), mam_query_rsm(Config, NS), - #iq{type = result, sub_els = []} = + #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} = send_recv(Config, #iq{type = set, sub_els = [#mam_prefs{xmlns = NS, default = never}]}), @@ -1765,7 +1765,7 @@ mam_slave(Config, NS) -> wait_for_master(Config), send(Config, #presence{}), ?recv2(#presence{}, #presence{from = Peer}), - #iq{type = result, sub_els = []} = + #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = always}]} = send_recv(Config, #iq{type = set, sub_els = [#mam_prefs{xmlns = NS, default = always}]}), @@ -1776,7 +1776,7 @@ mam_slave(Config, NS) -> ?recv1(#message{from = Peer, body = [Text], sub_els = [#mam_archived{by = ServerJID}]}) end, lists:seq(1, 5)), - #iq{type = result, sub_els = []} = + #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} = send_recv(Config, #iq{type = set, sub_els = [#mam_prefs{xmlns = NS, default = never}]}), disconnect(Config). From 8e6adb4b3c68b81ae5212c2e31be4fbbfd648495 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 11 Feb 2016 11:53:33 +0300 Subject: [PATCH 577/695] Do not forget sending initial presence in XEP-0013 test --- test/ejabberd_SUITE.erl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index c426213e1e4..b6ab8e5b7ca 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1496,6 +1496,10 @@ flex_offline_slave(Config) -> when (J == MyBareJID) and (P == Peer_s) -> N end, DiscoItems)), + %% Since headers are received we can send initial presence without a risk + %% of getting offline messages flood + send(Config, #presence{}), + ?recv1(#presence{from = MyJID}), %% Check full fetch I0 = send(Config, #iq{type = get, sub_els = [#offline{fetch = true}]}), lists:foreach( From 5680d4c3e967c87374d926d8b90a2b63db2c816b Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 11 Feb 2016 12:19:23 +0300 Subject: [PATCH 578/695] Get rid of calls to jlib.erl from tests --- test/ejabberd_SUITE.erl | 92 ++++++++++++++++++++--------------------- test/suite.erl | 16 +++---- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index b6ab8e5b7ca..339a47f000b 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -131,14 +131,14 @@ init_per_testcase(TestCase, OrigConfig) -> true -> Resource end, Slave = if IsCarbons -> - jlib:make_jid(<<"test_master">>, Server, SlaveResource); + jid:make(<<"test_master">>, Server, SlaveResource); true -> - jlib:make_jid(<<"test_slave">>, Server, Resource) + jid:make(<<"test_slave">>, Server, Resource) end, Master = if IsCarbons -> - jlib:make_jid(<<"test_master">>, Server, MasterResource); + jid:make(<<"test_master">>, Server, MasterResource); true -> - jlib:make_jid(<<"test_master">>, Server, Resource) + jid:make(<<"test_master">>, Server, Resource) end, Config = set_opt(user, User, set_opt(slave, Slave, @@ -555,7 +555,7 @@ disco(Config) -> sm(Config) -> Server = ?config(server, Config), - ServerJID = jlib:make_jid(<<"">>, Server, <<"">>), + ServerJID = jid:make(<<"">>, Server, <<"">>), Msg = #message{to = ServerJID, body = [#text{data = <<"body">>}]}, true = ?config(sm, Config), %% Enable the session management with resumption enabled @@ -577,7 +577,7 @@ sm_resume(Config) -> {sm, SMConfig} = ?config(saved_config, Config), ID = ?config(sm_previd, SMConfig), Server = ?config(server, Config), - ServerJID = jlib:make_jid(<<"">>, Server, <<"">>), + ServerJID = jid:make(<<"">>, Server, <<"">>), MyJID = my_jid(Config), Txt = #text{data = <<"body">>}, Msg = #message{from = ServerJID, to = MyJID, body = [Txt]}, @@ -593,7 +593,7 @@ sm_resume(Config) -> private(Config) -> Conference = #bookmark_conference{name = <<"Some name">>, autojoin = true, - jid = jlib:make_jid( + jid = jid:make( <<"some">>, <<"some.conference.org">>, <<>>)}, @@ -681,7 +681,7 @@ privacy(Config) -> blocking(Config) -> true = is_feature_advertised(Config, ?NS_BLOCKING), - JID = jlib:make_jid(<<"romeo">>, <<"montague.net">>, <<>>), + JID = jid:make(<<"romeo">>, <<"montague.net">>, <<>>), #iq{type = result, sub_els = [#block_list{}]} = send_recv(Config, #iq{type = get, sub_els = [#block_list{}]}), I1 = send(Config, #iq{type = set, @@ -880,7 +880,7 @@ roster_subscribe_master(Config) -> ?recv1(#presence{}), wait_for_slave(Config), Peer = ?config(slave, Config), - LPeer = jlib:jid_remove_resource(Peer), + LPeer = jid:remove_resource(Peer), send(Config, #presence{type = subscribe, to = LPeer}), Push1 = ?recv1(#iq{type = set, sub_els = [#roster{items = [#roster_item{ @@ -932,7 +932,7 @@ roster_subscribe_slave(Config) -> ?recv1(#presence{}), wait_for_master(Config), Peer = ?config(master, Config), - LPeer = jlib:jid_remove_resource(Peer), + LPeer = jid:remove_resource(Peer), ?recv1(#presence{type = subscribe, from = LPeer}), send(Config, #presence{type = subscribed, to = LPeer}), Push1 = ?recv1(#iq{type = set, @@ -961,7 +961,7 @@ roster_subscribe_slave(Config) -> roster_remove_master(Config) -> MyJID = my_jid(Config), Peer = ?config(slave, Config), - LPeer = jlib:jid_remove_resource(Peer), + LPeer = jid:remove_resource(Peer), Groups = [<<"A">>, <<"B">>], wait_for_slave(Config), send(Config, #presence{}), @@ -995,7 +995,7 @@ roster_remove_master(Config) -> roster_remove_slave(Config) -> MyJID = my_jid(Config), Peer = ?config(master, Config), - LPeer = jlib:jid_remove_resource(Peer), + LPeer = jid:remove_resource(Peer), send(Config, #presence{}), ?recv1(#presence{from = MyJID, type = undefined}), wait_for_master(Config), @@ -1054,16 +1054,16 @@ proxy65_slave(Config) -> muc_master(Config) -> MyJID = my_jid(Config), PeerJID = ?config(slave, Config), - PeerBareJID = jlib:jid_remove_resource(PeerJID), - PeerJIDStr = jlib:jid_to_string(PeerJID), + PeerBareJID = jid:remove_resource(PeerJID), + PeerJIDStr = jid:to_string(PeerJID), MUC = muc_jid(Config), Room = muc_room_jid(Config), MyNick = ?config(master_nick, Config), - MyNickJID = jlib:jid_replace_resource(Room, MyNick), + MyNickJID = jid:replace_resource(Room, MyNick), PeerNick = ?config(slave_nick, Config), - PeerNickJID = jlib:jid_replace_resource(Room, PeerNick), + PeerNickJID = jid:replace_resource(Room, PeerNick), Subject = ?config(room_subject, Config), - Localhost = jlib:make_jid(<<"">>, <<"localhost">>, <<"">>), + Localhost = jid:make(<<"">>, <<"localhost">>, <<"">>), true = is_feature_advertised(Config, ?NS_MUC, MUC), %% Joining send(Config, #presence{to = MyNickJID, sub_els = [#muc{}]}), @@ -1132,7 +1132,7 @@ muc_master(Config) -> %% Sending messages (and thus, populating history for our peer) lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, I = send(Config, #message{to = Room, body = [Text], type = groupchat}), ?recv1(#message{from = MyNickJID, id = I, @@ -1244,16 +1244,16 @@ muc_master(Config) -> muc_slave(Config) -> MyJID = my_jid(Config), - MyBareJID = jlib:jid_remove_resource(MyJID), + MyBareJID = jid:remove_resource(MyJID), PeerJID = ?config(master, Config), MUC = muc_jid(Config), Room = muc_room_jid(Config), MyNick = ?config(slave_nick, Config), - MyNickJID = jlib:jid_replace_resource(Room, MyNick), + MyNickJID = jid:replace_resource(Room, MyNick), PeerNick = ?config(master_nick, Config), - PeerNickJID = jlib:jid_replace_resource(Room, PeerNick), + PeerNickJID = jid:replace_resource(Room, PeerNick), Subject = ?config(room_subject, Config), - Localhost = jlib:make_jid(<<"">>, <<"localhost">>, <<"">>), + Localhost = jid:make(<<"">>, <<"localhost">>, <<"">>), %% Receive an invite from the peer ?recv1(#message{from = Room, type = normal, sub_els = @@ -1296,7 +1296,7 @@ muc_slave(Config) -> %% Receive MUC history lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{from = PeerNickJID, type = groupchat, body = [Text], @@ -1417,7 +1417,7 @@ muc_register_slave(Config) -> announce_master(Config) -> MyJID = my_jid(Config), ServerJID = server_jid(Config), - MotdJID = jlib:jid_replace_resource(ServerJID, <<"announce/motd">>), + MotdJID = jid:replace_resource(ServerJID, <<"announce/motd">>), MotdText = #text{data = <<"motd">>}, send(Config, #presence{}), ?recv1(#presence{from = MyJID}), @@ -1430,7 +1430,7 @@ announce_master(Config) -> announce_slave(Config) -> MyJID = my_jid(Config), ServerJID = server_jid(Config), - MotdDelJID = jlib:jid_replace_resource(ServerJID, <<"announce/motd/delete">>), + MotdDelJID = jid:replace_resource(ServerJID, <<"announce/motd/delete">>), MotdText = #text{data = <<"motd">>}, send(Config, #presence{}), ?recv2(#presence{from = MyJID}, @@ -1441,10 +1441,10 @@ announce_slave(Config) -> flex_offline_master(Config) -> Peer = ?config(slave, Config), - LPeer = jlib:jid_remove_resource(Peer), + LPeer = jid:remove_resource(Peer), lists:foreach( fun(I) -> - Body = jlib:integer_to_binary(I), + Body = integer_to_binary(I), send(Config, #message{to = LPeer, body = [#text{data = Body}], subject = [#text{data = <<"subject">>}]}) @@ -1504,7 +1504,7 @@ flex_offline_slave(Config) -> I0 = send(Config, #iq{type = get, sub_els = [#offline{fetch = true}]}), lists:foreach( fun({I, N}) -> - Text = jlib:integer_to_binary(I), + Text = integer_to_binary(I), ?recv1(#message{body = Body, sub_els = SubEls}), [#text{data = Text}] = Body, #offline{items = [#offline_item{node = N}]} = @@ -1524,7 +1524,7 @@ flex_offline_slave(Config) -> node = lists:nth(4, Nodes)}]}]}), lists:foreach( fun({I, N}) -> - Text = jlib:integer_to_binary(I), + Text = integer_to_binary(I), ?recv1(#message{body = [#text{data = Text}], sub_els = SubEls}), #offline{items = [#offline_item{node = N}]} = lists:keyfind(offline, 1, SubEls) @@ -1570,7 +1570,7 @@ flex_offline_slave(Config) -> offline_master(Config) -> Peer = ?config(slave, Config), - LPeer = jlib:jid_remove_resource(Peer), + LPeer = jid:remove_resource(Peer), send(Config, #message{to = LPeer, body = [#text{data = <<"body">>}], subject = [#text{data = <<"subject">>}]}), @@ -1589,7 +1589,7 @@ offline_slave(Config) -> carbons_master(Config) -> MyJID = my_jid(Config), - MyBareJID = jlib:jid_remove_resource(MyJID), + MyBareJID = jid:remove_resource(MyJID), Peer = ?config(slave, Config), Txt = #text{data = <<"body">>}, true = is_feature_advertised(Config, ?NS_CARBONS_2), @@ -1643,7 +1643,7 @@ carbons_master(Config) -> carbons_slave(Config) -> MyJID = my_jid(Config), - MyBareJID = jlib:jid_remove_resource(MyJID), + MyBareJID = jid:remove_resource(MyJID), Peer = ?config(master, Config), Txt = #text{data = <<"body">>}, wait_for_master(Config), @@ -1711,7 +1711,7 @@ mam_new_master(Config) -> mam_master(Config, NS) -> true = is_feature_advertised(Config, NS), MyJID = my_jid(Config), - BareMyJID = jlib:jid_remove_resource(MyJID), + BareMyJID = jid:remove_resource(MyJID), Peer = ?config(slave, Config), send(Config, #presence{}), ?recv1(#presence{}), @@ -1742,14 +1742,14 @@ mam_master(Config, NS) -> wait_for_slave(Config), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, send(Config, #message{to = Peer, body = [Text]}) end, lists:seq(1, 5)), ?recv1(#presence{type = unavailable, from = Peer}), mam_query_all(Config, NS), mam_query_with(Config, Peer, NS), - %% mam_query_with(Config, jlib:jid_remove_resource(Peer)), + %% mam_query_with(Config, jid:remove_resource(Peer)), mam_query_rsm(Config, NS), #iq{type = result, sub_els = [#mam_prefs{xmlns = NS, default = never}]} = send_recv(Config, #iq{type = set, @@ -1776,7 +1776,7 @@ mam_slave(Config, NS) -> wait_for_master(Config), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{from = Peer, body = [Text], sub_els = [#mam_archived{by = ServerJID}]}) end, lists:seq(1, 5)), @@ -1800,7 +1800,7 @@ mam_query_all(Config, NS) -> end, lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{to = MyJID, sub_els = [#mam_result{ @@ -1827,7 +1827,7 @@ mam_query_with(Config, JID, NS) -> {#mam_query{xmlns = NS, with = JID}, get}; true -> Fs = [#xdata_field{var = <<"jid">>, - values = [jlib:jid_to_string(JID)]}], + values = [jid:to_string(JID)]}], {#mam_query{xmlns = NS, xdata = #xdata{type = submit, fields = Fs}}, set} end, @@ -1838,7 +1838,7 @@ mam_query_with(Config, JID, NS) -> maybe_recv_iq_result(NS, I), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{to = MyJID, sub_els = [#mam_result{ @@ -1876,7 +1876,7 @@ mam_query_rsm(Config, NS) -> maybe_recv_iq_result(NS, I1), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{to = MyJID, sub_els = [#mam_result{ @@ -1908,7 +1908,7 @@ mam_query_rsm(Config, NS) -> maybe_recv_iq_result(NS, I2), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{to = MyJID, sub_els = [#mam_result{ @@ -1945,7 +1945,7 @@ mam_query_rsm(Config, NS) -> maybe_recv_iq_result(NS, I3), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{to = MyJID, sub_els = [#mam_result{ @@ -1996,7 +1996,7 @@ mam_query_rsm(Config, NS) -> maybe_recv_iq_result(NS, I5), lists:foreach( fun(N) -> - Text = #text{data = jlib:integer_to_binary(N)}, + Text = #text{data = integer_to_binary(N)}, ?recv1(#message{to = MyJID, sub_els = [#mam_result{ @@ -2067,14 +2067,14 @@ change_client_state(Config, NewState) -> bookmark_conference() -> #bookmark_conference{name = <<"Some name">>, autojoin = true, - jid = jlib:make_jid( + jid = jid:make( <<"some">>, <<"some.conference.org">>, <<>>)}. socks5_connect(#streamhost{host = Host, port = Port}, {SID, JID1, JID2}) -> - Hash = p1_sha:sha([SID, jlib:jid_to_string(JID1), jlib:jid_to_string(JID2)]), + Hash = p1_sha:sha([SID, jid:to_string(JID1), jid:to_string(JID2)]), {ok, Sock} = gen_tcp:connect(binary_to_list(Host), Port, [binary, {active, false}]), Init = <>, @@ -2176,7 +2176,7 @@ clear_riak_tables(Config) -> User = ?config(user, Config), Server = ?config(server, Config), Room = muc_room_jid(Config), - {URoom, SRoom, _} = jlib:jid_tolower(Room), + {URoom, SRoom, _} = jid:tolower(Room), ejabberd_auth:remove_user(User, Server), ejabberd_auth:remove_user(<<"test_slave">>, Server), ejabberd_auth:remove_user(<<"test_master">>, Server), diff --git a/test/suite.erl b/test/suite.erl index e04b9d980e8..a0e0a48237d 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -331,28 +331,28 @@ response(User, Passwd, Nonce, AuthzId, Realm, CNonce, hex((erlang:md5(T))). my_jid(Config) -> - jlib:make_jid(?config(user, Config), - ?config(server, Config), - ?config(resource, Config)). + jid:make(?config(user, Config), + ?config(server, Config), + ?config(resource, Config)). server_jid(Config) -> - jlib:make_jid(<<>>, ?config(server, Config), <<>>). + jid:make(<<>>, ?config(server, Config), <<>>). pubsub_jid(Config) -> Server = ?config(server, Config), - jlib:make_jid(<<>>, <<"pubsub.", Server/binary>>, <<>>). + jid:make(<<>>, <<"pubsub.", Server/binary>>, <<>>). proxy_jid(Config) -> Server = ?config(server, Config), - jlib:make_jid(<<>>, <<"proxy.", Server/binary>>, <<>>). + jid:make(<<>>, <<"proxy.", Server/binary>>, <<>>). muc_jid(Config) -> Server = ?config(server, Config), - jlib:make_jid(<<>>, <<"conference.", Server/binary>>, <<>>). + jid:make(<<>>, <<"conference.", Server/binary>>, <<>>). muc_room_jid(Config) -> Server = ?config(server, Config), - jlib:make_jid(<<"test">>, <<"conference.", Server/binary>>, <<>>). + jid:make(<<"test">>, <<"conference.", Server/binary>>, <<>>). id() -> id(undefined). From 3908c9710c00a7da08ac76dc3680f4587bbf4164 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 11 Feb 2016 21:53:36 +0100 Subject: [PATCH 579/695] Travis CI: Make sure Riak finds callback module Riak calls back into ejabberd_riak during MapReduce. --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d1215b2bb0e..ba2fc3521be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,10 @@ install: - sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev before_script: + - mkdir "$PWD/ebin" + - echo "[{riak_kv, [{add_paths, [\"$PWD/ebin/\"]}]}]." > advanced.config + - sudo mv advanced.config /etc/riak/advanced.config + - sudo service riak restart - mysql -u root -e "CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test';" - mysql -u root -e "CREATE DATABASE ejabberd_test;" - mysql -u root -e "GRANT ALL ON ejabberd_test.* TO 'ejabberd_test'@'localhost';" @@ -39,7 +43,7 @@ script: - make - make install - make xref - - ERL_LIBS=$PWD make test + - make test - grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log after_script: From 041e886b8702c556fcc37d655212839db8d91004 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 11 Feb 2016 22:24:14 +0100 Subject: [PATCH 580/695] mod_muc_room: Don't expose JIDs in anonymous rooms Don't let room members retrieve the member list unless the room is non-anonymous. --- src/mod_muc_room.erl | 3 ++- test/ejabberd_SUITE.erl | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index 17b88bc5b65..f25f3365604 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2569,7 +2569,8 @@ process_iq_admin(From, get, Lang, SubEl, StateData) -> SAffiliation -> if (FAffiliation == owner) or (FAffiliation == admin) or - ((FAffiliation == member) and (SAffiliation == member)) -> + ((FAffiliation == member) and (SAffiliation == member) and + not (StateData#state.config)#config.anonymous) -> Items = items_with_affiliation(SAffiliation, StateData), {result, Items, StateData}; diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 339a47f000b..947bc4bd537 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -1210,6 +1210,16 @@ muc_master(Config) -> %% Receive groupchat message from the peer ?recv1(#message{type = groupchat, from = PeerNickJID, body = [#text{data = Subject}]}), + %% Retrieving a member list + #iq{type = result, sub_els = [#muc_admin{items = MemberList}]} = + send_recv(Config, + #iq{type = get, to = Room, + sub_els = + [#muc_admin{items = [#muc_item{affiliation = member}]}]}), + [#muc_item{affiliation = member, + jid = Localhost}, + #muc_item{affiliation = member, + jid = MyBareJID}] = lists:keysort(#muc_item.jid, MemberList), %% Kick the peer I2 = send(Config, #iq{type = set, to = Room, @@ -1329,16 +1339,6 @@ muc_slave(Config) -> #muc_user{ items = [#muc_item{role = participant, affiliation = member}]}]}), - %% Retrieving a member list - #iq{type = result, sub_els = [#muc_admin{items = MemberList}]} = - send_recv(Config, - #iq{type = get, to = Room, - sub_els = - [#muc_admin{items = [#muc_item{affiliation = member}]}]}), - [#muc_item{affiliation = member, - jid = Localhost}, - #muc_item{affiliation = member, - jid = MyBareJID}] = lists:keysort(#muc_item.jid, MemberList), %% Sending groupchat message send(Config, #message{to = Room, type = groupchat, body = [#text{data = Subject}]}), From eaaab45c143ce532c336f5dcd38d5469823b18bc Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Thu, 11 Feb 2016 22:52:27 +0100 Subject: [PATCH 581/695] mod_muc_room: Let members see admin/owner JIDs Let members retrieve all affiliation lists in non-anonymous rooms, not just the list of members. --- src/mod_muc_room.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index f25f3365604..06fdf325f3a 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -2569,8 +2569,8 @@ process_iq_admin(From, get, Lang, SubEl, StateData) -> SAffiliation -> if (FAffiliation == owner) or (FAffiliation == admin) or - ((FAffiliation == member) and (SAffiliation == member) and - not (StateData#state.config)#config.anonymous) -> + ((FAffiliation == member) and not + (StateData#state.config)#config.anonymous) -> Items = items_with_affiliation(SAffiliation, StateData), {result, Items, StateData}; From 4f7f66fae80c1377637038ba94e2e5407841b804 Mon Sep 17 00:00:00 2001 From: Victor Rodrigues Date: Thu, 11 Feb 2016 23:11:16 +0100 Subject: [PATCH 582/695] Update Portuguese (Brazil) translations --- priv/msgs/pt-br.msg | 72 +++++++++++++++++++++---------------------- priv/msgs/pt-br.po | 75 +++++++++++++++++++++++---------------------- 2 files changed, 74 insertions(+), 73 deletions(-) diff --git a/priv/msgs/pt-br.msg b/priv/msgs/pt-br.msg index a18227f66a6..c866608e250 100644 --- a/priv/msgs/pt-br.msg +++ b/priv/msgs/pt-br.msg @@ -3,7 +3,7 @@ {"Access Control List Configuration","Configuração da Lista de Controle de Acesso"}. {"Access control lists","Listas de Controle de Acesso"}. {"Access Control Lists","Listas de Controle de Acesso"}. -{"Access denied by service policy","Aceso denegado por la política do serviço"}. +{"Access denied by service policy","Acesso negado pela política do serviço"}. {"Access rules","Regras de acesso"}. {"Access Rules","Regras de Acesso"}. {"Action on user","Ação no usuário"}. @@ -23,11 +23,11 @@ {"Allow visitors to change nickname","Permitir mudança de apelido aos visitantes"}. {"Allow visitors to send private messages to","Permitir visitantes enviar mensagem privada para"}. {"Allow visitors to send status text in presence updates","Permitir atualizações de status aos visitantes"}. -{"Allow visitors to send voice requests","Permitir aos visitantes o envio de convites"}. +{"Allow visitors to send voice requests","Permitir aos visitantes o envio de requisições de voz"}. {"All Users","Todos os usuários"}. {"Announcements","Anúncios"}. {"anyone","qualquer um"}. -{"A password is required to enter this room","Se necessita senha para entrar em esta sala"}. +{"A password is required to enter this room","Se necessita senha para entrar nesta sala"}. {"April","Abril"}. {"August","Agosto"}. {"Backup Management","Gestão de Backup"}. @@ -43,7 +43,7 @@ {"Chatroom configuration modified","Configuração da sala de bate-papo modificada"}. {"Chatroom is created","A sala de chat está criada"}. {"Chatroom is destroyed","A sala de chat está destruída"}. -{"Chatroom is started","A sala de chat está inciada"}. +{"Chatroom is started","A sala de chat está iniciada"}. {"Chatroom is stopped","A sala de chat está parada"}. {"Chatrooms","Salas de Chat"}. {"Choose a username and password to register with this server","Escolha um nome de usuário e senha para registrar-se neste servidor"}. @@ -52,7 +52,7 @@ {"Choose whether to approve this entity's subscription.","Aprovar esta assinatura."}. {"City","Cidade"}. {"Commands","Comandos"}. -{"Conference room does not exist","La sala de conferencias não existe"}. +{"Conference room does not exist","A sala de conferência não existe"}. {"Configuration","Configuração"}. {"Configuration of room ~s","Configuração para ~s"}. {"Connected Resources:","Recursos conectados:"}. @@ -60,7 +60,7 @@ {"Country","País"}. {"CPU Time:","Tempo de CPU"}. {"Database","Base de dados"}. -{"Database Tables at ~p","Tabelas do bancod de dados em ~p"}. +{"Database Tables at ~p","Tabelas da Base de dados em ~p"}. {"Database Tables Configuration at ","Configuração de Tabelas de Base de dados em "}. {"December","Dezembro"}. {"Default users as participants","Usuários padrões como participantes"}. @@ -71,9 +71,9 @@ {"Deliver event notifications","Entregar as notificações de evento"}. {"Deliver payloads with event notifications","Enviar payloads junto com as notificações de eventos"}. {"Description:","Descrição:"}. -{"Disc only copy","Somente copia em disco"}. +{"Disc only copy","Somente cópia em disco"}. {"Displayed Groups:","Grupos Exibidos:"}. -{"Don't tell your password to anybody, not even the administrators of the Jabber server.","Não revele o seu computador a ninguém, mesmo para o administrador deste servidor Jabber."}. +{"Don't tell your password to anybody, not even the administrators of the Jabber server.","Não revele a sua senha a ninguém, nem mesmo para o administrador deste servidor Jabber."}. {"Dump Backup to Text File at ","Exportar backup para texto em "}. {"Dump to Text File","Exportar para arquivo texto"}. {"Edit Properties","Editar propriedades"}. @@ -99,7 +99,7 @@ {"Enter path to text file","Introduza caminho para o arquivo texto"}. {"Enter the text you see","Insira o texto que você vê"}. {"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","Insira o nome de usuário e codificações que você deseja usar para conectar-se aos servidores de IRC. Depois, presione 'Next' ('Próximo') para exibir mais campos que devem ser preenchidos. Ao final, pressione 'Complete' ('Completar') para salvar a configuração."}. -{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Insira o nome de usuário, codificações, portas e senhas que vocêdeseja para usar nos servidores IRC"}. +{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Insira o nome de usuário, codificações, portas e senhas que você deseja para usar nos servidores IRC"}. {"Erlang Jabber Server","Servidor Jabber em Erlang"}. {"Error","Erro"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Exemplo: [{\"irc.teste.net\", \"koi8-r\"}, 6667, \"senha\"}, {\"dominio.foo.net\", \"iso8859-1\", 7000}, {\"irc.servidordeteste.net\", \"utf-8\"}]."}. @@ -129,7 +129,7 @@ {"has been kicked because of a system shutdown","foi desconectado porque o sistema foi desligado"}. {"has been kicked because the room has been changed to members-only","foi desconectado porque a política da sala mudou, só membros são permitidos"}. {"has been kicked","foi removido"}. -{" has set the subject to: "," a posto o assunto: "}. +{" has set the subject to: "," mudou o assunto para: "}. {"Host","Máquina"}. {"If you don't see the CAPTCHA image here, visit the web page.","Se você não conseguir ver o CAPTCHA aqui, visite a web page."}. {"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","Se você deseja especificar portas diferentes, senhas ou codifações para servidores de IRC, complete esta lista com os valores no formato: '{\"servidor IRC\", \"codificação\", porta, \"senha\"}'. Por padrão, este serviço usa a codificação \"~s\", porta \"~p\", e senha em branco (vazia)"}. @@ -155,7 +155,7 @@ {"IRC Username","Usuário IRC"}. {"is now known as","é agora conhecido como"}. {"It is not allowed to send private messages","Não é permitido enviar mensagens privadas"}. -{"It is not allowed to send private messages of type \"groupchat\"","No está permitido enviar mensagens privados do tipo \"groupchat\""}. +{"It is not allowed to send private messages of type \"groupchat\"","Não é permitido enviar mensagens privadas do tipo \"groupchat\""}. {"It is not allowed to send private messages to the conference","Impedir o envio de mensagens privadas para a sala"}. {"Jabber Account Registration","Registros de Contas Jabber"}. {"Jabber ID","ID Jabber"}. @@ -181,7 +181,7 @@ {"Make room CAPTCHA protected","Tornar protegida a senha da sala"}. {"Make room members-only","Tornar sala apenas para membros"}. {"Make room moderated","Tornar a sala moderada"}. -{"Make room password protected","Tornar protegida a senha da sala"}. +{"Make room password protected","Tornar sala protegida à senha"}. {"Make room persistent","Tornar sala persistente"}. {"Make room public searchable","Tornar sala pública possível de ser encontrada"}. {"March","Março"}. @@ -189,7 +189,7 @@ {"Max # of items to persist","Máximo # de elementos que persistem"}. {"Max payload size in bytes","Máximo tamanho do payload em bytes"}. {"May","Maio"}. -{"Membership is required to enter this room","Necessitas ser membro de esta sala para poder entrar"}. +{"Membership is required to enter this room","Necessitas ser membro desta sala para poder entrar"}. {"Members:","Membros:"}. {"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Memorize a sua senha, ou escreva-a em um papel e guarde-o em um lugar seguro. Jabber não é uma maneira automatizada para recuperar a sua senha, se você a esquecer eventualmente."}. {"Memory","Memória"}. @@ -211,7 +211,7 @@ {"New Password:","Nova Senha:"}. {"Nickname","Apelido"}. {"Nickname Registration at ","Registro do apelido em "}. -{"Nickname ~s does not exist in the room","O nick ~s não existe em la sala"}. +{"Nickname ~s does not exist in the room","O nick ~s não existe na sala"}. {"nobody","ninguém"}. {"No body provided for announce message","Nenhum corpo de texto fornecido para anunciar mensagem"}. {"No Data","Nenhum dado"}. @@ -238,19 +238,19 @@ {"Online","Conectado"}. {"Online Users","Usuários conectados"}. {"Online Users:","Usuários online"}. -{"Only deliver notifications to available users","Solo enviar notificações aos usuários disponíveis"}. +{"Only deliver notifications to available users","Somente enviar notificações aos usuários disponíveis"}. {"Only moderators and participants are allowed to change the subject in this room","Somente os moderadores e os participamentes podem alterar o assunto desta sala"}. {"Only moderators are allowed to change the subject in this room","Somente os moderadores podem alterar o assunto desta sala"}. {"Only moderators can approve voice requests","Somente moderadores podem aprovar requisições de voz"}. -{"Only occupants are allowed to send messages to the conference","Solo os ocupantes podem enviar mensagens a la sala"}. -{"Only occupants are allowed to send queries to the conference","Solo os ocupantes podem enviar consultas a la sala"}. +{"Only occupants are allowed to send messages to the conference","Somente os ocupantes podem enviar mensagens à sala"}. +{"Only occupants are allowed to send queries to the conference","Somente os ocupantes podem enviar consultas à sala"}. {"Only service administrators are allowed to send service messages","Apenas administradores possuem permissão para enviar mensagens de serviço"}. {"Options","Opções"}. {"Organization Name","Nome da organização"}. {"Organization Unit","Departamento/Unidade"}. {"Outgoing s2s Connections","Conexões que partam de s2s"}. {"Outgoing s2s Connections:","Conexões que partem de s2s"}. -{"Owner privileges required","Se requere privilégios de proprietário da sala"}. +{"Owner privileges required","Se requer privilégios de proprietário da sala"}. {"Packet","Pacote"}. {"Password ~b","Senha ~b"}. {"Password:","Senha:"}. @@ -276,18 +276,18 @@ {"PubSub subscriber request","PubSub requisição de assinante"}. {"Purge all items when the relevant publisher goes offline","Descartar todos os itens quando o publicante principal estiver offline"}. {"Queries to the conference members are not allowed in this room","Nesta sala não se permite consultas aos membros da sala"}. -{"RAM and disc copy","Copias na RAM e disco rígido"}. -{"RAM copy","Copia em RAM"}. +{"RAM and disc copy","Cópias na RAM e disco rígido"}. +{"RAM copy","Cópia em RAM"}. {"Raw","Intocado"}. {"Really delete message of the day?","Deletar realmente a mensagem do dia?"}. -{"Recipient is not in the conference room","O receptor não está em la sala de conferencia"}. +{"Recipient is not in the conference room","O receptor não está na sala de conferência"}. {"Register a Jabber account","Registrar uma conta Jabber"}. {"Registered nicknames","Usuários registrados"}. {"Registered Users:","Usuários registrados"}. {"Registered Users","Usuários Registrados"}. {"Register","Registrar"}. {"Registration in mod_irc for ","Registro em mod_irc para "}. -{"Remote copy","Copia remota"}. +{"Remote copy","Cópia remota"}. {"Remove All Offline Messages","Remover Todas as Mensagens Offline"}. {"Remove","Remover"}. {"Remove User","Remover usuário"}. @@ -301,7 +301,7 @@ {"Restore plain text backup immediately:","Restaurar backup formato texto imediatamente:"}. {"Restore","Restaurar"}. {"Room Configuration","Configuração de salas"}. -{"Room creation is denied by service policy","Se te a denegado criar la sala por política do serviço"}. +{"Room creation is denied by service policy","Sala não pode ser criada devido à política do serviço"}. {"Room description","Descrição da Sala"}. {"Room Occupants","Número de participantes"}. {"Room title","Título da sala"}. @@ -310,7 +310,7 @@ {"Roster of ","Lista de contatos de "}. {"Roster size","Tamanho da Lista"}. {"RPC Call Error","Erro de chamada RPC"}. -{"Running Nodes","Nos em execução"}. +{"Running Nodes","Nós em execução"}. {"~s access rule configuration","Configuração da Regra de Acesso ~s"}. {"Saturday","Sábado"}. {"Script check","Verificação de Script"}. @@ -330,7 +330,7 @@ {"Show Ordinary Table","Mostrar Tabela Ordinária"}. {"Shut Down Service","Parar Serviço"}. {"~s invites you to the room ~s","~s convidou você para a sala ~s"}. -{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clientes jabber podem salvar a sua senha no seu computador. Use recurso somente se você considera este computador seguro o suficiente."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clientes jabber podem salvar a sua senha no seu computador. Use o recurso somente se você considera este computador seguro o suficiente."}. {"Specify the access model","Especificar os modelos de acesso"}. {"Specify the event message type","Especificar o tipo de mensagem para o evento"}. {"Specify the publisher model","Especificar o modelo do publicante"}. @@ -343,7 +343,7 @@ {"Stop Modules at ","Parar módulos em "}. {"Stop Modules","Parar módulos"}. {"Stop","Parar"}. -{"Stopped Nodes","Nos parados"}. +{"Stopped Nodes","Nós parados"}. {"Storage Type","Tipo de armazenamento"}. {"Store binary backup:","Armazenar backup binário:"}. {"Store plain text backup:","Armazenar backup em texto:"}. @@ -361,9 +361,9 @@ {"the password is","a senha é"}. {"The password is too weak","Senha considerada fraca'"}. {"The password of your Jabber account was successfully changed.","A senha da sua conta Jabber foi mudada com sucesso."}. -{"There was an error changing the password: ","Houveram erros ao mudar a senha: "}. -{"There was an error creating the account: ","Houveram erras ao criar esta conta: "}. -{"There was an error deleting the account: ","Erro ao deletar esta conta: "}. +{"There was an error changing the password: ","Houve um erro ao mudar a senha: "}. +{"There was an error creating the account: ","Houve um erro ao criar esta conta: "}. +{"There was an error deleting the account: ","Houve um erro ao deletar esta conta: "}. {"This IP address is blacklisted in ~s","Este endereço IP está bloqueado em ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Não é 'case insensitive': macbeth é o mesmo que MacBeth e ainda Macbeth. "}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Esta pagina aceita criações de novas contas Jabber neste servidor. A sua JID (Identificador Jabber) será da seguinte forma: 'usuário@servidor'. Por favor, leia cuidadosamente as instruções para preencher corretamente os campos."}. @@ -372,7 +372,7 @@ {"Time delay","Intervalo (Tempo)"}. {"Time","Tempo"}. {"Too many CAPTCHA requests","Número excessivo de requisições para o CAPTCHA"}. -{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço serádesbloqueado as ~s UTC"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço será desbloqueado às ~s UTC"}. {"Too many unacked stanzas","número excessivo de instâncias sem confirmação"}. {"To","Para"}. {"To ~s","Para ~s"}. @@ -399,30 +399,30 @@ {"User Management","Gerenciamento de Usuários"}. {"Username:","Usuário:"}. {"Users are not allowed to register accounts so quickly","Usuários não estão autorizados a registrar contas imediatamente"}. -{"Users Last Activity","Ultimas atividades dos usuários"}. +{"Users Last Activity","Últimas atividades dos usuários"}. {"User ~s","Usuário ~s"}. {"Users","Usuários"}. {"User","Usuário"}. {"Validate","Validar"}. {"vCard User Search","Busca de Usuário vCard"}. {"Virtual Hosts","Hosts virtuais"}. -{"Visitors are not allowed to change their nicknames in this room","Nesta sala, os visitantes não pode mudar seus apelidos"}. +{"Visitors are not allowed to change their nicknames in this room","Nesta sala, os visitantes não podem mudar seus apelidos"}. {"Visitors are not allowed to send messages to all occupants","Os visitantes não podem enviar mensagens a todos os ocupantes"}. {"Voice request","Requisição de voz"}. -{"Voice requests are disabled in this conference","Requisições de voz estào desabilitadas nesta conferência"}. +{"Voice requests are disabled in this conference","Requisições de voz estão desabilitadas nesta conferência"}. {"Wednesday","Quarta"}. {"When to send the last published item","Quando enviar o último tópico publicado"}. {"Whether to allow subscriptions","Permitir subscrições"}. {"You can later change your password using a Jabber client.","Mais tarde você pode alterar a sua senha usando um cliente Jabber."}. -{"You have been banned from this room","As sido bloqueado em esta sala"}. +{"You have been banned from this room","Você foi banido desta sala"}. {"You must fill in field \"Nickname\" in the form","Você deve completar o campo \"Apelido\" no formulário"}. {"You need a client that supports x:data and CAPTCHA to register","Você precisa de um cliente com suporte de x:data para poder registrar o nick"}. {"You need a client that supports x:data to register the nickname","Você precisa de um cliente com suporte a x:data para registrar o seu apelido"}. -{"You need an x:data capable client to configure mod_irc settings","Necessitas um cliente com suporte de x:data para configurar las opções de mod_irc"}. +{"You need an x:data capable client to configure mod_irc settings","Necessitas um cliente com suporte de x:data para configurar as opções de mod_irc"}. {"You need an x:data capable client to configure room","Necessitas um cliente com suporte de x:data para configurar la sala"}. {"You need an x:data capable client to search","Necessitas um cliente com suporte de x:data para poder buscar"}. {"Your active privacy list has denied the routing of this stanza.","Sua lista de privacidade ativa negou o roteamento deste."}. {"Your contact offline message queue is full. The message has been discarded.","Sua fila de mensagens offline esta cheia. Sua mensagem foi descartada"}. -{"Your Jabber account was successfully created.","Sua conta jabber foi criada corretamente."}. +{"Your Jabber account was successfully created.","Sua conta jabber foi criada com sucesso."}. {"Your Jabber account was successfully deleted.","Sua conta Jabber foi deletada com sucesso."}. {"Your messages to ~s are being blocked. To unblock them, visit ~s","Suas mensagens para ~s estão bloqueadas. Para desbloqueá-las, visite: ~s"}. diff --git a/priv/msgs/pt-br.po b/priv/msgs/pt-br.po index e60153a8b69..6d2ae1c5788 100644 --- a/priv/msgs/pt-br.po +++ b/priv/msgs/pt-br.po @@ -1,11 +1,12 @@ msgid "" msgstr "" "Project-Id-Version: 2.1.0-alpha\n" -"Last-Translator: Otávio Fernandes\n" +"Last-Translator: Victor Rodrigues\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Language: Portuguese (Brazil)\n" +"X-Additional-Translator: Otávio Fernandes\n" "X-Additional-Translator: Renato Botelho\n" "X-Additional-Translator: Lucius Curado\n" "X-Additional-Translator: Felipe Brito Vasconcellos\n" @@ -153,7 +154,7 @@ msgstr "Usuários conectados" #: ejabberd_web_admin.erl:971 msgid "Users Last Activity" -msgstr "Ultimas atividades dos usuários" +msgstr "Últimas atividades dos usuários" #: ejabberd_web_admin.erl:975 msgid "Period: " @@ -281,7 +282,7 @@ msgstr "Nós" #: ejabberd_web_admin.erl:1814 mod_configure.erl:525 msgid "Running Nodes" -msgstr "Nos em execução" +msgstr "Nós em execução" #: ejabberd_web_admin.erl:1815 mod_configure.erl:526 msgid "Stopped Nodes" @@ -327,7 +328,7 @@ msgstr "Erro de chamada RPC" #: ejabberd_web_admin.erl:1917 msgid "Database Tables at ~p" -msgstr "Tabelas do bancod de dados em ~p" +msgstr "Tabelas da Base de dados em ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -687,19 +688,19 @@ msgstr "Selecione o tipo de armazenamento das tabelas" #: mod_configure.erl:1014 mod_configure.erl:1016 msgid "Disc only copy" -msgstr "Somente copia em disco" +msgstr "Somente cópia em disco" #: mod_configure.erl:1014 mod_configure.erl:1016 msgid "RAM and disc copy" -msgstr "Copias na RAM e disco rígido" +msgstr "Cópias na RAM e disco rígido" #: mod_configure.erl:1014 mod_configure.erl:1016 msgid "RAM copy" -msgstr "Copia em RAM" +msgstr "Cópia em RAM" #: mod_configure.erl:1014 mod_configure.erl:1016 msgid "Remote copy" -msgstr "Copia remota" +msgstr "Cópia remota" #: mod_configure.erl:1042 msgid "Stop Modules at " @@ -840,7 +841,7 @@ msgid "" "will be unblocked at ~s UTC" msgstr "" "Número excessivo (~p) de tentativas falhas de autenticação (~s). O endereço " -"serádesbloqueado as ~s UTC" +"será desbloqueado às ~s UTC" #: mod_http_upload.erl:586 msgid "Please specify file size." @@ -856,7 +857,7 @@ msgstr "Este endereço IP está bloqueado em ~s" #: mod_irc.erl:220 mod_muc.erl:455 msgid "Access denied by service policy" -msgstr "Aceso denegado por la política do serviço" +msgstr "Acesso negado pela política do serviço" #: mod_irc.erl:439 msgid "IRC Transport" @@ -869,7 +870,7 @@ msgstr "Módulo de IRC para ejabberd" #: mod_irc.erl:644 msgid "You need an x:data capable client to configure mod_irc settings" msgstr "" -"Necessitas um cliente com suporte de x:data para configurar las opções de " +"Necessitas um cliente com suporte de x:data para configurar as opções de " "mod_irc" #: mod_irc.erl:653 @@ -881,7 +882,7 @@ msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -"Insira o nome de usuário, codificações, portas e senhas que vocêdeseja para " +"Insira o nome de usuário, codificações, portas e senhas que você deseja para " "usar nos servidores IRC" #: mod_irc.erl:667 @@ -978,7 +979,7 @@ msgstr "" #: mod_muc.erl:610 msgid "Room creation is denied by service policy" -msgstr "Sala não pode ser criada devido a política de serviço" +msgstr "Sala não pode ser criada devido à política do serviço" #: mod_muc.erl:617 msgid "Conference room does not exist" @@ -1078,7 +1079,7 @@ msgstr "é agora conhecido como" #: mod_muc_log.erl:449 mod_muc_log.erl:788 msgid " has set the subject to: " -msgstr " a posto o assunto: " +msgstr " mudou o assunto para: " #: mod_muc_log.erl:489 msgid "Chatroom is created" @@ -1090,7 +1091,7 @@ msgstr "A sala de chat está destruída" #: mod_muc_log.erl:493 msgid "Chatroom is started" -msgstr "A sala de chat está inciada" +msgstr "A sala de chat está iniciada" #: mod_muc_log.erl:495 msgid "Chatroom is stopped" @@ -1190,7 +1191,7 @@ msgid "" "has sent an error message (~s) and got kicked from the room" msgstr "" "Não é permitido o envio de mensagens de erro a esta sala. O membro " -"(~s)enviou uma mensagem de erro (~s) e foi desconectado (\"kicked\")." +"(~s) enviou uma mensagem de erro (~s) e foi desconectado (\"kicked\")." #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1202,7 +1203,7 @@ msgstr "Por favor, espere antes de enviar uma nova requisição de voz" #: mod_muc_room.erl:329 msgid "Voice requests are disabled in this conference" -msgstr "Requisições de voz estào desabilitadas nesta conferência" +msgstr "Requisições de voz estão desabilitadas nesta conferência" #: mod_muc_room.erl:347 msgid "Failed to extract JID from your voice request approval" @@ -1218,11 +1219,11 @@ msgstr "Tipo de mensagem incorreto" #: mod_muc_room.erl:534 msgid "It is not allowed to send private messages of type \"groupchat\"" -msgstr "No está permitido enviar mensagens privados do tipo \"groupchat\"" +msgstr "Não é permitido enviar mensagens privadas do tipo \"groupchat\"" #: mod_muc_room.erl:546 mod_muc_room.erl:621 msgid "Recipient is not in the conference room" -msgstr "O receptor não está em la sala de conferencia" +msgstr "O receptor não está na sala de conferência" #: mod_muc_room.erl:576 mod_muc_room.erl:598 msgid "It is not allowed to send private messages" @@ -1230,11 +1231,11 @@ msgstr "Não é permitido enviar mensagens privadas" #: mod_muc_room.erl:588 mod_muc_room.erl:983 mod_muc_room.erl:4594 msgid "Only occupants are allowed to send messages to the conference" -msgstr "Solo os ocupantes podem enviar mensagens a la sala" +msgstr "Somente os ocupantes podem enviar mensagens à sala" #: mod_muc_room.erl:644 msgid "Only occupants are allowed to send queries to the conference" -msgstr "Solo os ocupantes podem enviar consultas a la sala" +msgstr "Somente os ocupantes podem enviar consultas à sala" #: mod_muc_room.erl:657 msgid "Queries to the conference members are not allowed in this room" @@ -1258,7 +1259,7 @@ msgstr "Os visitantes não podem enviar mensagens a todos os ocupantes" #: mod_muc_room.erl:1080 msgid "Visitors are not allowed to change their nicknames in this room" -msgstr "Nesta sala, os visitantes não pode mudar seus apelidos" +msgstr "Nesta sala, os visitantes não podem mudar seus apelidos" #: mod_muc_room.erl:1093 mod_muc_room.erl:1835 msgid "That nickname is already in use by another occupant" @@ -1266,15 +1267,15 @@ msgstr "O apelido (nick) já está sendo utilizado" #: mod_muc_room.erl:1822 msgid "You have been banned from this room" -msgstr "As sido bloqueado em esta sala" +msgstr "Você foi banido desta sala" #: mod_muc_room.erl:1826 msgid "Membership is required to enter this room" -msgstr "Necessitas ser membro de esta sala para poder entrar" +msgstr "Necessitas ser membro desta sala para poder entrar" #: mod_muc_room.erl:1872 msgid "A password is required to enter this room" -msgstr "Se necessita senha para entrar em esta sala" +msgstr "Se necessita senha para entrar nesta sala" #: mod_muc_room.erl:1898 mod_register.erl:295 msgid "Too many CAPTCHA requests" @@ -1302,7 +1303,7 @@ msgstr "O Jabber ID ~s não es válido" #: mod_muc_room.erl:2772 msgid "Nickname ~s does not exist in the room" -msgstr "O nick ~s não existe em la sala" +msgstr "O nick ~s não existe na sala" #: mod_muc_room.erl:2795 mod_muc_room.erl:3175 msgid "Invalid affiliation: ~s" @@ -1314,7 +1315,7 @@ msgstr "Cargo (role) é não válido: ~s" #: mod_muc_room.erl:3155 mod_muc_room.erl:3187 mod_muc_room.erl:4236 msgid "Owner privileges required" -msgstr "Se requere privilégios de proprietário da sala" +msgstr "Se requer privilégios de proprietário da sala" #: mod_muc_room.erl:3348 msgid "Configuration of room ~s" @@ -1342,7 +1343,7 @@ msgstr "Tornar pública a lista de participantes" #: mod_muc_room.erl:3380 msgid "Make room password protected" -msgstr "Tornar protegida a senha da sala" +msgstr "Tornar sala protegida à senha" #: mod_muc_room.erl:3394 msgid "Maximum Number of Occupants" @@ -1426,7 +1427,7 @@ msgstr "Permitir mudança de apelido aos visitantes" #: mod_muc_room.erl:3589 msgid "Allow visitors to send voice requests" -msgstr "Permitir aos visitantes o envio de convites" +msgstr "Permitir aos visitantes o envio de requisições de voz" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" @@ -1450,7 +1451,7 @@ msgstr "Permitir criação de logs" #: mod_muc_room.erl:3631 msgid "You need an x:data capable client to configure room" -msgstr "Necessitas um cliente com suporte de x:data para configurar la sala" +msgstr "Necessitas um cliente com suporte de x:data para configurar a sala" #: mod_muc_room.erl:4192 msgid "Number of occupants" @@ -1474,7 +1475,7 @@ msgstr "Usuário JID" #: mod_muc_room.erl:4355 msgid "Grant voice to this person?" -msgstr "Dar 'voice' a esta usuário?" +msgstr "Dar voz a esta pessoa?" #: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" @@ -1623,7 +1624,7 @@ msgstr "Quando enviar o último tópico publicado" #: mod_pubsub.erl:3777 msgid "Only deliver notifications to available users" -msgstr "Solo enviar notificações aos usuários disponíveis" +msgstr "Somente enviar notificações aos usuários disponíveis" #: mod_pubsub.erl:3779 msgid "The collections with which a node is affiliated" @@ -1652,11 +1653,11 @@ msgstr "Usuários não estão autorizados a registrar contas imediatamente" #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." -msgstr "Sua conta jabber foi criada corretamente." +msgstr "Sua conta jabber foi criada com sucesso." #: mod_register_web.erl:110 msgid "There was an error creating the account: " -msgstr "Houveram erras ao criar esta conta: " +msgstr "Houve um erro ao criar esta conta: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." @@ -1664,7 +1665,7 @@ msgstr "Sua conta Jabber foi deletada com sucesso." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " -msgstr "Erro ao deletar esta conta: " +msgstr "Houve um erro ao deletar esta conta: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." @@ -1672,7 +1673,7 @@ msgstr "A senha da sua conta Jabber foi mudada com sucesso." #: mod_register_web.erl:140 msgid "There was an error changing the password: " -msgstr "Houveram erros ao mudar a senha: " +msgstr "Houve um erro ao mudar a senha: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" @@ -1719,7 +1720,7 @@ msgid "" "Don't tell your password to anybody, not even the administrators of the " "Jabber server." msgstr "" -"Não revele o seu computador a ninguém, mesmo para o administrador deste " +"Não revele a sua senha a ninguém, nem mesmo para o administrador deste " "servidor Jabber." #: mod_register_web.erl:249 From c57931382164701661a2cd8dfb64d8436851ea7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Dr=C3=B6ge?= Date: Fri, 12 Feb 2016 18:45:45 +0100 Subject: [PATCH 583/695] Fix the color of links in tables in web admin --- src/ejabberd_web_admin.erl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 8a7be6cce9c..1b60f826775 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -512,6 +512,9 @@ css(Host) -> " background: #3eaffa;\n" " color: #fff;\n" "}\n" + "thead tr td a {\n" + " color: #fff;\n" + "}\n" "td.copy {\n" " text-align: center;\n" "}\n" From 47a67c7320089be64697232ccd218bc3c10ba508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 12 Feb 2016 23:37:48 +0100 Subject: [PATCH 584/695] Allow to pass \n in argument to ejabberdctl --- ejabberdctl.template | 6 +++++- src/ejabberd_ctl.erl | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index d585d66f768..0d1a642923a 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -163,7 +163,11 @@ shell_escape() { local RES=() for i in "$@"; do - printf '%q ' "$i" + if test -z "$i"; then + printf '"" ' + else + printf '"%q" ' "$i" | sed 's/\\\\n/\n/g;s/\\\\t/\t/g;s/\\\\r/\r/g' + fi done } diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 2bf20c2e72d..9ff30d7ff2d 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -324,7 +324,7 @@ format_args(Args, ArgsFormat) -> format_arg(Arg, integer) -> format_arg2(Arg, "~d"); format_arg(Arg, binary) -> - list_to_binary(format_arg(Arg, string)); + unicode:characters_to_binary(Arg, utf8); format_arg("", string) -> ""; format_arg(Arg, string) -> From d40a091eda4a4a9d3d6c9e27ea4c0aeea2a7496d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 15 Feb 2016 15:21:20 +0100 Subject: [PATCH 585/695] Another fix for \n in ejabberdctl arguments --- ejabberdctl.template | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 0d1a642923a..07395aafdd1 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -31,14 +31,14 @@ if [ "$INSTALLUSER" != "" ] ; then fi done if [ `id -g` -eq `id -g $INSTALLUSER` ] ; then - EXEC_CMD="sh -c" + EXEC_CMD="bash -c" fi if [ "$EXEC_CMD" = "false" ] ; then echo "This command can only be run by root or the user $INSTALLUSER" >&2 exit 4 fi else - EXEC_CMD="sh -c" + EXEC_CMD="bash -c" fi # parse command line parameters @@ -166,7 +166,7 @@ shell_escape() if test -z "$i"; then printf '"" ' else - printf '"%q" ' "$i" | sed 's/\\\\n/\n/g;s/\\\\t/\t/g;s/\\\\r/\r/g' + printf '%q ' "$i" fi done } From eece6e69cbc29b13cda1e489699ea83cfb3d49c5 Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 17 Feb 2016 20:43:35 +0100 Subject: [PATCH 586/695] Fix format_result so get_room_options command works again after aa5caa3 --- src/ejabberd_ctl.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index 9ff30d7ff2d..7a26644f536 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -349,7 +349,7 @@ format_result(Atom, {_Name, atom}) -> format_result(Int, {_Name, integer}) -> io_lib:format("~p", [Int]); -format_result(String, {_Name, string}) when is_list(String) -> +format_result([A|_]=String, {_Name, string}) when is_list(String) and is_integer(A) -> io_lib:format("~s", [String]); format_result(Binary, {_Name, string}) when is_binary(Binary) -> From 4b0860e7debf0326fac0cc93fbfedd202bf2f6d1 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 19 Feb 2016 16:15:11 +0300 Subject: [PATCH 587/695] Make it possible to define 'sm_db_type' per virtual host --- sql/lite.sql | 14 ++++++ src/ejabberd_sm.erl | 72 +++++++++++++++++---------- src/ejabberd_sm_odbc.erl | 4 +- src/ejabberd_sm_redis.erl | 4 +- test/ejabberd_SUITE_data/ejabberd.yml | 3 ++ 5 files changed, 67 insertions(+), 30 deletions(-) diff --git a/sql/lite.sql b/sql/lite.sql index 5132c917232..0cf7ff4145c 100644 --- a/sql/lite.sql +++ b/sql/lite.sql @@ -296,3 +296,17 @@ CREATE TABLE archive_prefs ( never text NOT NULL, created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ); + +CREATE TABLE sm ( + usec bigint NOT NULL, + pid text NOT NULL, + node text NOT NULL, + username text NOT NULL, + resource text NOT NULL, + priority text NOT NULL, + info text NOT NULL +); + +CREATE UNIQUE INDEX i_sm_sid ON sm(usec, pid); +CREATE INDEX i_sm_node ON sm(node); +CREATE INDEX i_sm_username ON sm(username); diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index a3442a9d2f2..b2e5a21f3e9 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -50,6 +50,7 @@ dirty_get_my_sessions_list/0, get_vh_session_list/1, get_vh_session_number/1, + get_vh_by_backend/1, register_iq_handler/4, register_iq_handler/5, unregister_iq_handler/2, @@ -133,10 +134,10 @@ open_session(SID, User, Server, Resource, Info) -> -spec close_session(sid(), binary(), binary(), binary()) -> ok. close_session(SID, User, Server, Resource) -> - Mod = get_sm_backend(), LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), + Mod = get_sm_backend(LServer), Info = case Mod:delete_session(LUser, LServer, LResource, SID) of {ok, #session{info = I}} -> I; {error, notfound} -> [] @@ -172,14 +173,14 @@ disconnect_removed_user(User, Server) -> get_user_resources(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), Ss = Mod:get_sessions(LUser, LServer), [element(3, S#session.usr) || S <- clean_session_list(Ss)]. -spec get_user_present_resources(binary(), binary()) -> [tuple()]. get_user_present_resources(LUser, LServer) -> - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), Ss = Mod:get_sessions(LUser, LServer), [{S#session.priority, element(3, S#session.usr)} || S <- clean_session_list(Ss), is_integer(S#session.priority)]. @@ -190,7 +191,7 @@ get_user_ip(User, Server, Resource) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), case Mod:get_sessions(LUser, LServer, LResource) of [] -> undefined; @@ -205,7 +206,7 @@ get_user_info(User, Server, Resource) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), case Mod:get_sessions(LUser, LServer, LResource) of [] -> offline; @@ -255,7 +256,7 @@ get_session_pid(User, Server, Resource) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), case Mod:get_sessions(LUser, LServer, LResource) of [#session{sid = {_, Pid}}] -> Pid; _ -> none @@ -264,33 +265,40 @@ get_session_pid(User, Server, Resource) -> -spec dirty_get_sessions_list() -> [ljid()]. dirty_get_sessions_list() -> - Mod = get_sm_backend(), - [S#session.usr || S <- Mod:get_sessions()]. + lists:flatmap( + fun(Mod) -> + [S#session.usr || S <- Mod:get_sessions()] + end, get_sm_backends()). -spec dirty_get_my_sessions_list() -> [#session{}]. dirty_get_my_sessions_list() -> - Mod = get_sm_backend(), - [S || S <- Mod:get_sessions(), node(element(2, S#session.sid)) == node()]. + lists:flatmap( + fun(Mod) -> + [S || S <- Mod:get_sessions(), + node(element(2, S#session.sid)) == node()] + end, get_sm_backends()). -spec get_vh_session_list(binary()) -> [ljid()]. get_vh_session_list(Server) -> LServer = jid:nameprep(Server), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), [S#session.usr || S <- Mod:get_sessions(LServer)]. -spec get_all_pids() -> [pid()]. get_all_pids() -> - Mod = get_sm_backend(), - [element(2, S#session.sid) || S <- Mod:get_sessions()]. + lists:flatmap( + fun(Mod) -> + [element(2, S#session.sid) || S <- Mod:get_sessions()] + end, get_sm_backends()). -spec get_vh_session_number(binary()) -> non_neg_integer(). get_vh_session_number(Server) -> LServer = jid:nameprep(Server), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), length(Mod:get_sessions(LServer)). register_iq_handler(Host, XMLNS, Module, Fun) -> @@ -312,8 +320,7 @@ unregister_iq_handler(Host, XMLNS) -> %%==================================================================== init([]) -> - Mod = get_sm_backend(), - Mod:init(), + lists:foreach(fun(Mod) -> Mod:init() end, get_sm_backends()), ets:new(sm_iqtable, [named_table]), lists:foreach( fun(Host) -> @@ -380,7 +387,7 @@ set_session(SID, User, Server, Resource, Priority, Info) -> LResource = jid:resourceprep(Resource), US = {LUser, LServer}, USR = {LUser, LServer, LResource}, - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), Mod:set_session(#session{sid = SID, usr = USR, us = US, priority = Priority, info = Info}). @@ -397,7 +404,7 @@ do_route(From, To, {broadcast, _} = Packet) -> get_user_resources(To#jid.user, To#jid.server)); _ -> {U, S, R} = jid:tolower(To), - Mod = get_sm_backend(), + Mod = get_sm_backend(S), case Mod:get_sessions(U, S, R) of [] -> ?DEBUG("packet dropped~n", []); @@ -498,7 +505,7 @@ do_route(From, To, #xmlel{} = Packet) -> _ -> ok end; _ -> - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), case Mod:get_sessions(LUser, LServer, LResource) of [] -> case Name of @@ -565,7 +572,7 @@ route_message(From, To, Packet, Type) -> lists:foreach(fun ({P, R}) when P == Priority; (P >= 0) and (Type == headline) -> LResource = jid:resourceprep(R), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), case Mod:get_sessions(LUser, LServer, LResource) of [] -> @@ -647,11 +654,11 @@ get_resource_sessions(User, Server, Resource) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), LResource = jid:resourceprep(Resource), - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), [S#session.sid || S <- Mod:get_sessions(LUser, LServer, LResource)]. check_max_sessions(LUser, LServer) -> - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), SIDs = [S#session.sid || S <- Mod:get_sessions(LUser, LServer)], MaxSessions = get_max_user_sessions(LUser, LServer), if length(SIDs) =< MaxSessions -> ok; @@ -703,17 +710,17 @@ process_iq(From, To, Packet) -> -spec force_update_presence({binary(), binary()}) -> any(). force_update_presence({LUser, LServer}) -> - Mod = get_sm_backend(), + Mod = get_sm_backend(LServer), Ss = Mod:get_sessions(LUser, LServer), lists:foreach(fun (#session{sid = {_, Pid}}) -> Pid ! {force_update_presence, LUser, LServer} end, Ss). --spec get_sm_backend() -> module(). +-spec get_sm_backend(binary()) -> module(). -get_sm_backend() -> - DBType = ejabberd_config:get_option(sm_db_type, +get_sm_backend(Host) -> + DBType = ejabberd_config:get_option({sm_db_type, Host}, fun(mnesia) -> mnesia; (internal) -> mnesia; (odbc) -> odbc; @@ -721,6 +728,19 @@ get_sm_backend() -> end, mnesia), list_to_atom("ejabberd_sm_" ++ atom_to_list(DBType)). +-spec get_sm_backends() -> [module()]. + +get_sm_backends() -> + lists:usort([get_sm_backend(Host) || Host <- ?MYHOSTS]). + +-spec get_vh_by_backend(module()) -> [binary()]. + +get_vh_by_backend(Mod) -> + lists:filter( + fun(Host) -> + get_sm_backend(Host) == Mod + end, ?MYHOSTS). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% ejabberd commands diff --git a/src/ejabberd_sm_odbc.erl b/src/ejabberd_sm_odbc.erl index debeafe9990..698763b5ea4 100644 --- a/src/ejabberd_sm_odbc.erl +++ b/src/ejabberd_sm_odbc.erl @@ -43,7 +43,7 @@ init() -> end; (_, Err) -> Err - end, ok, ?MYHOSTS). + end, ok, ejabberd_sm:get_vh_by_backend(?MODULE)). set_session(#session{sid = {Now, Pid}, usr = {U, LServer, R}, priority = Priority, info = Info}) -> @@ -90,7 +90,7 @@ get_sessions() -> lists:flatmap( fun(LServer) -> get_sessions(LServer) - end, ?MYHOSTS). + end, ejabberd_sm:get_vh_by_backend(?MODULE)). get_sessions(LServer) -> case ejabberd_odbc:sql_query( diff --git a/src/ejabberd_sm_redis.erl b/src/ejabberd_sm_redis.erl index 637e1364718..bf9e0eff544 100644 --- a/src/ejabberd_sm_redis.erl +++ b/src/ejabberd_sm_redis.erl @@ -107,7 +107,7 @@ get_sessions() -> lists:flatmap( fun(LServer) -> get_sessions(LServer) - end, ?MYHOSTS). + end, ejabberd_sm:get_vh_by_backend(?MODULE)). -spec get_sessions(binary()) -> [#session{}]. get_sessions(LServer) -> @@ -204,7 +204,7 @@ clean_table() -> ?ERROR_MSG("failed to clean redis table for " "server ~s: ~p", [LServer, Err]) end - end, ?MYHOSTS). + end, ejabberd_sm:get_vh_by_backend(?MODULE)). opt_type(redis_connect_timeout) -> fun (I) when is_integer(I), I > 0 -> I end; diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index c0d3aa8c17c..30eaa5edd3a 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -8,6 +8,7 @@ host_config: odbc_password: "@@pgsql_pass@@" odbc_database: "@@pgsql_db@@" auth_method: odbc + sm_db_type: odbc modules: mod_announce: db_type: odbc @@ -60,6 +61,7 @@ Welcome to this XMPP server." "sqlite.localhost": odbc_type: sqlite auth_method: odbc + sm_db_type: odbc modules: mod_announce: db_type: odbc @@ -118,6 +120,7 @@ Welcome to this XMPP server." odbc_password: "@@mysql_pass@@" odbc_database: "@@mysql_db@@" auth_method: odbc + sm_db_type: odbc modules: mod_announce: db_type: odbc From 8f9c18edf229c010229fa3cd65c7d77bb6bd566b Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 19 Feb 2016 17:06:41 +0300 Subject: [PATCH 588/695] Add Redis backend to the test suite --- .travis.yml | 1 + test/ejabberd_SUITE.erl | 9 ++++- test/ejabberd_SUITE_data/ejabberd.yml | 56 +++++++++++++++++++++++++++ test/suite.hrl | 1 + 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ba2fc3521be..15363180940 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ otp_release: services: - riak + - redis-server before_install: # diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 947bc4bd537..1b8d5f4775a 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -47,6 +47,9 @@ init_per_group(no_db, Config) -> init_per_group(mnesia, Config) -> mod_muc:shutdown_rooms(?MNESIA_VHOST), set_opt(server, ?MNESIA_VHOST, Config); +init_per_group(redis, Config) -> + mod_muc:shutdown_rooms(?REDIS_VHOST), + set_opt(server, ?REDIS_VHOST, Config); init_per_group(mysql, Config) -> case catch ejabberd_odbc:sql_query(?MYSQL_VHOST, [<<"select 1;">>]) of {selected, _, _} -> @@ -92,6 +95,8 @@ init_per_group(_GroupName, Config) -> end_per_group(mnesia, _Config) -> ok; +end_per_group(redis, _Config) -> + ok; end_per_group(mysql, _Config) -> ok; end_per_group(pgsql, _Config) -> @@ -227,7 +232,7 @@ db_tests(riak) -> {test_roster_remove, [parallel], [roster_remove_master, roster_remove_slave]}]; -db_tests(mnesia) -> +db_tests(DB) when DB == mnesia; DB == redis -> [{single_user, [sequence], [test_register, auth_plain, @@ -322,6 +327,7 @@ groups() -> {extauth, [sequence], extauth_tests()}, {no_db, [sequence], no_db_tests()}, {mnesia, [sequence], db_tests(mnesia)}, + {redis, [sequence], db_tests(redis)}, {mysql, [sequence], db_tests(mysql)}, {pgsql, [sequence], db_tests(pgsql)}, {sqlite, [sequence], db_tests(sqlite)}, @@ -331,6 +337,7 @@ all() -> [{group, ldap}, {group, no_db}, {group, mnesia}, + {group, redis}, {group, mysql}, {group, pgsql}, {group, sqlite}, diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 30eaa5edd3a..5507900b871 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -220,6 +220,61 @@ Welcome to this XMPP server." welcome_message: subject: "Welcome!" body: "Hi. +Welcome to this XMPP server." + mod_stats: [] + mod_time: [] + mod_version: [] + "redis.localhost": + auth_method: internal + sm_db_type: redis + modules: + mod_announce: + db_type: internal + access: local + mod_blocking: [] + mod_caps: + db_type: internal + mod_last: + db_type: internal + mod_muc: + db_type: internal + mod_offline: + db_type: internal + mod_privacy: + db_type: internal + mod_private: + db_type: internal + mod_pubsub: + access_createnode: pubsub_createnode + ignore_pep_from_offline: true + last_item_cache: false + plugins: + - "flat" + - "hometree" + - "pep" + mod_roster: + versioning: true + store_current_id: true + db_type: internal + mod_mam: + db_type: internal + mod_vcard: + db_type: internal + mod_vcard_xupdate: + db_type: internal + mod_carboncopy: [] + mod_client_state: + drop_chat_states: true + queue_presence: true + mod_adhoc: [] + mod_configure: [] + mod_disco: [] + mod_ping: [] + mod_proxy65: [] + mod_register: + welcome_message: + subject: "Welcome!" + body: "Hi. Welcome to this XMPP server." mod_stats: [] mod_time: [] @@ -295,6 +350,7 @@ Welcome to this XMPP server." hosts: - "localhost" - "mnesia.localhost" + - "redis.localhost" - "mysql.localhost" - "pgsql.localhost" - "extauth.localhost" diff --git a/test/suite.hrl b/test/suite.hrl index 5638fdb75d6..fb6b4f3acd7 100644 --- a/test/suite.hrl +++ b/test/suite.hrl @@ -74,6 +74,7 @@ -define(COMMON_VHOST, <<"localhost">>). -define(MNESIA_VHOST, <<"mnesia.localhost">>). +-define(REDIS_VHOST, <<"redis.localhost">>). -define(MYSQL_VHOST, <<"mysql.localhost">>). -define(PGSQL_VHOST, <<"pgsql.localhost">>). -define(SQLITE_VHOST, <<"sqlite.localhost">>). From 5b4aefbacd260d86e8e78a7d6680106383869783 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 19 Feb 2016 18:53:28 +0100 Subject: [PATCH 589/695] Accept stream compression request after SASL This is an updated version of the patch submitted to EJAB-1382 by Alexey (thanks!). --- src/ejabberd_c2s.erl | 99 +++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index b9f9d815d31..469350ba58f 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -469,6 +469,22 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> false -> [] end, + SockMod = + (StateData#state.sockmod):get_sockmod( + StateData#state.socket), + Zlib = StateData#state.zlib, + CompressFeature = + case Zlib andalso + ((SockMod == gen_tcp) orelse (SockMod == fast_tls)) of + true -> + [#xmlel{name = <<"compression">>, + attrs = [{<<"xmlns">>, ?NS_FEATURE_COMPRESS}], + children = [#xmlel{name = <<"method">>, + attrs = [], + children = [{xmlcdata, <<"zlib">>}]}]}]; + _ -> + [] + end, StreamFeatures1 = [#xmlel{name = <<"bind">>, attrs = [{<<"xmlns">>, ?NS_BIND}], children = []}, @@ -479,6 +495,7 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) -> ++ RosterVersioningFeature ++ StreamManagementFeature ++ + CompressFeature ++ ejabberd_hooks:run_fold(c2s_post_auth_features, Server, [], [Server]), StreamFeatures = ejabberd_hooks:run_fold(c2s_stream_features, @@ -815,38 +832,7 @@ wait_for_feature_request({xmlstreamelement, El}, {?NS_COMPRESS, <<"compress">>} when Zlib == true, (SockMod == gen_tcp) or (SockMod == fast_tls) -> - case fxml:get_subtag(El, <<"method">>) of - false -> - send_element(StateData, - #xmlel{name = <<"failure">>, - attrs = [{<<"xmlns">>, ?NS_COMPRESS}], - children = - [#xmlel{name = <<"setup-failed">>, - attrs = [], children = []}]}), - fsm_next_state(wait_for_feature_request, StateData); - Method -> - case fxml:get_tag_cdata(Method) of - <<"zlib">> -> - Socket = StateData#state.socket, - BCompressed = fxml:element_to_binary(#xmlel{name = <<"compressed">>, - attrs = [{<<"xmlns">>, ?NS_COMPRESS}]}), - ZlibSocket = (StateData#state.sockmod):compress(Socket, - BCompressed), - fsm_next_state(wait_for_stream, - StateData#state{socket = ZlibSocket, - streamid = new_id()}); - _ -> - send_element(StateData, - #xmlel{name = <<"failure">>, - attrs = [{<<"xmlns">>, ?NS_COMPRESS}], - children = - [#xmlel{name = - <<"unsupported-method">>, - attrs = [], - children = []}]}), - fsm_next_state(wait_for_feature_request, StateData) - end - end; + process_compression_request(El, wait_for_feature_request, StateData); _ -> if TLSRequired and not TLSEnabled -> Lang = StateData#state.lang, @@ -1089,7 +1075,19 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> end end end; - _ -> fsm_next_state(wait_for_bind, StateData) + _ -> + #xmlel{name = Name, attrs = Attrs, children = _Els} = El, + Zlib = StateData#state.zlib, + SockMod = + (StateData#state.sockmod):get_sockmod(StateData#state.socket), + case {fxml:get_attr_s(<<"xmlns">>, Attrs), Name} of + {?NS_COMPRESS, <<"compress">>} + when Zlib == true, + (SockMod == gen_tcp) or (SockMod == fast_tls) -> + process_compression_request(El, wait_for_bind, StateData); + _ -> + fsm_next_state(wait_for_bind, StateData) + end end; wait_for_bind(timeout, StateData) -> {stop, normal, StateData}; @@ -2510,6 +2508,41 @@ bounce_messages() -> after 0 -> ok end. +process_compression_request(El, StateName, StateData) -> + case fxml:get_subtag(El, <<"method">>) of + false -> + send_element(StateData, + #xmlel{name = <<"failure">>, + attrs = [{<<"xmlns">>, ?NS_COMPRESS}], + children = + [#xmlel{name = <<"setup-failed">>, + attrs = [], children = []}]}), + fsm_next_state(StateName, StateData); + Method -> + case fxml:get_tag_cdata(Method) of + <<"zlib">> -> + Socket = StateData#state.socket, + BCompressed = fxml:element_to_binary( + #xmlel{name = <<"compressed">>, + attrs = [{<<"xmlns">>, + ?NS_COMPRESS}]}), + ZlibSocket = (StateData#state.sockmod):compress( + Socket, BCompressed), + fsm_next_state(wait_for_stream, + StateData#state{socket = ZlibSocket, + streamid = new_id()}); + _ -> + send_element(StateData, + #xmlel{name = <<"failure">>, + attrs = [{<<"xmlns">>, ?NS_COMPRESS}], + children = + [#xmlel{name = <<"unsupported-method">>, + attrs = [], + children = []}]}), + fsm_next_state(StateName, StateData) + end + end. + %%%---------------------------------------------------------------------- %%% XEP-0191 %%%---------------------------------------------------------------------- From b971449f1267a3844bd3fe8aa6c4d22fbbaed0c0 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 20 Feb 2016 18:21:38 +0100 Subject: [PATCH 590/695] mod_http_upload: Expand 'docroot' before using it Expand the @HOME@ keyword within the 'docroot' value before setting the permissions of the document root directory. --- src/mod_http_upload.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 5d21b497089..24cf8aaf13b 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -273,6 +273,7 @@ init({ServerHost, Opts}) -> Thumbnail = gen_mod:get_opt(thumbnail, Opts, fun(B) when is_boolean(B) -> B end, true), + DocRoot1 = expand_home(str:strip(DocRoot, right, $/)), case ServiceURL of undefined -> ok; @@ -289,7 +290,7 @@ init({ServerHost, Opts}) -> undefined -> ok; Mode -> - file:change_mode(DocRoot, Mode) + file:change_mode(DocRoot1, Mode) end, case Thumbnail of true -> @@ -309,7 +310,7 @@ init({ServerHost, Opts}) -> secret_length = SecretLength, jid_in_url = JIDinURL, file_mode = FileMode, dir_mode = DirMode, thumbnail = Thumbnail, - docroot = expand_home(str:strip(DocRoot, right, $/)), + docroot = DocRoot1, put_url = expand_host(str:strip(PutURL, right, $/), ServerHost), get_url = expand_host(str:strip(GetURL, right, $/), ServerHost), service_url = ServiceURL}}. From 44f581c3b58b2b977480fdcee69236dd66df6f44 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Sat, 20 Feb 2016 20:13:30 +0100 Subject: [PATCH 591/695] mod_http_upload: Also expand @HOST@ in 'docroot' In some environments, it might be desirable to use separate document roots for each virtual host. --- src/mod_http_upload.erl | 23 +++++++++++++---------- src/mod_http_upload_quota.erl | 3 ++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 24cf8aaf13b..d360ac195c0 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -86,7 +86,8 @@ %% Utility functions. -export([get_proc_name/2, - expand_home/1]). + expand_home/1, + expand_host/2]). -include("ejabberd.hrl"). -include("ejabberd_http.hrl"). @@ -274,6 +275,7 @@ init({ServerHost, Opts}) -> fun(B) when is_boolean(B) -> B end, true), DocRoot1 = expand_home(str:strip(DocRoot, right, $/)), + DocRoot2 = expand_host(DocRoot1, ServerHost), case ServiceURL of undefined -> ok; @@ -290,7 +292,7 @@ init({ServerHost, Opts}) -> undefined -> ok; Mode -> - file:change_mode(DocRoot1, Mode) + file:change_mode(DocRoot2, Mode) end, case Thumbnail of true -> @@ -310,7 +312,7 @@ init({ServerHost, Opts}) -> secret_length = SecretLength, jid_in_url = JIDinURL, file_mode = FileMode, dir_mode = DirMode, thumbnail = Thumbnail, - docroot = DocRoot1, + docroot = DocRoot2, put_url = expand_host(str:strip(PutURL, right, $/), ServerHost), get_url = expand_host(str:strip(GetURL, right, $/), ServerHost), service_url = ServiceURL}}. @@ -510,6 +512,12 @@ expand_home(Subject) -> Parts = binary:split(Subject, <<"@HOME@">>, [global]), str:join(Parts, list_to_binary(Home)). +-spec expand_host(binary(), binary()) -> binary(). + +expand_host(Subject, Host) -> + Parts = binary:split(Subject, <<"@HOST@">>, [global]), + str:join(Parts, Host). + %%-------------------------------------------------------------------- %% Internal functions. %%-------------------------------------------------------------------- @@ -738,12 +746,6 @@ map_int_to_char(N) when N =< 9 -> N + 48; % Digit. map_int_to_char(N) when N =< 35 -> N + 55; % Upper-case character. map_int_to_char(N) when N =< 61 -> N + 61. % Lower-case character. --spec expand_host(binary(), binary()) -> binary(). - -expand_host(Subject, Host) -> - Parts = binary:split(Subject, <<"@HOST@">>, [global]), - str:join(Parts, Host). - -spec yield_content_type(binary()) -> binary(). yield_content_type(<<"">>) -> ?DEFAULT_CONTENT_TYPE; @@ -975,8 +977,9 @@ remove_user(User, Server) -> (node) -> node end, sha1), + DocRoot1 = expand_host(expand_home(DocRoot), ServerHost), UserStr = make_user_string(jid:make(User, Server, <<"">>), JIDinURL), - UserDir = str:join([expand_home(DocRoot), UserStr], <<$/>>), + UserDir = str:join([DocRoot1, UserStr], <<$/>>), case del_tree(UserDir) of ok -> ?INFO_MSG("Removed HTTP upload directory of ~s@~s", [User, Server]); diff --git a/src/mod_http_upload_quota.erl b/src/mod_http_upload_quota.erl index db0b4aa4caf..a5ae0c3cc01 100644 --- a/src/mod_http_upload_quota.erl +++ b/src/mod_http_upload_quota.erl @@ -132,6 +132,7 @@ init({ServerHost, Opts}) -> fun iolist_to_binary/1, <<"@HOME@/upload">>), DocRoot2 = mod_http_upload:expand_home(str:strip(DocRoot1, right, $/)), + DocRoot3 = mod_http_upload:expand_host(DocRoot2, ServerHost), Timers = if MaxDays == infinity -> []; true -> {ok, T1} = timer:send_after(?INITIAL_TIMEOUT, sweep), @@ -144,7 +145,7 @@ init({ServerHost, Opts}) -> access_soft_quota = AccessSoftQuota, access_hard_quota = AccessHardQuota, max_days = MaxDays, - docroot = DocRoot2, + docroot = DocRoot3, timers = Timers}}. -spec handle_call(_, {pid(), _}, state()) -> {noreply, state()}. From 576c10ee3ad2188ec188e6ca6962423381eb39c4 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Tue, 23 Feb 2016 14:14:24 +0100 Subject: [PATCH 592/695] Make caps warning less confusing (#955) --- src/node_pep.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_pep.erl b/src/node_pep.erl index 726146b90ae..da03253962f 100644 --- a/src/node_pep.erl +++ b/src/node_pep.erl @@ -257,7 +257,7 @@ complain_if_modcaps_disabled(ServerHost) -> false -> ?WARNING_MSG("The PEP plugin is enabled in mod_pubsub " "of host ~p. This plugin requires mod_caps " - "to be enabled, but it isn't.", + "but it does not seems enabled, please check config.", [ServerHost]); true -> ok end. From 2c856c71f65d60ad23e5c13319c83f98a4986b8f Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 24 Feb 2016 12:34:53 +0100 Subject: [PATCH 593/695] Update translated files, as there wee many improvements --- priv/msgs/cs.msg | 30 ++++++++++ priv/msgs/de.msg | 16 ++++- priv/msgs/he.msg | 1 + priv/msgs/ja.msg | 28 ++++++--- priv/msgs/pl.msg | 12 ++++ priv/msgs/pt-br.msg | 20 +++++-- priv/msgs/uk.msg | 48 ++++++++++++++- priv/msgs/wa.msg | 128 ++++++++++++++++++++++++++++++++++++++++ priv/msgs/zh.msg | 140 +++++++++++++++++++++++++++----------------- 9 files changed, 351 insertions(+), 72 deletions(-) diff --git a/priv/msgs/cs.msg b/priv/msgs/cs.msg index a370d02a695..f0c749887ed 100644 --- a/priv/msgs/cs.msg +++ b/priv/msgs/cs.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Přijmout"}. {"Access Configuration","Konfigurace přístupů"}. {"Access Control List Configuration","Konfigurace seznamu přístupových práv (ACL)"}. {"Access control lists","Seznamy přístupových práv (ACL)"}. @@ -31,6 +32,7 @@ {"April",". dubna"}. {"August",". srpna"}. {"Backup Management","Správa zálohování"}. +{"Backup of ~p","Záloha ~p"}. {"Backup to File at ","Záloha do souboru na "}. {"Backup","Zálohovat"}. {"Bad format","Nesprávný formát"}. @@ -59,6 +61,7 @@ {"Country","Země"}. {"CPU Time:","Čas procesoru"}. {"Database","Databáze"}. +{"Database Tables at ~p","Databázové tabulky na ~p"}. {"Database Tables Configuration at ","Konfigurace databázových tabulek "}. {"December",". prosince"}. {"Default users as participants","Uživatelé jsou implicitně členy"}. @@ -78,13 +81,16 @@ {"Either approve or decline the voice request.","Povolit nebo odmítnout voice žádost."}. {"ejabberd IRC module","ejabberd IRC modul"}. {"ejabberd MUC module","ejabberd MUC modul"}. +{"ejabberd Multicast service","Služba ejabberd Multicast"}. {"ejabberd Publish-Subscribe module","ejabberd Publish-Subscribe modul"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams modul"}. {"ejabberd vCard module","ejabberd vCard modul"}. {"ejabberd Web Admin","Webová administrace ejabberd"}. {"Elements","Položek"}. {"Email","E-mail"}. +{"Empty Rooms","Prázdné konference"}. {"Enable logging","Zaznamenávat konverzace"}. +{"Enable message archiving","Povolit ukládání historie zpráv"}. {"Encoding for server ~b","Kódování pro server ~b"}. {"End User Session","Ukončit sezení uživatele"}. {"Enter list of {Module, [Options]}","Vložte seznam modulů {Modul, [Parametry]}"}. @@ -100,6 +106,7 @@ {"Error","Chyba"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Příklad: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].2\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Vyloučit Jabber ID z procesu CAPTCHA ověřování"}. +{"Export all tables as SQL queries to a file:","Zálohovat všechny tabulky jako SQL dotazy do souboru:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Exportovat všechny uživatele do souboru ve formátu PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Exportovat uživatele na hostiteli do souboru ve formátu PIEFXIS (XEP-0227):"}. {"Failed to extract JID from your voice request approval","Došlo k chybě při získávání Jabber ID z vaší žádosti o voice práva"}. @@ -137,6 +144,7 @@ {"Import Users from Dir at ","Importovat uživatele z adresáře na "}. {"Import Users From jabberd14 Spool Files","Importovat uživatele z jabberd14 spool souborů"}. {"Improper message type","Nesprávný typ zprávy"}. +{"Incoming s2s Connections:",""}. {"Incorrect password","Nesprávné heslo"}. {"Invalid affiliation: ~s","Neplatné přiřazení: ~s"}. {"Invalid role: ~s","Neplatná role: ~s"}. @@ -149,6 +157,7 @@ {"IRC username","IRC přezdívka"}. {"IRC Username","IRC přezdívka"}. {"is now known as","se přejmenoval(a) na"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","Není povoleno posílat chybové zprávy do konference. Účastník (~s) odeslal chybovou zprávu (~s) a byl vyhozen z konference."}. {"It is not allowed to send private messages","Je zakázáno posílat soukromé zprávy"}. {"It is not allowed to send private messages of type \"groupchat\"","Není dovoleno odeslání soukromé zprávy typu \"skupinová zpráva\" "}. {"It is not allowed to send private messages to the conference","Není povoleno odesílat soukromé zprávy do konference"}. @@ -170,6 +179,7 @@ {"Listened Ports at ","Otevřené porty na "}. {"Listened Ports","Otevřené porty"}. {"List of modules to start","Seznam modulů, které mají být spuštěné"}. +{"List of rooms","Seznam konferencí"}. {"Low level update script","Nízkoúrovňový aktualizační skript"}. {"Make participants list public","Nastavit seznam účastníků jako veřejný"}. {"Make room CAPTCHA protected","Chránit místnost pomocí CAPTCHA"}. @@ -190,12 +200,16 @@ {"Message body","Tělo zprávy"}. {"Middle Name","Druhé jméno"}. {"Minimum interval between voice requests (in seconds)","Minimální interval mezi žádostmi o voice práva (v sekundách)"}. +{"Moderator","Moderátor"}. {"Moderator privileges required","Potřebujete práva moderátora"}. {"moderators only","moderátorům"}. {"Modified modules","Aktualizované moduly"}. {"Module","Modul"}. +{"Modules at ~p","Moduly v ~p"}. {"Modules","Moduly"}. {"Monday","Pondělí"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Víceuživatelský chat"}. {"Name:","Jméno:"}. {"Name","Jméno"}. {"Never","Nikdy"}. @@ -208,6 +222,7 @@ {"No Data","Žádná data"}. {"Node ID","ID uzlu"}. {"Node not found","Uzel nenalezen"}. +{"Node ~p","Uzel ~p"}. {"Nodes","Uzly"}. {"No limit","Bez limitu"}. {"None","Nic"}. @@ -229,6 +244,7 @@ {"Online Users:","Online uživatelé:"}. {"Online Users","Online uživatelé"}. {"Only deliver notifications to available users","Doručovat upozornění jen právě přihlášeným uživatelům"}. +{"Only members may query archives of this room","Pouze moderátoři mají povoleno měnit téma místnosti"}. {"Only moderators and participants are allowed to change the subject in this room","Jen moderátoři a účastníci mají povoleno měnit téma této místnosti"}. {"Only moderators are allowed to change the subject in this room","Jen moderátoři mají povoleno měnit téma místnosti"}. {"Only moderators can approve voice requests","Pouze moderátoři mohou schválit žádosti o voice práva"}. @@ -242,6 +258,7 @@ {"Outgoing s2s Connections","Odchozí s2s spojení"}. {"Owner privileges required","Jsou vyžadována práva vlastníka"}. {"Packet","Paket"}. +{"Participant","Účastník"}. {"Password ~b","Heslo ~b"}. {"Password:","Heslo:"}. {"Password","Heslo"}. @@ -251,9 +268,12 @@ {"Path to File","Cesta k souboru"}. {"Pending","Čekající"}. {"Period: ","Čas: "}. +{"Permanent rooms","Stálých konferencí"}. {"Persist items to storage","Uložit položky natrvalo do úložiště"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Podotýkáme, že tato nastavení budou zálohována do zabudované databáze Mnesia. Pokud používáte ODBC modul, musíte zálohovat svoji SQL databázi samostatně."}. +{"Please specify file name.","Zvolit jméno souboru."}. +{"Please specify file size.","Zvolit velikost souboru."}. {"Please, wait for a while before sending new voice request","Prosím, počkejte chvíli před posláním nové žádosti o voice práva"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. @@ -271,6 +291,7 @@ {"Really delete message of the day?","Skutečně smazat zprávu dne?"}. {"Recipient is not in the conference room","Příjemce se nenachází v konferenční místnosti"}. {"Register a Jabber account","Zaregistrujte si účet Jabberu"}. +{"Registered nicknames","Registrované přezdívky"}. {"Registered Users","Registrovaní uživatelé"}. {"Registered Users:","Registrovaní živatelé:"}. {"Register","Zaregistrovat se"}. @@ -288,6 +309,7 @@ {"Restore binary backup immediately:","Okamžitě obnovit binární zálohu:"}. {"Restore","Obnovit"}. {"Restore plain text backup immediately:","Okamžitě obnovit zálohu z textového souboru:"}. +{"Roles for which Presence is Broadcasted","Role, pro které je zpráva o stavu šířena"}. {"Room Configuration","Nastavení místnosti"}. {"Room creation is denied by service policy","Pravidla služby nepovolují vytvořit místnost"}. {"Room description","Popis místnosti"}. @@ -311,6 +333,7 @@ {"September",". září"}. {"Server ~b","Server ~b"}. {"Server:","Server:"}. +{"Server","Server"}. {"Set message of the day and send to online users","Nastavit zprávu dne a odeslat ji online uživatelům"}. {"Set message of the day on all hosts and send to online users","Nastavit zprávu dne a odeslat ji online uživatelům"}. {"Shared Roster Groups","Skupiny pro sdílený seznam kontaktů"}. @@ -352,6 +375,7 @@ {"There was an error changing the password: ","Při změně hesla došlo k chybě: "}. {"There was an error creating the account: ","Při vytváření účtu došlo k chybě."}. {"There was an error deleting the account: ","Při mazání účtu došlo k chybě: "}. +{"This IP address is blacklisted in ~s","IP adresa je blokována na ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Zde nezáleží na velikosti písmen: macbeth je stejný jako MacBeth a Macbeth."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Na této stránce si můžete vytvořit účet na tomto serveru Jabberu. Vaše JID (Jabber IDentifikátor) bude mít tvar: uživatelskéjméno@server. Přečtěte si prosím pozorně instrukce pro vyplnění údajů."}. {"This page allows to unregister a Jabber account in this Jabber server.","Zde můžete zrušit registraci účtu na tomto serveru Jabberu."}. @@ -359,8 +383,11 @@ {"Time","Čas"}. {"Time delay","Časový posun"}. {"Too many CAPTCHA requests","Přiliš mnoho CAPTCHA žádostí"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Příliš mnoho (~p) chybných pokusů o přihlášení z této IP adresy (~s). Adresa bude zablokována do ~s UTC"}. +{"Too many unacked stanzas","Příliš mnoho nepotvrzených stanz"}. {"To","Pro"}. {"To ~s","Pro ~s"}. +{"Total rooms","Celkem konferencí"}. {"Traffic rate limit is exceeded","Byl překročen limit"}. {"Transactions Aborted:","Transakce zrušena"}. {"Transactions Committed:","Transakce potvrzena"}. @@ -374,6 +401,7 @@ {"Update","Aktualizovat"}. {"Update message of the day (don't send)","Aktualizovat zprávu dne (neodesílat)"}. {"Update message of the day on all hosts (don't send)","Aktualizovat zprávu dne pro všechny hostitele (neodesílat)"}. +{"Update ~p","Aktualizovat ~p"}. {"Update plan","Aktualizovat plán"}. {"Update script","Aktualizované skripty"}. {"Uptime:","Čas běhu:"}. @@ -381,6 +409,7 @@ {"User JID","Jabber ID uživatele"}. {"User Management","Správa uživatelů"}. {"Username:","Uživatelské jméno:"}. +{"User ~s",""}. {"Users are not allowed to register accounts so quickly","Je zakázáno registrovat účty v tak rychlém sledu"}. {"Users Last Activity","Poslední aktivita uživatele"}. {"Users","Uživatelé"}. @@ -388,6 +417,7 @@ {"Validate","Ověřit"}. {"vCard User Search","Hledání uživatelů podle vizitek"}. {"Virtual Hosts","Virtuální hostitelé"}. +{"Visitor","Návštěvník"}. {"Visitors are not allowed to change their nicknames in this room","Návštěvníkům této místnosti je zakázáno měnit přezdívku"}. {"Visitors are not allowed to send messages to all occupants","Návštevníci nemají povoleno zasílat zprávy všem účastníkům konference"}. {"Voice requests are disabled in this conference","Voice žádosti jsou v této konferenci zakázány"}. diff --git a/priv/msgs/de.msg b/priv/msgs/de.msg index 1d313b2a842..dd22e684e73 100644 --- a/priv/msgs/de.msg +++ b/priv/msgs/de.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Akzeptieren"}. {"Access Configuration","Zugangskonfiguration"}. {"Access Control List Configuration","Konfiguration der Zugangskontrolllisten"}. {"Access control lists","Zugangskontroll-Listen (ACL)"}. @@ -87,6 +88,7 @@ {"ejabberd Web Admin","ejabberd Web-Admin"}. {"Elements","Elemente"}. {"Email","E-Mail"}. +{"Empty Rooms","Leere Räume"}. {"Enable logging","Protokollierung aktivieren"}. {"Enable message archiving","Nachrichtenarchivierung aktivieren"}. {"Encoding for server ~b","Kodierung für Server ~b"}. @@ -142,6 +144,7 @@ {"Import Users from Dir at ","Benutzer importieren aus dem Verzeichnis "}. {"Import Users From jabberd14 Spool Files","Importiere Benutzer aus jabberd14-Spool-Dateien"}. {"Improper message type","Unzulässiger Nachrichtentyp"}. +{"Incoming s2s Connections:","Eingehende s2s-Verbindungen:"}. {"Incorrect password","Falsches Passwort"}. {"Invalid affiliation: ~s","Ungültige Mitgliedschaft: ~s"}. {"Invalid role: ~s","Ungültige Rolle: ~s"}. @@ -154,6 +157,7 @@ {"IRC username","IRC Benutzername"}. {"IRC Username","IRC-Benutzername"}. {"is now known as","ist nun bekannt als"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","Es ist nicht erlaubt Fehlermeldungen an den Raum zu senden. Der Teilnehmer (~s) hat eine Fehlermeldung (~s) gesendet und wurde aus dem Raum entfernt"}. {"It is not allowed to send private messages","Es ist nicht erlaubt private Nachrichten zu senden"}. {"It is not allowed to send private messages of type \"groupchat\"","Es ist nicht erlaubt private Nachrichten des Typs \"Gruppenchat\" zu senden"}. {"It is not allowed to send private messages to the conference","Es ist nicht erlaubt private Nachrichten an den Raum zu schicken"}. @@ -196,6 +200,7 @@ {"Message body","Nachrichtentext"}. {"Middle Name","Zweiter Vorname"}. {"Minimum interval between voice requests (in seconds)","Mindestdauer zwischen Anfragen für Sprachrechte (in Sekunden)"}. +{"Moderator","Moderator"}. {"Moderator privileges required","Moderatorrechte benötigt"}. {"moderators only","ausschliesslich Moderatoren"}. {"Modified modules","Geänderte Module"}. @@ -210,7 +215,7 @@ {"Never","Nie"}. {"New Password:","Neues Passwort:"}. {"Nickname","Benutzername"}. -{"Nickname Registration at ","Registrieren des Benutzernames auf"}. +{"Nickname Registration at ","Registrieren des Benutzernames auf "}. {"Nickname ~s does not exist in the room","Der Benutzername ~s existiert im Raum nicht"}. {"nobody","niemanden"}. {"No body provided for announce message","Kein Text für die Ankündigungsnachricht angegeben"}. @@ -239,6 +244,7 @@ {"Online Users:","Angemeldete Benutzer:"}. {"Online Users","Angemeldete Benutzer"}. {"Only deliver notifications to available users","Benachrichtigungen nur an verfügbare Benutzer schicken"}. +{"Only members may query archives of this room","Nur Mitglieder dürfen den Verlauf dieses Raumes abrufen"}. {"Only moderators and participants are allowed to change the subject in this room","Nur Moderatoren und Mitglieder dürfen das Thema in diesem Raum ändern"}. {"Only moderators are allowed to change the subject in this room","Nur Moderatoren dürfen das Thema in diesem Raum ändern"}. {"Only moderators can approve voice requests","Nur Moderatoren können Anfragen für Sprachrechte bestätigen"}. @@ -252,6 +258,7 @@ {"Outgoing s2s Connections","Ausgehende s2s-Verbindungen"}. {"Owner privileges required","Besitzerrechte benötigt"}. {"Packet","Paket"}. +{"Participant","Teilnehmer"}. {"Password ~b","Passwort ~b"}. {"Password:","Passwort:"}. {"Password","Passwort"}. @@ -261,10 +268,12 @@ {"Path to File","Pfad zur Datei"}. {"Pending","Schwebend"}. {"Period: ","Zeitraum: "}. -{"Permanent rooms","permanente Chaträume"}. +{"Permanent rooms","Permanente Chaträume"}. {"Persist items to storage","Einträge dauerhaft speichern"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Beachten sie, das diese Optionen nur die eingebaute Mnesia-Datenbank sichern. Wenn sie das ODBC-Modul verwenden, müssen sie die SQL-Datenbank manuell sichern."}. +{"Please specify file name.","Bitte geben Sie den Dateinamen an."}. +{"Please specify file size.","Bitte geben Sie die Dateigröße an."}. {"Please, wait for a while before sending new voice request","Bitte warten sie ein wenig, bevor sie eine weitere Anfrage für Sprachrechte senden"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. @@ -300,6 +309,7 @@ {"Restore binary backup immediately:","Stelle binäre Sicherung sofort wieder her:"}. {"Restore plain text backup immediately:","Stelle Klartext-Sicherung sofort wieder her:"}. {"Restore","Wiederherstellung"}. +{"Roles for which Presence is Broadcasted","Rollen, für die der Status übertragen wird"}. {"Room Configuration","Raum-Konfiguration"}. {"Room creation is denied by service policy","Anlegen des Raumes aufgrund der Dienstrichtlinien verweigert"}. {"Room description","Raum Beschreibung"}. @@ -323,6 +333,7 @@ {"September","September"}. {"Server ~b","Server ~b"}. {"Server:","Server:"}. +{"Server","Server"}. {"Set message of the day and send to online users","Setze Nachricht des Tages und sende sie an alle angemeldeten Benutzer"}. {"Set message of the day on all hosts and send to online users","Setze Nachricht des Tages auf allen Hosts und sende sie an alle angemeldeten Benutzer"}. {"Shared Roster Groups","Gruppen der gemeinsamen Kontaktliste"}. @@ -406,6 +417,7 @@ {"Validate","Validieren"}. {"vCard User Search","vCard-Benutzer-Suche"}. {"Virtual Hosts","Virtuelle Hosts"}. +{"Visitor","Besucher"}. {"Visitors are not allowed to change their nicknames in this room","Besucher dürfen in diesem Raum ihren Benutzernamen nicht ändern"}. {"Visitors are not allowed to send messages to all occupants","Besucher dürfen nicht an alle Teilnehmer Nachrichten verschicken"}. {"Voice request","Anfrage für Sprachrechte"}. diff --git a/priv/msgs/he.msg b/priv/msgs/he.msg index 2fa51b74b6f..65092de436c 100644 --- a/priv/msgs/he.msg +++ b/priv/msgs/he.msg @@ -244,6 +244,7 @@ {"Online Users","משתמשים מקוונים"}. {"Online","מקוון"}. {"Only deliver notifications to available users","מסור התראות למשתמשים זמינים בלבד"}. +{"Only members may query archives of this room","רק חברים רשאים לתשאל ארכיונים של חדר זה"}. {"Only moderators and participants are allowed to change the subject in this room","רק אחראים ומשתתפים רשאים לשנות את הנושא בחדר זה"}. {"Only moderators are allowed to change the subject in this room","רק אחראים רשאים לשנות את הנושא בחדר זה"}. {"Only moderators can approve voice requests","רק אחראים יכולים לאשר בקשות ביטוי"}. diff --git a/priv/msgs/ja.msg b/priv/msgs/ja.msg index d6a9a0a4bfa..404a1620da3 100644 --- a/priv/msgs/ja.msg +++ b/priv/msgs/ja.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","許可"}. {"Access Configuration","アクセス設定"}. {"Access Control List Configuration","アクセスコントロールリスト設定"}. {"Access control lists","アクセスコントロールリスト"}. @@ -72,7 +73,7 @@ {"Deliver payloads with event notifications","イベント通知と同時にペイロードを配送する"}. {"Description:","説明:"}. {"Disc only copy","ディスクだけのコピー"}. -{"Displayed Groups:","表示グループ"}. +{"Displayed Groups:","表示グループ:"}. {"Don't tell your password to anybody, not even the administrators of the Jabber server.","パスワードは誰にも教えないようにしてください。Jabber サーバーの管理者があなたにパスワードを尋ねることはありません。"}. {"Dump Backup to Text File at ","テキストファイルにバックアップ: "}. {"Dump to Text File","テキストファイルに出力"}. @@ -87,6 +88,7 @@ {"ejabberd Web Admin","ejabberd ウェブ管理"}. {"Elements","要素"}. {"Email","メールアドレス"}. +{"Empty Rooms","空のルーム"}. {"Enable logging","ロギングを有効"}. {"Enable message archiving","メッセージアーカイブを有効化"}. {"Encoding for server ~b","サーバーのエンコーディング ~b"}. @@ -103,7 +105,7 @@ {"Erlang Jabber Server","Erlang Jabber Server"}. {"Error","エラー"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","例: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. -{"Exclude Jabber IDs from CAPTCHA challenge","CAPTCHA 試験を免除する Jabber ID"}. +{"Exclude Jabber IDs from CAPTCHA challenge","CAPTCHA 入力を免除する Jabber ID"}. {"Export all tables as SQL queries to a file:","すべてのテーブルをSQL形式でファイルにエクスポート: "}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","サーバーにあるすべてのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","ホストのユーザーデータを PIEFXIS ファイルにエクスポート (XEP-0227):"}. @@ -113,7 +115,7 @@ {"Fill in fields to search for any matching Jabber User","項目を入力してユーザーを検索してください"}. {"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","項目を入力してユーザーを検索を行えます (* を使用すると部分文字列にマッチします)"}. {"Friday","金曜日"}. -{"From ~s","差出人 ~s"}. +{"From ~s","From ~s"}. {"From","差出人"}. {"Full Name","氏名"}. {"Get Number of Online Users","オンラインユーザー数を取得"}. @@ -142,6 +144,7 @@ {"Import Users from Dir at ","ディレクトリからユーザーをインポート: "}. {"Import Users From jabberd14 Spool Files","jabberd14 Spool ファイルからユーザーをインポート"}. {"Improper message type","誤ったメッセージタイプです"}. +{"Incoming s2s Connections:","内向き s2s コネクション:"}. {"Incorrect password","パスワードが違います"}. {"Invalid affiliation: ~s","無効な分掌です: ~s"}. {"Invalid role: ~s","無効な役です: ~s"}. @@ -154,6 +157,7 @@ {"IRC username","IRC ユーザー名"}. {"IRC Username","IRC ユーザー名"}. {"is now known as","は名前を変更しました: "}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","このルームにエラーメッセージを送ることは許可されていません。参加者(~s)はエラーメッセージを(~s)を送信してルームからキックされました。"}. {"It is not allowed to send private messages of type \"groupchat\"","種別が\"groupchat\" であるプライベートメッセージを送信することはできません"}. {"It is not allowed to send private messages to the conference","この会議にプライベートメッセージを送信することはできません"}. {"It is not allowed to send private messages","プライベートメッセージを送信することはできません"}. @@ -196,6 +200,7 @@ {"Message body","本文"}. {"Middle Name","ミドルネーム"}. {"Minimum interval between voice requests (in seconds)","発言権の要求の最小時間間隔 (秒)"}. +{"Moderator","モデレーター"}. {"Moderator privileges required","モデレーター権限が必要です"}. {"moderators only","モデレーターにのみ"}. {"Modified modules","更新されたモジュール"}. @@ -221,7 +226,7 @@ {"Nodes","ノード"}. {"No limit","制限なし"}. {"None","なし"}. -{"No resource provided","リソースが提供されませんでした"}. +{"No resource provided","リソースが指定されていません"}. {"Not Found","見つかりません"}. {"Notify subscribers when items are removed from the node","アイテムがノードから消された時に購読者へ通知する"}. {"Notify subscribers when the node configuration changes","ノード設定に変更があった時に購読者へ通知する"}. @@ -239,6 +244,7 @@ {"Online Users:","オンラインユーザー:"}. {"Online Users","オンラインユーザー"}. {"Only deliver notifications to available users","有効なユーザーにのみ告知を送信する"}. +{"Only members may query archives of this room","メンバーのみがこのルームのアーカイブを取得できます"}. {"Only moderators and participants are allowed to change the subject in this room","モデレーターと参加者のみがチャットルームの件名を変更できます"}. {"Only moderators are allowed to change the subject in this room","モデレーターのみがチャットルームの件名を変更できます"}. {"Only moderators can approve voice requests","モデレーターだけが発言権の要求を承認できます"}. @@ -252,7 +258,8 @@ {"Outgoing s2s Connections","外向き s2s コネクション"}. {"Owner privileges required","主宰者の権限が必要です"}. {"Packet","パケット"}. -{"Password:","パスワード"}. +{"Participant","参加者"}. +{"Password:","パスワード:"}. {"Password","パスワード"}. {"Password ~b","パスワード ~b"}. {"Password Verification:","パスワード (確認):"}. @@ -265,6 +272,8 @@ {"Persist items to storage","アイテムをストレージに保存する"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","これらのオプションは組み込みの Mnesia データーベースのバックアップのみを行うことに注意してください。もし ODBC モジュールを使用している場合は、SQL データーベースのバックアップを別に行う必要があります。"}. +{"Please specify file name.","ファイル名を指定してください。"}. +{"Please specify file size.","ファイルサイズを指定してください。"}. {"Please, wait for a while before sending new voice request","新しい発言権の要求を送るまで少し間をおいてください"}. {"Pong","Pong"}. {"Port","ポート"}. @@ -300,6 +309,7 @@ {"Restore binary backup after next ejabberd restart (requires less memory):","ejabberd の再起動時にバイナリバックアップからリストア (メモリ少):"}. {"Restore binary backup immediately:","直ちにバイナリバックアップからリストア:"}. {"Restore plain text backup immediately:","直ちにプレーンテキストバックアップからリストア:"}. +{"Roles for which Presence is Broadcasted","プレゼンスをブロードキャストするロール"}. {"Room Configuration","チャットルームの設定"}. {"Room creation is denied by service policy","サービスポリシーによってチャットルームの作成が禁止されています"}. {"Room description","チャットルームの説明"}. @@ -322,6 +332,7 @@ {"Send announcement to all users","すべてのユーザーにアナウンスを送信"}. {"September","9月"}. {"Server:","サーバー:"}. +{"Server","サーバー"}. {"Server ~b","サーバー ~b"}. {"Set message of the day and send to online users","お知らせメッセージを設定し、オンラインユーザーに送信"}. {"Set message of the day on all hosts and send to online users","全ホストのお知らせメッセージを設定し、オンラインユーザーに送信"}. @@ -367,7 +378,7 @@ {"This IP address is blacklisted in ~s","このIPアドレスはアクセスを禁止されています ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","大文字と小文字は区別しません: macbeth は MacBeth や Macbeth と同じです。"}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","ここはこの Jabber サーバーにアカウントを作成するページです。あなたの JID (JabberID) は username@server のような形式になります。注意事項どおり、正しく項目を記入してください。"}. -{"This page allows to unregister a Jabber account in this Jabber server.","ここはこの Jabber サーバーのアカウントを削除するページです。"}. +{"This page allows to unregister a Jabber account in this Jabber server.","このページはサーバー上のJabberアカウントを削除するページです。"}. {"Thursday","木曜日"}. {"Time delay","遅延時間"}. {"Time","時間"}. @@ -376,7 +387,7 @@ {"Too many unacked stanzas","多くのスタンザが応答していません"}. {"To ~s","宛先 ~s"}. {"Total rooms","チャットルーム数"}. -{"To","宛先"}. +{"To","To"}. {"Traffic rate limit is exceeded","トラフィックレートの制限を超えました"}. {"Transactions Aborted:","トランザクションの失敗:"}. {"Transactions Committed:","トランザクションのコミット:"}. @@ -394,7 +405,7 @@ {"Update script","スクリプトの更新"}. {"Update","更新"}. {"Uptime:","起動時間:"}. -{"Use of STARTTLS required","STARTTLS の使用が必要です"}. +{"Use of STARTTLS required","STARTTLS の使用が必須です"}. {"User","ユーザー"}. {"User JID","ユーザー JID"}. {"User Management","ユーザー管理"}. @@ -408,6 +419,7 @@ {"Virtual Hosts","バーチャルホスト"}. {"Visitors are not allowed to change their nicknames in this room","傍聴者はこのチャットルームでニックネームを変更することはできません"}. {"Visitors are not allowed to send messages to all occupants","傍聴者はすべての在室者にメッセージを送信することはできません"}. +{"Visitor","傍聴者"}. {"Voice requests are disabled in this conference","この会議では、発言権の要求はできません"}. {"Voice request","発言権を要求"}. {"Wednesday","水曜日"}. diff --git a/priv/msgs/pl.msg b/priv/msgs/pl.msg index 4bab696cfcb..03fbd3d0044 100644 --- a/priv/msgs/pl.msg +++ b/priv/msgs/pl.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Zaakceptuj"}. {"Access Configuration","Konfiguracja dostępu"}. {"Access Control List Configuration","Konfiguracja listy dostępowej"}. {"Access Control Lists","Lista dostępowa"}. @@ -87,6 +88,7 @@ {"ejabberd Web Admin","ejabberd: Panel Administracyjny"}. {"Elements","Elementy"}. {"Email","Email"}. +{"Empty Rooms","Puste pokoje"}. {"Enable logging","Włącz logowanie"}. {"Enable message archiving","Włącz archiwizowanie rozmów"}. {"Encoding for server ~b","Kodowanie znaków dla serwera ~b"}. @@ -142,6 +144,7 @@ {"Import Users from Dir at ","Importuj użytkowników z katalogu na "}. {"Import Users From jabberd14 Spool Files","Importuj użytkowników z plików roboczych serwera jabberd14"}. {"Improper message type","Nieprawidłowy typ wiadomości"}. +{"Incoming s2s Connections:","Przychodzące połączenia s2s:"}. {"Incorrect password","Nieprawidłowe hasło"}. {"Invalid affiliation: ~s","Nieprawidłowa przynależność: ~s"}. {"Invalid role: ~s","Nieprawidłowa rola: ~s"}. @@ -154,6 +157,7 @@ {"IRC username","Nazwa użytkownika IRC"}. {"IRC Username","Nazwa użytkownika IRC"}. {"is now known as","jest teraz znany jako"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","Użytkownik nie może wysyłać wiadomości o błędach do pokoju. Użytkownik (~s) wysłał błąd (~s) i został wyrzucony z pokoju"}. {"It is not allowed to send private messages of type \"groupchat\"","Nie można wysyłać prywatnych wiadomości typu \"groupchat\""}. {"It is not allowed to send private messages to the conference","Nie wolno wysyłac prywatnych wiadomości na konferencję"}. {"It is not allowed to send private messages","Wysyłanie prywatnych wiadomości jest zabronione"}. @@ -196,6 +200,7 @@ {"Message body","Treść wiadomości"}. {"Middle Name","Drugie imię"}. {"Minimum interval between voice requests (in seconds)","Minimalny odstęp między żądaniami głosowymi (w sekundach)"}. +{"Moderator","Moderatorzy"}. {"Moderator privileges required","Wymagane uprawnienia moderatora"}. {"moderators only","tylko moderatorzy"}. {"Modified modules","Zmodyfikowane moduły"}. @@ -239,6 +244,7 @@ {"Online Users:","Użytkownicy zalogowani:"}. {"Online Users","Użytkownicy zalogowani"}. {"Only deliver notifications to available users","Dostarczaj powiadomienia tylko dostępnym użytkownikom"}. +{"Only members may query archives of this room","Tylko moderatorzy mogą przeglądać archiwa tego pokoju"}. {"Only moderators and participants are allowed to change the subject in this room","Tylko moderatorzy i uczestnicy mogą zmienić temat tego pokoju"}. {"Only moderators are allowed to change the subject in this room","Tylko moderatorzy mogą zmienić temat tego pokoju"}. {"Only moderators can approve voice requests","Tylko moderatorzy mogą zatwierdzać żądania głosowe"}. @@ -252,6 +258,7 @@ {"Outgoing s2s Connections","Wychodzące połączenia s2s"}. {"Owner privileges required","Wymagane uprawnienia właściciela"}. {"Packet","Pakiet"}. +{"Participant","Uczestnicy"}. {"Password ~b","Hasło ~b"}. {"Password:","Hasło:"}. {"Password","Hasło"}. @@ -265,6 +272,8 @@ {"Persist items to storage","Przechowuj na stałe dane PubSub"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Te opcje kopii zapasowych dotyczą tylko wbudowanej bazy danych typu Mnesia. Jeśli korzystasz z modułu ODBC, musisz wykonać kopie bazy we własnym zakresie."}. +{"Please specify file name.","Proszę podać nazwę pliku."}. +{"Please specify file size.","Proszę podać rozmiar pliku."}. {"Please, wait for a while before sending new voice request","Proszę poczekać chwile, zanim wyślesz nowe żądanie głosowe"}. {"Pong","Pong"}. {"Port ~b","Port ~b"}. @@ -300,6 +309,7 @@ {"Restore binary backup immediately:","Natychmiast odtwórz kopię binarną:"}. {"Restore plain text backup immediately:","Natychmiast odtwórz kopię z postaci tekstowej:"}. {"Restore","Przywróć z kopii"}. +{"Roles for which Presence is Broadcasted","Role dla których wysyłane są statusy"}. {"Room Configuration","Konfiguracja pokoju"}. {"Room creation is denied by service policy","Zasady serwera zabraniają tworzyć nowe pokoje"}. {"Room description","Opis pokoju"}. @@ -323,6 +333,7 @@ {"September","Wrzesień"}. {"Server ~b","Serwer ~b"}. {"Server:","Serwer:"}. +{"Server","Serwer"}. {"Set message of the day and send to online users","Wyślij wiadomość dnia do wszystkich zalogowanych użytkowników"}. {"Set message of the day on all hosts and send to online users","Ustaw wiadomość dnia dla wszystkich hostów i wyślij do zalogowanych uzytkowników"}. {"Shared Roster Groups","Wspólne grupy kontaktów"}. @@ -406,6 +417,7 @@ {"Validate","Potwierdź"}. {"vCard User Search","Wyszukiwanie vCard użytkowników"}. {"Virtual Hosts","Wirtualne Hosty"}. +{"Visitor","Odwiedzający"}. {"Visitors are not allowed to change their nicknames in this room","Uczestnicy tego pokoju nie mogą zmieniać swoich nicków"}. {"Visitors are not allowed to send messages to all occupants","Odwiedzający nie mogą wysyłać wiadomości do wszystkich obecnych"}. {"Voice requests are disabled in this conference","Głosowe żądania są wyłączone w tym pokoju"}. diff --git a/priv/msgs/pt-br.msg b/priv/msgs/pt-br.msg index c866608e250..3e7b28ee9ef 100644 --- a/priv/msgs/pt-br.msg +++ b/priv/msgs/pt-br.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Aceito"}. {"Access Configuration","Configuração de Acesso"}. {"Access Control List Configuration","Configuração da Lista de Controle de Acesso"}. {"Access control lists","Listas de Controle de Acesso"}. @@ -87,6 +88,7 @@ {"ejabberd Web Admin","ejabberd Web Admin"}. {"Elements","Elementos"}. {"Email","Email"}. +{"Empty Rooms","Salas vazias"}. {"Enable logging","Permitir criação de logs"}. {"Enable message archiving","Habilitar arquivamento de mensagens"}. {"Encoding for server ~b","Codificação para o servidor ~b"}. @@ -121,7 +123,7 @@ {"Get User Last Login Time","Obter a Data do Último Login"}. {"Get User Password","Obter Senha do Usuário"}. {"Get User Statistics","Obter Estatísticas do Usuário"}. -{"Grant voice to this person?","Dar 'voice' a esta usuário?"}. +{"Grant voice to this person?","Dar voz a esta pessoa?"}. {"Group ","Grupo "}. {"Groups","Grupos"}. {"has been banned","foi banido"}. @@ -142,6 +144,7 @@ {"Import Users from Dir at ","Importar usuários a partir do diretório em "}. {"Import Users From jabberd14 Spool Files","Importar usuários de arquivos jabberd14 (spool files)"}. {"Improper message type","Tipo de mensagem incorreto"}. +{"Incoming s2s Connections:","Conexões que entram de s2s"}. {"Incorrect password","Senha incorreta"}. {"Invalid affiliation: ~s","Afiliação não válida: ~s"}. {"Invalid role: ~s","Cargo (role) é não válido: ~s"}. @@ -154,6 +157,7 @@ {"IRC username","Usuário IRC"}. {"IRC Username","Usuário IRC"}. {"is now known as","é agora conhecido como"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","Não é permitido o envio de mensagens de erro a esta sala. O membro (~s) enviou uma mensagem de erro (~s) e foi desconectado (\"kicked\")."}. {"It is not allowed to send private messages","Não é permitido enviar mensagens privadas"}. {"It is not allowed to send private messages of type \"groupchat\"","Não é permitido enviar mensagens privadas do tipo \"groupchat\""}. {"It is not allowed to send private messages to the conference","Impedir o envio de mensagens privadas para a sala"}. @@ -196,6 +200,7 @@ {"Message body","Corpo da mensagem"}. {"Middle Name","Nome do meio"}. {"Minimum interval between voice requests (in seconds)","O intervalo mínimo entre requisições de voz (em segundos)"}. +{"Moderator","Moderador"}. {"Moderator privileges required","Se necessita privilégios de moderador"}. {"moderators only","apenas moderadores"}. {"Modified modules","Módulos atualizados"}. @@ -239,6 +244,7 @@ {"Online Users","Usuários conectados"}. {"Online Users:","Usuários online"}. {"Only deliver notifications to available users","Somente enviar notificações aos usuários disponíveis"}. +{"Only members may query archives of this room","Somente os membros podem procurar nos arquivos desta sala"}. {"Only moderators and participants are allowed to change the subject in this room","Somente os moderadores e os participamentes podem alterar o assunto desta sala"}. {"Only moderators are allowed to change the subject in this room","Somente os moderadores podem alterar o assunto desta sala"}. {"Only moderators can approve voice requests","Somente moderadores podem aprovar requisições de voz"}. @@ -252,6 +258,7 @@ {"Outgoing s2s Connections:","Conexões que partem de s2s"}. {"Owner privileges required","Se requer privilégios de proprietário da sala"}. {"Packet","Pacote"}. +{"Participant","Participante"}. {"Password ~b","Senha ~b"}. {"Password:","Senha:"}. {"Password","Senha"}. @@ -265,6 +272,8 @@ {"Persist items to storage","Persistir elementos ao armazenar"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Observe que tais opções farão backup apenas da base de dados Mnesia. Caso você esteja utilizando o modulo ODBC, você precisará fazer backup de sua base de dados SQL separadamente."}. +{"Please specify file name.","Por favor informe o nome do arquivo."}. +{"Please specify file size.","Por favor informe o tamanho do arquivo."}. {"Please, wait for a while before sending new voice request","Por favor, espere antes de enviar uma nova requisição de voz"}. {"Pong","Pong"}. {"Port ~b","Porta ~b"}. @@ -300,6 +309,7 @@ {"Restore binary backup immediately:","Restaurar backup binário imediatamente"}. {"Restore plain text backup immediately:","Restaurar backup formato texto imediatamente:"}. {"Restore","Restaurar"}. +{"Roles for which Presence is Broadcasted","Para quem a presença será notificada"}. {"Room Configuration","Configuração de salas"}. {"Room creation is denied by service policy","Sala não pode ser criada devido à política do serviço"}. {"Room description","Descrição da Sala"}. @@ -323,6 +333,7 @@ {"September","Setembro"}. {"Server ~b","Servidor ~b"}. {"Server:","Servidor:"}. +{"Server","Servidor"}. {"Set message of the day and send to online users","Definir mensagem do dia e enviar a todos usuários online"}. {"Set message of the day on all hosts and send to online users","Definir mensagem do dia em todos os hosts e enviar para os usuários online"}. {"Shared Roster Groups","Grupos Shared Roster"}. @@ -330,7 +341,7 @@ {"Show Ordinary Table","Mostrar Tabela Ordinária"}. {"Shut Down Service","Parar Serviço"}. {"~s invites you to the room ~s","~s convidou você para a sala ~s"}. -{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clientes jabber podem salvar a sua senha no seu computador. Use o recurso somente se você considera este computador seguro o suficiente."}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Alguns clientes jabber podem salvar a sua senha no seu computador. Use recurso somente se você considera este computador seguro o suficiente."}. {"Specify the access model","Especificar os modelos de acesso"}. {"Specify the event message type","Especificar o tipo de mensagem para o evento"}. {"Specify the publisher model","Especificar o modelo do publicante"}. @@ -343,7 +354,7 @@ {"Stop Modules at ","Parar módulos em "}. {"Stop Modules","Parar módulos"}. {"Stop","Parar"}. -{"Stopped Nodes","Nós parados"}. +{"Stopped Nodes","Nos parados"}. {"Storage Type","Tipo de armazenamento"}. {"Store binary backup:","Armazenar backup binário:"}. {"Store plain text backup:","Armazenar backup em texto:"}. @@ -408,6 +419,7 @@ {"Virtual Hosts","Hosts virtuais"}. {"Visitors are not allowed to change their nicknames in this room","Nesta sala, os visitantes não podem mudar seus apelidos"}. {"Visitors are not allowed to send messages to all occupants","Os visitantes não podem enviar mensagens a todos os ocupantes"}. +{"Visitor","Visitante"}. {"Voice request","Requisição de voz"}. {"Voice requests are disabled in this conference","Requisições de voz estão desabilitadas nesta conferência"}. {"Wednesday","Quarta"}. @@ -419,7 +431,7 @@ {"You need a client that supports x:data and CAPTCHA to register","Você precisa de um cliente com suporte de x:data para poder registrar o nick"}. {"You need a client that supports x:data to register the nickname","Você precisa de um cliente com suporte a x:data para registrar o seu apelido"}. {"You need an x:data capable client to configure mod_irc settings","Necessitas um cliente com suporte de x:data para configurar as opções de mod_irc"}. -{"You need an x:data capable client to configure room","Necessitas um cliente com suporte de x:data para configurar la sala"}. +{"You need an x:data capable client to configure room","Necessitas um cliente com suporte de x:data para configurar a sala"}. {"You need an x:data capable client to search","Necessitas um cliente com suporte de x:data para poder buscar"}. {"Your active privacy list has denied the routing of this stanza.","Sua lista de privacidade ativa negou o roteamento deste."}. {"Your contact offline message queue is full. The message has been discarded.","Sua fila de mensagens offline esta cheia. Sua mensagem foi descartada"}. diff --git a/priv/msgs/uk.msg b/priv/msgs/uk.msg index 985796ca05a..568ac0926cc 100644 --- a/priv/msgs/uk.msg +++ b/priv/msgs/uk.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Прийняти"}. {"Access Configuration","Конфігурація доступу"}. {"Access Control List Configuration","Конфігурація списків керування доступом"}. {"Access control lists","Списки керування доступом"}. @@ -21,7 +22,9 @@ {"Allow users to send invites","Дозволити користувачам надсилати запрошення"}. {"Allow users to send private messages","Дозволити приватні повідомлення"}. {"Allow visitors to change nickname","Дозволити відвідувачам змінювати псевдонім"}. +{"Allow visitors to send private messages to","Дозволити відвідувачам відсилати приватні повідомлення"}. {"Allow visitors to send status text in presence updates","Дозволити відвідувачам відсилати текст статусу в оновленнях присутності"}. +{"Allow visitors to send voice requests","Дозволити відвідувачам надсилати голосові запрошення"}. {"All Users","Всі користувачі"}. {"Announcements","Сповіщення"}. {"anyone","всім учасникам"}. @@ -29,6 +32,7 @@ {"April","квітня"}. {"August","серпня"}. {"Backup Management","Керування резервним копіюванням"}. +{"Backup of ~p","Резервне копіювання ~p"}. {"Backup to File at ","Резервне копіювання в файл на "}. {"Backup","Резервне копіювання"}. {"Bad format","Неправильний формат"}. @@ -56,6 +60,7 @@ {"Connections parameters","Параметри з'єднання"}. {"Country","Країна"}. {"CPU Time:","Процесорний час:"}. +{"Database Tables at ~p","Таблиці бази даних на ~p"}. {"Database Tables Configuration at ","Конфігурація таблиць бази даних на "}. {"Database","База даних"}. {"December","грудня"}. @@ -73,15 +78,19 @@ {"Dump Backup to Text File at ","Копіювання в текстовий файл на "}. {"Dump to Text File","Копіювання в текстовий файл"}. {"Edit Properties","Змінити параметри"}. +{"Either approve or decline the voice request.","Підтвердить або відхилите голосовий запит"}. {"ejabberd IRC module","ejabberd IRC модуль"}. {"ejabberd MUC module","ejabberd MUC модуль"}. +{"ejabberd Multicast service","Мультікаст ejabberd сервіс"}. {"ejabberd Publish-Subscribe module","Модуль ejabberd Публікації-Підписки"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 Bytestreams модуль"}. {"ejabberd vCard module","ejabberd vCard модуль"}. {"ejabberd Web Admin","Веб-інтерфейс Адміністрування ejabberd"}. {"Elements","Елементи"}. {"Email","Електронна пошта"}. +{"Empty Rooms","Порожні кімнати"}. {"Enable logging","Включити журнал роботи"}. +{"Enable message archiving","Ввімкнути архівацію повідомлень"}. {"Encoding for server ~b","Кодування для сервера ~b"}. {"End User Session","Закінчити Сеанс Користувача"}. {"Enter list of {Module, [Options]}","Введіть перелік такого виду {Module, [Options]}"}. @@ -97,8 +106,10 @@ {"Error","Помилка"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Приклад: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. {"Exclude Jabber IDs from CAPTCHA challenge","Пропускати ці Jabber ID без CAPTCHA-запиту"}. +{"Export all tables as SQL queries to a file:","Експорт усіх таблиць, як SQL запити, у файл"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","Експорт даних всіх користувачів сервера до файлу PIEFXIS (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","Експорт даних користувачів домена до файлу PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Помилка витягнення JID з вашого схвалення голосового запиту"}. {"Family Name","Прізвище"}. {"February","лютого"}. {"Fill in fields to search for any matching Jabber User","Заповніть поля для пошуку користувача Jabber"}. @@ -112,6 +123,7 @@ {"Get User Last Login Time","Отримати Час Останнього Підключення Користувача"}. {"Get User Password","Отримати Пароль Користувача"}. {"Get User Statistics","Отримати Статистику по Користувачу"}. +{"Grant voice to this person?","Надати голос персоні?"}. {"Groups","Групи"}. {"Group ","Група "}. {"has been banned","заборонили вхід в кімнату"}. @@ -130,8 +142,9 @@ {"Import users data from a PIEFXIS file (XEP-0227):","Імпорт даних користовучів з файлу PIEFXIS (XEP-0227):"}. {"Import users data from jabberd14 spool directory:","Імпорт користувачів з діректорії спула jabberd14:"}. {"Import Users from Dir at ","Імпортування користувача з директорії на "}. -{"Import Users From jabberd14 Spool Files","Імпорт користувачів зі спулу jabberd14"}. +{"Import Users From jabberd14 Spool Files","Імпорт користувачів з jabberd14 файлів \"Spool\""}. {"Improper message type","Неправильний тип повідомлення"}. +{"Incoming s2s Connections:","Вхідні s2s-з'єднання:"}. {"Incorrect password","Неправильний пароль"}. {"Invalid affiliation: ~s","Недопустимий ранг: ~s"}. {"Invalid role: ~s","Недопустима роль: ~s"}. @@ -144,6 +157,7 @@ {"IRC username","Ім'я користувача IRC"}. {"IRC Username","Ім'я користувача IRC"}. {"is now known as","змінив(ла) псевдонім на"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","Не дозволяється відправляти помилкові повідомлення в кімнату. Учасник (~s) відправив помилкове повідомлення (~s), та був виганий з кімнати"}. {"It is not allowed to send private messages of type \"groupchat\"","Не дозволяється надсилати приватні повідомлення типу \"groupchat\""}. {"It is not allowed to send private messages to the conference","Не дозволяється надсилати приватні повідомлення в конференцію"}. {"It is not allowed to send private messages","Приватні повідомлення не дозволені"}. @@ -165,6 +179,7 @@ {"Listened Ports at ","Відкриті порти на "}. {"Listened Ports","Відкриті порти"}. {"List of modules to start","Список завантажуваних модулів"}. +{"List of rooms","Перелік кімнат"}. {"Low level update script","Низькорівневий сценарій поновлення"}. {"Make participants list public","Зробити список учасників видимим всім"}. {"Make room CAPTCHA protected","Зробити кімнату захищеною капчею"}. @@ -184,12 +199,17 @@ {"Memory","Пам'ять"}. {"Message body","Тіло повідомлення"}. {"Middle Name","По-батькові"}. +{"Minimum interval between voice requests (in seconds)","Мінімальний інтервал між голосовими запитами (в секундах)"}. {"Moderator privileges required","Необхідні права модератора"}. {"moderators only","тільки модераторам"}. +{"Moderator","Модератор"}. {"Modified modules","Змінені модулі"}. +{"Modules at ~p","Модулі на ~p"}. {"Modules","Модулі"}. {"Module","Модуль"}. {"Monday","Понеділок"}. +{"Multicast","Мультікаст"}. +{"Multi-User Chat","Багато-користувальницький чат"}. {"Name:","Назва:"}. {"Name","Назва"}. {"Never","Ніколи"}. @@ -198,9 +218,11 @@ {"Nickname ~s does not exist in the room","Псевдонім ~s в кімнаті відсутній"}. {"Nickname","Псевдонім"}. {"No body provided for announce message","Тіло оголошення має бути непустим"}. +{"nobody","ніхто"}. {"No Data","Немає даних"}. {"Node ID","ID вузла"}. {"Node not found","Вузол не знайдено"}. +{"Node ~p","Вузол ~p"}. {"Nodes","Вузли"}. {"No limit","Без обмежень"}. {"None","Немає"}. @@ -222,8 +244,10 @@ {"Online Users","Підключені користувачі"}. {"Online","Підключений"}. {"Only deliver notifications to available users","Доставляти повідомленнями тільки доступним користувачам"}. +{"Only members may query archives of this room","Тільки модератори можуть запитувати архіви цієї кімнати"}. {"Only moderators and participants are allowed to change the subject in this room","Тільки модератори та учасники можуть змінювати тему в цій кімнаті"}. {"Only moderators are allowed to change the subject in this room","Тільки модератори можуть змінювати тему в цій кімнаті"}. +{"Only moderators can approve voice requests","Тільки модератори можуть схвалювати голосові запити"}. {"Only occupants are allowed to send messages to the conference","Тільки присутнім дозволяється надсилати повідомленняя в конференцію"}. {"Only occupants are allowed to send queries to the conference","Тільки присутнім дозволяється відправляти запити в конференцію"}. {"Only service administrators are allowed to send service messages","Тільки адміністратор сервісу може надсилати службові повідомлення"}. @@ -234,6 +258,7 @@ {"Outgoing s2s Connections","Вихідні s2s-з'єднання"}. {"Owner privileges required","Необхідні права власника"}. {"Packet","Пакет"}. +{"Participant","Учасник"}. {"Password ~b","Пароль ~b"}. {"Password Verification:","Перевірка Пароля:"}. {"Password Verification","Перевірка Пароля"}. @@ -243,9 +268,13 @@ {"Path to File","Шлях до файла"}. {"Pending","Очікування"}. {"Period: ","Період"}. +{"Permanent rooms","Постійні кімнати"}. {"Persist items to storage","Зберегати публікації до сховища"}. {"Ping","Пінг"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Зауважте, що ця опція відповідає за резервне копіювання тільки вбудованної бази даних Mnesia. Якщо Ви також використовуєте інше сховище для даних (наприклад за допомогою модуля ODBC), то його резервне копіювання потрібно робити окремо."}. +{"Please specify file name.","Будь ласка вкажіть ім'я файлу."}. +{"Please specify file size.","Будь ласка вкажіть розмір файлу."}. +{"Please, wait for a while before sending new voice request","Будь ласка, почекайте деякий час перед тим, як знову відправляти голосовий запит"}. {"Pong","Понг"}. {"Port ~b","Порт ~b"}. {"Port","Порт"}. @@ -259,9 +288,10 @@ {"RAM and disc copy","ОЗП та диск"}. {"RAM copy","ОЗП"}. {"Raw","необроблений формат"}. -{"Really delete message of the day?","Насправді видалити повідомлення дня?"}. +{"Really delete message of the day?","Насправді, видалити повідомлення дня?"}. {"Recipient is not in the conference room","Адресата немає в конференції"}. {"Register a Jabber account","Зареєструвати Jabber-акаунт"}. +{"Registered nicknames","Зареєстровані імена"}. {"Registered Users:","Зареєстровані користувачі:"}. {"Registered Users","Зареєстровані користувачі"}. {"Register","Реєстрація"}. @@ -279,6 +309,7 @@ {"Restore binary backup immediately:","Відновити з бінарної резервної копії негайно:"}. {"Restore plain text backup immediately:","Відновити з текстової резервної копії негайно:"}. {"Restore","Відновлення з резервної копії"}. +{"Roles for which Presence is Broadcasted","Ролі для яких поширюється наявність"}. {"Room Configuration","Конфігурація кімнати"}. {"Room creation is denied by service policy","Створювати конференцію заборонено політикою служби"}. {"Room description","Опис кімнати"}. @@ -302,6 +333,7 @@ {"September","вересня"}. {"Server ~b","Сервер ~b"}. {"Server:","Сервер:"}. +{"Server","Сервер:"}. {"Set message of the day and send to online users","Встановити повідомлення дня та надіслати його підключеним користувачам"}. {"Set message of the day on all hosts and send to online users","Встановити повідомлення дня на всіх хостах та надійслати його підключеним користувачам"}. {"Shared Roster Groups","Спільні групи контактів"}. @@ -343,6 +375,7 @@ {"There was an error changing the password: ","Помилка при зміні пароля: "}. {"There was an error creating the account: ","Помилка при створенні акаунту:"}. {"There was an error deleting the account: ","Помилка при видаленні акаунту: "}. +{"This IP address is blacklisted in ~s","Ця IP адреса у чорному списку ~s"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Регістр не має значення: \"МАША\" та \"маша\" буде сприйматися як одне й те саме ім'я."}. {"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Тут ви можете зареєструвати обліковий запис Jabber на цьому сервері. Ваш JID (ідентифікатор Jabber) матиме вигляд \"користувач@сервер\". Щоб вірно заповнити поля нижче, будь ласка, уважно читайте інструкції до них."}. {"This page allows to unregister a Jabber account in this Jabber server.","Ця сторінка дозволяє видалити свій акаунт з Jabber-сервера."}. @@ -350,7 +383,10 @@ {"Time delay","Час затримки"}. {"Time","Час"}. {"Too many CAPTCHA requests","Надто багато CAPTCHA-запитів"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","Забагато (~p) помилок авторизації з цієї IP адреси (~s). Адресу буде розблоковано о ~s UTC"}. +{"Too many unacked stanzas","Занадто багато пакетів без відповідей"}. {"To ~s","До ~s"}. +{"Total rooms","Всього кімнат"}. {"To","Кому"}. {"Traffic rate limit is exceeded","Швидкість передачі інформації було перевищено"}. {"Transactions Aborted:","Транзакції відмінені:"}. @@ -364,15 +400,18 @@ {"Unregister","Видалити"}. {"Update message of the day (don't send)","Оновити повідомлення дня (не надсилати)"}. {"Update message of the day on all hosts (don't send)","Оновити повідомлення дня на всіх хостах (не надсилати)"}. -{"Update plan","План поновлення"}. +{"Update plan","План оновлення"}. +{"Update ~p","Оновлення ~p"}. {"Update script","Сценарій поновлення"}. {"Update","Обновити"}. {"Uptime:","Час роботи:"}. {"Use of STARTTLS required","Ви мусите використовувати STARTTLS"}. +{"User JID","JID Користувача"}. {"User Management","Управління Користувачами"}. {"Username:","Ім'я користувача:"}. {"Users are not allowed to register accounts so quickly","Користувачам не дозволено так часто реєструвати облікові записи"}. {"Users Last Activity","Статистика останнього підключення користувачів"}. +{"User ~s","Користувач ~s"}. {"Users","Користувачі"}. {"User","Користувач"}. {"Validate","Затвердити"}. @@ -380,6 +419,9 @@ {"Virtual Hosts","віртуальні хости"}. {"Visitors are not allowed to change their nicknames in this room","Відвідувачам не дозволяється змінювати псевдонім в цій кімнаті"}. {"Visitors are not allowed to send messages to all occupants","Відвідувачам не дозволяється надсилати повідомлення всім присутнім"}. +{"Visitor","Відвідувач"}. +{"Voice requests are disabled in this conference","Голосові запити відключені в цій конференції"}. +{"Voice request","Голосовий запит"}. {"Wednesday","Середа"}. {"When to send the last published item","Коли надсилати останній опублікований елемент"}. {"Whether to allow subscriptions","Дозволяти підписку"}. diff --git a/priv/msgs/wa.msg b/priv/msgs/wa.msg index 9c79a6f7d30..8946b71dde4 100644 --- a/priv/msgs/wa.msg +++ b/priv/msgs/wa.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","Accepter"}. {"Access Configuration","Apontiaedje des accès"}. {"Access Control List Configuration","Apontiaedje des droets (ACL)"}. {"Access control lists","Droets (ACL)"}. @@ -16,24 +17,35 @@ {"A friendly name for the node","On no uzeu-ahessåve pol nuk"}. {"All activity","Dispoy todi"}. {"Allow this Jabber ID to subscribe to this pubsub node?","Permete ki ci Jabber ID ci si poye abouner a ç' nuk eplaidaedje-abounmint ci?"}. +{"Allow users to change the subject","Les uzeus polèt candjî l' tite"}. {"Allow users to query other users","Les uzeus polèt cweri ls ôtes uzeus"}. {"Allow users to send invites","Les uzeus polèt evoyî priyaedjes"}. {"Allow users to send private messages","Les uzeus polèt evoyî des messaedjes privés"}. {"Allow visitors to change nickname","Permete ki les viziteus candjexhe leus metous nos"}. +{"Allow visitors to send private messages to","Les uzeus polèt evoyî des messaedjes privés"}. {"Allow visitors to send status text in presence updates","Permete ki les viziteus evoyexhe des tecse d' estat dins leus messaedjes di prezince"}. +{"Allow visitors to send voice requests","Les uzeus polèt evoyî des dmandes di vwès"}. {"All Users","Tos les uzeus"}. {"Announcements","Anonces"}. {"anyone","tot l' minme kî"}. +{"A password is required to enter this room","I fåt dner on scret po poleur intrer dins cisse såle ci"}. {"April","avri"}. {"August","awousse"}. {"Backup","Copeye di såvrité"}. {"Backup Management","Manaedjaedje des copeyes di såvrité"}. +{"Backup of ~p","Copeye di såvrité po ~p"}. {"Backup to File at ","Fé ene copeye di såvrité dins on fitchî so "}. {"Bad format","Mwais fôrmat"}. {"Birthday","Date d' askepiaedje"}. +{"CAPTCHA web page","Pådje web CAPTCHA"}. {"Change Password","Candjî l' sicret"}. {"Change User Password","Candjî l' sicret d' l' uzeu"}. +{"Characters not allowed:","Caracteres nén permetous:"}. {"Chatroom configuration modified","L' apontiaedje del såle di berdelaedje a candjî"}. +{"Chatroom is created","Li såle di berdelaedje est ahivêye"}. +{"Chatroom is destroyed","Li såle di berdelaedje est distrûte"}. +{"Chatroom is started","Li såle di berdelaedje est enondêye"}. +{"Chatroom is stopped","Li såle di berdelaedje est ahotêye"}. {"Chatrooms","Såles di berdelaedje"}. {"Choose a username and password to register with this server","Tchoezixhoz on no d' uzeu eyet on scret po vs edjîstrer so ç' sierveu ci"}. {"Choose modules to stop","Tchoezixhoz les modules a-z arester"}. @@ -43,10 +55,13 @@ {"Commands","Comandes"}. {"Conference room does not exist","Li såle di conferince n' egzistêye nén"}. {"Configuration","Apontiaedjes"}. +{"Configuration of room ~s","Apontiaedje del såle ~s"}. {"Connected Resources:","Raloyî avou les rsoûces:"}. +{"Connections parameters","Parametes des raloyaedjes"}. {"Country","Payis"}. {"CPU Time:","Tins CPU:"}. {"Database","Båze di dnêyes"}. +{"Database Tables at ~p","Tåves del båze di dnêyes so ~p"}. {"Database Tables Configuration at ","Apontiaedje des tåves del båze di dnêyes so "}. {"December","decimbe"}. {"Default users as participants","Les uzeus sont des pårticipants come prémetowe dujhance"}. @@ -59,17 +74,24 @@ {"Description:","Discrijhaedje:"}. {"Disc only copy","Copeye seulmint sol deure plake"}. {"Displayed Groups:","Groupes håynés:"}. +{"Don't tell your password to anybody, not even the administrators of the Jabber server.","Ni dnez vosse sicret a nolu, nén ddja ås manaedjeus do sierveu Jabber."}. {"Dump Backup to Text File at ","Copeye di såvritè viè on fitchî tecse so "}. {"Dump to Text File","Schaper en on fitchî tecse"}. {"Edit Properties","Candjî les prôpietés"}. +{"Either approve or decline the voice request.","Aprover oudonbén rifuzer li dmande di vwès."}. {"ejabberd IRC module","Module IRC po ejabberd"}. {"ejabberd MUC module","Module MUC (såles di berdelaedje) po ejabberd"}. +{"ejabberd Multicast service","siervice multicast d' ejabberd"}. {"ejabberd Publish-Subscribe module","Module d' eplaidaedje-abounmint po ejabberd"}. {"ejabberd SOCKS5 Bytestreams module","Module SOCKS5 Bytestreams po ejabberd"}. {"ejabberd vCard module","Module vCard ejabberd"}. {"ejabberd Web Admin","Manaedjeu waibe ejabberd"}. +{"Elements","Elemints"}. {"Email","Emile"}. +{"Empty Rooms","Såles vudes"}. {"Enable logging","Mete en alaedje li djournå"}. +{"Enable message archiving","Mete en alaedje l' årtchivaedje des messaedjes"}. +{"Encoding for server ~b","Ecôdaedje pol sierveu ~b"}. {"End User Session","Fini l' session d' l' uzeu"}. {"Enter list of {Module, [Options]}","Dinez ene djivêye del cogne {Module, [Tchuzes]}"}. {"Enter nickname you want to register","Dinez l' metou no ki vos vloz edjîstrer"}. @@ -77,7 +99,17 @@ {"Enter path to jabberd14 spool dir","Dinez l' tchimin viè l' ridant di spool jabberd14"}. {"Enter path to jabberd14 spool file","Dinez l' tchimin viè l' fitchî di spool jabberd14"}. {"Enter path to text file","Dinez l' tchimin viè l' fitchî tecse"}. +{"Enter the text you see","Tapez l' tecse ki vos voeyoz"}. +{"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","Dinez les nos d' uzeu et ls ecôdaedjes ki vos vloz eployî po vs raloyî åzès sierveus IRC Clitchîz so «Shuvant» po-z aveur di pus di tchamps a rimpli. Clitchîz so «Fini» po schaper les apontiaedjes."}. +{"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","Dinez l' no d' uzeu, les ecôdaedjes, les pôrts et les screts ki vos vloz eployî po vs raloyî åzès sierveus IRC"}. {"Erlang Jabber Server","Sierveu Jabber Erlang"}. +{"Error","Aroke"}. +{"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","Egzimpe: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. +{"Exclude Jabber IDs from CAPTCHA challenge","Esclure les IDs Jabber des kesses CAPTCHA"}. +{"Export all tables as SQL queries to a file:","Espoirter totes les tåves, come des cmandes SQL, viè on fitchî"}. +{"Export data of all users in the server to PIEFXIS files (XEP-0227):","Espoirter les dnêyes di tos les uzeus do sierveu viè des fitchîs PIEFXIS (XEP-0227):"}. +{"Export data of users in a host to PIEFXIS files (XEP-0227):","Espoirter les dnêyes di tos les uzeus do sierveu viè des fitchîs PIEFXIS (XEP-0227):"}. +{"Failed to extract JID from your voice request approval","Nén moyén di rsaetchî on JID foû d' l' aprovaedje di vosse dimande di vwès"}. {"Family Name","No d' famile"}. {"February","fevrî"}. {"Fill in fields to search for any matching Jabber User","Rimplixhoz les tchamps po cweri èn uzeu Jabber"}. @@ -91,6 +123,7 @@ {"Get User Last Login Time","Riçure li date/eure do dierin elodjaedje di l' uzeu"}. {"Get User Password","Riçure sicret d' l' uzeu"}. {"Get User Statistics","Riçure les statistikes di l' uzeu"}. +{"Grant voice to this person?","Permete li vwès po cisse djin ci?"}. {"Group ","Groupe "}. {"Groups","Groupes"}. {"has been banned","a stî bani"}. @@ -100,26 +133,42 @@ {"has been kicked because the room has been changed to members-only","a stî pité evoye cåze ki l' såle a stî ristrindowe åzès mimbes seulmint"}. {" has set the subject to: "," a candjî l' tite a: "}. {"Host","Sierveu"}. +{"If you don't see the CAPTCHA image here, visit the web page.","Si vos n' voeyoz nole imådje CAPTCHA chal, vizitez l' pådje waibe."}. +{"If you want to specify different ports, passwords, encodings for IRC servers, fill this list with values in format '{\"irc server\", \"encoding\", port, \"password\"}'. By default this service use \"~s\" encoding, port ~p, empty password.","Si vos vloz dner des pôrts, sicrets ou ecôdaedjes diferins po les sierveus IRC, rimplixhoz cisse djivêye ci avou des valixhances del cogne «{\"sierveu irc\", \"ecôdaedje\", pôrt, \"sicret\"}». Les prémetowès valixhances do siervice sont «~s» po l' ecôdaedje, «~p» pol pôrt, et on vude sicret."}. {"Import Directory","Sititchî d' on ridant"}. {"Import File","Sititchî d' on fitchî"}. +{"Import user data from jabberd14 spool file:","Sititchî des dnêyes uzeus foû d' on fitchî spoûle jabberd14:"}. {"Import User from File at ","Sititchî uzeu d' on fitchî so "}. +{"Import users data from a PIEFXIS file (XEP-0227):","Sititchî des dnêyes uzeus foû d' on fitchî PIEFXIS (XEP-0227):"}. +{"Import users data from jabberd14 spool directory:","Sititchî des dnêyes uzeus foû d' on ridant spoûle jabberd14:"}. {"Import Users from Dir at ","Sitichî des uzeus d' on ridant so "}. {"Import Users From jabberd14 Spool Files","Sititchî des uzeus Jabberd 1.4"}. {"Improper message type","Sôre di messaedje nén valide"}. +{"Incoming s2s Connections:","Raloyaedjes s2s en intrêye:"}. {"Incorrect password","Sicret nén corek"}. {"Invalid affiliation: ~s","Afiyaedje nén valide: ~s"}. {"Invalid role: ~s","Role nén valide: ~s"}. {"IP addresses","Adresses IP"}. +{"IP","IP"}. +{"IRC channel (don't put the first #)","Canå IRC (èn nén mete li prumî #)"}. +{"IRC server","Sierveu IRC"}. +{"IRC settings","Apontiaedjes IRC"}. {"IRC Transport","Transpoirt IRC"}. +{"IRC username","No d' uzeu IRC"}. {"IRC Username","No d' uzeu IRC"}. {"is now known as","est asteure kinoxhou come"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","On n' pout nén evoyî des messaedjes d' aroke sol såle. Li pårticipan (~s) a-st evoyî on messaedje d' aroke (~s) ey a stî tapé foû."}. {"It is not allowed to send private messages","Ci n' est nén permetou d' evoyî des messaedjes privés"}. {"It is not allowed to send private messages of type \"groupchat\"","C' est nén possibe d' evoyî des messaedjes privés del sôre «groupchat»"}. {"It is not allowed to send private messages to the conference","On n' pout nén evoyî des messaedjes privés dins cisse conferince ci"}. +{"Jabber Account Registration","Edjîstraedje di conte Jabber"}. {"Jabber ID","ID Jabber"}. {"Jabber ID ~s is invalid","Li Jabber ID ~s n' est nén valide"}. {"January","djanvî"}. +{"Join IRC channel","Radjonde canå IRC"}. {"joins the room","arive sol såle"}. +{"Join the IRC channel here.","Radjonde li canå IRC droci."}. +{"Join the IRC channel in this Jabber ID: ~s","Radjonde li canå IRC e cist ID Jabber: ~s"}. {"July","djulete"}. {"June","djun"}. {"Last Activity","Dierinne activité"}. @@ -130,8 +179,10 @@ {"Listened Ports at ","Pôrts drovous so "}. {"Listened Ports","Pôrts drovous"}. {"List of modules to start","Djivêye di modules a-z enonder"}. +{"List of rooms","Djivêye des såles"}. {"Low level update script","Sicripe di metaedje a djoû d' bas livea"}. {"Make participants list public","Rinde publike li djivêye des pårticipants"}. +{"Make room CAPTCHA protected","Rinde li såle di berdelaedje protedjeye pa CAPTCHA"}. {"Make room members-only","Rinde li såle di berdelaedje ristrindowe ås mimbes seulmint"}. {"Make room moderated","Rinde li såle di berdelaedje moderêye"}. {"Make room password protected","Rinde li såle di berdelaedje protedjeye pa scret"}. @@ -142,29 +193,41 @@ {"Max # of items to persist","Nombe macsimoms di cayets permanints"}. {"Max payload size in bytes","Contnou macsimom en octets"}. {"May","may"}. +{"Membership is required to enter this room","I fåt esse mimbe po poleur intrer dins cisse såle ci"}. {"Members:","Mimbes:"}. +{"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","Rimimbrez vosse sicret, ou scrijhoz l' so on papî ki vos wådroz en ene place bén a hoûte, ca avou Jabber i n' a pont moyén di rapexhî vosse sicret si vos l' rovyîz."}. {"Memory","Memwere"}. {"Message body","Coir do messaedje"}. {"Middle Name","No do mitan"}. +{"Minimum interval between voice requests (in seconds)","Tins minimom etur deus dmandes di vwès (e segondes)"}. +{"Moderator","Moderateu"}. {"Moderator privileges required","I fåt des priviledjes di moderateu"}. {"moderators only","les moderateus seulmint"}. +{"Modified modules","Modules di candjîs"}. {"Module","Module"}. +{"Modules at ~p","Modules so ~p"}. {"Modules","Modules"}. {"Monday","londi"}. +{"Multicast","Multicast"}. +{"Multi-User Chat","Berdelaedje a sacwants"}. {"Name","No"}. {"Name:","Pitit no:"}. {"Never","Måy"}. +{"New Password:","Novea scret:"}. {"Nickname","Metou no"}. {"Nickname Registration at ","Edjîstraedje di metou no amon "}. {"Nickname ~s does not exist in the room","Li metou no ~s n' egzistêye nén dins l' såle"}. +{"nobody","nolu"}. {"No body provided for announce message","I n' a nou coir do messaedje po ciste anonce la"}. {"No Data","Nole dinêye disponibe"}. {"Node ID","ID d' nuk"}. {"Node not found","Nuk nén trové"}. +{"Node ~p","Nuk ~p"}. {"Nodes","Nuks"}. {"No limit","Pont d' limite"}. {"None","Nole"}. {"No resource provided","Nole rissoûce di dnêye"}. +{"Not Found","Nén trové"}. {"Notify subscribers when items are removed from the node","Notifyî åzès abounés cwand des cayets sont oisté foû do nuk"}. {"Notify subscribers when the node configuration changes","Notifyî åzès abounés cwand l' apontiaedje do nuk candje"}. {"Notify subscribers when the node is deleted","Notifyî åzès abounés cwand l' nuk est disfacé"}. @@ -176,10 +239,15 @@ {"Offline Messages:","Messaedjes ki ratindèt:"}. {"Offline Messages","Messaedjes ki ratindèt"}. {"OK","'l est bon"}. +{"Old Password:","Vî scret:"}. {"Online","Raloyî"}. {"Online Users:","Uzeus raloyîs:"}. {"Online Users","Uzeus raloyîs"}. {"Only deliver notifications to available users","Seulmint evoyî des notifiaedje åzès uzeus disponibes"}. +{"Only members may query archives of this room","Seulmint les mimbes polèt cweri les årtchives dins cisse såle ci"}. +{"Only moderators and participants are allowed to change the subject in this room","Seulmint les moderateus et les pårticipants polèt candjî l' sudjet dins cisse såle ci"}. +{"Only moderators are allowed to change the subject in this room","Seulmint les moderateus polèt candjî l' sudjet dins cisse såle ci"}. +{"Only moderators can approve voice requests","Seulmint les moderateus polèt aprover des dmandes di vwès"}. {"Only occupants are allowed to send messages to the conference","Seulmint les prezints polèt evoyî des messaedjes al conferince"}. {"Only occupants are allowed to send queries to the conference","Seulmint les prezints polèt evoyî des cweraedjes sol conferince"}. {"Only service administrators are allowed to send service messages","Seulmint les manaedjeus d' siervices polèt evoyî des messaedjes di siervice"}. @@ -190,31 +258,46 @@ {"Outgoing s2s Connections","Raloyaedjes s2s e rexhowe"}. {"Owner privileges required","I fåt des priviledjes di prôpietaire"}. {"Packet","Paket"}. +{"Participant","Pårticipant"}. +{"Password ~b","Sicret ~b"}. {"Password:","Sicret:"}. {"Password","Sicret"}. +{"Password Verification:","Acertinaedje do scret:"}. {"Password Verification","Acertinaedje do scret"}. {"Path to Dir","Tchimin viè l' ridant"}. {"Path to File","Tchimin viè l' fitchî"}. {"Pending","Ratindant"}. {"Period: ","Termene:"}. +{"Permanent rooms","Såles tofer la"}. {"Persist items to storage","Cayets permanints a wårder"}. {"Ping","Ping"}. +{"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","Notez ki ces tchuzes la vont seulmint fé ene copeye di såvrité del båze di dnêyes Mnesia costrûte å dvins do programe. Si vos eployîz ene difoûtrinne båze di dnêyes avou l' module ODBC, vos dvoz fé ene copeye di såvrité del båze SQL da vosse sepårumint."}. +{"Please specify file name.","Dinez l' no do fitchî."}. +{"Please specify file size.","Dinez l' grandeu do fitchî."}. +{"Please, wait for a while before sending new voice request","Ratindez ene miete s' i vs plait divant d' rivoyî ene nouve dimande di vwès"}. {"Pong","Pong"}. +{"Port ~b","Pôrt ~b"}. {"Port","Pôrt"}. {"Present real Jabber IDs to","Mostrer les vraiys Jabber IDs a"}. {"private, ","privé, "}. +{"Protocol","Protocole"}. {"Publish-Subscribe","Eplaidaedje-abounmint"}. {"PubSub subscriber request","Dimande d' eplaidaedje-abounmint d' èn abouné"}. +{"Purge all items when the relevant publisher goes offline","Purdjî tos les cayets cwand l' eplaideu aloyî va foû raloyaedje"}. {"Queries to the conference members are not allowed in this room","Les cweraedjes des mimbes del conferince ni sont nén permetous dins cisse såle ci"}. {"RAM and disc copy","Copeye e memwere (RAM) et sol deure plake"}. {"RAM copy","Copeye e memwere (RAM)"}. {"Raw","Dinêyes brutes"}. {"Really delete message of the day?","Voloz vs vormint disfacer l' messaedje do djoû?"}. {"Recipient is not in the conference room","Li riçuveu n' est nén dins l' såle di conferince"}. +{"Register a Jabber account","Edjîstrer on conte Jabber"}. +{"Register","Edjîstrer"}. +{"Registered nicknames","Metous nos edjistrés"}. {"Registered Users:","Uzeus edjistrés:"}. {"Registered Users","Uzeus edjistrés"}. {"Registration in mod_irc for ","Edjîstraedje dins mod_irc po "}. {"Remote copy","Copeye å lon"}. +{"Remove All Offline Messages","Oister tos les messaedjes ki ratindèt"}. {"Remove","Oister"}. {"Remove User","Disfacer l' uzeu"}. {"Replaced by new connection","Replaecî pa on novea raloyaedje"}. @@ -226,8 +309,11 @@ {"Restore binary backup immediately:","Rapexhî do côp foû d' ene copeye di såvrité binaire:"}. {"Restore plain text backup immediately:","Rapexhî do côp foû d' ene copeye di såvrité tecse:"}. {"Restore","Rapexhî"}. +{"Roles for which Presence is Broadcasted","Roles ki leu prezince est difuzêye"}. {"Room Configuration","Apontiaedje del såle"}. {"Room creation is denied by service policy","L' ahivaedje del såle est rfuzé pal politike do siervice"}. +{"Room description","Discrijhaedje del såle"}. +{"Room Occupants","Prezints el såle"}. {"Room title","Tite del såle"}. {"Roster","Djivêye des soçons"}. {"Roster groups allowed to subscribe","Pårtaedjîs groupes di soçons k' on s' î pout abouner"}. @@ -245,6 +331,9 @@ {"Send announcement to all users","Evoyî l' anonce a tos les uzeus"}. {"Send announcement to all users on all hosts","Evoyî l' anonce a tos les uzeus so tos les lodjoes"}. {"September","setimbe"}. +{"Server ~b","Sierveu ~b"}. +{"Server:","Sierveu:"}. +{"Server","Sierveu"}. {"Set message of the day and send to online users","Defini l' messaedje do djoû et l' evoyî åzès uzeus raloyîs"}. {"Set message of the day on all hosts and send to online users","Defini l' messaedje do djoû so tos les lodjoes et l' evoyî åzès uzeus raloyîs"}. {"Shared Roster Groups","Pårtaedjîs groupes ezès djivêyes di soçons"}. @@ -252,7 +341,9 @@ {"Show Ordinary Table","Mostrer crexhince"}. {"Shut Down Service","Arester siervice"}. {"~s invites you to the room ~s","~s vos preye sol såle ~s"}. +{"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","Des cliyints Jabber k' i gn a polèt wårder vosse sicret sol copiutrece, mins vos n' duvrîz fé çoula ki sol copiutrece da vosse, po des råjhons di såvrité."}. {"Specify the access model","Sipecifyî l' modele d' accès"}. +{"Specify the event message type","Sipecifyî l' sôre do messaedje d' evenmint"}. {"Specify the publisher model","Dinez l' modele d' eplaideu"}. {"~s's Offline Messages Queue","messaedjes ki ratindèt el cawêye po ~s"}. {"Start","Enonder"}. @@ -273,27 +364,54 @@ {"Subscriber Address","Adresse di l' abouné"}. {"Subscription","Abounmimnt"}. {"Sunday","dimegne"}. +{"That nickname is already in use by another occupant","Li metou no est ddja eployî pa ene ôte sakî sol såle"}. +{"That nickname is registered by another person","Li metou no est ddja edjîstré pa ene ôte sakî"}. +{"The CAPTCHA is valid.","Li CAPTCHA est valide."}. +{"The CAPTCHA verification has failed","Li verifiaedje CAPTCHA a fwait berwete"}. +{"The collections with which a node is affiliated","Les ramexhnêyes k' on nuk est afiyî avou"}. {"the password is","li scret est"}. +{"The password is too weak","li scret est trop flåw"}. +{"The password of your Jabber account was successfully changed.","Li scret do conte Jabber da vosse a stî candjî comifåt."}. +{"There was an error changing the password: ","Åk n' a nén stî tot candjant l' sicret: "}. +{"There was an error creating the account: ","Åk n' a nén stî tot ahivant l' conte: "}. +{"There was an error deleting the account: ","Åk n' a nén stî tot disfaçant l' conte: "}. +{"This IP address is blacklisted in ~s","Ciste adresse IP est so ene noere djivêye e ~s"}. +{"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","Pont d' diferince etur les grandes et ptitès letes: «macbeth» est l' minme ki «MacBeth» ou co «Macbeth»"}. +{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","Cisse pådje permete d' ahiver on conte Jabber so ç' sierveu Jabber ci. Li JID (IDintifieu Jabber) da vosse serè del cogne: noduzeu@sierveu. Lijhoz atintivmint les instruccions po bén rimpli les tchamps."}. +{"This page allows to unregister a Jabber account in this Jabber server.","Cisse pådje permete di disdjîstrer on conte Jabber so ç' sierveu ci."}. {"Thursday","djudi"}. {"Time","Date"}. {"Time delay","Tårdjaedje"}. +{"Too many CAPTCHA requests","Pår trop di dmandes CAPTCHA"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","I gn a-st avou pår trop (~p) d' otintifiaedjes k' ont fwait berwete vinant di ciste adresse IP la (~s). L' adresse serè disblokêye a ~s UTC"}. +{"Too many unacked stanzas","Pår trop di messaedjes sins acertinaedje di rçuvaedje"}. {"To","Po"}. {"To ~s","Viè ~s"}. +{"Total rooms","Totå di såles"}. {"Traffic rate limit is exceeded","Li limite pol volume di trafik a stî passêye"}. {"Transactions Aborted:","Transaccions arestêyes:"}. {"Transactions Committed:","Transaccions evoyeyes:"}. {"Transactions Logged:","Transaccions wårdêyes e djournå:"}. {"Transactions Restarted:","Transaccions renondêyes:"}. {"Tuesday","mårdi"}. +{"Unable to generate a CAPTCHA","Nén moyén di djenerer on CAPTCHA"}. +{"Unauthorized","Nén otorijhî"}. +{"Unregister a Jabber account","Disdjîstrer on conte Jabber"}. +{"Unregister","Disdjîstrer"}. {"Update message of the day (don't send)","Mete a djoû l' messaedje do djoû (nén l' evoyî)"}. {"Update message of the day on all hosts (don't send)","Mete a djoû l' messaedje do djoû so tos les lodjoes (nén l' evoyî)"}. {"Update","Mete a djoû"}. {"Update plan","Plan d' metaedje a djoû"}. +{"Update ~p","Metaedje a djoû di ~p"}. {"Update script","Sicripe di metaedje a djoû"}. {"Uptime:","Tins dispoy l' enondaedje:"}. {"Use of STARTTLS required","L' eployaedje di STARTTL est oblidjî"}. +{"User JID","JID d' l' uzeu"}. {"User Management","Manaedjaedje des uzeus"}. +{"Username:","No d' uzeu:"}. +{"Users are not allowed to register accounts so quickly","Les noveas uzeus n' si polèt nén edjîstrer si raddimint"}. {"Users Last Activity","Dierinne activité des uzeus"}. +{"User ~s","Uzeu ~s"}. {"Users","Uzeus"}. {"User","Uzeu"}. {"Validate","Valider"}. @@ -301,12 +419,22 @@ {"Virtual Hosts","Forveyous sierveus"}. {"Visitors are not allowed to change their nicknames in this room","Les viziteus èn polèt nén candjî leus metous no po ç' såle ci"}. {"Visitors are not allowed to send messages to all occupants","Les viziteus n' polèt nén evoyî des messaedjes a tos les prezints"}. +{"Visitor","Viziteu"}. +{"Voice request","Dimande di vwès"}. +{"Voice requests are disabled in this conference","Les dmandes di vwès sont dismetowes e cisse conferince ci"}. {"Wednesday","mierkidi"}. {"When to send the last published item","Cwand evoyî l' dierin cayet eplaidî"}. {"Whether to allow subscriptions","Si on permete les abounmints"}. +{"You can later change your password using a Jabber client.","Vos ploz candjî vosse sicret pus tård avou on cliyint Jabber."}. {"You have been banned from this room","Vos avoz stî bani di cisse såle ci"}. {"You must fill in field \"Nickname\" in the form","Vos dvoz rimpli l' tchamp «Metou no» dins l' formiulaire"}. +{"You need a client that supports x:data and CAPTCHA to register","Vos avoz mezåjhe d' on cliyint ki sopoite x:data eyet CAPTCHA po vs edjîstrer"}. +{"You need a client that supports x:data to register the nickname","Vos avoz mezåjhe d' on cliyint ki sopoite x:data po-z edjîstrer l' metou no"}. {"You need an x:data capable client to configure mod_irc settings","Vos avoz mezåjhe d' on cliyint ki sopoite x:data po candjî ls apontiaedjes di mod_irc"}. {"You need an x:data capable client to configure room","I vs fåt on cliyint ki sopoite x:data por vos poleur apontyî l' såle"}. {"You need an x:data capable client to search","Vos avoz mezåjhe d' on cliyint ki sopoite x:data po fé on cweraedje"}. +{"Your active privacy list has denied the routing of this stanza.","Vosse djivêye di privaceye active a rfuzé l' evoyaedje di ç' messaedje ci."}. {"Your contact offline message queue is full. The message has been discarded.","Li cawêye di messaedjes e môde disraloyî di vosse soçon est plinne. Li messaedje a stî tapé å diale."}. +{"Your Jabber account was successfully created.","Li conte Jabber da vosse a stî ahivé comifåt."}. +{"Your Jabber account was successfully deleted.","Li conte Jabber da vosse a stî disfacé comifåt."}. +{"Your messages to ~s are being blocked. To unblock them, visit ~s","Vos messaedjes po ~s sont blokés. Po les disbloker, alez vey ~s"}. diff --git a/priv/msgs/zh.msg b/priv/msgs/zh.msg index 41309b16557..84ac76919e0 100644 --- a/priv/msgs/zh.msg +++ b/priv/msgs/zh.msg @@ -1,4 +1,5 @@ %% -*- coding: latin-1 -*- +{"Accept","接受"}. {"Access Configuration","访问配置"}. {"Access Control List Configuration","访问控制列表(ACL)配置"}. {"Access control lists","访问控制列表(ACL)"}. @@ -7,7 +8,7 @@ {"Access rules","访问规则"}. {"Access Rules","访问规则"}. {"Action on user","对用户的动作"}. -{"Add Jabber ID","添加 Jabber ID"}. +{"Add Jabber ID","添加Jabber ID"}. {"Add New","添加新用户"}. {"Add User","添加用户"}. {"Administration of ","管理"}. @@ -15,7 +16,7 @@ {"Administrator privileges required","需要管理员权限"}. {"A friendly name for the node","该节点的友好名称"}. {"All activity","所有活动"}. -{"Allow this Jabber ID to subscribe to this pubsub node?","允许该 Jabber ID 订阅该 pubsub 节点?"}. +{"Allow this Jabber ID to subscribe to this pubsub node?","允许该Jabber ID订阅该pubsub节点?"}. {"Allow users to change the subject","允许用户更改主题"}. {"Allow users to query other users","允许用户查询其它用户"}. {"Allow users to send invites","允许用户发送邀请"}. @@ -31,6 +32,7 @@ {"April","四月"}. {"August","八月"}. {"Backup Management","备份管理"}. +{"Backup of ~p","~p的备份"}. {"Backup to File at ","备份文件位于"}. {"Backup","备份"}. {"Bad format","格式错误"}. @@ -52,12 +54,13 @@ {"City","城市"}. {"Commands","命令"}. {"Conference room does not exist","会议室不存在"}. -{"Configuration of room ~s","房间 ~s 的配置 "}. +{"Configuration of room ~s","房间~s的配置 "}. {"Configuration","配置"}. {"Connected Resources:","已连接资源:"}. {"Connections parameters","连接参数"}. {"Country","国家"}. -{"CPU Time:","CPU 时间:"}. +{"CPU Time:","CPU时间:"}. +{"Database Tables at ~p","位于~p的数据库表"}. {"Database Tables Configuration at ","数据库表格配置位于"}. {"Database","数据库"}. {"December","十二月"}. @@ -71,42 +74,46 @@ {"Description:","描述:"}. {"Disc only copy","仅磁盘复制"}. {"Displayed Groups:","已显示的组:"}. -{"Don't tell your password to anybody, not even the administrators of the Jabber server.","不要将密码告诉任何人, 就算是 Jabber 服务器的管理员也不可以."}. +{"Don't tell your password to anybody, not even the administrators of the Jabber server.","不要将密码告诉任何人, 就算是Jabber服务器的管理员也不可以."}. {"Dump Backup to Text File at ","转储备份到文本文件于"}. {"Dump to Text File","转储到文本文件"}. {"Edit Properties","编辑属性"}. {"Either approve or decline the voice request.","接受或拒绝声音请求"}. {"ejabberd IRC module","ejabberd IRC 模块"}. {"ejabberd MUC module","ejabberd MUC 模块"}. +{"ejabberd Multicast service","ejabberd多重映射服务"}. {"ejabberd Publish-Subscribe module","ejabberd 发行-订阅模块"}. {"ejabberd SOCKS5 Bytestreams module","ejabberd SOCKS5 字节流模块"}. -{"ejabberd vCard module","ejabberd vCard 模块"}. -{"ejabberd Web Admin","ejabberd 网页管理"}. +{"ejabberd vCard module","ejabberd vCard模块"}. +{"ejabberd Web Admin","ejabberd网页管理"}. {"Elements","元素"}. {"Email","电子邮件"}. +{"Empty Rooms","空房间"}. {"Enable logging","启用服务器端聊天记录"}. -{"Encoding for server ~b","服务器 ~b 的编码"}. +{"Enable message archiving","启用消息归档"}. +{"Encoding for server ~b","服务器~b的编码"}. {"End User Session","结束用户会话"}. {"Enter list of {Module, [Options]}","请输入{模块, [选项]}列表"}. {"Enter nickname you want to register","请输入您想要注册的昵称"}. {"Enter path to backup file","请输入备份文件的路径"}. -{"Enter path to jabberd14 spool dir","请输入 jabberd14 spool 目录的路径"}. +{"Enter path to jabberd14 spool dir","请输入jabberd14 spool目录的路径"}. {"Enter path to jabberd14 spool file","请输入 jabberd14 spool 文件的路径"}. {"Enter path to text file","请输入文本文件的路径"}. {"Enter the text you see","请输入您所看到的文本"}. {"Enter username and encodings you wish to use for connecting to IRC servers. Press 'Next' to get more fields to fill in. Press 'Complete' to save settings.","请输入您想使用的用来连接到 IRC 服务器的用户名和编码. 按 '下一步' 获取更多待填字段. 按 '完成' 保存设置."}. {"Enter username, encodings, ports and passwords you wish to use for connecting to IRC servers","请输入您想使用的用来连接到IRC服务器的用户名, 编码, 端口和密码."}. -{"Erlang Jabber Server","Erlang Jabber 服务器"}. +{"Erlang Jabber Server","Erlang Jabber服务器"}. {"Error","错误"}. {"Example: [{\"irc.lucky.net\", \"koi8-r\", 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}].","例如: [{\"irc.lucky.net\", \"koi8-r\"}, 6667, \"secret\"}, {\"vendetta.fef.net\", \"iso8859-1\", 7000}, {\"irc.sometestserver.net\", \"utf-8\"}]."}. -{"Exclude Jabber IDs from CAPTCHA challenge","从验证码挑战中排除 Jabber ID"}. +{"Exclude Jabber IDs from CAPTCHA challenge","从验证码挑战中排除Jabber ID"}. +{"Export all tables as SQL queries to a file:","将所有表以SQL查询语句导出到文件:"}. {"Export data of all users in the server to PIEFXIS files (XEP-0227):","将服务器上所有用户的数据导出到 PIEFXIS 文件 (XEP-0227):"}. {"Export data of users in a host to PIEFXIS files (XEP-0227):","将某主机的用户数据导出到 PIEFXIS 文件 (XEP-0227):"}. {"Failed to extract JID from your voice request approval","无法从你的声音请求确认信息中提取JID"}. {"Family Name","姓氏"}. {"February","二月"}. -{"Fill in fields to search for any matching Jabber User","填充字段以搜索任何匹配的 Jabber 用户"}. -{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","填充表单以搜索任何匹配的 Jabber 用户(在字段末添加*来匹配子串)"}. +{"Fill in fields to search for any matching Jabber User","填充字段以搜索任何匹配的Jabber用户"}. +{"Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)","填充表单以搜索任何匹配的Jabber用户(在字段末添加*来匹配子串)"}. {"Friday","星期五"}. {"From ~s","来自~s"}. {"From","从"}. @@ -131,35 +138,37 @@ {"Import Directory","导入目录"}. {"Import File","导入文件"}. {"Import user data from jabberd14 spool file:","从 jabberd14 Spool 文件导入用户数据:"}. -{"Import User from File at ","导入用户的文件位于 "}. +{"Import User from File at ","导入用户的文件位于"}. {"Import users data from a PIEFXIS file (XEP-0227):","从 PIEFXIS 文件 (XEP-0227) 导入用户数据:"}. -{"Import users data from jabberd14 spool directory:","从 jabberd14 Spool 目录导入用户数据:"}. -{"Import Users from Dir at ","导入用户的目录位于 "}. +{"Import users data from jabberd14 spool directory:","从jabberd14 Spool目录导入用户数据:"}. +{"Import Users from Dir at ","导入用户的目录位于"}. {"Import Users From jabberd14 Spool Files","从 jabberd14 Spool 文件导入用户"}. {"Improper message type","不恰当的消息类型"}. +{"Incoming s2s Connections:","入站 s2s 连接:"}. {"Incorrect password","密码不正确"}. {"Invalid affiliation: ~s","无效加入: ~s"}. {"Invalid role: ~s","无效角色: ~s"}. -{"IP addresses","IP 地址"}. +{"IP addresses","IP地址"}. {"IP","IP"}. -{"IRC channel (don't put the first #)","IRC 频道 (不要输入第一个#号)"}. -{"IRC server","IRC 服务器"}. -{"IRC settings","IRC 设置"}. -{"IRC Transport","IRC 传输"}. -{"IRC username","IRC 用户名"}. -{"IRC Username","IRC 用户名"}. +{"IRC channel (don't put the first #)","IRC频道 (不要输入第一个#号)"}. +{"IRC server","IRC服务器"}. +{"IRC settings","IRC设置"}. +{"IRC Transport","IRC传输"}. +{"IRC username","IRC用户名"}. +{"IRC Username","IRC用户名"}. {"is now known as","现在称呼为"}. +{"It is not allowed to send error messages to the room. The participant (~s) has sent an error message (~s) and got kicked from the room","不允许将错误消息发送到该房间. 参与者(~s)已发送过一条消息(~s)并已被踢出房间"}. {"It is not allowed to send private messages of type \"groupchat\"","\"群组聊天\"类型不允许发送私聊消息"}. {"It is not allowed to send private messages to the conference","不允许向会议发送私聊消息"}. {"It is not allowed to send private messages","不可以发送私聊消息"}. -{"Jabber Account Registration","Jabber 帐户注册"}. +{"Jabber Account Registration","Jabber帐户注册"}. {"Jabber ID","Jabber ID"}. {"Jabber ID ~s is invalid","Jabber ID ~s 无效"}. {"January","一月"}. -{"Join IRC channel","加入 IRC 频道"}. +{"Join IRC channel","加入IRC频道"}. {"joins the room","加入房间"}. -{"Join the IRC channel here.","在这里加入 IRC 频道."}. -{"Join the IRC channel in this Jabber ID: ~s","用此 Jabber ID: ~s 加入 IRC 频道"}. +{"Join the IRC channel here.","在这里加入IRC频道."}. +{"Join the IRC channel in this Jabber ID: ~s","用此Jabber ID ~s加入IRC频道"}. {"July","七月"}. {"June","六月"}. {"Last Activity","上次活动"}. @@ -167,9 +176,10 @@ {"Last month","上个月"}. {"Last year","上一年"}. {"leaves the room","离开房间"}. -{"Listened Ports at ","监听的端口位于 "}. +{"Listened Ports at ","监听的端口位于"}. {"Listened Ports","被监听的端口"}. {"List of modules to start","要启动的模块列表"}. +{"List of rooms","房间列表"}. {"Low level update script","低级别更新脚本"}. {"Make participants list public","公开参与人列表"}. {"Make room CAPTCHA protected","保护房间验证码"}. @@ -185,29 +195,34 @@ {"May","五月"}. {"Membership is required to enter this room","进入此房间需要会员身份"}. {"Members:","会员:"}. -{"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","记住你的密码, 或将其记到纸上并放于安全位置. 如果你忘记了密码, Jabber 也没有自动恢复密码的方式."}. +{"Memorize your password, or write it in a paper placed in a safe place. In Jabber there isn't an automated way to recover your password if you forget it.","记住你的密码, 或将其记到纸上并放于安全位置. 如果你忘记了密码, Jabber也没有自动恢复密码的方式."}. {"Memory","内存"}. {"Message body","消息主体"}. {"Middle Name","中间名"}. {"Minimum interval between voice requests (in seconds)","声音请求的最小间隔(以秒为单位)"}. {"Moderator privileges required","需要主持人权限"}. {"moderators only","仅主持人"}. +{"Moderator","主持人"}. {"Modified modules","被修改模块"}. +{"Modules at ~p","位于~p的模块"}. {"Modules","模块"}. {"Module","模块"}. {"Monday","星期一"}. +{"Multicast","多重映射"}. +{"Multi-User Chat","多用户聊天"}. {"Name:","姓名:"}. {"Name","姓名"}. {"Never","从未"}. -{"New Password:","新密码: "}. -{"Nickname Registration at ","昵称注册于 "}. -{"Nickname ~s does not exist in the room","昵称 ~s 不在该房间"}. +{"New Password:","新密码:"}. +{"Nickname Registration at ","昵称注册于"}. +{"Nickname ~s does not exist in the room","昵称~s不在该房间"}. {"Nickname","昵称"}. {"No body provided for announce message","通知消息无正文内容"}. {"nobody","没有人"}. {"No Data","没有数据"}. -{"Node ID","节点 ID"}. +{"Node ID","节点ID"}. {"Node not found","没有找到节点"}. +{"Node ~p","节点~p"}. {"Nodes","节点"}. {"No limit","不限"}. {"None","无"}. @@ -229,6 +244,7 @@ {"Online Users","在线用户"}. {"Online","在线"}. {"Only deliver notifications to available users","仅将通知发送给可发送的用户"}. +{"Only members may query archives of this room","只有会员可以查询本房间的存档"}. {"Only moderators and participants are allowed to change the subject in this room","只有主持人和参与人可以在此房间里更改主题"}. {"Only moderators are allowed to change the subject in this room","只有主持人可以在此房间里更改主题"}. {"Only moderators can approve voice requests","仅主持人能确认声音请求"}. @@ -242,7 +258,8 @@ {"Outgoing s2s Connections","出站 s2s 连接"}. {"Owner privileges required","需要持有人权限"}. {"Packet","数据包"}. -{"Password ~b","~b 的密码"}. +{"Participant","参与人"}. +{"Password ~b","~b的密码"}. {"Password Verification:","密码确认:"}. {"Password Verification","确认密码"}. {"Password:","密码:"}. @@ -251,18 +268,21 @@ {"Path to File","文件路径"}. {"Pending","挂起"}. {"Period: ","持续时间: "}. +{"Permanent rooms","永久房间"}. {"Persist items to storage","持久化内容条目"}. {"Ping","Ping"}. {"Please note that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately.","注意:这些选项仅将备份内置的 Mnesia 数据库. 如果您正在使用 ODBC 模块, 您还需要分别备份您的数据库."}. +{"Please specify file name.","请指定文件名称."}. +{"Please specify file size.","请指定文件大小."}. {"Please, wait for a while before sending new voice request","请稍后再发送新的声音请求"}. {"Pong","Pong"}. -{"Port ~b","~b 的端口"}. +{"Port ~b","~b的端口"}. {"Port","端口"}. -{"Present real Jabber IDs to","将真实 Jabber ID 显示给"}. +{"Present real Jabber IDs to","将真实Jabber ID显示给"}. {"private, ","保密, "}. {"Protocol","协议"}. {"Publish-Subscribe","发行-订阅"}. -{"PubSub subscriber request","PubSub 订阅人请求"}. +{"PubSub subscriber request","PubSub订阅人请求"}. {"Purge all items when the relevant publisher goes offline","相关发布人离线后清除所有选项"}. {"Queries to the conference members are not allowed in this room","本房间不可以查询会议成员信息"}. {"RAM and disc copy","内存与磁盘复制"}. @@ -270,7 +290,8 @@ {"Raw","原始格式"}. {"Really delete message of the day?","确实要删除每日消息吗?"}. {"Recipient is not in the conference room","接收人不在会议室"}. -{"Register a Jabber account","注册 Jabber 帐户"}. +{"Register a Jabber account","注册Jabber帐户"}. +{"Registered nicknames","注册的昵称"}. {"Registered Users:","注册用户:"}. {"Registered Users","注册用户"}. {"Register","注册"}. @@ -288,45 +309,47 @@ {"Restore binary backup immediately:","立即恢复二进制备份:"}. {"Restore plain text backup immediately:","立即恢复普通文本备份:"}. {"Restore","恢复"}. +{"Roles for which Presence is Broadcasted","广播存在性的角色"}. {"Room Configuration","房间配置"}. {"Room creation is denied by service policy","创建房间被服务策略拒绝"}. {"Room description","房间描述"}. {"Room Occupants","房间人数"}. {"Room title","房间标题"}. {"Roster groups allowed to subscribe","允许订阅的花名册组"}. -{"Roster of ","花名册属于 "}. +{"Roster of ","花名册属于"}. {"Roster size","花名册大小"}. {"Roster","花名册"}. {"RPC Call Error","RPC 调用错误"}. {"Running Nodes","运行中的节点"}. -{"~s access rule configuration","~s 访问规则配置"}. +{"~s access rule configuration","~s访问规则配置"}. {"Saturday","星期六"}. {"Script check","脚本检查"}. {"Search Results for ","搜索结果属于关键词 "}. -{"Search users in ","搜索用户于 "}. +{"Search users in ","搜索用户于"}. {"Send announcement to all online users on all hosts","发送通知给所有主机的在线用户"}. {"Send announcement to all online users","发送通知给所有在线用户"}. {"Send announcement to all users on all hosts","发送通知给所有主机上的所有用户"}. {"Send announcement to all users","发送通知给所有用户"}. {"September","九月"}. -{"Server ~b","服务器 ~b"}. +{"Server ~b","服务器~b"}. {"Server:","服务器:"}. +{"Server","服务器"}. {"Set message of the day and send to online users","设定每日消息并发送给所有在线用户"}. {"Set message of the day on all hosts and send to online users","设置所有主机上的每日消息并发送给在线用户"}. {"Shared Roster Groups","共享的花名册组群"}. {"Show Integral Table","显示完整列表"}. {"Show Ordinary Table","显示普通列表"}. {"Shut Down Service","关闭服务"}. -{"~s invites you to the room ~s","~s 邀请你到 ~s 房间"}. +{"~s invites you to the room ~s","~s邀请你到房间~s"}. {"Some Jabber clients can store your password in the computer, but you should do this only in your personal computer for safety reasons.","某些 Jabber 客户端可以在你的计算机里存储密码. 请仅在你确认你的计算机安全的情况下使用该功能."}. {"Specify the access model","指定访问范例"}. {"Specify the event message type","指定事件消息类型"}. {"Specify the publisher model","指定发布人范例"}. -{"~s's Offline Messages Queue","~s 的离线消息队列"}. +{"~s's Offline Messages Queue","~s的离线消息队列"}. {"Start Modules at ","要启动的模块位于 "}. {"Start Modules","启动模块"}. {"Start","开始"}. -{"Statistics of ~p","~p 的统计"}. +{"Statistics of ~p","~p的统计"}. {"Statistics","统计"}. {"Stop Modules at ","要停止的模块位于 "}. {"Stop Modules","停止模块"}. @@ -348,18 +371,22 @@ {"The collections with which a node is affiliated","加入结点的集合"}. {"The password is too weak","密码强度太弱"}. {"the password is","密码是"}. -{"The password of your Jabber account was successfully changed.","你的 Jabber 帐户密码已成功更新."}. +{"The password of your Jabber account was successfully changed.","你的Jabber帐户密码已成功更新."}. {"There was an error changing the password: ","修改密码出错: "}. {"There was an error creating the account: ","帐户创建出错: "}. {"There was an error deleting the account: ","帐户删除失败: "}. +{"This IP address is blacklisted in ~s","此IP地址在~s中已被列入黑名单"}. {"This is case insensitive: macbeth is the same that MacBeth and Macbeth.","此处不区分大小写: macbeth 与 MacBeth 和 Macbeth 是一样的."}. -{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","本页面允许在此服务器上创建 Jabber 帐户. 你的 JID (Jabber ID) 的形式如下: 用户名@服务器. 请仔细阅读说明并正确填写相应字段."}. -{"This page allows to unregister a Jabber account in this Jabber server.","此页面允许在此 Jabber 服务器上注销 Jabber 帐户"}. +{"This page allows to create a Jabber account in this Jabber server. Your JID (Jabber IDentifier) will be of the form: username@server. Please read carefully the instructions to fill correctly the fields.","本页面允许在此服务器上创建Jabber帐户. 你的JID (Jabber ID) 的形式如下: 用户名@服务器. 请仔细阅读说明并正确填写相应字段."}. +{"This page allows to unregister a Jabber account in this Jabber server.","此页面允许在此Jabber服务器上注销Jabber帐户"}. {"Thursday","星期四"}. {"Time delay","时间延迟"}. {"Time","时间"}. {"Too many CAPTCHA requests","验证码请求太多"}. +{"Too many (~p) failed authentications from this IP address (~s). The address will be unblocked at ~s UTC","来自IP地址(~p)的(~s)失败认证太多. 该地址将在UTC时间~s被禁用."}. +{"Too many unacked stanzas","未被确认的节太多"}. {"To ~s","发送给~s"}. +{"Total rooms","所有房间"}. {"To","到"}. {"Traffic rate limit is exceeded","已经超过传输率限制"}. {"Transactions Aborted:","取消的事务:"}. @@ -369,42 +396,45 @@ {"Tuesday","星期二"}. {"Unable to generate a CAPTCHA","无法生成验证码"}. {"Unauthorized","未认证的"}. -{"Unregister a Jabber account","注销 Jabber 帐户"}. +{"Unregister a Jabber account","注销Jabber帐户"}. {"Unregister","取消注册"}. {"Update message of the day (don't send)","更新每日消息(不发送)"}. {"Update message of the day on all hosts (don't send)","更新所有主机上的每日消息(不发送)"}. {"Update plan","更新计划"}. +{"Update ~p","更新~p"}. {"Update script","更新脚本"}. {"Update","更新"}. {"Uptime:","正常运行时间:"}. {"Use of STARTTLS required","要求使用 STARTTLS"}. -{"User JID","用户 JID"}. +{"User JID","用户JID"}. {"User Management","用户管理"}. {"Username:","用户名:"}. {"Users are not allowed to register accounts so quickly","不允许用户太频繁地注册帐户"}. {"Users Last Activity","用户上次活动"}. {"Users","用户"}. +{"User ~s","用户~s"}. {"User","用户"}. {"Validate","确认"}. -{"vCard User Search","vCard 用户搜索"}. +{"vCard User Search","vCard用户搜索"}. {"Virtual Hosts","虚拟主机"}. {"Visitors are not allowed to change their nicknames in this room","此房间不允许用户更改昵称"}. {"Visitors are not allowed to send messages to all occupants","不允许访客给所有占有者发送消息"}. +{"Visitor","访客"}. {"Voice requests are disabled in this conference","该会议的声音请求以被禁用"}. {"Voice request","声音请求"}. {"Wednesday","星期三"}. {"When to send the last published item","何时发送最新发布的内容条目"}. {"Whether to allow subscriptions","是否允许订阅"}. -{"You can later change your password using a Jabber client.","你可以稍后用 Jabber 客户端修改你的密码."}. +{"You can later change your password using a Jabber client.","你可以稍后用Jabber客户端修改你的密码."}. {"You have been banned from this room","您已被禁止进入该房间"}. {"You must fill in field \"Nickname\" in the form","您必须填充表单中\"昵称\"项"}. {"You need a client that supports x:data and CAPTCHA to register","您需要一个支持 x:data 和验证码的客户端进行注册"}. {"You need a client that supports x:data to register the nickname","您需要一个支持 x:data 的客户端来注册昵称"}. -{"You need an x:data capable client to configure mod_irc settings","您需要一个兼容 x:data 的客户端来配置 mod_irc 设置"}. +{"You need an x:data capable client to configure mod_irc settings","您需要一个兼容 x:data 的客户端来配置mod_irc设置"}. {"You need an x:data capable client to configure room","您需要一个兼容 x:data 的客户端来配置房间"}. {"You need an x:data capable client to search","您需要一个兼容 x:data 的客户端来搜索"}. {"Your active privacy list has denied the routing of this stanza.","你的活跃私聊列表拒绝了在此房间进行路由分发."}. {"Your contact offline message queue is full. The message has been discarded.","您的联系人离线消息队列已满. 消息已被丢弃"}. -{"Your Jabber account was successfully created.","你的 Jabber 帐户已成功创建."}. +{"Your Jabber account was successfully created.","你的Jabber帐户已成功创建."}. {"Your Jabber account was successfully deleted.","你的 Jabber 帐户已成功删除."}. -{"Your messages to ~s are being blocked. To unblock them, visit ~s","您发送给 ~s 的消息已被阻止. 要解除阻止, 请访问 ~s"}. +{"Your messages to ~s are being blocked. To unblock them, visit ~s","您发送给~s的消息已被阻止. 要解除阻止, 请访问 ~s"}. From a9de13c5d91b7aefe9d1346756e82dde90cb6eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 18 Feb 2016 16:42:57 +0100 Subject: [PATCH 594/695] Don't include empty line after java example --- src/ejabberd_commands_doc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_commands_doc.erl b/src/ejabberd_commands_doc.erl index df4ba9df938..dc00c5d2aef 100644 --- a/src/ejabberd_commands_doc.erl +++ b/src/ejabberd_commands_doc.erl @@ -158,7 +158,7 @@ java_call(Name, ArgsDesc, Values, HTMLOutput) -> Indent, ?ID_L("client"), ?OP_L("."), ?ID_L("setConfig"), ?OP_L("("), ?ID_L("config"), ?OP_L(");"), ?BR, Indent, ?BR, Indent, ?ID_L("client"), ?OP_L("."), ?ID_L("execute"), ?OP_L("("), ?STR_A(Name), ?OP_L(", "), java_gen_map(lists:map(fun({A,B})->java_gen(A, B, Indent, HTMLOutput) end, lists:zip(ArgsDesc, Values)), Indent, HTMLOutput), - ?OP_L(");"), ?BR]. + ?OP_L(");")]. -define(XML_S(N, V), ?OP_L("<"), ?FIELD_L(??N), ?OP_L(">"), V). -define(XML_E(N), ?OP_L("")). From d9ec9233576c3e2dfaace5efedecc8fa59f9bc8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 25 Feb 2016 12:16:47 +0100 Subject: [PATCH 595/695] Elixir want {src_dirs, ["include"]} on top of a config --- rebar.config | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 19122c308f7..2414253bbad 100644 --- a/rebar.config +++ b/rebar.config @@ -66,7 +66,10 @@ {if_var_true, elixir, rebar_elixir_compiler}, {if_var_true, elixir, rebar_exunit}]}. -{lib_dirs, [{if_var_true, elixir, "deps/elixir/lib"}]}. +{if_var_true, elixir, + {lib_dirs, ["deps/elixir/lib"]}}. +{if_var_true, elixir, + {src_dirs, ["include"]}}. {sub_dirs, ["rel"]}. From 24617b5e2594383a498f009aa42ba3bd4c60ca65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 25 Feb 2016 12:19:00 +0100 Subject: [PATCH 596/695] Split long lines --- rebar.config | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/rebar.config b/rebar.config index 2414253bbad..12b03ffefdb 100644 --- a/rebar.config +++ b/rebar.config @@ -19,20 +19,33 @@ {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.7"}}}, {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2.git", {tag, "0.6.1"}}}, {p1_xmlrpc, ".*", {git, "https://github.com/processone/p1_xmlrpc", {tag, "1.15.1"}}}, - {luerl, ".*", {git, "https://github.com/rvirding/luerl", "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, - {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.1"}}}}, - {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.0.1"}}}}, - {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.5"}}}}, - {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.0"}}}}, - {if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib", {tag, "1.0.1"}}}}, - {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 - {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, - {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.1.0"}}}}, + {luerl, ".*", {git, "https://github.com/rvirding/luerl", + "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, + {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", + {tag, "1.0.1"}}}}, + {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", + {tag, "1.0.1"}}}}, + {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", + {tag, "1.1.5"}}}}, + {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", + {tag, "1.0.0"}}}}, + {if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib", + {tag, "1.0.1"}}}}, + {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", + "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 + {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", + "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, + {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", + {tag, "v1.1.0"}}}}, %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin - {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, - {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv", {tag, "1.0.0"}}}}, - {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", {tag, "0.8.2"}}}}, - {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", {tag, "v1.0.8"}}}}]}. + {if_var_true, elixir, {rebar_elixir_plugin, ".*", + {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, + {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv", + {tag, "1.0.0"}}}}, + {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", + {tag, "0.8.2"}}}}, + {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", + {tag, "v1.0.8"}}}}]}. {if_var_true, latest_deps, {floating_deps, [cache_tab, From 217ba0940846a7b78841f28220e3ccca89d0a3df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 29 Jan 2016 11:22:20 +0100 Subject: [PATCH 597/695] Add extra items to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index b4950e01ef8..bf5fe286359 100644 --- a/.gitignore +++ b/.gitignore @@ -39,8 +39,10 @@ XmppAddr.hrl /vars.config /dialyzer/ /test/*.beam +/test/*.ctc /logs/ /priv/sql /rel/ejabberd /_build /mnesiadb +/.rebar From ebaf750a9b80722e6f3425463babf97dcf44acc1 Mon Sep 17 00:00:00 2001 From: Marek Foss Date: Thu, 25 Feb 2016 18:56:43 +0100 Subject: [PATCH 598/695] Fix for #935 --- src/ejabberd_web_admin.erl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index 1b60f826775..d69b2a6c15b 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -383,6 +383,9 @@ css(Host) -> " background: #f9f9f9;\n" " font-family: sans-serif;\n" "}\n" + "body {\n" + " min-width: 990px;\n" + "}\n" "a {\n" " text-decoration: none;\n" " color: #3eaffa;\n" @@ -461,13 +464,15 @@ css(Host) -> " font-size: 0.75em;\n" " text-align: center;\n" "}\n" + "#navigation {\n" + " display: inline-block;\n" + " vertical-align: top;\n" + " width: 30%;\n" + "}\n" "#navigation ul {\n" - " position: absolute;\n" - " top: 75px;\n" - " left: 0;\n" " padding: 0;\n" " margin: 0;\n" - " width: 17em;\n" + " width: 90%;\n" " background: #fff;\n" "}\n" "#navigation ul li {\n" @@ -595,8 +600,10 @@ css(Host) -> " list-style-type: none;\n" "}\n" "#content {\n" - " padding-left: 19em;\n" + " display: inline-block;\n" + " vertical-align: top;\n" " padding-top: 25px;\n" + " width: 70%;\n" "}\n" "div.guidelink,\n" "p[dir=ltr] {\n" From 1c6d20924b27a3bb2544ef6fd57e1b7dea356aa5 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 26 Feb 2016 09:33:07 +0100 Subject: [PATCH 599/695] Fix host/serverhost usage (#902) --- src/mod_pubsub.erl | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 03f3131e5db..33016c46dfe 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -482,7 +482,7 @@ send_loop(State) -> -> [xmlel()] ). disco_local_identity(Acc, _From, To, <<>>, _Lang) -> - case lists:member(?PEPNODE, plugins(To#jid.lserver)) of + case lists:member(?PEPNODE, plugins(host(To#jid.lserver))) of true -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"pubsub">>}, @@ -1236,7 +1236,7 @@ iq_get_vcard(Lang) -> ). iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang) -> - iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(ServerHost)). + iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, all, plugins(Host)). -spec(iq_pubsub/8 :: ( @@ -3997,16 +3997,11 @@ get_cached_item(Host, Nidx) -> host(ServerHost) -> config(ServerHost, host, <<"pubsub.", ServerHost/binary>>). -serverhost({_U, Server, _R})-> - Server; +serverhost({_U, ServerHost, _R})-> + ServerHost; serverhost(Host) -> - case binary:match(Host, <<"pubsub.">>) of - {0,7} -> - [_,ServerHost] = binary:split(Host, <<".">>), - ServerHost; - _ -> - Host - end. + [_, ServerHost] = binary:split(Host, <<".">>), + ServerHost. tree(Host) -> case config(serverhost(Host), nodetree) of @@ -4062,14 +4057,14 @@ select_type(ServerHost, Host, Node, Type) -> _ -> Type end, - ConfiguredTypes = plugins(ServerHost), + ConfiguredTypes = plugins(Host), case lists:member(SelectedType, ConfiguredTypes) of true -> SelectedType; false -> hd(ConfiguredTypes) end. select_type(ServerHost, Host, Node) -> - select_type(ServerHost, Host, Node, hd(plugins(ServerHost))). + select_type(ServerHost, Host, Node, hd(plugins(Host))). feature(<<"rsm">>) -> ?NS_RSM; feature(Feature) -> <<(?NS_PUBSUB)/binary, "#", Feature/binary>>. From 56523784e1824af2b149cdb65f756c5b6fd79866 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 26 Feb 2016 10:32:03 +0100 Subject: [PATCH 600/695] Implementation of pubsub#itemreply (EJAB-1347)(#928) --- src/mod_pubsub.erl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 33016c46dfe..7fb0fa6db26 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3292,9 +3292,14 @@ broadcast_publish_item(Host, Node, Nidx, Type, NodeOptions, ItemId, From, Payloa true -> Payload; false -> [] end, + Attrs = case get_option(NodeOptions, itemreply, none) of + owner -> itemAttr(ItemId); %% owner not supported + publisher -> itemAttr(ItemId, {<<"publisher">>, jid:to_string(From)}); + none -> itemAttr(ItemId) + end, Stanza = event_stanza( [#xmlel{name = <<"items">>, attrs = nodeAttr(Node), - children = [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), + children = [#xmlel{name = <<"item">>, attrs = Attrs, children = Content}]}]), broadcast_stanza(Host, From, Node, Nidx, Type, NodeOptions, SubsByDepth, items, Stanza, true), @@ -3775,7 +3780,9 @@ get_configure_xfields(_Type, Options, Lang, Groups) -> ?BOOL_CONFIG_FIELD(<<"Only deliver notifications to available users">>, presence_based_delivery), ?NLIST_CONFIG_FIELD(<<"The collections with which a node is affiliated">>, - collection)]. + collection), + ?ALIST_CONFIG_FIELD(<<"Whether owners or publisher should receive replies to items">>, + itemreply, [none, owner, publisher])]. %%

    There are several reasons why the node configuration request might fail:

    %%
      @@ -3929,6 +3936,8 @@ set_xoption(Host, [{<<"pubsub#collection">>, Value} | Opts], NewOpts) -> set_xoption(Host, [{<<"pubsub#node">>, [Value]} | Opts], NewOpts) -> % NewValue = string_to_node(Value), ?SET_LIST_XOPT(node, Value); +set_xoption(Host, [{<<"pubsub#itemreply">>, [Val]} | Opts], NewOpts) -> + ?SET_ALIST_XOPT(itemreply, Val, [none, owner, publisher]); set_xoption(Host, [_ | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts). @@ -4266,6 +4275,7 @@ nodeAttr(Node) -> [{<<"node">>, Node}]. itemAttr([]) -> []; itemAttr(ItemId) -> [{<<"id">>, ItemId}]. +itemAttr(ItemId, From) -> [{<<"id">>, ItemId}, From]. itemsEls(Items) -> [#xmlel{name = <<"item">>, attrs = itemAttr(ItemId), children = Payload} From 6b126171da22dbf8b49fd10ac4248be588a4d0f2 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Fri, 26 Feb 2016 17:27:12 +0300 Subject: [PATCH 601/695] Improve LDAP shared roster support (EJAB-1480) --- src/mod_shared_roster_ldap.erl | 1043 ++++++++++++++++++++------------ 1 file changed, 667 insertions(+), 376 deletions(-) diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index a4ac65c10e0..3275394be60 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -3,6 +3,7 @@ %%% Author : Realloc %%% Marcin Owsiany %%% Evgeniy Khramtsov +%%% Contributor : Mike Kaganski %%% Description : LDAP shared roster management %%% Created : 5 Mar 2005 by Alexey Shchepin %%% @@ -26,8 +27,6 @@ %%%------------------------------------------------------------------- -module(mod_shared_roster_ldap). --behaviour(ejabberd_config). - -behaviour(gen_server). -behaviour(gen_mod). @@ -44,19 +43,15 @@ out_subscription/4, mod_opt_type/1, opt_type/1]). -include("ejabberd.hrl"). --include("logger.hrl"). -include("jlib.hrl"). -include("mod_roster.hrl"). - -include("eldap.hrl"). +-define(ERROR_MSG(Fmt, Args), error_logger:error_msg(Fmt, Args)). --define(CACHE_SIZE, 1000). - --define(USER_CACHE_VALIDITY, 300). - --define(GROUP_CACHE_VALIDITY, 300). - --define(LDAP_SEARCH_TIMEOUT, 5). +-define(CACHE_SIZE, 1). +-define(CACHE_VALIDITY, 300). %% in seconds +-define(LDAP_SEARCH_TIMEOUT, 5). %% Timeout for LDAP search queries in seconds +-define(INVALID_SETTING_MSG, "~s is not properly set! ~s will not function."). -record(state, {host = <<"">> :: binary(), @@ -74,7 +69,6 @@ group_attr = <<"">> :: binary(), group_desc = <<"">> :: binary(), user_desc = <<"">> :: binary(), - user_uid = <<"">> :: binary(), uid_format = <<"">> :: binary(), uid_format_re = <<"">> :: binary(), filter = <<"">> :: binary(), @@ -82,25 +76,51 @@ rfilter = <<"">> :: binary(), gfilter = <<"">> :: binary(), auth_check = true :: boolean(), - user_cache_size = ?CACHE_SIZE :: non_neg_integer(), - group_cache_size = ?CACHE_SIZE :: non_neg_integer(), - user_cache_validity = ?USER_CACHE_VALIDITY :: non_neg_integer(), - group_cache_validity = ?GROUP_CACHE_VALIDITY :: non_neg_integer()}). - + %% Group data parameters + group_base = <<"">> :: binary(), + %% - Subgroup of roster filter + %% This filter defines which groups are displayed in the shared roster + %% Valid values are 'all' or "LDAP filter string" or "LDAP filter string containing %g" + shgfilter = <<"">> :: binary(), + shg_attr = <<"">> :: binary(), + %% - Subgroup of group filter + group_is_dn = true :: boolean(), + member_attr = <<"">> :: binary(), + %% User data parameters + member_selection_mode = memberattr_dn :: memberattr_normal | memberattr_dn | + group_children, + %% Algorithm control parameters + subscribe_all = false :: binary(), + roster_cache_size = ?CACHE_SIZE :: non_neg_integer(), + roster_cache_validity = ?CACHE_VALIDITY :: non_neg_integer()}). + +%% If #state.member_selection_mode is memberattr_normal or memberattr_dn, +%% then members is list of member_attr values; +%% if #state.member_selection_mode is group_children, +%% then members is dn of the group (to make it possible to search for its subtree) -record(group_info, {desc, members}). +-record(user_info, {us, name}). + +-record(shared_roster_item, {us, name, groups}). + +% Groups visible to this group +% grp may be atom 'all' or a group name string. +% shgrps is a list containing one or more grp +-record(shg_data, {grp, shgrps}). + %%==================================================================== %% API %%==================================================================== start_link(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), gen_server:start_link({local, Proc}, ?MODULE, - [Host, Opts], []). + [Host, Opts], []). start(Host, Opts) -> Proc = gen_mod:get_module_proc(Host, ?MODULE), ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, - permanent, 1000, worker, [?MODULE]}, + permanent, 1000, worker, [?MODULE]}, supervisor:start_child(ejabberd_sup, ChildSpec). stop(Host) -> @@ -112,109 +132,92 @@ stop(Host) -> %% Hooks %%-------------------------------------------------------------------- get_user_roster(Items, {U, S} = US) -> - SRUsers = get_user_to_groups_map(US, true), - {NewItems1, SRUsersRest} = lists:mapfoldl(fun (Item, - SRUsers1) -> - {_, _, {U1, S1, _}} = - Item#roster.usj, - US1 = {U1, S1}, - case dict:find(US1, - SRUsers1) - of - {ok, _GroupNames} -> - {Item#roster{subscription - = - both, - ask = - none}, - dict:erase(US1, - SRUsers1)}; - error -> - {Item, SRUsers1} - end - end, - SRUsers, Items), + {ok, State} = eldap_utils:get_state(S, ?MODULE), + SRUsers = get_shared_roster(State, US), + %%?ERROR_MSG("XXXXXX get_user_roster: SRUsers=~p", [SRUsers]), + %% If partially subscribed users are also in shared roster, + %% show them as totally subscribed: + {NewItems1, SRUsersRest} = lists:mapfoldl( + fun(Item, SRUsers1) -> + {_, _, {U1, S1, _}} = Item#roster.usj, + US1 = {U1, S1}, + case lists:keytake(US1, #shared_roster_item.us, SRUsers1) of + %%case dict:find(US1, SRUsers1) of + {value, _, SRUsers2} -> {Item#roster{subscription = both, ask = none}, SRUsers2}; + %%{ok, _GroupNames} -> {Item#roster{subscription = both, ask = none}, dict:erase(US1, SRUsers1)}; + error -> {Item, SRUsers1} + end + end, + SRUsers, Items), + %% Export items in roster format: SRItems = [#roster{usj = {U, S, {U1, S1, <<"">>}}, - us = US, jid = {U1, S1, <<"">>}, - name = get_user_name(U1, S1), subscription = both, - ask = none, groups = GroupNames} - || {{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)], + us = US, + jid = {U1, S1, <<"">>}, + name = Name, + subscription = both, + ask = none, + groups = Groups} || + #shared_roster_item{us = {U1, S1}, name = Name, groups = Groups} <- SRUsersRest], + %% SRItems = [#roster{usj = {U, S, {U1, S1, <<"">>}}, + %% us = US, jid = {U1, S1, <<"">>}, + %% name = get_user_name(U1, S1), subscription = both, + %% ask = none, groups = GroupNames} + %% || {{U1, S1}, GroupNames} <- dict:to_list(SRUsersRest)], SRItems ++ NewItems1. %% This function in use to rewrite the roster entries when moving or renaming %% them in the user contact list. process_item(RosterItem, _Host) -> - USFrom = RosterItem#roster.us, - {User, Server, _Resource} = RosterItem#roster.jid, - USTo = {User, Server}, - Map = get_user_to_groups_map(USFrom, false), - case dict:find(USTo, Map) of - error -> RosterItem; - {ok, []} -> RosterItem; - {ok, GroupNames} - when RosterItem#roster.subscription == remove -> - RosterItem#roster{subscription = both, ask = none, - groups = GroupNames}; - _ -> RosterItem#roster{subscription = both, ask = none} + {ok, State} = eldap_utils:get_state(_Host, ?MODULE), + {User,Server,_Resource} = RosterItem#roster.jid, + USTo = {User,Server}, + SR = get_shared_roster(State, RosterItem#roster.us), + case lists:keysearch(USTo, #shared_roster_item.us, SR) of + false -> + RosterItem; + {value, #shared_roster_item{groups = Groups}} when RosterItem#roster.subscription == remove -> + %% Roster item cannot be removed: + %% We simply reset the original groups: + RosterItem#roster{subscription = both, ask = none, + groups=Groups}; + _ -> + RosterItem#roster{subscription = both, ask = none} end. get_subscription_lists({F, T}, User, Server) -> - LUser = jid:nodeprep(User), - LServer = jid:nameprep(Server), - US = {LUser, LServer}, - DisplayedGroups = get_user_displayed_groups(US), - SRUsers = lists:usort(lists:flatmap(fun (Group) -> - get_group_users(LServer, Group) - end, - DisplayedGroups)), - SRJIDs = [{U1, S1, <<"">>} || {U1, S1} <- SRUsers], + U = jlib:nodeprep(User), + S = jlib:nameprep(Server), + {ok, State} = eldap_utils:get_state(S, ?MODULE), + SRJIDs = get_presense_subscribers(State, {U, S}), +%?INFO_MSG("SRJIDs: ~p", [SRJIDs]), {lists:usort(SRJIDs ++ F), lists:usort(SRJIDs ++ T)}. -get_jid_info({Subscription, Groups}, User, Server, - JID) -> - LUser = jid:nodeprep(User), - LServer = jid:nameprep(Server), - US = {LUser, LServer}, - {U1, S1, _} = jid:tolower(JID), +get_jid_info({Subscription, Groups}, User, Server, JID) -> + {ok, State} = eldap_utils:get_state(Server, ?MODULE), + {U1, S1, _} = jlib:jid_tolower(JID), US1 = {U1, S1}, - SRUsers = get_user_to_groups_map(US, false), - case dict:find(US1, SRUsers) of - {ok, GroupNames} -> - NewGroups = if Groups == [] -> GroupNames; - true -> Groups - end, - {both, NewGroups}; - error -> {Subscription, Groups} + SR = get_shared_roster(State, {User, Server}), + case lists:keysearch(US1, #shared_roster_item.us, SR) of + false -> {Subscription, Groups}; + {value, #shared_roster_item{groups = GroupNames}} when Groups == [] -> {both, GroupNames}; + _ -> {both, Groups} end. -in_subscription(Acc, User, Server, JID, Type, - _Reason) -> +in_subscription(Acc, User, Server, JID, Type, _Reason) -> process_subscription(in, User, Server, JID, Type, Acc). out_subscription(User, Server, JID, Type) -> - process_subscription(out, User, Server, JID, Type, - false). - -process_subscription(Direction, User, Server, JID, - _Type, Acc) -> - LUser = jid:nodeprep(User), - LServer = jid:nameprep(Server), - US = {LUser, LServer}, - {U1, S1, _} = - jid:tolower(jid:remove_resource(JID)), + process_subscription(out, User, Server, JID, Type, false). + +process_subscription(Direction, User, Server, JID, _Type, Acc) -> + {ok, State} = eldap_utils:get_state(Server, ?MODULE), + {U1, S1, _} = jlib:jid_tolower(JID), US1 = {U1, S1}, - DisplayedGroups = get_user_displayed_groups(US), - SRUsers = lists:usort(lists:flatmap(fun (Group) -> - get_group_users(LServer, Group) - end, - DisplayedGroups)), - case lists:member(US1, SRUsers) of - true -> - case Direction of - in -> {stop, false}; - out -> stop - end; - false -> Acc + SR = get_shared_roster(State, {User, Server}), + case lists:keysearch(US1, #shared_roster_item.us, SR) of + false -> Acc; + _ when Direction == in -> {stop, false}; + _ -> stop end. %%==================================================================== @@ -222,267 +225,509 @@ process_subscription(Direction, User, Server, JID, %%==================================================================== init([Host, Opts]) -> State = parse_options(Host, Opts), - cache_tab:new(shared_roster_ldap_user, - [{max_size, State#state.user_cache_size}, {lru, false}, - {life_time, State#state.user_cache_validity}]), - cache_tab:new(shared_roster_ldap_group, - [{max_size, State#state.group_cache_size}, {lru, false}, - {life_time, State#state.group_cache_validity}]), - ejabberd_hooks:add(roster_get, Host, ?MODULE, - get_user_roster, 70), + if + State#state.roster_cache_size > 0 -> + cache_tab:new(shared_roster_ldap_sr, + [{max_size, State#state.roster_cache_size}, + {lru, false}, % We don't need LRU algorithm + {life_time, State#state.roster_cache_validity}]); + true -> + false + end, + ejabberd_hooks:add(roster_get, Host, + ?MODULE, get_user_roster, 70), ejabberd_hooks:add(roster_in_subscription, Host, - ?MODULE, in_subscription, 30), + ?MODULE, in_subscription, 30), ejabberd_hooks:add(roster_out_subscription, Host, - ?MODULE, out_subscription, 30), + ?MODULE, out_subscription, 30), ejabberd_hooks:add(roster_get_subscription_lists, Host, - ?MODULE, get_subscription_lists, 70), - ejabberd_hooks:add(roster_get_jid_info, Host, ?MODULE, - get_jid_info, 70), - ejabberd_hooks:add(roster_process_item, Host, ?MODULE, - process_item, 50), + ?MODULE, get_subscription_lists, 70), + ejabberd_hooks:add(roster_get_jid_info, Host, + ?MODULE, get_jid_info, 70), + ejabberd_hooks:add(roster_process_item, Host, + ?MODULE, process_item, 50), eldap_pool:start_link(State#state.eldap_id, - State#state.servers, State#state.backups, - State#state.port, State#state.dn, - State#state.password, State#state.tls_options), + State#state.servers, + State#state.backups, + State#state.port, + State#state.dn, + State#state.password, + State#state.tls_options), {ok, State}. handle_call(get_state, _From, State) -> {reply, {ok, State}, State}; + handle_call(_Request, _From, State) -> {reply, {error, badarg}, State}. -handle_cast(_Msg, State) -> {noreply, State}. +handle_cast(_Msg, State) -> + {noreply, State}. -handle_info(_Info, State) -> {noreply, State}. +handle_info(_Info, State) -> + {noreply, State}. terminate(_Reason, State) -> Host = State#state.host, - ejabberd_hooks:delete(roster_get, Host, ?MODULE, - get_user_roster, 70), + ejabberd_hooks:delete(roster_get, Host, + ?MODULE, get_user_roster, 70), ejabberd_hooks:delete(roster_in_subscription, Host, - ?MODULE, in_subscription, 30), + ?MODULE, in_subscription, 30), ejabberd_hooks:delete(roster_out_subscription, Host, - ?MODULE, out_subscription, 30), - ejabberd_hooks:delete(roster_get_subscription_lists, - Host, ?MODULE, get_subscription_lists, 70), + ?MODULE, out_subscription, 30), + ejabberd_hooks:delete(roster_get_subscription_lists, Host, + ?MODULE, get_subscription_lists, 70), ejabberd_hooks:delete(roster_get_jid_info, Host, - ?MODULE, get_jid_info, 70), + ?MODULE, get_jid_info, 70), ejabberd_hooks:delete(roster_process_item, Host, - ?MODULE, process_item, 50). + ?MODULE, process_item, 50). -code_change(_OldVsn, State, _Extra) -> {ok, State}. +code_change(_OldVsn, State, _Extra) -> + {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -get_user_to_groups_map({_, Server} = US, SkipUS) -> - DisplayedGroups = get_user_displayed_groups(US), - lists:foldl(fun (Group, Dict1) -> - GroupName = get_group_name(Server, Group), - lists:foldl(fun (Contact, Dict) -> - if SkipUS, Contact == US -> Dict; - true -> - dict:append(Contact, - GroupName, Dict) - end - end, - Dict1, get_group_users(Server, Group)) - end, - dict:new(), DisplayedGroups). - -eldap_search(State, FilterParseArgs, AttributesList) -> - case apply(eldap_filter, parse, FilterParseArgs) of - {ok, EldapFilter} -> - case eldap_pool:search(State#state.eldap_id, - [{base, State#state.base}, - {filter, EldapFilter}, - {timeout, ?LDAP_SEARCH_TIMEOUT}, - {deref_aliases, State#state.deref_aliases}, - {attributes, AttributesList}]) - of - #eldap_search_result{entries = Es} -> - %% A result with entries. Return their list. - Es; - _ -> - %% Something else. Pretend we got no results. - [] - end; - _ -> - %% Filter parsing failed. Pretend we got no results. - [] +do_eldap_search(PoolName, Opts) -> + case eldap_pool:search(PoolName, Opts) of + #eldap_search_result{entries = Es} -> + %% A result with entries. Return their list. + Es; + Err -> + %% Something else. Pretend we got no results. + ?ERROR_MSG("Error searching: ~p ~p", [Err, Opts]), + [] end. -get_user_displayed_groups({User, Host}) -> - {ok, State} = eldap_utils:get_state(Host, ?MODULE), - GroupAttr = State#state.group_attr, - Entries = eldap_search(State, - [eldap_filter:do_sub(State#state.rfilter, - [{<<"%u">>, User}])], - [GroupAttr]), - Reply = lists:flatmap(fun (#eldap_entry{attributes = - Attrs}) -> - case Attrs of - [{GroupAttr, ValuesList}] -> ValuesList; - _ -> [] - end - end, - Entries), - lists:usort(Reply). - -get_group_users(Host, Group) -> - {ok, State} = eldap_utils:get_state(Host, ?MODULE), - case cache_tab:dirty_lookup(shared_roster_ldap_group, - {Group, Host}, - fun () -> search_group_info(State, Group) end) - of - {ok, #group_info{members = Members}} - when Members /= undefined -> - Members; - _ -> [] +%% Pass given Filter or FilterTemplate and SubstList to eldap_filter:parse, +%% and if successful, run LDAP search on the whole subtree of Base, using +%% resulting filter, retrieving given AttributesList. Return the result entries. +%% On any error, print an error message and return an empty list of results. +eldap_search(State, Base, EldapFilter, AttributesList) when is_tuple(EldapFilter) -> + do_eldap_search(State#state.eldap_id, + [{base, Base}, +%% {scope, wholeSubtree} %% This is the default + {filter, EldapFilter}, + {timeout, ?LDAP_SEARCH_TIMEOUT}, + {deref_aliases, State#state.deref_aliases}, + {attributes, AttributesList}]); +%% Filter is string +eldap_search(State, Base, Filter, AttributesList) -> + eldap_search(State, Base, Filter, [], AttributesList). + +eldap_search(State, Base, FilterTemplate, SubstList, AttributesList) -> + case apply(eldap_filter, parse, [eldap_filter:do_sub(FilterTemplate, SubstList)]) of + {ok, EldapFilter} -> + %% Filter parsing succeeded + eldap_search(State, Base, EldapFilter, AttributesList); + Err -> + %% Filter parsing failed. Pretend we got no results. + ?ERROR_MSG("Error parsing filter: ~p", [Err]), + [] end. -get_group_name(Host, Group) -> - {ok, State} = eldap_utils:get_state(Host, ?MODULE), - case cache_tab:dirty_lookup(shared_roster_ldap_group, - {Group, Host}, - fun () -> search_group_info(State, Group) end) - of - {ok, #group_info{desc = GroupName}} - when GroupName /= undefined -> - GroupName; - _ -> Group +%% The same as above, but gets the Attributes for the specified DN. +%% Note that this function doesn't honor the State's base DN; +%% TODO: fix this (create a custom check?) +eldap_search_dn(State, DN, EldapFilter, AttributesList) when is_tuple(EldapFilter) -> + do_eldap_search(State#state.eldap_id, + [{scope, baseObject}, + {base, DN}, + {filter, EldapFilter}, + {timeout, ?LDAP_SEARCH_TIMEOUT}, + {deref_aliases, State#state.deref_aliases}, + {attributes, AttributesList}]); +%% Filter is string. +eldap_search_dn(State, DN, Filter, AttributesList) -> + case eldap_filter:parse(Filter) of + {ok, EldapFilter} -> + %% Filter parsing succeeded + eldap_search_dn(State, DN, EldapFilter, AttributesList); + Err -> + %% Filter parsing failed. Pretend we got no results. + ?ERROR_MSG("Error parsing filter: ~p", [Err]), + [] end. -get_user_name(User, Host) -> - {ok, State} = eldap_utils:get_state(Host, ?MODULE), - case cache_tab:dirty_lookup(shared_roster_ldap_user, - {User, Host}, - fun () -> search_user_name(State, User) end) - of - {ok, UserName} -> UserName; - error -> User +intersection(L1,L2) -> lists:filter(fun(X) -> lists:member(X,L1) end, L2). + +filter_roster(Roster, all) -> Roster; +filter_roster(_, []) -> []; +filter_roster(Roster, IncludeGroups) when is_list(IncludeGroups) -> + lists:foldl( + fun(RosterItem, Acc) -> + case intersection(IncludeGroups, RosterItem#shared_roster_item.groups) of + [] -> Acc; + CommonGroups -> [RosterItem#shared_roster_item{groups=CommonGroups} | Acc] + end + end, + [], Roster). + +get_user_visible_groups(UserGroups, VisibilityMap) -> + lists:foldl( + fun(Group, Acc) -> + case (lists:keysearch(Group, #shg_data.grp, VisibilityMap)) of + {value, #shg_data{shgrps=Gs}} when is_list(Gs) -> Gs ++ Acc; + _ -> Acc + end + end, + UserGroups, UserGroups). + +%% Returns [#shared_roster_item]; +%% Removes the US from returned data +%% If State#state.user_groups_only is 'true', then it removes all users that are not in US's groups, +%% and also removes the groups from the users that the US is not member of. +get_shared_roster(State, {_, Server} = US) -> + case (catch get_full_roster(State, Server)) of + {ok, {VisibilityMap, FullRoster}} -> + %%?ERROR_MSG("XXXXXX get_shared_roster: VMap=~p FullRoster=~p", [VisibilityMap, FullRoster]), + CommonRosterGroups = lists:foldl( + fun(_, all) -> all; + (#shg_data{grp=all, shgrps=all}, _) -> all; + (#shg_data{grp=all, shgrps=Gs}, Acc) when is_list(Gs) -> Gs ++ Acc; + (_, Acc) -> Acc + end, + [], VisibilityMap), + case lists:keytake(US, #shared_roster_item.us, FullRoster) of + false -> filter_roster(FullRoster, CommonRosterGroups); + {value, #shared_roster_item{groups=UserGroups}, Roster2} -> + VisibleGroups = case (CommonRosterGroups) of + all -> all; + CRG -> get_user_visible_groups(UserGroups, VisibilityMap) ++ CRG + end, + filter_roster(Roster2, VisibleGroups) + end; + {'EXIT', CatchData} -> ?ERROR_MSG("Error getting shared roster for user ~p: ~p", [US, CatchData]), []; + _Unexpected -> [] end. +%% 1. If user is not a member of shared roster -> no additional subscriptions +%% 2. Else if ldap_subscribe_all is set AND this user is member of a group published to all -> +%% add all registered users of this vhost +%% 3. Else add only those groups this user' groups are published to +get_presense_subscribers(State, {_, Server} = US) -> + case (catch get_full_roster(State, Server)) of + {ok, {VisibilityMap, FullRoster}} -> + case lists:keytake(US, #shared_roster_item.us, FullRoster) of + false -> []; % Case #1 + {value, #shared_roster_item{groups=UserGroups}, Roster2} -> + AllGroups = lists:usort(lists:foldl( + fun(#shared_roster_item{groups=Gs}, Acc) -> Gs ++ Acc end, + [], FullRoster)), + Fun = case (State#state.subscribe_all) of + true -> % Possible case 2 + fun(_, all) -> all; + (#shg_data{grp=all, shgrps=all}, _) -> all; + (#shg_data{grp=all, shgrps=Gs}, Acc) when is_list(Gs) -> + case intersection(Gs, UserGroups) of + [] -> Acc; + _SomeCommon -> all + end; + (#shg_data{grp=G, shgrps=Gs}, Acc) when is_list(Gs) -> + case intersection(Gs, UserGroups) of + [] -> Acc; + _SomeCommon -> [G | Acc] + end; + (_, Acc) -> Acc + end; + _False -> % Case 3 + fun(#shg_data{grp=all}, Acc) -> AllGroups ++ Acc; + (#shg_data{grp=G, shgrps=Gs}, Acc) when is_list(Gs) -> + case intersection(Gs, UserGroups) of + [] -> Acc; + _SomeCommon -> [G | Acc] + end; + (_, Acc) -> Acc + end + end, + PublishTo = lists:foldl(Fun, [], VisibilityMap), + case (PublishTo) of + all -> + [{U1, S1, <<"">>} || {U1, S1} <- ejabberd_auth:get_vh_registered_users(Server)]; + Groups -> + [{U1, S1, <<"">>} || #shared_roster_item{us = {U1, S1}} <- filter_roster(Roster2, UserGroups ++ Groups)] + end + end; + {'EXIT', CatchData} -> ?ERROR_MSG("Error getting shared roster for user ~p: ~p", [US, CatchData]), []; + _Unexpected -> [] + end. + +get_full_roster(State, Server) when State#state.roster_cache_size > 0 -> + cache_tab:dirty_lookup(shared_roster_ldap_sr, + {Server}, + fun() -> search_roster_info(State, Server) end); +get_full_roster(State, Server) -> + search_roster_info(State, Server). + +search_visible_groups(State, _) when State#state.shgfilter == all -> + [{all, all}]; +search_visible_groups(State, _) when State#state.shgfilter == none -> + [{all, none}]; +search_visible_groups(State, Groups) -> + case (string:str(State#state.shgfilter, "%g")) of + 0 -> [{all, search_group_visible_groups(State, "")}]; + _ -> lists:map( + fun(Group) -> {Group, search_group_visible_groups(State, Group)} end, + Groups) + end. + +search_group_visible_groups(State, Group) -> + Entries = eldap_search(State, State#state.group_base, State#state.shgfilter, [{<<"%g">>, Group}], [State#state.shg_attr]), + lists:usort(lists:flatmap( + fun(#eldap_entry{attributes = Attrs}) -> + case Attrs of + [{_GroupAttr, ValuesList}] -> + ValuesList; + _ -> + [] + end + end, Entries)). + +group2name(all, _) -> all; +group2name(none, _) -> none; +group2name(Group, GroupNames) -> + case (lists:keysearch(Group, 1, GroupNames)) of + {value, {_, Name}} -> Name; + _ -> false + end. + +groups2names(all, _) -> all; +groups2names(none, _) -> none; +groups2names(GroupList, GroupNames) -> + lists:foldl( + fun(G, Acc) -> + case (group2name(G, GroupNames)) of + false -> Acc; + Name -> [Name | Acc] + end + end, + [], GroupList). + +prep_vis_map(VisGroups, GroupNames) -> + lists:foldl( + fun({G, Gs}, Acc) -> + case (group2name(G, GroupNames)) of + false -> Acc; + Name -> [#shg_data{grp=Name, shgrps=groups2names(Gs, GroupNames)} | Acc] + end + end, + [], VisGroups). + +search_roster_info(State, _Host) -> + Entries = eldap_search(State, State#state.group_base, State#state.rfilter, [State#state.group_attr]), + AllGroupIds = lists:usort(lists:flatmap( + fun(#eldap_entry{attributes = Attrs}) -> + case Attrs of + [{_GroupAttr, ValuesList}] -> + ValuesList; + _ -> + [] + end + end, Entries)), + VisGroups = search_visible_groups(State, AllGroupIds), + %%?ERROR_MSG("XXXXXX search_roster_info: VisGroups=~p", [VisGroups]), + + {GroupNames, RosterItems} = case State#state.member_selection_mode of + group_children -> + {GroupNames0, UsersDict0} = lists:foldl( + fun(Group, {GrNAcc, Dict1} = Acc) -> + case search_group_info(State, Group) of + {ok, #group_info{desc = GroupName, members = GroupDN}} -> + {[{Group, GroupName} | GrNAcc], search_users_info(State, GroupDN, GroupName, Dict1)}; + _ -> Acc %% Error getting group data -> No users! + end + end, + {[], dict:new()}, AllGroupIds), + + {GroupNames0, dict:fold( + fun(#user_info{us=US, name=UserName}, Groups, AccIn) -> + [#shared_roster_item{us = US, name = UserName, groups = Groups} | AccIn] + end, + [], UsersDict0)}; + _ -> + {GroupNames1, UsersDict1} = lists:foldl( + fun(Group, {GrNAcc, Dict1} = Acc) -> + case search_group_info(State, Group) of + {ok, #group_info{desc = GroupName, members = Members}} -> + {[{Group, GroupName} | GrNAcc], lists:foldl( + fun(Member, Dict) -> dict:append(Member, GroupName, Dict) end, + Dict1, Members)}; + _ -> Acc %% Error getting group data -> No users! + end + end, + {[], dict:new()}, AllGroupIds), + + %%?ERROR_MSG("UsersDict1: ~p", [UsersDict1]), + %%?ERROR_MSG("GroupNames1: ~p", [GroupNames1]), + + {GroupNames1, dict:fold( + fun(Member, Groups, AccIn) -> + case search_user_info(State, Member) of + {ok, #user_info{us=US, name=UserName}} -> + %%?ERROR_MSG("XXXX found user: ~p ~p ~p", [UserName, Groups, US]), + [#shared_roster_item{us = US, name = UserName, groups = Groups} | AccIn]; + _ -> AccIn + end + end, + [], UsersDict1)} + end, + + VisibilityMap = prep_vis_map(VisGroups, GroupNames), + {ok, {VisibilityMap, RosterItems}}. + search_group_info(State, Group) -> + AttList = case State#state.member_selection_mode of + group_children -> [State#state.group_desc]; + _ -> [State#state.group_desc, State#state.member_attr] + end, + SearchResult = case State#state.group_is_dn of + true -> eldap_search_dn(State, + Group, + State#state.gfilter, + AttList); + _ -> eldap_search(State, + State#state.group_base, + State#state.gfilter, + [{<<"%g">>, Group}], + AttList) + end, + case SearchResult of + [] -> + error; + LDAPEntries -> + case State#state.member_selection_mode of + group_children -> + [#eldap_entry{object_name=Name, attributes=Attrs} | _] = LDAPEntries, + {ok, #group_info{desc = eldap_utils:get_ldap_attr(State#state.group_desc, Attrs), + members = Name}}; + _ -> + {GroupDesc, MembersLists} = lists:foldl( + fun(#eldap_entry{attributes=Attrs}, {DescAcc, MembersAcc}) -> + case {eldap_utils:get_ldap_attr(State#state.group_desc, Attrs), + lists:keysearch(State#state.member_attr, 1, Attrs)} of + {Desc, {value, {GroupMemberAttr, Members}}} + when GroupMemberAttr == State#state.member_attr -> + {Desc, lists:usort(Members ++ MembersAcc)}; + _ -> + {DescAcc, MembersAcc} + end + end, + {Group, []}, LDAPEntries), + {ok, #group_info{desc = GroupDesc, + members = lists:usort(MembersLists)}} + end + end. + +%% Takes the attributes from LDAP user search; +%% returns error or {ok, #user_info} +construct_user(State, Attrs) -> Extractor = case State#state.uid_format_re of - <<"">> -> - fun (UID) -> - catch eldap_utils:get_user_part(UID, - State#state.uid_format) - end; - _ -> - fun (UID) -> - catch get_user_part_re(UID, - State#state.uid_format_re) - end - end, + <<"">> -> fun(UID) -> + catch eldap_utils:get_user_part(UID, State#state.uid_format) + end; + _ -> fun(UID) -> + catch get_user_part_re(UID, State#state.uid_format_re) + end + end, AuthChecker = case State#state.auth_check of - true -> fun ejabberd_auth:is_user_exists/2; - _ -> fun (_U, _S) -> true end - end, + true -> fun ejabberd_auth:is_user_exists/2; + _ -> fun(_U, _S) -> true end + end, Host = State#state.host, - case eldap_search(State, - [eldap_filter:do_sub(State#state.gfilter, - [{<<"%g">>, Group}])], - [State#state.group_attr, State#state.group_desc, - State#state.uid]) - of - [] -> error; - LDAPEntries -> - {GroupDesc, MembersLists} = lists:foldl(fun - (#eldap_entry{attributes = - Attrs}, - {DescAcc, JIDsAcc}) -> - case - {eldap_utils:get_ldap_attr(State#state.group_attr, - Attrs), - eldap_utils:get_ldap_attr(State#state.group_desc, - Attrs), - lists:keysearch(State#state.uid, - 1, - Attrs)} - of - {ID, Desc, - {value, - {GroupMemberAttr, - Members}}} - when ID /= <<"">>, - GroupMemberAttr - == - State#state.uid -> - JIDs = - lists:foldl(fun - ({ok, - UID}, - L) -> - PUID = - jid:nodeprep(UID), - case - PUID - of - error -> - L; - _ -> - case - AuthChecker(PUID, - Host) - of - true -> - [{PUID, - Host} - | L]; - _ -> - L - end - end; - (_, - L) -> - L - end, - [], - lists:map(Extractor, - Members)), - {Desc, - [JIDs - | JIDsAcc]}; - _ -> - {DescAcc, JIDsAcc} - end - end, - {Group, []}, LDAPEntries), - {ok, - #group_info{desc = GroupDesc, - members = lists:usort(lists:flatten(MembersLists))}} + + case {eldap_utils:get_ldap_attr(State#state.uid, Attrs), + eldap_utils:get_ldap_attr(State#state.user_desc, Attrs)} of + {UID, Desc} when UID /= "" -> + %% By returning "" get_ldap_attr means "not found" + case Extractor(UID) of + {ok, UID1} -> + UID2 = jlib:nodeprep(UID1), + case UID2 of + error -> error; + _ -> + case AuthChecker(UID2, Host) of + true -> {ok, #user_info{us={UID2, Host}, name=Desc}}; + _ -> error + end + end; + _ -> error + end; + _ -> + error end. -search_user_name(State, User) -> - case eldap_search(State, - [eldap_filter:do_sub(State#state.ufilter, - [{<<"%u">>, User}])], - [State#state.user_desc, State#state.user_uid]) - of - [#eldap_entry{attributes = Attrs} | _] -> - case {eldap_utils:get_ldap_attr(State#state.user_uid, - Attrs), - eldap_utils:get_ldap_attr(State#state.user_desc, Attrs)} - of - {UID, Desc} when UID /= <<"">> -> {ok, Desc}; - _ -> error - end; - [] -> error +%% This function is used when State#state.member_selection_mode is group_children +%% Returns UsersDict to which the users (#user_info) of this group are added +%%search_users_info(State, GroupInfo) -> +search_users_info(State, GroupDN, GroupName, UsersDict) -> + SearchResult = eldap_search(State, + GroupDN, + State#state.ufilter, + [State#state.user_desc, State#state.uid]), + lists:foldl( + fun(#eldap_entry{attributes=Attrs}, Dict1) -> + case construct_user(State, Attrs) of + {ok, UserInfo} -> + dict:append(UserInfo, GroupName, Dict1); + _ -> Dict1 + end + end, UsersDict, SearchResult). + +%% This function is used when State#state.member_selection_mode is either memberattr_normal or memberattr_dn +search_user_info(State, User) -> + %%?ERROR_MSG("XXX search_user_info: searching for ~p", [User]), + SearchResult = case State#state.member_selection_mode of + memberattr_dn -> eldap_search_dn(State, + User, + State#state.ufilter, + [State#state.user_desc, State#state.uid]); + memberattr_normal -> eldap_search(State, + State#state.base, + State#state.ufilter, + [{<<"%u">>, User}], + [State#state.user_desc, State#state.uid]) + end, + case SearchResult of + [#eldap_entry{attributes=Attrs}|_] -> + construct_user(State, Attrs); + [] -> + %%?ERROR_MSG("XX not found", []), + error end. %% Getting User ID part by regex pattern get_user_part_re(String, Pattern) -> case catch re:run(String, Pattern) of - {match, Captured} -> - {First, Len} = lists:nth(2, Captured), - Result = str:sub_string(String, First + 1, First + Len), - {ok, Result}; - _ -> {error, badmatch} + {match, Captured} -> + {First, Len} = lists:nth(2,Captured), + Result = string:sub_string(String, First+1, First+Len), + {ok,Result}; + _ -> {error, badmatch} end. +% select(SelectFirst, First, Second) -> +% case SelectFirst of +% true -> First; +% _ -> Second +% end. + +% prepare_filter(Opts, Name, Default, ReturnParsed) -> +% F = gen_mod:get_opt(Name, Opts, Default), +% prepare_filter(F, Name, ReturnParsed). + +% prepare_filter(F, Name, ReturnParsed) -> +% case eldap_filter:parse(F) of +% {ok, EldapFilter} -> +% case ReturnParsed of +% true -> EldapFilter; +% _ -> F +% end; +% _ -> +% ?ERROR_MSG(?INVALID_SETTING_MSG, [atom_to_list(Name), ?MODULE]), +% [] +% end. + parse_options(Host, Opts) -> Eldap_ID = jlib:atom_to_binary(gen_mod:get_module_proc(Host, ?MODULE)), Cfg = eldap_utils:get_config(Host, Opts), @@ -516,84 +761,114 @@ parse_options(Host, Opts) -> (false) -> false; (true) -> true end, true), - UserCacheValidity = gen_mod:get_opt( - {ldap_user_cache_validity, Host}, Opts, - fun(I) when is_integer(I), I>0 -> I end, - ?USER_CACHE_VALIDITY), - GroupCacheValidity = gen_mod:get_opt( + RosterCacheValidity = eldap_utils:get_opt( {ldap_group_cache_validity, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, - ?GROUP_CACHE_VALIDITY), - UserCacheSize = gen_mod:get_opt( - {ldap_user_cache_size, Host}, Opts, - fun(I) when is_integer(I), I>0 -> I end, - ?CACHE_SIZE), - GroupCacheSize = gen_mod:get_opt( - {ldap_group_cache_size, Host}, Opts, + ?CACHE_VALIDITY), + RosterCacheSize = eldap_utils:get_opt( + {ldap_roster_cache_size, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?CACHE_SIZE), - ConfigFilter = gen_mod:get_opt({ldap_filter, Host}, Opts, + ConfigFilter = eldap_utils:get_opt({ldap_filter, Host}, Opts, fun check_filter/1, <<"">>), - ConfigUserFilter = gen_mod:get_opt({ldap_ufilter, Host}, Opts, + ConfigUserFilter = eldap_utils:get_opt({ldap_ufilter, Host}, Opts, fun check_filter/1, <<"">>), - ConfigGroupFilter = gen_mod:get_opt({ldap_gfilter, Host}, Opts, + ConfigGroupFilter = eldap_utils:get_opt({ldap_gfilter, Host}, Opts, fun check_filter/1, <<"">>), - RosterFilter = gen_mod:get_opt({ldap_rfilter, Host}, Opts, + RosterFilter = eldap_utils:get_opt({ldap_rfilter, Host}, Opts, fun check_filter/1, <<"">>), SubFilter = <<"(&(", UIDAttr/binary, "=", - UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>, + UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>, UserSubFilter = case ConfigUserFilter of - <<"">> -> - eldap_filter:do_sub(SubFilter, [{<<"%g">>, <<"*">>}]); - UString -> UString - end, + <<"">> -> + eldap_filter:do_sub(SubFilter, [{<<"%g">>, <<"*">>}]); + UString -> UString + end, GroupSubFilter = case ConfigGroupFilter of - <<"">> -> - eldap_filter:do_sub(SubFilter, - [{<<"%u">>, <<"*">>}]); - GString -> GString + <<"">> -> + eldap_filter:do_sub(SubFilter, + [{<<"%u">>, <<"*">>}]); + GString -> GString end, Filter = case ConfigFilter of - <<"">> -> SubFilter; - _ -> - <<"(&", SubFilter/binary, ConfigFilter/binary, ")">> - end, + <<"">> -> SubFilter; + _ -> + <<"(&", SubFilter/binary, ConfigFilter/binary, ")">> + end, UserFilter = case ConfigFilter of - <<"">> -> UserSubFilter; - _ -> - <<"(&", UserSubFilter/binary, ConfigFilter/binary, ")">> - end, + <<"">> -> UserSubFilter; + _ -> + <<"(&", UserSubFilter/binary, ConfigFilter/binary, ")">> + end, GroupFilter = case ConfigFilter of - <<"">> -> GroupSubFilter; - _ -> - <<"(&", GroupSubFilter/binary, ConfigFilter/binary, - ")">> - end, + <<"">> -> GroupSubFilter; + _ -> + <<"(&", GroupSubFilter/binary, ConfigFilter/binary, + ")">> + end, +%%%%%%%%%%%%% + GroupBase = gen_mod:get_opt(ldap_group_base, Opts, fun iolist_to_binary/1, + Cfg#eldap_config.base), + GroupIsDN = gen_mod:get_opt(ldap_group_is_dn, Opts, + fun(on) -> true; + (off) -> false; + (false) -> false; + (true) -> true + end, true), + MemberSelMode = gen_mod:get_opt(ldap_member_selection_mode, Opts, + fun(memberattr_normal) -> memberattr_normal; + (memberattr_dn) -> memberattr_dn; + (group_children) -> group_children; + (Invalid) -> + ?ERROR_MSG("Invalid ldap_member_selection_mode '~p'. " + "Value 'memberattr_normal' will be used instead.", + [Invalid]) + end, memberattr_normal), + SubscribeAll = gen_mod:get_opt(ldap_subscribe_all, Opts, + fun(on) -> true; + (off) -> false; + (false) -> false; + (true) -> true + end, false), + % MemberIsDN = (MemberSelMode == member_attr_dn) or (MemberSelMode == group_children), + ShGFilter = gen_mod:get_opt(ldap_shgfilter, Opts, + fun(all) -> all; + (none) -> none; + (S) -> check_filter(S) + end, all), + ShGAttr = gen_mod:get_opt(ldap_shgattr, Opts, + fun iolist_to_binary/1, + << GroupAttr/binary >>), +%%%%%% #state{host = Host, eldap_id = Eldap_ID, - servers = Cfg#eldap_config.servers, - backups = Cfg#eldap_config.backups, + servers = Cfg#eldap_config.servers, + backups = Cfg#eldap_config.backups, port = Cfg#eldap_config.port, - tls_options = Cfg#eldap_config.tls_options, - dn = Cfg#eldap_config.dn, + tls_options = Cfg#eldap_config.tls_options, + dn = Cfg#eldap_config.dn, password = Cfg#eldap_config.password, base = Cfg#eldap_config.base, deref_aliases = Cfg#eldap_config.deref_aliases, - uid = UIDAttr, - group_attr = GroupAttr, group_desc = GroupDesc, - user_desc = UserDesc, user_uid = UserUID, - uid_format = UIDAttrFormat, - uid_format_re = UIDAttrFormatRe, filter = Filter, - ufilter = UserFilter, rfilter = RosterFilter, - gfilter = GroupFilter, auth_check = AuthCheck, - user_cache_size = UserCacheSize, - user_cache_validity = UserCacheValidity, - group_cache_size = GroupCacheSize, - group_cache_validity = GroupCacheValidity}. + group_attr = GroupAttr, group_desc = GroupDesc, + user_desc = UserDesc, uid = UserUID, + uid_format = UIDAttrFormat, + uid_format_re = UIDAttrFormatRe, filter = Filter, + ufilter = UserFilter, rfilter = RosterFilter, + gfilter = GroupFilter, auth_check = AuthCheck, + group_base = GroupBase, + member_attr = UIDAttr, + member_selection_mode = MemberSelMode, + group_is_dn = GroupIsDN, + shgfilter = ShGFilter, + shg_attr = ShGAttr, + subscribe_all = SubscribeAll, + roster_cache_size = RosterCacheSize, + roster_cache_validity = RosterCacheValidity}. check_filter(F) -> - NewF = iolist_to_binary(F), - {ok, _} = eldap_filter:parse(NewF), - NewF. + NewF = iolist_to_binary(F), + {ok, _} = eldap_filter:parse(NewF), + NewF. mod_opt_type(deref_aliases) -> fun (never) -> never; @@ -661,6 +936,20 @@ mod_opt_type(ldap_user_cache_validity) -> fun (I) when is_integer(I), I > 0 -> I end; mod_opt_type(ldap_userdesc) -> fun iolist_to_binary/1; mod_opt_type(ldap_useruid) -> fun iolist_to_binary/1; +mod_opt_type(ldap_group_base) -> fun iolist_to_binary/1; +mod_opt_type(ldap_group_is_dn) -> fun(B) when is_boolean(B) -> B end; +mod_opt_type(ldap_member_selection_mode) -> + fun(memberattr_normal) -> memberattr_normal; + (memberattr_dn) -> memberattr_dn; + (group_children) -> group_children + end; +mod_opt_type(ldap_subscribe_all) -> fun(B) when is_boolean(B) -> B end; +mod_opt_type(ldap_shgfilter) -> + fun(all) -> all; + (none) -> none; + (S) -> check_filter(S) + end; +mod_opt_type(ldap_shgattr) -> fun iolist_to_binary/1; mod_opt_type(_) -> [ldap_auth_check, ldap_filter, ldap_gfilter, ldap_group_cache_size, ldap_group_cache_validity, @@ -672,7 +961,9 @@ mod_opt_type(_) -> ldap_deref_aliases, ldap_encrypt, ldap_password, ldap_port, ldap_rootdn, ldap_servers, ldap_tls_cacertfile, ldap_tls_certfile, ldap_tls_depth, - ldap_tls_verify]. + ldap_tls_verify, ldap_group_base, ldap_group_is_dn, + ldap_member_selection_mode, ldap_subscribe_all, + ldap_shgfilter, ldap_shgattr]. opt_type(ldap_filter) -> fun check_filter/1; opt_type(ldap_gfilter) -> fun check_filter/1; From 6d8c7232d8b4ae7c84192b5858d84093065dd176 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 29 Feb 2016 00:39:57 +0100 Subject: [PATCH 602/695] mod_register_web: Choose the right error messages --- src/mod_register_web.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod_register_web.erl b/src/mod_register_web.erl index 0bdebaca8bb..5b7f950ad78 100644 --- a/src/mod_register_web.erl +++ b/src/mod_register_web.erl @@ -282,9 +282,9 @@ form_new_post(Q) -> case catch get_register_parameters(Q) of [Username, Host, Password, Password, Id, Key] -> form_new_post(Username, Host, Password, {Id, Key}); - [_Username, _Password, _Password2, false, false] -> + [_Username, _Host, _Password, _Password2, false, false] -> {error, passwords_not_identical}; - [_Username, _Password, _Password2, Id, Key] -> + [_Username, _Host, _Password, _Password2, Id, Key] -> ejabberd_captcha:check_captcha(Id, Key), {error, passwords_not_identical}; _ -> {error, wrong_parameters} @@ -392,7 +392,7 @@ form_changepass_post(Q) -> [Username, Host, PasswordOld, Password, Password] -> try_change_password(Username, Host, PasswordOld, Password); - [_Username, _PasswordOld, _Password, _Password2] -> + [_Username, _Host, _PasswordOld, _Password, _Password2] -> {error, passwords_not_identical}; _ -> {error, wrong_parameters} end. From 59fe967ebbb3b142a0dd01acebaf33271708c1a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 29 Feb 2016 13:51:59 +0100 Subject: [PATCH 603/695] Enable undefined_function_calls xref option --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 12b03ffefdb..aa28d40b0de 100644 --- a/rebar.config +++ b/rebar.config @@ -90,7 +90,7 @@ {xref_warnings, false}. -{xref_checks, [deprecated_function_calls]}. +{xref_checks, [deprecated_function_calls, undefined_function_calls]}. {xref_exclusions, [ "(\"gen_transport\":_/_)", From 382c7c21ad01c2600009d4ffe44cc08995f9ba36 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Mon, 29 Feb 2016 16:35:45 +0300 Subject: [PATCH 604/695] Do not call to deprected/undefined functions from mod_shared_roster_ldap --- src/mod_shared_roster_ldap.erl | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index 3275394be60..f57957d1a2b 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -185,8 +185,8 @@ process_item(RosterItem, _Host) -> end. get_subscription_lists({F, T}, User, Server) -> - U = jlib:nodeprep(User), - S = jlib:nameprep(Server), + U = jid:nodeprep(User), + S = jid:nameprep(Server), {ok, State} = eldap_utils:get_state(S, ?MODULE), SRJIDs = get_presense_subscribers(State, {U, S}), %?INFO_MSG("SRJIDs: ~p", [SRJIDs]), @@ -194,7 +194,7 @@ get_subscription_lists({F, T}, User, Server) -> get_jid_info({Subscription, Groups}, User, Server, JID) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), - {U1, S1, _} = jlib:jid_tolower(JID), + {U1, S1, _} = jid:tolower(JID), US1 = {U1, S1}, SR = get_shared_roster(State, {User, Server}), case lists:keysearch(US1, #shared_roster_item.us, SR) of @@ -211,7 +211,7 @@ out_subscription(User, Server, JID, Type) -> process_subscription(Direction, User, Server, JID, _Type, Acc) -> {ok, State} = eldap_utils:get_state(Server, ?MODULE), - {U1, S1, _} = jlib:jid_tolower(JID), + {U1, S1, _} = jid:tolower(JID), US1 = {U1, S1}, SR = get_shared_roster(State, {User, Server}), case lists:keysearch(US1, #shared_roster_item.us, SR) of @@ -642,7 +642,7 @@ construct_user(State, Attrs) -> %% By returning "" get_ldap_attr means "not found" case Extractor(UID) of {ok, UID1} -> - UID2 = jlib:nodeprep(UID1), + UID2 = jid:nodeprep(UID1), case UID2 of error -> error; _ -> @@ -761,22 +761,22 @@ parse_options(Host, Opts) -> (false) -> false; (true) -> true end, true), - RosterCacheValidity = eldap_utils:get_opt( + RosterCacheValidity = gen_mod:get_opt( {ldap_group_cache_validity, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?CACHE_VALIDITY), - RosterCacheSize = eldap_utils:get_opt( + RosterCacheSize = gen_mod:get_opt( {ldap_roster_cache_size, Host}, Opts, fun(I) when is_integer(I), I>0 -> I end, ?CACHE_SIZE), - ConfigFilter = eldap_utils:get_opt({ldap_filter, Host}, Opts, - fun check_filter/1, <<"">>), - ConfigUserFilter = eldap_utils:get_opt({ldap_ufilter, Host}, Opts, - fun check_filter/1, <<"">>), - ConfigGroupFilter = eldap_utils:get_opt({ldap_gfilter, Host}, Opts, - fun check_filter/1, <<"">>), - RosterFilter = eldap_utils:get_opt({ldap_rfilter, Host}, Opts, - fun check_filter/1, <<"">>), + ConfigFilter = gen_mod:get_opt({ldap_filter, Host}, Opts, + fun check_filter/1, <<"">>), + ConfigUserFilter = gen_mod:get_opt({ldap_ufilter, Host}, Opts, + fun check_filter/1, <<"">>), + ConfigGroupFilter = gen_mod:get_opt({ldap_gfilter, Host}, Opts, + fun check_filter/1, <<"">>), + RosterFilter = gen_mod:get_opt({ldap_rfilter, Host}, Opts, + fun check_filter/1, <<"">>), SubFilter = <<"(&(", UIDAttr/binary, "=", UIDAttrFormat/binary, ")(", GroupAttr/binary, "=%g))">>, UserSubFilter = case ConfigUserFilter of From 8c49d1e1afb7f5247fa01a701e8c31e3729b52b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 29 Feb 2016 14:56:28 +0100 Subject: [PATCH 605/695] Disable back undefined_function_calls xref check --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index aa28d40b0de..12b03ffefdb 100644 --- a/rebar.config +++ b/rebar.config @@ -90,7 +90,7 @@ {xref_warnings, false}. -{xref_checks, [deprecated_function_calls, undefined_function_calls]}. +{xref_checks, [deprecated_function_calls]}. {xref_exclusions, [ "(\"gen_transport\":_/_)", From eeac7f9b02774fa29a074531a899302450f1e5e6 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 29 Feb 2016 17:51:06 +0100 Subject: [PATCH 606/695] Update ejabberd version for hex.pm release --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 1f91e146112..f03dfdd5458 100644 --- a/mix.exs +++ b/mix.exs @@ -3,7 +3,7 @@ defmodule Ejabberd.Mixfile do def project do [app: :ejabberd, - version: "16.01.0-beta1", + version: "16.02.0", description: description, elixir: "~> 1.1", elixirc_paths: ["lib"], From 6374ef48669283933931946f9fbe9a6fccd811ed Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Tue, 9 Feb 2016 19:23:15 +0300 Subject: [PATCH 607/695] New parse transform for SQL queries, use prepare/execute calls with Postgres --- include/ejabberd_sql_pt.hrl | 27 ++++ src/ejabberd_odbc.erl | 130 +++++++++++++++++- src/ejabberd_sql_pt.erl | 255 ++++++++++++++++++++++++++++++++++++ 3 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 include/ejabberd_sql_pt.hrl create mode 100644 src/ejabberd_sql_pt.erl diff --git a/include/ejabberd_sql_pt.hrl b/include/ejabberd_sql_pt.hrl new file mode 100644 index 00000000000..ca6df9ec9eb --- /dev/null +++ b/include/ejabberd_sql_pt.hrl @@ -0,0 +1,27 @@ +%%%---------------------------------------------------------------------- +%%% +%%% ejabberd, Copyright (C) 2002-2016 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-define(SQL_MARK, sql__mark_). +-define(SQL(SQL), ?SQL_MARK(SQL)). + +-record(sql_query, {hash, format_query, format_res, args, loc}). + +-record(sql_escape, {string, integer, boolean}). + diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index a15c66b5d29..ef3c61d0a20 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -63,6 +63,7 @@ -include("ejabberd.hrl"). -include("logger.hrl"). +-include("ejabberd_sql_pt.hrl"). -record(state, {db_ref = self() :: pid(), @@ -92,6 +93,8 @@ -define(KEEPALIVE_QUERY, [<<"SELECT 1;">>]). +-define(PREPARE_KEY, ejabberd_odbc_prepare). + %%-define(DBGFSM, true). -ifdef(DBGFSM). @@ -116,11 +119,12 @@ start_link(Host, StartInterval) -> [Host, StartInterval], fsm_limit_opts() ++ (?FSMOPTS)). --type sql_query() :: [sql_query() | binary()]. +-type sql_query() :: [sql_query() | binary()] | #sql_query{}. -type sql_query_result() :: {updated, non_neg_integer()} | {error, binary()} | {selected, [binary()], - [[binary()]]}. + [[binary()]]} | + {selected, [any]}. -spec sql_query(binary(), sql_query()) -> sql_query_result(). @@ -469,6 +473,52 @@ execute_bloc(F) -> Res -> {atomic, Res} end. +sql_query_internal(#sql_query{} = Query) -> + State = get(?STATE_KEY), + Res = + try + case State#state.db_type of + odbc -> + generic_sql_query(Query); + pgsql -> + Key = {?PREPARE_KEY, Query#sql_query.hash}, + case get(Key) of + undefined -> + case pgsql_prepare(Query, State) of + {ok, _, _, _} -> + put(Key, prepared); + {error, Error} -> + ?ERROR_MSG("PREPARE failed for SQL query " + "at ~p: ~p", + [Query#sql_query.loc, Error]), + put(Key, ignore) + end; + _ -> + ok + end, + case get(Key) of + prepared -> + pgsql_execute_sql_query(Query, State); + _ -> + generic_sql_query(Query) + end; + mysql -> + generic_sql_query(Query); + sqlite -> + generic_sql_query(Query) + end + catch + Class:Reason -> + ST = erlang:get_stacktrace(), + ?ERROR_MSG("Internal error while processing SQL query: ~p", + [{Class, Reason, ST}]), + {error, <<"internal error">>} + end, + case Res of + {error, <<"No SQL-driver information available.">>} -> + {updated, 0}; + _Else -> Res + end; sql_query_internal(Query) -> State = get(?STATE_KEY), ?DEBUG("SQL: \"~s\"", [Query]), @@ -495,6 +545,66 @@ sql_query_internal(Query) -> _Else -> Res end. +generic_sql_query(SQLQuery) -> + sql_query_format_res( + sql_query_internal(generic_sql_query_format(SQLQuery)), + SQLQuery). + +generic_sql_query_format(SQLQuery) -> + Args = (SQLQuery#sql_query.args)(generic_escape()), + (SQLQuery#sql_query.format_query)(Args). + +generic_escape() -> + #sql_escape{string = fun(X) -> <<"'", (escape(X))/binary, "'">> end, + integer = fun(X) -> integer_to_binary(X) end, + boolean = fun(true) -> <<"1">>; + (false) -> <<"0">> + end + }. + +pgsql_prepare(SQLQuery, State) -> + Escape = #sql_escape{_ = fun(X) -> X end}, + N = length((SQLQuery#sql_query.args)(Escape)), + Args = [<<$$, (integer_to_binary(I))/binary>> || I <- lists:seq(1, N)], + Query = (SQLQuery#sql_query.format_query)(Args), + pgsql:prepare(State#state.db_ref, SQLQuery#sql_query.hash, Query). + +pgsql_execute_escape() -> + #sql_escape{string = fun(X) -> X end, + integer = fun(X) -> integer_to_binary(X) end, + boolean = fun(true) -> <<"1">>; + (false) -> <<"0">> + end + }. + +pgsql_execute_sql_query(SQLQuery, State) -> + Args = (SQLQuery#sql_query.args)(pgsql_execute_escape()), + ExecuteRes = + pgsql:execute(State#state.db_ref, SQLQuery#sql_query.hash, Args), + Res = pgsql_execute_to_odbc(ExecuteRes), + sql_query_format_res(Res, SQLQuery). + + +sql_query_format_res({selected, _, Rows}, SQLQuery) -> + Res = + lists:flatmap( + fun(Row) -> + try + [(SQLQuery#sql_query.format_res)(Row)] + catch + Class:Reason -> + ST = erlang:get_stacktrace(), + ?ERROR_MSG("Error while processing " + "SQL query result: ~p~n" + "row: ~p", + [{Class, Reason, ST}, Row]), + [] + end + end, Rows), + {selected, Res}; +sql_query_format_res(Res, _SQLQuery) -> + Res. + %% Generate the OTP callback return tuple depending on the driver result. abort_on_driver_error({error, <<"query timed out">>} = Reply, @@ -606,6 +716,18 @@ pgsql_item_to_odbc(<<"UPDATE ", N/binary>>) -> pgsql_item_to_odbc({error, Error}) -> {error, Error}; pgsql_item_to_odbc(_) -> {updated, undefined}. +pgsql_execute_to_odbc({ok, {<<"SELECT", _/binary>>, Rows}}) -> + {selected, [], [[Field || {_, Field} <- Row] || Row <- Rows]}; +pgsql_execute_to_odbc({ok, {'INSERT', N}}) -> + {updated, N}; +pgsql_execute_to_odbc({ok, {'DELETE', N}}) -> + {updated, N}; +pgsql_execute_to_odbc({ok, {'UPDATE', N}}) -> + {updated, N}; +pgsql_execute_to_odbc({error, Error}) -> {error, Error}; +pgsql_execute_to_odbc(_) -> {updated, undefined}. + + %% == Native MySQL code %% part of init/1 @@ -800,6 +922,10 @@ fsm_limit_opts() -> _ -> [] end. +check_error({error, Why} = Err, #sql_query{} = Query) -> + ?ERROR_MSG("SQL query '~s' at ~p failed: ~p", + [Query#sql_query.hash, Query#sql_query.loc, Why]), + Err; check_error({error, Why} = Err, Query) -> ?ERROR_MSG("SQL query '~s' failed: ~p", [Query, Why]), Err; diff --git a/src/ejabberd_sql_pt.erl b/src/ejabberd_sql_pt.erl new file mode 100644 index 00000000000..f9701a0bee3 --- /dev/null +++ b/src/ejabberd_sql_pt.erl @@ -0,0 +1,255 @@ +%%%------------------------------------------------------------------- +%%% File : ejabberd_sql_pt.erl +%%% Author : Alexey Shchepin +%%% Description : Parse transform for SQL queries +%%% +%%% Created : 20 Jan 2016 by Alexey Shchepin +%%%------------------------------------------------------------------- +-module(ejabberd_sql_pt). + +%% API +-export([parse_transform/2]). + +-export([parse/2]). + +-include("ejabberd_sql_pt.hrl"). + +-record(state, {loc, + 'query' = [], + params = [], + param_pos = 0, + args = [], + res = [], + res_vars = [], + res_pos = 0}). + +-define(QUERY_RECORD, "sql_query"). + +-define(ESCAPE_RECORD, "sql_escape"). +-define(ESCAPE_VAR, "__SQLEscape"). + +-define(MOD, sql__module_). + +%%==================================================================== +%% API +%%==================================================================== +%%-------------------------------------------------------------------- +%% Function: +%% Description: +%%-------------------------------------------------------------------- +parse_transform(AST, _Options) -> + %io:format("PT: ~p~nOpts: ~p~n", [AST, Options]), + NewAST = top_transform(AST), + %io:format("NewPT: ~p~n", [NewAST]), + NewAST. + + + +%%==================================================================== +%% Internal functions +%%==================================================================== + + +transform(Form) -> + case erl_syntax:type(Form) of + application -> + case erl_syntax_lib:analyze_application(Form) of + {?SQL_MARK, 1} -> + case erl_syntax:application_arguments(Form) of + [Arg] -> + case erl_syntax:type(Arg) of + string -> + S = erl_syntax:string_value(Arg), + ParseRes = + parse(S, erl_syntax:get_pos(Arg)), + make_sql_query(ParseRes); + _ -> + throw({error, erl_syntax:get_pos(Form), + "?SQL argument must be " + "a constant string"}) + end; + _ -> + throw({error, erl_syntax:get_pos(Form), + "wrong number of ?SQL args"}) + end; + _ -> + Form + end; + attribute -> + case erl_syntax:atom_value(erl_syntax:attribute_name(Form)) of + module -> + case erl_syntax:attribute_arguments(Form) of + [M | _] -> + Module = erl_syntax:atom_value(M), + %io:format("module ~p~n", [Module]), + put(?MOD, Module), + Form; + _ -> + Form + end; + _ -> + Form + end; + _ -> + Form + end. + +top_transform(Forms) when is_list(Forms) -> + lists:map( + fun(Form) -> + try + Form2 = erl_syntax_lib:map( + fun(Node) -> + %io:format("asd ~p~n", [Node]), + transform(Node) + end, Form), + Form3 = erl_syntax:revert(Form2), + Form3 + catch + throw:{error, Line, Error} -> + {error, {Line, erl_parse, Error}} + end + end, Forms). + +parse(S, Loc) -> + parse1(S, [], #state{loc = Loc}). + +parse1([], Acc, State) -> + State1 = append_string(lists:reverse(Acc), State), + State1#state{'query' = lists:reverse(State1#state.'query'), + params = lists:reverse(State1#state.params), + args = lists:reverse(State1#state.args), + res = lists:reverse(State1#state.res), + res_vars = lists:reverse(State1#state.res_vars) + }; +parse1([$@, $( | S], Acc, State) -> + State1 = append_string(lists:reverse(Acc), State), + {Name, Type, S1, State2} = parse_name(S, State1), + Var = "__V" ++ integer_to_list(State2#state.res_pos), + EVar = erl_syntax:variable(Var), + Convert = + case Type of + integer -> + erl_syntax:application( + erl_syntax:atom(binary_to_integer), + [EVar]); + string -> + EVar; + boolean -> + erl_syntax:application( + erl_syntax:atom(ejabberd_odbc), + erl_syntax:atom(to_bool), + [EVar]) + end, + State3 = append_string(Name, State2), + State4 = State3#state{res_pos = State3#state.res_pos + 1, + res = [Convert | State3#state.res], + res_vars = [EVar | State3#state.res_vars]}, + parse1(S1, [], State4); +parse1([$%, $( | S], Acc, State) -> + State1 = append_string(lists:reverse(Acc), State), + {Name, Type, S1, State2} = parse_name(S, State1), + Var = "__V" ++ integer_to_list(State2#state.param_pos), + EVar = erl_syntax:variable(Var), + Convert = + erl_syntax:application( + erl_syntax:record_access( + erl_syntax:variable(?ESCAPE_VAR), + erl_syntax:atom(?ESCAPE_RECORD), + erl_syntax:atom(Type)), + [erl_syntax:variable(Name)]), + State3 = State2, + State4 = + State3#state{'query' = [{var, EVar} | State3#state.'query'], + args = [Convert | State3#state.args], + params = [EVar | State3#state.params], + param_pos = State3#state.param_pos + 1}, + parse1(S1, [], State4); +parse1([C | S], Acc, State) -> + parse1(S, [C | Acc], State). + +append_string([], State) -> + State; +append_string(S, State) -> + State#state{query = [{str, S} | State#state.query]}. + +parse_name(S, State) -> + parse_name(S, [], State). + +parse_name([], Acc, State) -> + % todo + error; +parse_name([$), T | S], Acc, State) -> + Type = + case T of + $d -> integer; + $s -> string; + $b -> boolean; + _ -> + % todo + error + end, + {lists:reverse(Acc), Type, S, State}; +parse_name([$) | _], Acc, State) -> + % todo + error; +parse_name([C | S], Acc, State) -> + parse_name(S, [C | Acc], State). + + +make_sql_query(State) -> + Hash = erlang:phash2(State#state{loc = undefined}), + SHash = <<"Q", (integer_to_binary(Hash))/binary>>, + Query = pack_query(State#state.'query'), + EQuery = + lists:map( + fun({str, S}) -> + erl_syntax:binary( + [erl_syntax:binary_field( + erl_syntax:string(S))]); + ({var, V}) -> V + end, Query), + erl_syntax:record_expr( + erl_syntax:atom(?QUERY_RECORD), + [erl_syntax:record_field( + erl_syntax:atom(hash), + %erl_syntax:abstract(SHash) + erl_syntax:binary( + [erl_syntax:binary_field( + erl_syntax:string(binary_to_list(SHash)))])), + erl_syntax:record_field( + erl_syntax:atom(args), + erl_syntax:fun_expr( + [erl_syntax:clause( + [erl_syntax:variable(?ESCAPE_VAR)], + none, + [erl_syntax:list(State#state.args)] + )])), + erl_syntax:record_field( + erl_syntax:atom(format_query), + erl_syntax:fun_expr( + [erl_syntax:clause( + [erl_syntax:list(State#state.params)], + none, + [erl_syntax:list(EQuery)] + )])), + erl_syntax:record_field( + erl_syntax:atom(format_res), + erl_syntax:fun_expr( + [erl_syntax:clause( + [erl_syntax:list(State#state.res_vars)], + none, + [erl_syntax:tuple(State#state.res)] + )])), + erl_syntax:record_field( + erl_syntax:atom(loc), + erl_syntax:abstract({get(?MOD), State#state.loc})) + ]). + +pack_query([]) -> + []; +pack_query([{str, S1}, {str, S2} | Rest]) -> + pack_query([{str, S1 ++ S2} | Rest]); +pack_query([X | Rest]) -> + [X | pack_query(Rest)]. + From c58a4be6eec3aa733402bb6d2cde3a220fc689b2 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 11 Feb 2016 20:00:00 +0300 Subject: [PATCH 608/695] Support for run-time SQL queries selection depending on DBMS version --- src/ejabberd_odbc.erl | 75 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index ef3c61d0a20..2a253082b13 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -68,6 +68,7 @@ -record(state, {db_ref = self() :: pid(), db_type = odbc :: pgsql | mysql | sqlite | odbc | mssql, + db_version = undefined :: undefined | non_neg_integer(), start_interval = 0 :: non_neg_integer(), host = <<"">> :: binary(), max_pending_requests_len :: non_neg_integer(), @@ -263,15 +264,16 @@ connecting(connect, #state{host = Host} = State) -> end, {_, PendingRequests} = State#state.pending_requests, case ConnectRes of - {ok, Ref} -> - erlang:monitor(process, Ref), - lists:foreach(fun (Req) -> - (?GEN_FSM):send_event(self(), Req) - end, - queue:to_list(PendingRequests)), - {next_state, session_established, - State#state{db_ref = Ref, - pending_requests = {0, queue:new()}}}; + {ok, Ref} -> + erlang:monitor(process, Ref), + lists:foreach(fun (Req) -> + (?GEN_FSM):send_event(self(), Req) + end, + queue:to_list(PendingRequests)), + State1 = State#state{db_ref = Ref, + pending_requests = {0, queue:new()}}, + State2 = get_db_version(State1), + {next_state, session_established, State2}; {error, Reason} -> ?INFO_MSG("~p connection failed:~n** Reason: ~p~n** " "Retry after: ~p seconds", @@ -473,6 +475,14 @@ execute_bloc(F) -> Res -> {atomic, Res} end. +sql_query_internal([{_, _} | _] = Queries) -> + State = get(?STATE_KEY), + case select_sql_query(Queries, State) of + undefined -> + {error, <<"no matching query for the current DBMS found">>}; + Query -> + sql_query_internal(Query) + end; sql_query_internal(#sql_query{} = Query) -> State = get(?STATE_KEY), Res = @@ -545,6 +555,28 @@ sql_query_internal(Query) -> _Else -> Res end. +select_sql_query(Queries, State) -> + select_sql_query( + Queries, State#state.db_type, State#state.db_version, undefined). + +select_sql_query([], _Type, _Version, undefined) -> + undefined; +select_sql_query([], _Type, _Version, Query) -> + Query; +select_sql_query([{Type, Query} | _], Type, _Version, _) -> + Query; +select_sql_query([{{Type, _Version1}, Query1} | Rest], Type, undefined, _) -> + select_sql_query(Rest, Type, undefined, Query1); +select_sql_query([{{Type, Version1}, Query1} | Rest], Type, Version, Query) -> + if + Version >= Version1 -> + Query1; + true -> + select_sql_query(Rest, Type, Version, Query) + end; +select_sql_query([{_, _} | Rest], Type, Version, Query) -> + select_sql_query(Rest, Type, Version, Query). + generic_sql_query(SQLQuery) -> sql_query_format_res( sql_query_internal(generic_sql_query_format(SQLQuery)), @@ -780,6 +812,24 @@ to_odbc({error, Reason}) when is_list(Reason) -> to_odbc(Res) -> Res. +get_db_version(#state{db_type = pgsql} = State) -> + case pgsql:squery(State#state.db_ref, + <<"select current_setting('server_version_num')">>) of + {ok, [{_, _, [[SVersion]]}]} -> + case catch binary_to_integer(SVersion) of + Version when is_integer(Version) -> + State#state{db_version = Version}; + Error -> + ?WARNING_MSG("error getting pgsql version: ~p", [Error]), + State + end; + Res -> + ?WARNING_MSG("error getting pgsql version: ~p", [Res]), + State + end; +get_db_version(State) -> + State. + log(Level, Format, Args) -> case Level of debug -> ?DEBUG(Format, Args); @@ -927,7 +977,12 @@ check_error({error, Why} = Err, #sql_query{} = Query) -> [Query#sql_query.hash, Query#sql_query.loc, Why]), Err; check_error({error, Why} = Err, Query) -> - ?ERROR_MSG("SQL query '~s' failed: ~p", [Query, Why]), + case catch iolist_to_binary(Query) of + SQuery when is_binary(SQuery) -> + ?ERROR_MSG("SQL query '~s' failed: ~p", [SQuery, Why]); + _ -> + ?ERROR_MSG("SQL query ~p failed: ~p", [Query, Why]) + end, Err; check_error(Result, _Query) -> Result. From 437e768e4a990a4ea2057a36329170c934ffecf8 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 11 Feb 2016 20:01:32 +0300 Subject: [PATCH 609/695] Better error handling in ejabberd_sql_pt --- src/ejabberd_sql_pt.erl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ejabberd_sql_pt.erl b/src/ejabberd_sql_pt.erl index f9701a0bee3..23fc263ba27 100644 --- a/src/ejabberd_sql_pt.erl +++ b/src/ejabberd_sql_pt.erl @@ -177,8 +177,8 @@ parse_name(S, State) -> parse_name(S, [], State). parse_name([], Acc, State) -> - % todo - error; + throw({error, State#state.loc, + "expected ')', found end of string"}); parse_name([$), T | S], Acc, State) -> Type = case T of @@ -186,13 +186,13 @@ parse_name([$), T | S], Acc, State) -> $s -> string; $b -> boolean; _ -> - % todo - error + throw({error, State#state.loc, + ["unknown type specifier '", T, "'"]}) end, {lists:reverse(Acc), Type, S, State}; -parse_name([$) | _], Acc, State) -> - % todo - error; +parse_name([$)], Acc, State) -> + throw({error, State#state.loc, + "expected type specifier, found end of string"}); parse_name([C | S], Acc, State) -> parse_name(S, [C | Acc], State). From ba35c1ed9d578b80a661048e83a313f63eb41687 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 11 Feb 2016 20:05:00 +0300 Subject: [PATCH 610/695] Use 'any' to match any DBMS in sql_query --- src/ejabberd_odbc.erl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 2a253082b13..b430d920a44 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -563,6 +563,8 @@ select_sql_query([], _Type, _Version, undefined) -> undefined; select_sql_query([], _Type, _Version, Query) -> Query; +select_sql_query([{any, Query} | _], _Type, _Version, _) -> + Query; select_sql_query([{Type, Query} | _], Type, _Version, _) -> Query; select_sql_query([{{Type, _Version1}, Query1} | Rest], Type, undefined, _) -> From 99255631ddca2fbae2642bb7edcc35c7fe7458da Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Fri, 12 Feb 2016 16:25:09 +0300 Subject: [PATCH 611/695] Updated some mod_offline SQL queries to the new API --- src/mod_offline.erl | 100 ++++++++++++++++--------------------------- src/odbc_queries.erl | 24 ++++++----- 2 files changed, 50 insertions(+), 74 deletions(-) diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 28c2ba39af5..0db1dd6817a 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -25,6 +25,8 @@ -module(mod_offline). +-compile([{parse_transform, ejabberd_sql_pt}]). + -author('alexey@process-one.net'). -protocol({xep, 13, '1.2'}). @@ -79,6 +81,8 @@ -include("mod_offline.hrl"). +-include("ejabberd_sql_pt.hrl"). + -define(PROCNAME, ejabberd_offline). -define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000). @@ -686,13 +690,10 @@ pop_offline_messages(Ls, LUser, LServer, mnesia) -> _ -> Ls end; pop_offline_messages(Ls, LUser, LServer, odbc) -> - EUser = ejabberd_odbc:escape(LUser), - case odbc_queries:get_and_del_spool_msg_t(LServer, - EUser) - of - {atomic, {selected, [<<"username">>, <<"xml">>], Rs}} -> + case odbc_queries:get_and_del_spool_msg_t(LServer, LUser) of + {atomic, {selected, Rs}} -> Ls ++ - lists:flatmap(fun ([_, XML]) -> + lists:flatmap(fun ({_, XML}) -> case fxml_stream:parse_element(XML) of {error, _Reason} -> []; @@ -811,8 +812,7 @@ remove_user(LUser, LServer, mnesia) -> F = fun () -> mnesia:delete({offline_msg, US}) end, 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, LUser); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete_by_index(offline_msg, <<"us">>, {LUser, LServer})}. @@ -883,13 +883,13 @@ get_offline_els(LUser, LServer, DBType) jlib:replace_from_to(From, To, Packet) end, Msgs); get_offline_els(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch ejabberd_odbc:sql_query(LServer, - [<<"select xml from spool where username='">>, - Username, <<"' order by seq;">>]) of - {selected, [<<"xml">>], Rs} -> + case catch ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(xml)s from spool where " + "username=%(LUser)s order by seq")) of + {selected, Rs} -> lists:flatmap( - fun([XML]) -> + fun({XML}) -> case fxml_stream:parse_element(XML) of #xmlel{} = El -> case offline_msg_to_route(LServer, El) of @@ -1050,20 +1050,20 @@ read_all_msgs(LUser, LServer, riak) -> [] end; read_all_msgs(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch ejabberd_odbc:sql_query(LServer, - [<<"select xml from spool where username='">>, - Username, <<"' order by seq;">>]) - of - {selected, [<<"xml">>], Rs} -> - lists:flatmap(fun ([XML]) -> - case fxml_stream:parse_element(XML) of - {error, _Reason} -> []; - El -> [El] - end - end, - Rs); - _ -> [] + case catch ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(xml)s from spool where " + "username=%(LUser)s order by seq")) of + {selected, Rs} -> + lists:flatmap( + fun({XML}) -> + case fxml_stream:parse_element(XML) of + {error, _Reason} -> []; + El -> [El] + end + end, + Rs); + _ -> [] end. format_user_queue(Msgs, DBType) when DBType == mnesia; DBType == riak -> @@ -1246,30 +1246,7 @@ us_to_list({User, Server}) -> jid:to_string({User, Server, <<"">>}). get_queue_length(LUser, LServer) -> - get_queue_length(LUser, LServer, - gen_mod:db_type(LServer, ?MODULE)). - -get_queue_length(LUser, LServer, mnesia) -> - length(mnesia:dirty_read({offline_msg, - {LUser, LServer}})); -get_queue_length(LUser, LServer, riak) -> - case ejabberd_riak:count_by_index(offline_msg, - <<"us">>, {LUser, LServer}) of - {ok, N} -> - N; - _ -> - 0 - end; -get_queue_length(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch ejabberd_odbc:sql_query(LServer, - [<<"select count(*) from spool where username='">>, - Username, <<"';">>]) - of - {selected, [_], [[SCount]]} -> - jlib:binary_to_integer(SCount); - _ -> 0 - end. + count_offline_messages(LUser, LServer). get_messages_subset(User, Host, MsgsAll, DBType) -> Access = gen_mod:get_module_opt(Host, ?MODULE, access_max_user_messages, @@ -1342,8 +1319,7 @@ delete_all_msgs(LUser, LServer, riak) -> <<"us">>, {LUser, LServer}), {atomic, Res}; delete_all_msgs(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:del_spool_msg(LServer, Username), + odbc_queries:del_spool_msg(LServer, LUser), {atomic, ok}. webadmin_user_parse_query(_, <<"removealloffline">>, @@ -1379,15 +1355,13 @@ count_offline_messages(LUser, LServer, mnesia) -> _ -> 0 end; count_offline_messages(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:count_records_where(LServer, - <<"spool">>, - <<"where username='", - Username/binary, "'">>) - of - {selected, [_], [[Res]]} -> - jlib:binary_to_integer(Res); - _ -> 0 + case catch ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(count(*))d from spool " + "where username=%(LUser)s")) of + {selected, [{Res}]} -> + Res; + _ -> 0 end; count_offline_messages(LUser, LServer, riak) -> case ejabberd_riak:count_by_index( diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 2f488a0bd4a..ee8fa16906b 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -25,6 +25,8 @@ -module(odbc_queries). +-compile([{parse_transform, ejabberd_sql_pt}]). + -behaviour(ejabberd_config). -author("mremond@process-one.net"). @@ -60,6 +62,7 @@ -include("ejabberd.hrl"). -include("logger.hrl"). +-include("ejabberd_sql_pt.hrl"). %% Almost a copy of string:join/2. %% We use this version because string:join/2 is relatively @@ -291,23 +294,22 @@ add_spool_sql(Username, XML) -> add_spool(LServer, Queries) -> ejabberd_odbc:sql_transaction(LServer, Queries). -get_and_del_spool_msg_t(LServer, Username) -> +get_and_del_spool_msg_t(LServer, LUser) -> F = fun () -> Result = - ejabberd_odbc:sql_query_t([<<"select username, xml from spool where " - "username='">>, - Username, - <<"' order by seq;">>]), - ejabberd_odbc:sql_query_t([<<"delete from spool where username='">>, - Username, <<"';">>]), + ejabberd_odbc:sql_query_t( + ?SQL("select @(username)s, @(xml)s from spool where " + "username=%(LUser)s order by seq;")), + ejabberd_odbc:sql_query_t( + ?SQL("delete from spool where username=%(LUser)s;")), Result end, ejabberd_odbc:sql_transaction(LServer, F). -del_spool_msg(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"delete from spool where username='">>, Username, - <<"';">>]). +del_spool_msg(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from spool where username=%(LUser)s")). get_roster(LServer, Username) -> ejabberd_odbc:sql_query(LServer, From 7f3bffe821f6a898990a27edd4a23ba159596c9a Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Fri, 12 Feb 2016 16:26:51 +0300 Subject: [PATCH 612/695] Allow balanced expressions inside @(...) in ejabberd_sql_pt --- src/ejabberd_sql_pt.erl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_sql_pt.erl b/src/ejabberd_sql_pt.erl index 23fc263ba27..6b26cbcd66a 100644 --- a/src/ejabberd_sql_pt.erl +++ b/src/ejabberd_sql_pt.erl @@ -174,12 +174,12 @@ append_string(S, State) -> State#state{query = [{str, S} | State#state.query]}. parse_name(S, State) -> - parse_name(S, [], State). + parse_name(S, [], 0, State). -parse_name([], Acc, State) -> +parse_name([], _Acc, _Depth, State) -> throw({error, State#state.loc, "expected ')', found end of string"}); -parse_name([$), T | S], Acc, State) -> +parse_name([$), T | S], Acc, 0, State) -> Type = case T of $d -> integer; @@ -190,11 +190,15 @@ parse_name([$), T | S], Acc, State) -> ["unknown type specifier '", T, "'"]}) end, {lists:reverse(Acc), Type, S, State}; -parse_name([$)], Acc, State) -> +parse_name([$)], Acc, 0, State) -> throw({error, State#state.loc, "expected type specifier, found end of string"}); -parse_name([C | S], Acc, State) -> - parse_name(S, [C | Acc], State). +parse_name([$( = C | S], Acc, Depth, State) -> + parse_name(S, [C | Acc], Depth + 1, State); +parse_name([$) = C | S], Acc, Depth, State) -> + parse_name(S, [C | Acc], Depth - 1, State); +parse_name([C | S], Acc, Depth, State) -> + parse_name(S, [C | Acc], Depth, State). make_sql_query(State) -> From 3d8219d8f9cd6432b3febd29a18c36e2bf1001f0 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 15 Feb 2016 21:02:22 +0300 Subject: [PATCH 613/695] Update mod_roster and ejabberd_auth_odbc SQL queries to the new API --- src/ejabberd_auth_odbc.erl | 66 ++++++++-------- src/mod_roster.erl | 149 +++++++++++++++---------------------- src/odbc_queries.erl | 107 +++++++++++++------------- 3 files changed, 145 insertions(+), 177 deletions(-) diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index b8b4594b630..60812781757 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -72,22 +72,18 @@ check_password(User, Server, Password) -> (LUser == <<>>) or (LServer == <<>>) -> false; true -> - Username = ejabberd_odbc:escape(LUser), case is_scrammed() of true -> - try odbc_queries:get_password_scram(LServer, Username) of - {selected, [<<"password">>, <<"serverkey">>, - <<"salt">>, <<"iterationcount">>], - [[StoredKey, ServerKey, Salt, IterationCount]]} -> + try odbc_queries:get_password_scram(LServer, LUser) of + {selected, + [{StoredKey, ServerKey, Salt, IterationCount}]} -> Scram = #scram{storedkey = StoredKey, serverkey = ServerKey, salt = Salt, - iterationcount = binary_to_integer( - IterationCount)}, + iterationcount = IterationCount}, is_password_scram_valid(Password, Scram); - {selected, [<<"password">>, <<"serverkey">>, - <<"salt">>, <<"iterationcount">>], []} -> + {selected, []} -> false; %% Account does not exist {error, _Error} -> false %% Typical error is that table doesn't exist @@ -96,12 +92,12 @@ check_password(User, Server, Password) -> false %% Typical error is database not accessible end; false -> - try odbc_queries:get_password(LServer, Username) of - {selected, [<<"password">>], [[Password]]} -> + try odbc_queries:get_password(LServer, LUser) of + {selected, [{Password}]} -> Password /= <<"">>; - {selected, [<<"password">>], [[_Password2]]} -> + {selected, [{_Password2}]} -> false; %% Password is not correct - {selected, [<<"password">>], []} -> + {selected, []} -> false; %% Account does not exist {error, _Error} -> false %% Typical error is that table doesn't exist @@ -124,10 +120,9 @@ check_password(User, Server, Password, Digest, true -> case is_scrammed() of false -> - Username = ejabberd_odbc:escape(LUser), - try odbc_queries:get_password(LServer, Username) of + try odbc_queries:get_password(LServer, LUser) of %% Account exists, check if password is valid - {selected, [<<"password">>], [[Passwd]]} -> + {selected, [{Passwd}]} -> DigRes = if Digest /= <<"">> -> Digest == DigestGen(Passwd); true -> false @@ -135,7 +130,7 @@ check_password(User, Server, Password, Digest, if DigRes -> true; true -> (Passwd == Password) and (Password /= <<"">>) end; - {selected, [<<"password">>], []} -> + {selected, []} -> false; %% Account does not exist {error, _Error} -> false %% Typical error is that table doesn't exist @@ -267,24 +262,22 @@ get_password(User, Server) -> (LUser == <<>>) or (LServer == <<>>) -> false; true -> - Username = ejabberd_odbc:escape(LUser), case is_scrammed() of true -> case catch odbc_queries:get_password_scram( - LServer, Username) of - {selected, [<<"password">>, <<"serverkey">>, - <<"salt">>, <<"iterationcount">>], - [[StoredKey, ServerKey, Salt, IterationCount]]} -> + LServer, LUser) of + {selected, + [{StoredKey, ServerKey, Salt, IterationCount}]} -> {jlib:decode_base64(StoredKey), jlib:decode_base64(ServerKey), jlib:decode_base64(Salt), - binary_to_integer(IterationCount)}; + IterationCount}; _ -> false end; false -> - case catch odbc_queries:get_password(LServer, Username) + case catch odbc_queries:get_password(LServer, LUser) of - {selected, [<<"password">>], [[Password]]} -> Password; + {selected, [{Password}]} -> Password; _ -> false end end @@ -300,9 +293,8 @@ get_password_s(User, Server) -> true -> case is_scrammed() of false -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_password(LServer, Username) of - {selected, [<<"password">>], [[Password]]} -> Password; + case catch odbc_queries:get_password(LServer, LUser) of + {selected, [{Password}]} -> Password; _ -> <<"">> end; true -> <<"">> @@ -311,15 +303,17 @@ get_password_s(User, Server) -> %% @spec (User, Server) -> true | false | {error, Error} is_user_exists(User, Server) -> - case jid:nodeprep(User) of - error -> false; - LUser -> - Username = ejabberd_odbc:escape(LUser), - LServer = jid:nameprep(Server), - try odbc_queries:get_password(LServer, Username) of - {selected, [<<"password">>], [[_Password]]} -> + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), + if (LUser == error) or (LServer == error) -> + false; + (LUser == <<>>) or (LServer == <<>>) -> + false; + true -> + try odbc_queries:get_password(LServer, LUser) of + {selected, [{_Password}]} -> true; %% Account exists - {selected, [<<"password">>], []} -> + {selected, []} -> false; %% Account does not exist {error, Error} -> {error, Error} catch diff --git a/src/mod_roster.erl b/src/mod_roster.erl index f68300763a3..1e5e3b70c22 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -203,11 +203,9 @@ read_roster_version(LUser, LServer, mnesia) -> [] -> error end; read_roster_version(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case odbc_queries:get_roster_version(LServer, Username) - of - {selected, [<<"version">>], [[Version]]} -> Version; - {selected, [<<"version">>], []} -> error + case odbc_queries:get_roster_version(LServer, LUser) of + {selected, [{Version}]} -> Version; + {selected, []} -> error end; read_roster_version(LServer, LUser, riak) -> case ejabberd_riak:get(roster_version, roster_version_schema(), @@ -369,46 +367,37 @@ get_roster(LUser, LServer, riak) -> _Err -> [] end; get_roster(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_roster(LServer, Username) of - {selected, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - Items} - when is_list(Items) -> - JIDGroups = case catch - odbc_queries:get_roster_jid_groups(LServer, - Username) - of - {selected, [<<"jid">>, <<"grp">>], JGrps} - when is_list(JGrps) -> - JGrps; - _ -> [] - end, - GroupsDict = lists:foldl(fun ([J, G], Acc) -> - dict:append(J, G, Acc) - end, - dict:new(), JIDGroups), - RItems = lists:flatmap(fun (I) -> - case raw_to_record(LServer, I) of - %% Bad JID in database: - error -> []; - R -> - SJID = - 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; - _ -> [] + case catch odbc_queries:get_roster(LServer, LUser) of + {selected, Items} when is_list(Items) -> + JIDGroups = case catch odbc_queries:get_roster_jid_groups( + LServer, LUser) of + {selected, JGrps} + when is_list(JGrps) -> + JGrps; + _ -> [] + end, + GroupsDict = lists:foldl(fun({J, G}, Acc) -> + dict:append(J, G, Acc) + end, + dict:new(), JIDGroups), + RItems = + lists:flatmap( + fun(I) -> + case raw_to_record(LServer, I) of + %% Bad JID in database: + error -> []; + R -> + SJID = 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. set_roster(#roster{us = {LUser, LServer}, jid = LJID} = Item) -> @@ -460,14 +449,8 @@ get_roster_by_jid_t(LUser, LServer, LJID, mnesia) -> xs = []} end; get_roster_by_jid_t(LUser, LServer, LJID, odbc) -> - Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jid:to_string(LJID)), - {selected, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - Res} = - odbc_queries:get_roster_by_jid(LServer, Username, SJID), + {selected, Res} = + odbc_queries:get_roster_by_jid(LServer, LUser, jid:to_string(LJID)), case Res of [] -> #roster{usj = {LUser, LServer, LJID}, @@ -750,30 +733,18 @@ get_roster_by_jid_with_groups_t(LUser, LServer, LJID, end; get_roster_by_jid_with_groups_t(LUser, LServer, LJID, odbc) -> - Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jid:to_string(LJID)), - case odbc_queries:get_roster_by_jid(LServer, Username, - SJID) - of - {selected, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - [I]} -> - R = raw_to_record(LServer, I), - Groups = case odbc_queries:get_roster_groups(LServer, - Username, SJID) - of - {selected, [<<"grp">>], JGrps} when is_list(JGrps) -> - [JGrp || [JGrp] <- JGrps]; - _ -> [] - end, - R#roster{groups = Groups}; - {selected, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - []} -> + SJID = jid:to_string(LJID), + case odbc_queries:get_roster_by_jid(LServer, LUser, SJID) of + {selected, [I]} -> + R = raw_to_record(LServer, I), + Groups = + case odbc_queries:get_roster_groups(LServer, LUser, SJID) of + {selected, JGrps} when is_list(JGrps) -> + [JGrp || {JGrp} <- JGrps]; + _ -> [] + end, + R#roster{groups = Groups}; + {selected, []} -> #roster{usj = {LUser, LServer, LJID}, us = {LUser, LServer}, jid = LJID} end; @@ -995,8 +966,7 @@ remove_user(LUser, LServer, mnesia) -> end, mnesia:transaction(F); remove_user(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:del_user_roster_t(LServer, Username), + odbc_queries:del_user_roster_t(LServer, LUser), ok; remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete_by_index(roster, <<"us">>, {LUser, LServer})}. @@ -1243,12 +1213,9 @@ read_subscription_and_groups(LUser, LServer, LJID, end; read_subscription_and_groups(LUser, LServer, LJID, odbc) -> - Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jid:to_string(LJID)), - case catch odbc_queries:get_subscription(LServer, - Username, SJID) - of - {selected, [<<"subscription">>], [[SSubscription]]} -> + SJID = jid:to_string(LJID), + case catch odbc_queries:get_subscription(LServer, LUser, SJID) of + {selected, [{SSubscription}]} -> Subscription = case SSubscription of <<"B">> -> both; <<"T">> -> to; @@ -1256,11 +1223,11 @@ read_subscription_and_groups(LUser, LServer, LJID, _ -> none end, Groups = case catch - odbc_queries:get_rostergroup_by_jid(LServer, Username, + odbc_queries:get_rostergroup_by_jid(LServer, LUser, SJID) of - {selected, [<<"grp">>], JGrps} when is_list(JGrps) -> - [JGrp || [JGrp] <- JGrps]; + {selected, JGrps} when is_list(JGrps) -> + [JGrp || {JGrp} <- JGrps]; _ -> [] end, {Subscription, Groups}; @@ -1297,6 +1264,12 @@ get_jid_info(_, User, Server, JID) -> raw_to_record(LServer, [User, SJID, Nick, SSubscription, SAsk, SAskMessage, _SServer, _SSubscribe, _SType]) -> + raw_to_record(LServer, + {User, SJID, Nick, SSubscription, SAsk, SAskMessage, + _SServer, _SSubscribe, _SType}); +raw_to_record(LServer, + {User, SJID, Nick, SSubscription, SAsk, SAskMessage, + _SServer, _SSubscribe, _SType}) -> case jid:from_string(SJID) of error -> error; JID -> diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index ee8fa16906b..b6c9a36c0eb 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -139,16 +139,17 @@ del_last(LServer, Username) -> [<<"delete from last where username='">>, Username, <<"'">>]). -get_password(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select password from users where username='">>, - Username, <<"';">>]). +get_password(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(password)s from users where username=%(LUser)s")). -get_password_scram(LServer, Username) -> +get_password_scram(LServer, LUser) -> ejabberd_odbc:sql_query( LServer, - [<<"select password, serverkey, salt, iterationcount from users where " - "username='">>, Username, <<"';">>]). + ?SQL("select @(password)s, @(serverkey)s, @(salt)s, @(iterationcount)d" + " from users" + " where username=%(LUser)s")). set_password_t(LServer, Username, Pass) -> ejabberd_odbc:sql_transaction(LServer, @@ -311,46 +312,46 @@ del_spool_msg(LServer, LUser) -> LServer, ?SQL("delete from spool where username=%(LUser)s")). -get_roster(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select username, jid, nick, subscription, " - "ask, askmessage, server, subscribe, " - "type from rosterusers where username='">>, - Username, <<"'">>]). - -get_roster_jid_groups(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select jid, grp from rostergroups where " - "username='">>, - Username, <<"'">>]). - -get_roster_groups(_LServer, Username, SJID) -> - ejabberd_odbc:sql_query_t([<<"select grp from rostergroups where username='">>, - Username, <<"' and jid='">>, SJID, <<"';">>]). +get_roster(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(username)s, @(jid)s, @(nick)s, @(subscription)s, " + "@(ask)s, @(askmessage)s, @(server)s, @(subscribe)s, " + "@(type)s from rosterusers where username=%(LUser)s")). -del_user_roster_t(LServer, Username) -> - ejabberd_odbc:sql_transaction(LServer, - fun () -> - ejabberd_odbc:sql_query_t([<<"delete from rosterusers where " - "username='">>, - Username, - <<"';">>]), - ejabberd_odbc:sql_query_t([<<"delete from rostergroups where " - "username='">>, - Username, - <<"';">>]) - end). +get_roster_jid_groups(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(jid)s, @(grp)s from rostergroups where " + "username=%(LUser)s")). -get_roster_by_jid(_LServer, Username, SJID) -> - ejabberd_odbc:sql_query_t([<<"select username, jid, nick, subscription, " - "ask, askmessage, server, subscribe, " - "type from rosterusers where username='">>, - Username, <<"' and jid='">>, SJID, <<"';">>]). +get_roster_groups(_LServer, LUser, SJID) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(grp)s from rostergroups" + " where username=%(LUser)s and jid=%(SJID)s")). -get_rostergroup_by_jid(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"select grp from rostergroups where username='">>, - Username, <<"' and jid='">>, SJID, <<"'">>]). +del_user_roster_t(LServer, LUser) -> + ejabberd_odbc:sql_transaction( + LServer, + fun () -> + ejabberd_odbc:sql_query_t( + ?SQL("delete from rosterusers where username=%(LUser)s")), + ejabberd_odbc:sql_query_t( + ?SQL("delete from rostergroups where username=%(LUser)s")) + end). + +get_roster_by_jid(_LServer, LUser, SJID) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(username)s, @(jid)s, @(nick)s, @(subscription)s," + " @(ask)s, @(askmessage)s, @(server)s, @(subscribe)s," + " @(type)s from rosterusers" + " where username=%(LUser)s and jid=%(SJID)s")). + +get_rostergroup_by_jid(LServer, LUser, SJID) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(grp)s from rostergroups" + " where username=%(LUser)s and jid=%(SJID)s")). del_roster(_LServer, Username, SJID) -> ejabberd_odbc:sql_query_t([<<"delete from rosterusers where " @@ -421,11 +422,11 @@ roster_subscribe(_LServer, Username, SJID, ItemVals) -> [<<"username='">>, Username, <<"' and jid='">>, SJID, <<"'">>]). -get_subscription(LServer, Username, SJID) -> - ejabberd_odbc:sql_query(LServer, - [<<"select subscription from rosterusers " - "where username='">>, - Username, <<"' and jid='">>, SJID, <<"'">>]). +get_subscription(LServer, LUser, SJID) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(subscription)s from rosterusers " + "where username=%(LUser)s and jid=%(SJID)s")). set_private_data(_LServer, Username, LXMLNS, SData) -> update_t(<<"private_storage">>, @@ -639,10 +640,10 @@ count_records_where(LServer, Table, WhereClause) -> WhereClause, <<";">>]). get_roster_version(LServer, LUser) -> - ejabberd_odbc:sql_query(LServer, - [<<"select version from roster_version where " - "username = '">>, - LUser, <<"'">>]). + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(version)s from roster_version" + " where username = %(LUser)s")). set_roster_version(LUser, Version) -> update_t(<<"roster_version">>, From 2d042f078e6d23a947819c1bb9629be501c6d9c2 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 18 Feb 2016 17:38:25 +0300 Subject: [PATCH 614/695] New parse transform for ?SQL_UPSERT and ?SQL_UPSERT_T --- include/ejabberd_sql_pt.hrl | 6 + src/ejabberd_odbc.erl | 14 ++ src/ejabberd_sql_pt.erl | 270 +++++++++++++++++++++++++++++++++++- 3 files changed, 283 insertions(+), 7 deletions(-) diff --git a/include/ejabberd_sql_pt.hrl b/include/ejabberd_sql_pt.hrl index ca6df9ec9eb..f189fdcf61f 100644 --- a/include/ejabberd_sql_pt.hrl +++ b/include/ejabberd_sql_pt.hrl @@ -21,6 +21,12 @@ -define(SQL_MARK, sql__mark_). -define(SQL(SQL), ?SQL_MARK(SQL)). +-define(SQL_UPSERT_MARK, sql_upsert__mark_). +-define(SQL_UPSERT(Host, Table, Fields), + ejabberd_odbc:sql_query(Host, ?SQL_UPSERT_MARK(Table, Fields))). +-define(SQL_UPSERT_T(Table, Fields), + ejabberd_odbc:sql_query_t(Host, ?SQL_UPSERT_MARK(Table, Fields))). + -record(sql_query, {hash, format_query, format_res, args, loc}). -record(sql_escape, {string, integer, boolean}). diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index b430d920a44..4f818f51323 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -475,6 +475,12 @@ execute_bloc(F) -> Res -> {atomic, Res} end. +execute_fun(F) when is_function(F, 0) -> + F(); +execute_fun(F) when is_function(F, 2) -> + State = get(?STATE_KEY), + F(State#state.db_type, State#state.db_version). + sql_query_internal([{_, _} | _] = Queries) -> State = get(?STATE_KEY), case select_sql_query(Queries, State) of @@ -529,6 +535,11 @@ sql_query_internal(#sql_query{} = Query) -> {updated, 0}; _Else -> Res end; +sql_query_internal(F) when is_function(F) -> + case catch execute_fun(F) of + {'EXIT', Reason} -> {error, Reason}; + Res -> Res + end; sql_query_internal(Query) -> State = get(?STATE_KEY), ?DEBUG("SQL: \"~s\"", [Query]), @@ -615,6 +626,9 @@ pgsql_execute_sql_query(SQLQuery, State) -> Args = (SQLQuery#sql_query.args)(pgsql_execute_escape()), ExecuteRes = pgsql:execute(State#state.db_ref, SQLQuery#sql_query.hash, Args), +% {T, ExecuteRes} = +% timer:tc(pgsql, execute, [State#state.db_ref, SQLQuery#sql_query.hash, Args]), +% io:format("T ~s ~p~n", [SQLQuery#sql_query.hash, T]), Res = pgsql_execute_to_odbc(ExecuteRes), sql_query_format_res(Res, SQLQuery). diff --git a/src/ejabberd_sql_pt.erl b/src/ejabberd_sql_pt.erl index 6b26cbcd66a..cb7a82e0f1e 100644 --- a/src/ejabberd_sql_pt.erl +++ b/src/ejabberd_sql_pt.erl @@ -72,6 +72,26 @@ transform(Form) -> throw({error, erl_syntax:get_pos(Form), "wrong number of ?SQL args"}) end; + {?SQL_UPSERT_MARK, 2} -> + case erl_syntax:application_arguments(Form) of + [TableArg, FieldsArg] -> + case {erl_syntax:type(TableArg), + erl_syntax:is_proper_list(FieldsArg)}of + {string, true} -> + Table = erl_syntax:string_value(TableArg), + ParseRes = + parse_upsert( + erl_syntax:list_elements(FieldsArg)), + make_sql_upsert(Table, ParseRes); + _ -> + throw({error, erl_syntax:get_pos(Form), + "?SQL_UPSERT arguments must be " + "a constant string and a list"}) + end; + _ -> + throw({error, erl_syntax:get_pos(Form), + "wrong number of ?SQL_UPSERT args"}) + end; _ -> Form end; @@ -114,6 +134,9 @@ top_transform(Forms) when is_list(Forms) -> parse(S, Loc) -> parse1(S, [], #state{loc = Loc}). +parse(S, ParamPos, Loc) -> + parse1(S, [], #state{loc = Loc, param_pos = ParamPos}). + parse1([], Acc, State) -> State1 = append_string(lists:reverse(Acc), State), State1#state{'query' = lists:reverse(State1#state.'query'), @@ -149,8 +172,7 @@ parse1([$@, $( | S], Acc, State) -> parse1([$%, $( | S], Acc, State) -> State1 = append_string(lists:reverse(Acc), State), {Name, Type, S1, State2} = parse_name(S, State1), - Var = "__V" ++ integer_to_list(State2#state.param_pos), - EVar = erl_syntax:variable(Var), + Var = State2#state.param_pos, Convert = erl_syntax:application( erl_syntax:record_access( @@ -160,9 +182,9 @@ parse1([$%, $( | S], Acc, State) -> [erl_syntax:variable(Name)]), State3 = State2, State4 = - State3#state{'query' = [{var, EVar} | State3#state.'query'], + State3#state{'query' = [{var, Var} | State3#state.'query'], args = [Convert | State3#state.args], - params = [EVar | State3#state.params], + params = [Var | State3#state.params], param_pos = State3#state.param_pos + 1}, parse1(S1, [], State4); parse1([C | S], Acc, State) -> @@ -190,7 +212,7 @@ parse_name([$), T | S], Acc, 0, State) -> ["unknown type specifier '", T, "'"]}) end, {lists:reverse(Acc), Type, S, State}; -parse_name([$)], Acc, 0, State) -> +parse_name([$)], _Acc, 0, State) -> throw({error, State#state.loc, "expected type specifier, found end of string"}); parse_name([$( = C | S], Acc, Depth, State) -> @@ -201,6 +223,11 @@ parse_name([C | S], Acc, Depth, State) -> parse_name(S, [C | Acc], Depth, State). +make_var(V) -> + Var = "__V" ++ integer_to_list(V), + erl_syntax:variable(Var). + + make_sql_query(State) -> Hash = erlang:phash2(State#state{loc = undefined}), SHash = <<"Q", (integer_to_binary(Hash))/binary>>, @@ -211,7 +238,7 @@ make_sql_query(State) -> erl_syntax:binary( [erl_syntax:binary_field( erl_syntax:string(S))]); - ({var, V}) -> V + ({var, V}) -> make_var(V) end, Query), erl_syntax:record_expr( erl_syntax:atom(?QUERY_RECORD), @@ -233,7 +260,7 @@ make_sql_query(State) -> erl_syntax:atom(format_query), erl_syntax:fun_expr( [erl_syntax:clause( - [erl_syntax:list(State#state.params)], + [erl_syntax:list(lists:map(fun make_var/1, State#state.params))], none, [erl_syntax:list(EQuery)] )])), @@ -257,3 +284,232 @@ pack_query([{str, S1}, {str, S2} | Rest]) -> pack_query([X | Rest]) -> [X | pack_query(Rest)]. + +parse_upsert(Fields) -> + {Fs, _} = + lists:foldr( + fun(F, {Acc, Param}) -> + case erl_syntax:type(F) of + string -> + V = erl_syntax:string_value(F), + {_, _, State} = Res = + parse_upsert_field( + V, Param, erl_syntax:get_pos(F)), + {[Res | Acc], State#state.param_pos}; + _ -> + throw({error, erl_syntax:get_pos(F), + "?SQL_UPSERT field must be " + "a constant string"}) + end + end, {[], 0}, Fields), + %io:format("asd ~p~n", [{Fields, Fs}]), + Fs. + +parse_upsert_field([$! | S], ParamPos, Loc) -> + {Name, ParseState} = parse_upsert_field1(S, [], ParamPos, Loc), + {Name, true, ParseState}; +parse_upsert_field(S, ParamPos, Loc) -> + {Name, ParseState} = parse_upsert_field1(S, [], ParamPos, Loc), + {Name, false, ParseState}. + +parse_upsert_field1([], _Acc, _ParamPos, Loc) -> + throw({error, Loc, + "?SQL_UPSERT fields must have the " + "following form: \"[!]name=value\""}); +parse_upsert_field1([$= | S], Acc, ParamPos, Loc) -> + {lists:reverse(Acc), parse(S, ParamPos, Loc)}; +parse_upsert_field1([C | S], Acc, ParamPos, Loc) -> + parse_upsert_field1(S, [C | Acc], ParamPos, Loc). + + +make_sql_upsert(Table, ParseRes) -> + erl_syntax:fun_expr( + [erl_syntax:clause( + [erl_syntax:atom(pgsql), erl_syntax:variable("__Version")], + [erl_syntax:infix_expr( + erl_syntax:variable("__Version"), + erl_syntax:operator('>='), + erl_syntax:integer(90100))], + [make_sql_upsert_pgsql901(Table, ParseRes), + erl_syntax:atom(ok)]), + erl_syntax:clause( + [erl_syntax:underscore(), erl_syntax:underscore()], + none, + [make_sql_upsert_generic(Table, ParseRes)]) + ]). + +make_sql_upsert_generic(Table, ParseRes) -> + Update = make_sql_query(make_sql_upsert_update(Table, ParseRes)), + Insert = make_sql_query(make_sql_upsert_insert(Table, ParseRes)), + InsertBranch = + erl_syntax:case_expr( + erl_syntax:application( + erl_syntax:atom(ejabberd_odbc), + erl_syntax:atom(sql_query_t), + [Insert]), + [erl_syntax:clause( + [erl_syntax:abstract({updated, 1})], + none, + [erl_syntax:atom(ok)]), + erl_syntax:clause( + [erl_syntax:variable("__UpdateRes")], + none, + [erl_syntax:variable("__UpdateRes")])]), + erl_syntax:case_expr( + erl_syntax:application( + erl_syntax:atom(ejabberd_odbc), + erl_syntax:atom(sql_query_t), + [Update]), + [erl_syntax:clause( + [erl_syntax:abstract({updated, 1})], + none, + [erl_syntax:atom(ok)]), + erl_syntax:clause( + [erl_syntax:underscore()], + none, + [InsertBranch])]). + +make_sql_upsert_update(Table, ParseRes) -> + WPairs = + lists:flatmap( + fun({_Field, false, _ST}) -> + []; + ({Field, true, ST}) -> + [ST#state{ + 'query' = [{str, Field}, {str, "="}] ++ ST#state.'query' + }] + end, ParseRes), + Where = join_states(WPairs, " AND "), + SPairs = + lists:flatmap( + fun({_Field, true, _ST}) -> + []; + ({Field, false, ST}) -> + [ST#state{ + 'query' = [{str, Field}, {str, "="}] ++ ST#state.'query' + }] + end, ParseRes), + Set = join_states(SPairs, ", "), + State = + concat_states( + [#state{'query' = [{str, "UPDATE "}, {str, Table}, {str, " SET "}]}, + Set, + #state{'query' = [{str, " WHERE "}]}, + Where + ]), + State. + +make_sql_upsert_insert(Table, ParseRes) -> + Vals = + lists:map( + fun({_Field, _, ST}) -> + ST + end, ParseRes), + Fields = + lists:map( + fun({Field, _, _ST}) -> + #state{'query' = [{str, Field}]} + end, ParseRes), + State = + concat_states( + [#state{'query' = [{str, "INSERT INTO "}, {str, Table}, {str, "("}]}, + join_states(Fields, ", "), + #state{'query' = [{str, ") VALUES ("}]}, + join_states(Vals, ", "), + #state{'query' = [{str, ")"}]} + ]), + State. + +make_sql_upsert_pgsql901(Table, ParseRes) -> + Update = make_sql_upsert_update(Table, ParseRes), + Vals = + lists:map( + fun({_Field, _, ST}) -> + ST + end, ParseRes), + Fields = + lists:map( + fun({Field, _, _ST}) -> + #state{'query' = [{str, Field}]} + end, ParseRes), + Insert = + concat_states( + [#state{'query' = [{str, "INSERT INTO "}, {str, Table}, {str, "("}]}, + join_states(Fields, ", "), + #state{'query' = [{str, ") SELECT "}]}, + join_states(Vals, ", "), + #state{'query' = [{str, " WHERE NOT EXISTS (SELECT * FROM upsert)"}]} + ]), + State = + concat_states( + [#state{'query' = [{str, "WITH upsert AS ("}]}, + Update, + #state{'query' = [{str, " RETURNING *) "}]}, + Insert + ]), + Upsert = make_sql_query(State), + erl_syntax:application( + erl_syntax:atom(ejabberd_odbc), + erl_syntax:atom(sql_query_t), + [Upsert]). + + +concat_states(States) -> + lists:foldr( + fun(ST11, ST2) -> + ST1 = resolve_vars(ST11, ST2), + ST1#state{ + 'query' = ST1#state.'query' ++ ST2#state.'query', + params = ST1#state.params ++ ST2#state.params, + args = ST1#state.args ++ ST2#state.args, + res = ST1#state.res ++ ST2#state.res, + res_vars = ST1#state.res_vars ++ ST2#state.res_vars, + loc = case ST1#state.loc of + undefined -> ST2#state.loc; + _ -> ST1#state.loc + end + } + end, #state{}, States). + +resolve_vars(ST1, ST2) -> + Max = lists:max([0 | ST1#state.params ++ ST2#state.params]), + {Map, _} = + lists:foldl( + fun(Var, {Acc, New}) -> + case lists:member(Var, ST2#state.params) of + true -> + {dict:store(Var, New, Acc), New + 1}; + false -> + {Acc, New} + end + end, {dict:new(), Max + 1}, ST1#state.params), + NewParams = + lists:map( + fun(Var) -> + case dict:find(Var, Map) of + {ok, New} -> + New; + error -> + Var + end + end, ST1#state.params), + NewQuery = + lists:map( + fun({var, Var}) -> + case dict:find(Var, Map) of + {ok, New} -> + {var, New}; + error -> + {var, Var} + end; + (S) -> S + end, ST1#state.'query'), + ST1#state{params = NewParams, 'query' = NewQuery}. + + + +join_states([], _Sep) -> + #state{}; +join_states([H | T], Sep) -> + J = [[H] | [[#state{'query' = [{str, Sep}]}, X] || X <- T]], + concat_states(lists:append(J)). From 6d7ce0237af67a0e3f143a19bb0b313661ee116b Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 18 Feb 2016 18:49:14 +0300 Subject: [PATCH 615/695] Update mod_last SQL queries to the new API --- src/mod_last.erl | 28 ++++++++-------------------- src/odbc_queries.erl | 28 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/mod_last.erl b/src/mod_last.erl index d76b604918e..33f88e0202e 100644 --- a/src/mod_last.erl +++ b/src/mod_last.erl @@ -185,18 +185,12 @@ get_last(LUser, LServer, riak) -> Err end; get_last(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_last(LServer, Username) of - {selected, [<<"seconds">>, <<"state">>], []} -> - not_found; - {selected, [<<"seconds">>, <<"state">>], - [[STimeStamp, Status]]} -> - case catch jlib:binary_to_integer(STimeStamp) of - TimeStamp when is_integer(TimeStamp) -> - {ok, TimeStamp, Status}; - Reason -> {error, {invalid_timestamp, Reason}} - end; - Reason -> {error, {invalid_result, Reason}} + case catch odbc_queries:get_last(LServer, LUser) of + {selected, []} -> + not_found; + {selected, [{TimeStamp, Status}]} -> + {ok, TimeStamp, Status}; + Reason -> {error, {invalid_result, Reason}} end. get_last_iq(IQ, SubEl, LUser, LServer) -> @@ -260,12 +254,7 @@ store_last_info(LUser, LServer, TimeStamp, Status, last_activity_schema())}; store_last_info(LUser, LServer, TimeStamp, Status, odbc) -> - Username = ejabberd_odbc:escape(LUser), - Seconds = - ejabberd_odbc:escape(iolist_to_binary(integer_to_list(TimeStamp))), - State = ejabberd_odbc:escape(Status), - odbc_queries:set_last_t(LServer, Username, Seconds, - State). + odbc_queries:set_last_t(LServer, LUser, TimeStamp, Status). %% @spec (LUser::string(), LServer::string()) -> %% {ok, TimeStamp::integer(), Status::string()} | not_found @@ -286,8 +275,7 @@ remove_user(LUser, LServer, mnesia) -> F = fun () -> mnesia:delete({last_activity, US}) end, mnesia:transaction(F); remove_user(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:del_last(LServer, Username); + odbc_queries:del_last(LServer, LUser); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete(last_activity, {LUser, LServer})}. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index b6c9a36c0eb..283e33dfe97 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -122,22 +122,22 @@ update(LServer, Table, Fields, Vals, Where) -> sql_transaction(LServer, F) -> ejabberd_odbc:sql_transaction(LServer, F). -get_last(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select seconds, state from last where " - "username='">>, - Username, <<"'">>]). +get_last(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(seconds)d, @(state)s from last" + " where username=%(LUser)s")). -set_last_t(LServer, Username, Seconds, State) -> - update(LServer, <<"last">>, - [<<"username">>, <<"seconds">>, <<"state">>], - [Username, Seconds, State], - [<<"username='">>, Username, <<"'">>]). +set_last_t(LServer, LUser, TimeStamp, Status) -> + ?SQL_UPSERT(LServer, "last", + ["!username=%(LUser)s", + "seconds=%(TimeStamp)d", + "state=%(Status)s"]). -del_last(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"delete from last where username='">>, Username, - <<"'">>]). +del_last(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from last where username=%(LUser)s")). get_password(LServer, LUser) -> ejabberd_odbc:sql_query( From d8fbe8a28910b11e276f635cc04642b53e3a326c Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Tue, 23 Feb 2016 02:56:43 +0300 Subject: [PATCH 616/695] Update more SQL queries --- include/ejabberd_sql_pt.hrl | 2 +- src/ejabberd_auth_odbc.erl | 14 +- src/ejabberd_odbc.erl | 6 +- src/mod_blocking.erl | 40 ++--- src/mod_privacy.erl | 168 ++++++--------------- src/mod_private.erl | 24 +-- src/odbc_queries.erl | 292 ++++++++++++++++++------------------ 7 files changed, 228 insertions(+), 318 deletions(-) diff --git a/include/ejabberd_sql_pt.hrl b/include/ejabberd_sql_pt.hrl index f189fdcf61f..0048661dac7 100644 --- a/include/ejabberd_sql_pt.hrl +++ b/include/ejabberd_sql_pt.hrl @@ -25,7 +25,7 @@ -define(SQL_UPSERT(Host, Table, Fields), ejabberd_odbc:sql_query(Host, ?SQL_UPSERT_MARK(Table, Fields))). -define(SQL_UPSERT_T(Table, Fields), - ejabberd_odbc:sql_query_t(Host, ?SQL_UPSERT_MARK(Table, Fields))). + ejabberd_odbc:sql_query_t(?SQL_UPSERT_MARK(Table, Fields))). -record(sql_query, {hash, format_query, format_res, args, loc}). diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index 60812781757..f38c8286c32 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -153,26 +153,24 @@ set_password(User, Server, Password) -> (LUser == <<>>) or (LServer == <<>>) -> {error, invalid_jid}; true -> - Username = ejabberd_odbc:escape(LUser), case is_scrammed() of true -> Scram = password_to_scram(Password), case catch odbc_queries:set_password_scram_t( LServer, - Username, - ejabberd_odbc:escape(Scram#scram.storedkey), - ejabberd_odbc:escape(Scram#scram.serverkey), - ejabberd_odbc:escape(Scram#scram.salt), - integer_to_binary(Scram#scram.iterationcount) + LUser, + Scram#scram.storedkey, + Scram#scram.serverkey, + Scram#scram.salt, + Scram#scram.iterationcount ) of {atomic, ok} -> ok; Other -> {error, Other} end; false -> - Pass = ejabberd_odbc:escape(Password), case catch odbc_queries:set_password_t(LServer, - Username, Pass) + LUser, Password) of {atomic, ok} -> ok; Other -> {error, Other} diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 4f818f51323..b7aff7b148f 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -616,9 +616,9 @@ pgsql_prepare(SQLQuery, State) -> pgsql_execute_escape() -> #sql_escape{string = fun(X) -> X end, - integer = fun(X) -> integer_to_binary(X) end, - boolean = fun(true) -> <<"1">>; - (false) -> <<"0">> + integer = fun(X) -> [integer_to_binary(X)] end, + boolean = fun(true) -> "1"; + (false) -> "0" end }. diff --git a/src/mod_blocking.erl b/src/mod_blocking.erl index 981c5735f92..815884ff220 100644 --- a/src/mod_blocking.erl +++ b/src/mod_blocking.erl @@ -223,23 +223,18 @@ process_blocklist_block(LUser, LServer, Filter, odbc) -> Default = case mod_privacy:sql_get_default_privacy_list_t(LUser) of - {selected, [<<"name">>], []} -> + {selected, []} -> Name = <<"Blocked contacts">>, mod_privacy:sql_add_privacy_list(LUser, Name), mod_privacy:sql_set_default_privacy_list(LUser, Name), Name; - {selected, [<<"name">>], [[Name]]} -> Name + {selected, [{Name}]} -> Name end, - {selected, [<<"id">>], [[ID]]} = + {selected, [{ID}]} = mod_privacy:sql_get_privacy_list_id_t(LUser, Default), - case mod_privacy:sql_get_privacy_list_data_by_id_t(ID) - of - {selected, - [<<"t">>, <<"value">>, <<"action">>, <<"ord">>, - <<"match_all">>, <<"match_iq">>, <<"match_message">>, - <<"match_presence_in">>, <<"match_presence_out">>], - RItems = [_ | _]} -> + case mod_privacy:sql_get_privacy_list_data_by_id_t(ID) of + {selected, RItems = [_ | _]} -> List = lists:flatmap(fun mod_privacy:raw_to_item/1, RItems); _ -> List = [] end, @@ -345,17 +340,12 @@ unblock_by_filter(LUser, LServer, Filter, odbc) -> F = fun () -> case mod_privacy:sql_get_default_privacy_list_t(LUser) of - {selected, [<<"name">>], []} -> ok; - {selected, [<<"name">>], [[Default]]} -> - {selected, [<<"id">>], [[ID]]} = + {selected, []} -> ok; + {selected, [{Default}]} -> + {selected, [{ID}]} = mod_privacy:sql_get_privacy_list_id_t(LUser, Default), - case mod_privacy:sql_get_privacy_list_data_by_id_t(ID) - of - {selected, - [<<"t">>, <<"value">>, <<"action">>, <<"ord">>, - <<"match_all">>, <<"match_iq">>, <<"match_message">>, - <<"match_presence_in">>, <<"match_presence_out">>], - RItems = [_ | _]} -> + case mod_privacy:sql_get_privacy_list_data_by_id_t(ID) of + {selected, RItems = [_ | _]} -> List = lists:flatmap(fun mod_privacy:raw_to_item/1, RItems), NewList = Filter(List), @@ -435,16 +425,12 @@ process_blocklist_get(LUser, LServer, odbc) -> case catch mod_privacy:sql_get_default_privacy_list(LUser, LServer) of - {selected, [<<"name">>], []} -> []; - {selected, [<<"name">>], [[Default]]} -> + {selected, []} -> []; + {selected, [{Default}]} -> case catch mod_privacy:sql_get_privacy_list_data(LUser, LServer, Default) of - {selected, - [<<"t">>, <<"value">>, <<"action">>, <<"ord">>, - <<"match_all">>, <<"match_iq">>, <<"match_message">>, - <<"match_presence_in">>, <<"match_presence_out">>], - RItems} -> + {selected, RItems} -> lists:flatmap(fun mod_privacy:raw_to_item/1, RItems); {'EXIT', _} -> error end; diff --git a/src/mod_privacy.erl b/src/mod_privacy.erl index e8e6ee7bea5..193befe8224 100644 --- a/src/mod_privacy.erl +++ b/src/mod_privacy.erl @@ -181,16 +181,14 @@ process_lists_get(LUser, LServer, _Active, riak) -> error end; process_lists_get(LUser, LServer, _Active, odbc) -> - Default = case catch sql_get_default_privacy_list(LUser, - LServer) - of - {selected, [<<"name">>], []} -> none; - {selected, [<<"name">>], [[DefName]]} -> DefName; + Default = case catch sql_get_default_privacy_list(LUser, LServer) of + {selected, []} -> none; + {selected, [{DefName}]} -> DefName; _ -> none end, case catch sql_get_privacy_list_names(LUser, LServer) of - {selected, [<<"name">>], Names} -> - LItems = lists:map(fun ([N]) -> + {selected, Names} -> + LItems = lists:map(fun ({N}) -> #xmlel{name = <<"list">>, attrs = [{<<"name">>, N}], children = []} @@ -242,17 +240,11 @@ process_list_get(LUser, LServer, Name, riak) -> error end; process_list_get(LUser, LServer, Name, odbc) -> - case catch sql_get_privacy_list_id(LUser, LServer, Name) - of - {selected, [<<"id">>], []} -> not_found; - {selected, [<<"id">>], [[ID]]} -> - case catch sql_get_privacy_list_data_by_id(ID, LServer) - of - {selected, - [<<"t">>, <<"value">>, <<"action">>, <<"ord">>, - <<"match_all">>, <<"match_iq">>, <<"match_message">>, - <<"match_presence_in">>, <<"match_presence_out">>], - RItems} -> + case catch sql_get_privacy_list_id(LUser, LServer, Name) of + {selected, []} -> not_found; + {selected, [{ID}]} -> + case catch sql_get_privacy_list_data_by_id(ID, LServer) of + {selected, RItems} -> lists:flatmap(fun raw_to_item/1, RItems); _ -> error end; @@ -405,9 +397,9 @@ process_default_set(LUser, LServer, {value, Name}, odbc) -> F = fun () -> case sql_get_privacy_list_names_t(LUser) of - {selected, [<<"name">>], []} -> not_found; - {selected, [<<"name">>], Names} -> - case lists:member([Name], Names) of + {selected, []} -> not_found; + {selected, Names} -> + case lists:member({Name}, Names) of true -> sql_set_default_privacy_list(LUser, Name), ok; false -> not_found end @@ -473,17 +465,11 @@ process_active_set(LUser, LServer, Name, riak) -> error end; process_active_set(LUser, LServer, Name, odbc) -> - case catch sql_get_privacy_list_id(LUser, LServer, Name) - of - {selected, [<<"id">>], []} -> error; - {selected, [<<"id">>], [[ID]]} -> - case catch sql_get_privacy_list_data_by_id(ID, LServer) - of - {selected, - [<<"t">>, <<"value">>, <<"action">>, <<"ord">>, - <<"match_all">>, <<"match_iq">>, <<"match_message">>, - <<"match_presence_in">>, <<"match_presence_out">>], - RItems} -> + case catch sql_get_privacy_list_id(LUser, LServer, Name) of + {selected, []} -> error; + {selected, [{ID}]} -> + case catch sql_get_privacy_list_data_by_id(ID, LServer) of + {selected, RItems} -> lists:flatmap(fun raw_to_item/1, RItems); _ -> error end; @@ -520,9 +506,9 @@ remove_privacy_list(LUser, LServer, Name, riak) -> remove_privacy_list(LUser, LServer, Name, odbc) -> F = fun () -> case sql_get_default_privacy_list_t(LUser) of - {selected, [<<"name">>], []} -> + {selected, []} -> sql_remove_privacy_list(LUser, Name), ok; - {selected, [<<"name">>], [[Default]]} -> + {selected, [{Default}]} -> if Name == Default -> conflict; true -> sql_remove_privacy_list(LUser, Name), ok end @@ -590,12 +576,12 @@ set_privacy_list(LUser, LServer, Name, List, odbc) -> RItems = lists:map(fun item_to_raw/1, List), F = fun () -> ID = case sql_get_privacy_list_id_t(LUser, Name) of - {selected, [<<"id">>], []} -> + {selected, []} -> sql_add_privacy_list(LUser, Name), - {selected, [<<"id">>], [[I]]} = + {selected, [{I}]} = sql_get_privacy_list_id_t(LUser, Name), I; - {selected, [<<"id">>], [[I]]} -> I + {selected, [{I}]} -> I end, sql_set_privacy_list(ID, RItems), ok @@ -785,16 +771,11 @@ get_user_list(_, LUser, LServer, riak) -> get_user_list(_, LUser, LServer, odbc) -> case catch sql_get_default_privacy_list(LUser, LServer) of - {selected, [<<"name">>], []} -> {none, []}; - {selected, [<<"name">>], [[Default]]} -> + {selected, []} -> {none, []}; + {selected, [{Default}]} -> case catch sql_get_privacy_list_data(LUser, LServer, - Default) - of - {selected, - [<<"t">>, <<"value">>, <<"action">>, <<"ord">>, - <<"match_all">>, <<"match_iq">>, <<"match_message">>, - <<"match_presence_in">>, <<"match_presence_out">>], - RItems} -> + Default) of + {selected, RItems} -> {Default, lists:flatmap(fun raw_to_item/1, RItems)}; _ -> {none, []} end; @@ -822,26 +803,21 @@ get_user_lists(LUser, LServer, riak) -> end; get_user_lists(LUser, LServer, odbc) -> Default = case catch sql_get_default_privacy_list(LUser, LServer) of - {selected, [<<"name">>], []} -> + {selected, []} -> none; - {selected, [<<"name">>], [[DefName]]} -> + {selected, [{DefName}]} -> DefName; _ -> none end, case catch sql_get_privacy_list_names(LUser, LServer) of - {selected, [<<"name">>], Names} -> + {selected, Names} -> Lists = lists:flatmap( - fun([Name]) -> + fun({Name}) -> case catch sql_get_privacy_list_data( LUser, LServer, Name) of - {selected, - [<<"t">>, <<"value">>, <<"action">>, - <<"ord">>, <<"match_all">>, <<"match_iq">>, - <<"match_message">>, <<"match_presence_in">>, - <<"match_presence_out">>], - RItems} -> + {selected, RItems} -> [{Name, lists:flatmap(fun raw_to_item/1, RItems)}]; _ -> [] @@ -994,9 +970,9 @@ updated_list(_, #userlist{name = OldName} = Old, true -> Old end. -raw_to_item([SType, SValue, SAction, SOrder, SMatchAll, - SMatchIQ, SMatchMessage, SMatchPresenceIn, - SMatchPresenceOut] = Row) -> +raw_to_item({SType, SValue, SAction, Order, MatchAll, + MatchIQ, MatchMessage, MatchPresenceIn, + MatchPresenceOut} = Row) -> try {Type, Value} = case SType of <<"n">> -> {none, none}; @@ -1018,12 +994,6 @@ raw_to_item([SType, SValue, SAction, SOrder, SMatchAll, <<"a">> -> allow; <<"d">> -> deny end, - Order = jlib:binary_to_integer(SOrder), - MatchAll = ejabberd_odbc:to_bool(SMatchAll), - MatchIQ = ejabberd_odbc:to_bool(SMatchIQ), - MatchMessage = ejabberd_odbc:to_bool(SMatchMessage), - MatchPresenceIn = ejabberd_odbc:to_bool(SMatchPresenceIn), - MatchPresenceOut = ejabberd_odbc:to_bool(SMatchPresenceOut), [#listitem{type = Type, value = Value, action = Action, order = Order, match_all = MatchAll, match_iq = MatchIQ, match_message = MatchMessage, @@ -1057,58 +1027,29 @@ item_to_raw(#listitem{type = Type, value = Value, allow -> <<"a">>; deny -> <<"d">> end, - SOrder = iolist_to_binary(integer_to_list(Order)), - SMatchAll = if MatchAll -> <<"1">>; - true -> <<"0">> - end, - SMatchIQ = if MatchIQ -> <<"1">>; - true -> <<"0">> - end, - SMatchMessage = if MatchMessage -> <<"1">>; - true -> <<"0">> - end, - SMatchPresenceIn = if MatchPresenceIn -> <<"1">>; - true -> <<"0">> - end, - SMatchPresenceOut = if MatchPresenceOut -> <<"1">>; - true -> <<"0">> - end, - [SType, SValue, SAction, SOrder, SMatchAll, SMatchIQ, - SMatchMessage, SMatchPresenceIn, SMatchPresenceOut]. + {SType, SValue, SAction, Order, MatchAll, MatchIQ, + MatchMessage, MatchPresenceIn, MatchPresenceOut}. sql_get_default_privacy_list(LUser, LServer) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:get_default_privacy_list(LServer, - Username). + odbc_queries:get_default_privacy_list(LServer, LUser). sql_get_default_privacy_list_t(LUser) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:get_default_privacy_list_t(Username). + odbc_queries:get_default_privacy_list_t(LUser). sql_get_privacy_list_names(LUser, LServer) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:get_privacy_list_names(LServer, Username). + odbc_queries:get_privacy_list_names(LServer, LUser). sql_get_privacy_list_names_t(LUser) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:get_privacy_list_names_t(Username). + odbc_queries:get_privacy_list_names_t(LUser). sql_get_privacy_list_id(LUser, LServer, Name) -> - Username = ejabberd_odbc:escape(LUser), - SName = ejabberd_odbc:escape(Name), - odbc_queries:get_privacy_list_id(LServer, Username, - SName). + odbc_queries:get_privacy_list_id(LServer, LUser, Name). sql_get_privacy_list_id_t(LUser, Name) -> - Username = ejabberd_odbc:escape(LUser), - SName = ejabberd_odbc:escape(Name), - odbc_queries:get_privacy_list_id_t(Username, SName). + odbc_queries:get_privacy_list_id_t(LUser, Name). sql_get_privacy_list_data(LUser, LServer, Name) -> - Username = ejabberd_odbc:escape(LUser), - SName = ejabberd_odbc:escape(Name), - odbc_queries:get_privacy_list_data(LServer, Username, - SName). + odbc_queries:get_privacy_list_data(LServer, LUser, Name). sql_get_privacy_list_data_t(LUser, Name) -> Username = ejabberd_odbc:escape(LUser), @@ -1122,33 +1063,22 @@ sql_get_privacy_list_data_by_id_t(ID) -> odbc_queries:get_privacy_list_data_by_id_t(ID). sql_set_default_privacy_list(LUser, Name) -> - Username = ejabberd_odbc:escape(LUser), - SName = ejabberd_odbc:escape(Name), - odbc_queries:set_default_privacy_list(Username, SName). + odbc_queries:set_default_privacy_list(LUser, Name). sql_unset_default_privacy_list(LUser, LServer) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:unset_default_privacy_list(LServer, - Username). + odbc_queries:unset_default_privacy_list(LServer, LUser). sql_remove_privacy_list(LUser, Name) -> - Username = ejabberd_odbc:escape(LUser), - SName = ejabberd_odbc:escape(Name), - odbc_queries:remove_privacy_list(Username, SName). + odbc_queries:remove_privacy_list(LUser, Name). sql_add_privacy_list(LUser, Name) -> - Username = ejabberd_odbc:escape(LUser), - SName = ejabberd_odbc:escape(Name), - odbc_queries:add_privacy_list(Username, SName). + odbc_queries:add_privacy_list(LUser, Name). sql_set_privacy_list(ID, RItems) -> odbc_queries:set_privacy_list(ID, RItems). sql_del_privacy_lists(LUser, LServer) -> - Username = ejabberd_odbc:escape(LUser), - Server = ejabberd_odbc:escape(LServer), - odbc_queries:del_privacy_lists(LServer, Server, - Username). + odbc_queries:del_privacy_lists(LServer, LUser). update_table() -> Fields = record_info(fields, privacy), diff --git a/src/mod_private.erl b/src/mod_private.erl index ee3a6c1f332..f3dceeaafbe 100644 --- a/src/mod_private.erl +++ b/src/mod_private.erl @@ -152,11 +152,8 @@ set_data(LUser, LServer, {XmlNS, Xmlel}, mnesia) -> {LUser, LServer, XmlNS}, xml = Xmlel}); set_data(LUser, LServer, {XMLNS, El}, odbc) -> - Username = ejabberd_odbc:escape(LUser), - LXMLNS = ejabberd_odbc:escape(XMLNS), - SData = ejabberd_odbc:escape(fxml:element_to_binary(El)), - odbc_queries:set_private_data(LServer, Username, LXMLNS, - SData); + SData = fxml:element_to_binary(El), + odbc_queries:set_private_data(LServer, LUser, XMLNS, SData); set_data(LUser, LServer, {XMLNS, El}, riak) -> ejabberd_riak:put(#private_storage{usns = {LUser, LServer, XMLNS}, xml = El}, @@ -184,12 +181,10 @@ get_data(LUser, LServer, mnesia, end; get_data(LUser, LServer, odbc, [{XMLNS, El} | Els], Res) -> - Username = ejabberd_odbc:escape(LUser), - LXMLNS = ejabberd_odbc:escape(XMLNS), case catch odbc_queries:get_private_data(LServer, - Username, LXMLNS) + LUser, XMLNS) of - {selected, [<<"data">>], [[SData]]} -> + {selected, [{SData}]} -> case fxml_stream:parse_element(SData) of Data when is_record(Data, xmlel) -> get_data(LUser, LServer, odbc, Els, [Data | Res]) @@ -217,11 +212,10 @@ get_all_data(LUser, LServer, mnesia) -> xml = '$1'}, [], ['$1']}])); get_all_data(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_private_data(LServer, Username) of - {selected, [<<"namespace">>, <<"data">>], Res} -> + case catch odbc_queries:get_private_data(LServer, LUser) of + {selected, Res} -> lists:flatmap( - fun([_, SData]) -> + fun({_, SData}) -> case fxml_stream:parse_element(SData) of #xmlel{} = El -> [El]; @@ -269,9 +263,7 @@ remove_user(LUser, LServer, mnesia) -> end, mnesia:transaction(F); remove_user(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - odbc_queries:del_user_private_storage(LServer, - Username); + odbc_queries:del_user_private_storage(LServer, LUser); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete_by_index(private_storage, <<"us">>, {LUser, LServer})}. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 283e33dfe97..73abc2a0a6c 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -56,7 +56,7 @@ set_default_privacy_list/2, unset_default_privacy_list/2, remove_privacy_list/2, add_privacy_list/2, set_privacy_list/2, - del_privacy_lists/3, set_vcard/26, get_vcard/2, + del_privacy_lists/2, set_vcard/26, get_vcard/2, escape/1, count_records_where/3, get_roster_version/2, set_roster_version/2, opt_type/1]). @@ -151,33 +151,29 @@ get_password_scram(LServer, LUser) -> " from users" " where username=%(LUser)s")). -set_password_t(LServer, Username, Pass) -> - ejabberd_odbc:sql_transaction(LServer, - fun () -> - update_t(<<"users">>, - [<<"username">>, - <<"password">>], - [Username, Pass], - [<<"username='">>, Username, - <<"'">>]) - end). +set_password_t(LServer, LUser, Password) -> + ejabberd_odbc:sql_transaction( + LServer, + fun () -> + ?SQL_UPSERT_T( + "users", + ["!username=%(LUser)s", + "password=%(Password)s"]) + end). -set_password_scram_t(LServer, Username, +set_password_scram_t(LServer, LUser, StoredKey, ServerKey, Salt, IterationCount) -> - ejabberd_odbc:sql_transaction(LServer, - fun () -> - update_t(<<"users">>, - [<<"username">>, - <<"password">>, - <<"serverkey">>, - <<"salt">>, - <<"iterationcount">>], - [Username, StoredKey, - ServerKey, Salt, - IterationCount], - [<<"username='">>, Username, - <<"'">>]) - end). + ejabberd_odbc:sql_transaction( + LServer, + fun () -> + ?SQL_UPSERT_T( + "users", + ["!username=%(LUser)s", + "password=%(StoredKey)s", + "serverkey=%(ServerKey)s", + "salt=%(Salt)s", + "iterationcount=%(IterationCount)d"]) + end). add_user(LServer, Username, Pass) -> ejabberd_odbc:sql_query(LServer, @@ -428,12 +424,12 @@ get_subscription(LServer, LUser, SJID) -> ?SQL("select @(subscription)s from rosterusers " "where username=%(LUser)s and jid=%(SJID)s")). -set_private_data(_LServer, Username, LXMLNS, SData) -> - update_t(<<"private_storage">>, - [<<"username">>, <<"namespace">>, <<"data">>], - [Username, LXMLNS, SData], - [<<"username='">>, Username, <<"' and namespace='">>, - LXMLNS, <<"'">>]). +set_private_data(_LServer, LUser, XMLNS, SData) -> + ?SQL_UPSERT_T( + "private_storage", + ["!username=%(LUser)s", + "!namespace=%(XMLNS)s", + "data=%(SData)s"]). set_private_data_sql(Username, LXMLNS, SData) -> [[<<"delete from private_storage where username='">>, @@ -443,22 +439,23 @@ set_private_data_sql(Username, LXMLNS, SData) -> Username, <<"', '">>, LXMLNS, <<"', '">>, SData, <<"');">>]]. -get_private_data(LServer, Username, LXMLNS) -> - ejabberd_odbc:sql_query(LServer, - [<<"select data from private_storage where " - "username='">>, - Username, <<"' and namespace='">>, LXMLNS, - <<"';">>]). +get_private_data(LServer, LUser, XMLNS) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(data)s from private_storage" + " where username=%(LUser)s and namespace=%(XMLNS)s")). -get_private_data(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select namespace, data from private_storage " - "where username='">>, Username, <<"';">>]). +get_private_data(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(namespace)s, @(data)s from private_storage" + " where username=%(LUser)s")). -del_user_private_storage(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"delete from private_storage where username='">>, - Username, <<"';">>]). +del_user_private_storage(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from private_storage" + " where username=%(LUser)s")). set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, SFamily, SGiven, SLBDay, SLCTRY, SLEMail, SLFN, @@ -508,122 +505,128 @@ get_vcard(LServer, Username) -> [<<"select vcard from vcard where username='">>, Username, <<"';">>]). -get_default_privacy_list(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select name from privacy_default_list " - "where username='">>, - Username, <<"';">>]). +get_default_privacy_list(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(name)s from privacy_default_list " + "where username=%(LUser)s")). -get_default_privacy_list_t(Username) -> - ejabberd_odbc:sql_query_t([<<"select name from privacy_default_list " - "where username='">>, - Username, <<"';">>]). +get_default_privacy_list_t(LUser) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(name)s from privacy_default_list " + "where username=%(LUser)s")). -get_privacy_list_names(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select name from privacy_list where " - "username='">>, - Username, <<"';">>]). +get_privacy_list_names(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(name)s from privacy_list" + " where username=%(LUser)s")). -get_privacy_list_names_t(Username) -> - ejabberd_odbc:sql_query_t([<<"select name from privacy_list where " - "username='">>, - Username, <<"';">>]). +get_privacy_list_names_t(LUser) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(name)s from privacy_list" + " where username=%(LUser)s")). -get_privacy_list_id(LServer, Username, SName) -> - ejabberd_odbc:sql_query(LServer, - [<<"select id from privacy_list where username='">>, - Username, <<"' and name='">>, SName, <<"';">>]). +get_privacy_list_id(LServer, LUser, Name) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(id)d from privacy_list" + " where username=%(LUser)s and name=%(Name)s")). -get_privacy_list_id_t(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"select id from privacy_list where username='">>, - Username, <<"' and name='">>, SName, <<"';">>]). +get_privacy_list_id_t(LUser, Name) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(id)d from privacy_list" + " where username=%(LUser)s and name=%(Name)s")). -get_privacy_list_data(LServer, Username, SName) -> - ejabberd_odbc:sql_query(LServer, - [<<"select t, value, action, ord, match_all, " - "match_iq, match_message, match_presence_in, " - "match_presence_out from privacy_list_data " - "where id = (select id from privacy_list " - "where username='">>, - Username, <<"' and name='">>, SName, - <<"') order by ord;">>]). - -get_privacy_list_data_t(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"select t, value, action, ord, match_all, " - "match_iq, match_message, match_presence_in, " - "match_presence_out from privacy_list_data " - "where id = (select id from privacy_list " - "where username='">>, - Username, <<"' and name='">>, SName, - <<"') order by ord;">>]). +get_privacy_list_data(LServer, LUser, Name) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(t)s, @(value)s, @(action)s, @(ord)d, @(match_all)b, " + "@(match_iq)b, @(match_message)b, @(match_presence_in)b, " + "@(match_presence_out)b from privacy_list_data " + "where id =" + " (select id from privacy_list" + " where username=%(LUser)s and name=%(Name)s) " + "order by ord")). + +%% Not used? +get_privacy_list_data_t(LUser, Name) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(t)s, @(value)s, @(action)s, @(ord)d, @(match_all)b, " + "@(match_iq)b, @(match_message)b, @(match_presence_in)b, " + "@(match_presence_out)b from privacy_list_data " + "where id =" + " (select id from privacy_list" + " where username=%(LUser)s and name=%(Name)s) " + "order by ord")). get_privacy_list_data_by_id(LServer, ID) -> - ejabberd_odbc:sql_query(LServer, - [<<"select t, value, action, ord, match_all, " - "match_iq, match_message, match_presence_in, " - "match_presence_out from privacy_list_data " - "where id='">>, - ID, <<"' order by ord;">>]). + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(t)s, @(value)s, @(action)s, @(ord)d, @(match_all)b, " + "@(match_iq)b, @(match_message)b, @(match_presence_in)b, " + "@(match_presence_out)b from privacy_list_data " + "where id=%(ID)d order by ord")). get_privacy_list_data_by_id_t(ID) -> - ejabberd_odbc:sql_query_t([<<"select t, value, action, ord, match_all, " - "match_iq, match_message, match_presence_in, " - "match_presence_out from privacy_list_data " - "where id='">>, - ID, <<"' order by ord;">>]). - -set_default_privacy_list(Username, SName) -> - update_t(<<"privacy_default_list">>, - [<<"username">>, <<"name">>], [Username, SName], - [<<"username='">>, Username, <<"'">>]). - -unset_default_privacy_list(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"delete from privacy_default_list " - " where username='">>, - Username, <<"';">>]). + ejabberd_odbc:sql_query_t( + ?SQL("select @(t)s, @(value)s, @(action)s, @(ord)d, @(match_all)b, " + "@(match_iq)b, @(match_message)b, @(match_presence_in)b, " + "@(match_presence_out)b from privacy_list_data " + "where id=%(ID)d order by ord")). + +set_default_privacy_list(LUser, Name) -> + ?SQL_UPSERT_T( + "privacy_default_list", + ["!username=%(LUser)s", + "name=%(Name)s"]). + +unset_default_privacy_list(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from privacy_default_list" + " where username=%(LUser)s")). -remove_privacy_list(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"delete from privacy_list where username='">>, - Username, <<"' and name='">>, SName, <<"';">>]). +remove_privacy_list(LUser, Name) -> + ejabberd_odbc:sql_query_t( + ?SQL("delete from privacy_list where" + " username=%(LUser)s and name=%(Name)s")). -add_privacy_list(Username, SName) -> - ejabberd_odbc:sql_query_t([<<"insert into privacy_list(username, name) " - "values ('">>, - Username, <<"', '">>, SName, <<"');">>]). +add_privacy_list(LUser, Name) -> + ejabberd_odbc:sql_query_t( + ?SQL("insert into privacy_list(username, name) " + "values (%(LUser)s, %(Name)s)")). set_privacy_list(ID, RItems) -> - ejabberd_odbc:sql_query_t([<<"delete from privacy_list_data where " - "id='">>, - ID, <<"';">>]), - lists:foreach(fun (Items) -> - ejabberd_odbc:sql_query_t([<<"insert into privacy_list_data(id, t, " - "value, action, ord, match_all, match_iq, " - "match_message, match_presence_in, match_prese" - "nce_out ) values ('">>, - ID, <<"', '">>, - join(Items, <<"', '">>), - <<"');">>]) + ejabberd_odbc:sql_query_t( + ?SQL("delete from privacy_list_data where id=%(ID)d")), + lists:foreach( + fun({SType, SValue, SAction, Order, MatchAll, MatchIQ, + MatchMessage, MatchPresenceIn, MatchPresenceOut}) -> + ejabberd_odbc:sql_query_t( + ?SQL("insert into privacy_list_data(id, t, " + "value, action, ord, match_all, match_iq, " + "match_message, match_presence_in, match_presence_out) " + "values (%(ID)d, %(SType)s, %(SValue)s, %(SAction)s," + " %(Order)d, %(MatchAll)b, %(MatchIQ)b," + " %(MatchMessage)b, %(MatchPresenceIn)b," + " %(MatchPresenceOut)b)")) end, RItems). -del_privacy_lists(LServer, Server, Username) -> -%% Characters to escape -%% Count number of records in a table given a where clause - ejabberd_odbc:sql_query(LServer, - [<<"delete from privacy_list where username='">>, - Username, <<"';">>]), - ejabberd_odbc:sql_query(LServer, - [<<"delete from privacy_list_data where " - "value='">>, - <>, - <<"';">>]), - ejabberd_odbc:sql_query(LServer, - [<<"delete from privacy_default_list where " - "username='">>, - Username, <<"';">>]). +del_privacy_lists(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from privacy_list where username=%(LUser)s")), + %US = <>, + %ejabberd_odbc:sql_query( + % LServer, + % ?SQL("delete from privacy_list_data where value=%(US)s")), + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from privacy_default_list where username=%(LUser)s")). +%% Characters to escape escape($\000) -> <<"\\0">>; escape($\n) -> <<"\\n">>; escape($\t) -> <<"\\t">>; @@ -634,6 +637,7 @@ escape($") -> <<"\\\"">>; escape($\\) -> <<"\\\\">>; escape(C) -> <>. +%% Count number of records in a table given a where clause count_records_where(LServer, Table, WhereClause) -> ejabberd_odbc:sql_query(LServer, [<<"select count(*) from ">>, Table, <<" ">>, From 968576d4f202dab5776a999b69cb3a8166722678 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Tue, 23 Feb 2016 17:27:30 +0300 Subject: [PATCH 617/695] Update p1_pgsql tag --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 12b03ffefdb..d662f4190bf 100644 --- a/rebar.config +++ b/rebar.config @@ -24,7 +24,7 @@ {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.1"}}}}, {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", - {tag, "1.0.1"}}}}, + {tag, "1.1.0"}}}}, {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.5"}}}}, {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", From 1f9fd25ff8820fddab4fc36bc9c75a697031db49 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 25 Feb 2016 20:31:58 +0300 Subject: [PATCH 618/695] Update more SQL queries --- src/ejabberd_auth_odbc.erl | 97 ++++++++++++++------------ src/ejabberd_odbc.erl | 10 ++- src/odbc_queries.erl | 138 +++++++++++++++++-------------------- 3 files changed, 127 insertions(+), 118 deletions(-) diff --git a/src/ejabberd_auth_odbc.erl b/src/ejabberd_auth_odbc.erl index f38c8286c32..18d0620129b 100644 --- a/src/ejabberd_auth_odbc.erl +++ b/src/ejabberd_auth_odbc.erl @@ -187,26 +187,23 @@ try_register(User, Server, Password) -> (LUser == <<>>) or (LServer == <<>>) -> {error, invalid_jid}; true -> - Username = ejabberd_odbc:escape(LUser), case is_scrammed() of true -> Scram = password_to_scram(Password), case catch odbc_queries:add_user_scram( LServer, - Username, - ejabberd_odbc:escape(Scram#scram.storedkey), - ejabberd_odbc:escape(Scram#scram.serverkey), - ejabberd_odbc:escape(Scram#scram.salt), - integer_to_binary(Scram#scram.iterationcount) + LUser, + Scram#scram.storedkey, + Scram#scram.serverkey, + Scram#scram.salt, + Scram#scram.iterationcount ) of {updated, 1} -> {atomic, ok}; _ -> {atomic, exists} end; false -> - Pass = ejabberd_odbc:escape(Password), - case catch odbc_queries:add_user(LServer, Username, - Pass) - of + case catch odbc_queries:add_user(LServer, LUser, + Password) of {updated, 1} -> {atomic, ok}; _ -> {atomic, exists} end @@ -221,35 +218,51 @@ dirty_get_registered_users() -> Servers). get_vh_registered_users(Server) -> - LServer = jid:nameprep(Server), - case catch odbc_queries:list_users(LServer) of - {selected, [<<"username">>], Res} -> - [{U, LServer} || [U] <- Res]; - _ -> [] + case jid:nameprep(Server) of + error -> []; + <<>> -> []; + LServer -> + case catch odbc_queries:list_users(LServer) of + {selected, Res} -> + [{U, LServer} || {U} <- Res]; + _ -> [] + end end. get_vh_registered_users(Server, Opts) -> - LServer = jid:nameprep(Server), - case catch odbc_queries:list_users(LServer, Opts) of - {selected, [<<"username">>], Res} -> - [{U, LServer} || [U] <- Res]; - _ -> [] + case jid:nameprep(Server) of + error -> []; + <<>> -> []; + LServer -> + case catch odbc_queries:list_users(LServer, Opts) of + {selected, Res} -> + [{U, LServer} || {U} <- Res]; + _ -> [] + end end. get_vh_registered_users_number(Server) -> - LServer = jid:nameprep(Server), - case catch odbc_queries:users_number(LServer) of - {selected, [_], [[Res]]} -> - jlib:binary_to_integer(Res); - _ -> 0 + case jid:nameprep(Server) of + error -> 0; + <<>> -> 0; + LServer -> + case catch odbc_queries:users_number(LServer) of + {selected, [{Res}]} -> + Res; + _ -> 0 + end end. get_vh_registered_users_number(Server, Opts) -> - LServer = jid:nameprep(Server), - case catch odbc_queries:users_number(LServer, Opts) of - {selected, [_], [[Res]]} -> - jlib:binary_to_integer(Res); - _Other -> 0 + case jid:nameprep(Server) of + error -> 0; + <<>> -> 0; + LServer -> + case catch odbc_queries:users_number(LServer, Opts) of + {selected, [{Res}]} -> + Res; + _Other -> 0 + end end. get_password(User, Server) -> @@ -323,12 +336,14 @@ is_user_exists(User, Server) -> %% @doc Remove user. %% Note: it may return ok even if there was some problem removing the user. remove_user(User, Server) -> - case jid:nodeprep(User) of - error -> error; - LUser -> - Username = ejabberd_odbc:escape(LUser), - LServer = jid:nameprep(Server), - catch odbc_queries:del_user(LServer, Username), + LServer = jid:nameprep(Server), + LUser = jid:nodeprep(User), + if (LUser == error) or (LServer == error) -> + error; + (LUser == <<>>) or (LServer == <<>>) -> + error; + true -> + catch odbc_queries:del_user(LServer, LUser), ok end. @@ -351,16 +366,12 @@ remove_user(User, Server, Password) -> false -> not_allowed end; false -> - Username = ejabberd_odbc:escape(LUser), - Pass = ejabberd_odbc:escape(Password), F = fun () -> Result = odbc_queries:del_user_return_password( - LServer, Username, Pass), + LServer, LUser, Password), case Result of - {selected, [<<"password">>], - [[Password]]} -> ok; - {selected, [<<"password">>], - []} -> not_exists; + {selected, [{Password}]} -> ok; + {selected, []} -> not_exists; _ -> not_allowed end end, diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index b7aff7b148f..6f7ce4c8ba0 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -41,6 +41,7 @@ sql_bloc/2, escape/1, escape_like/1, + escape_like_arg/1, to_bool/1, sqlite_db/1, sqlite_file/1, @@ -125,7 +126,7 @@ start_link(Host, StartInterval) -> {error, binary()} | {selected, [binary()], [[binary()]]} | - {selected, [any]}. + {selected, [any()]}. -spec sql_query(binary(), sql_query()) -> sql_query_result(). @@ -199,6 +200,13 @@ escape_like($%) -> <<"\\%">>; escape_like($_) -> <<"\\_">>; escape_like(C) when is_integer(C), C >= 0, C =< 255 -> odbc_queries:escape(C). +escape_like_arg(S) when is_binary(S) -> + << <<(escape_like_arg(C))/binary>> || <> <= S >>; +escape_like_arg($%) -> <<"\\%">>; +escape_like_arg($_) -> <<"\\_">>; +escape_like_arg($\\) -> <<"\\\\">>; +escape_like_arg(C) when is_integer(C), C >= 0, C =< 255 -> <>. + to_bool(<<"t">>) -> true; to_bool(<<"true">>) -> true; to_bool(<<"1">>) -> true; diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 73abc2a0a6c..44e2dbfb092 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -175,39 +175,39 @@ set_password_scram_t(LServer, LUser, "iterationcount=%(IterationCount)d"]) end). -add_user(LServer, Username, Pass) -> - ejabberd_odbc:sql_query(LServer, - [<<"insert into users(username, password) " - "values ('">>, - Username, <<"', '">>, Pass, <<"');">>]). +add_user(LServer, LUser, Password) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("insert into users(username, password) " + "values (%(LUser)s, %(Password)s)")). -add_user_scram(LServer, Username, +add_user_scram(LServer, LUser, StoredKey, ServerKey, Salt, IterationCount) -> - ejabberd_odbc:sql_query(LServer, - [<<"insert into users(username, password, serverkey, salt, iterationcount) " - "values ('">>, - Username, <<"', '">>, StoredKey, <<"', '">>, - ServerKey, <<"', '">>, - Salt, <<"', '">>, - IterationCount, <<"');">>]). - -del_user(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"delete from users where username='">>, Username, - <<"';">>]). + ejabberd_odbc:sql_query( + LServer, + ?SQL("insert into users(username, password, serverkey, salt, " + "iterationcount) " + "values (%(LUser)s, %(StoredKey)s, %(ServerKey)s," + " %(Salt)s, %(IterationCount)d)")). -del_user_return_password(_LServer, Username, Pass) -> +del_user(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("delete from users where username=%(LUser)s")). + +del_user_return_password(_LServer, LUser, Password) -> P = - ejabberd_odbc:sql_query_t([<<"select password from users where username='">>, - Username, <<"';">>]), - ejabberd_odbc:sql_query_t([<<"delete from users where username='">>, - Username, <<"' and password='">>, Pass, - <<"';">>]), + ejabberd_odbc:sql_query_t( + ?SQL("select @(password)s from users where username=%(LUser)s")), + ejabberd_odbc:sql_query_t( + ?SQL("delete from users" + " where username=%(LUser)s and password=%(Password)s")), P. list_users(LServer) -> - ejabberd_odbc:sql_query(LServer, - [<<"select username from users">>]). + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(username)s from users")). list_users(LServer, [{from, Start}, {to, End}]) when is_integer(Start) and is_integer(End) -> @@ -222,64 +222,54 @@ list_users(LServer, {offset, Start - 1}]); list_users(LServer, [{limit, Limit}, {offset, Offset}]) when is_integer(Limit) and is_integer(Offset) -> - ejabberd_odbc:sql_query(LServer, - [list_to_binary( - io_lib:format( - "select username from users " ++ - "order by username " ++ - "limit ~w offset ~w", - [Limit, Offset]))]); + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(username)s from users " + "order by username " + "limit %(Limit)d offset %(Offset)d")); list_users(LServer, [{prefix, Prefix}, {limit, Limit}, {offset, Offset}]) when is_binary(Prefix) and is_integer(Limit) and is_integer(Offset) -> - ejabberd_odbc:sql_query(LServer, - [list_to_binary( - io_lib:format( - "select username from users " ++ - "where username like '~s%' " ++ - "order by username " ++ - "limit ~w offset ~w ", - [Prefix, Limit, Offset]))]). + SPrefix = ejabberd_odbc:escape_like_arg(Prefix), + SPrefix2 = <>, + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(username)s from users " + "where username like %(SPrefix2)s " + "order by username " + "limit %(Limit)d offset %(Offset)d")). users_number(LServer) -> - Type = ejabberd_config:get_option({odbc_type, LServer}, - fun(pgsql) -> pgsql; - (mysql) -> mysql; - (sqlite) -> sqlite; - (odbc) -> odbc - end, odbc), - case Type of - pgsql -> - case - ejabberd_config:get_option( - {pgsql_users_number_estimate, LServer}, - fun(V) when is_boolean(V) -> V end, - false) - of - true -> - ejabberd_odbc:sql_query(LServer, - [<<"select reltuples from pg_class where " - "oid = 'users'::regclass::oid">>]); - _ -> - ejabberd_odbc:sql_query(LServer, - [<<"select count(*) from users">>]) + ejabberd_odbc:sql_query( + LServer, + fun(pgsql, _) -> + case + ejabberd_config:get_option( + {pgsql_users_number_estimate, LServer}, + fun(V) when is_boolean(V) -> V end, + false) of + true -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(reltuples :: bigint)d from pg_class" + " where oid = 'users'::regclass::oid")); + _ -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(count(*))d from users")) end; - _ -> - ejabberd_odbc:sql_query(LServer, - [<<"select count(*) from users">>]) - end. + (_Type, _) -> + ejabberd_odbc:sql_query_t( + ?SQL("select @(count(*))d from users")) + end). users_number(LServer, [{prefix, Prefix}]) when is_binary(Prefix) -> - ejabberd_odbc:sql_query(LServer, - [list_to_binary( - io_lib:fwrite( - "select count(*) from users " ++ - %% Warning: Escape prefix at higher level to prevent SQL - %% injection. - "where username like '~s%'", - [Prefix]))]); + SPrefix = ejabberd_odbc:escape_like_arg(Prefix), + SPrefix2 = <>, + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(count(*))d from users " + "where username like %(SPrefix2)s")); users_number(LServer, []) -> users_number(LServer). From e21f25f5b9229cfa2c97a2c0aec340ff71cfe26c Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Fri, 26 Feb 2016 15:45:28 +0300 Subject: [PATCH 619/695] Update more SQL queries --- src/ejabberd_odbc.erl | 3 +- src/mod_roster.erl | 44 ++++++++---- src/mod_vcard.erl | 65 ++++++----------- src/odbc_queries.erl | 159 ++++++++++++++++++++---------------------- 4 files changed, 128 insertions(+), 143 deletions(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index 6f7ce4c8ba0..f756fdeb1ec 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -121,7 +121,8 @@ start_link(Host, StartInterval) -> [Host, StartInterval], fsm_limit_opts() ++ (?FSMOPTS)). --type sql_query() :: [sql_query() | binary()] | #sql_query{}. +-type sql_query() :: [sql_query() | binary()] | #sql_query{} | + fun(() -> any()) | fun((atom(), _) -> any()). -type sql_query_result() :: {updated, non_neg_integer()} | {error, binary()} | {selected, [binary()], diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 1e5e3b70c22..79655af8ad3 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -694,12 +694,9 @@ roster_subscribe_t(LUser, LServer, LJID, Item) -> roster_subscribe_t(_LUser, _LServer, _LJID, Item, mnesia) -> mnesia:write(Item); -roster_subscribe_t(LUser, LServer, LJID, Item, odbc) -> - ItemVals = record_to_string(Item), - Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jid:to_string(LJID)), - odbc_queries:roster_subscribe(LServer, Username, SJID, - ItemVals); +roster_subscribe_t(_LUser, _LServer, _LJID, Item, odbc) -> + ItemVals = record_to_row(Item), + odbc_queries:roster_subscribe(ItemVals); roster_subscribe_t(LUser, LServer, _LJID, Item, riak) -> ejabberd_riak:put(Item, roster_schema(), [{'2i', [{<<"us">>, {LUser, LServer}}]}]). @@ -1034,11 +1031,10 @@ update_roster_t(_LUser, _LServer, _LJID, Item, mnesia) -> mnesia:write(Item); update_roster_t(LUser, LServer, LJID, Item, odbc) -> - Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jid:to_string(LJID)), - ItemVals = record_to_string(Item), - ItemGroups = groups_to_string(Item), - odbc_queries:update_roster(LServer, Username, SJID, ItemVals, + SJID = jid:to_string(LJID), + ItemVals = record_to_row(Item), + ItemGroups = Item#roster.groups, + odbc_queries:update_roster(LServer, LUser, SJID, ItemVals, ItemGroups); update_roster_t(LUser, LServer, _LJID, Item, riak) -> ejabberd_riak:put(Item, roster_schema(), @@ -1051,9 +1047,8 @@ del_roster_t(LUser, LServer, LJID) -> del_roster_t(LUser, LServer, LJID, mnesia) -> mnesia:delete({roster, {LUser, LServer, LJID}}); del_roster_t(LUser, LServer, LJID, odbc) -> - Username = ejabberd_odbc:escape(LUser), - SJID = ejabberd_odbc:escape(jid:to_string(LJID)), - odbc_queries:del_roster(LServer, Username, SJID); + SJID = jid:to_string(LJID), + odbc_queries:del_roster(LServer, LUser, SJID); del_roster_t(LUser, LServer, LJID, riak) -> ejabberd_riak:delete(roster, {LUser, LServer, LJID}). @@ -1319,6 +1314,27 @@ record_to_string(#roster{us = {User, _Server}, [Username, SJID, Nick, SSubscription, SAsk, SAskMessage, <<"N">>, <<"">>, <<"item">>]. +record_to_row( + #roster{us = {LUser, _LServer}, + jid = JID, name = Name, subscription = Subscription, + ask = Ask, askmessage = AskMessage}) -> + SJID = jid:to_string(jid:tolower(JID)), + 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, + {LUser, SJID, Name, SSubscription, SAsk, AskMessage}. + groups_to_string(#roster{us = {User, _Server}, jid = JID, groups = Groups}) -> Username = ejabberd_odbc:escape(User), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index b9b207a7d4f..3652fb2af07 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -25,6 +25,8 @@ -module(mod_vcard). +-compile([{parse_transform, ejabberd_sql_pt}]). + -author('alexey@process-one.net'). -protocol({xep, 54, '1.2'}). @@ -39,6 +41,7 @@ -include("ejabberd.hrl"). -include("logger.hrl"). +-include("ejabberd_sql_pt.hrl"). -include("jlib.hrl"). @@ -212,14 +215,13 @@ get_vcard(LUser, LServer, mnesia) -> {aborted, _Reason} -> error end; get_vcard(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_vcard(LServer, Username) of - {selected, [<<"vcard">>], [[SVCARD]]} -> + case catch odbc_queries:get_vcard(LServer, LUser) of + {selected, [{SVCARD}]} -> case fxml_stream:parse_element(SVCARD) of {error, _Reason} -> error; VCARD -> [VCARD] end; - {selected, [<<"vcard">>], []} -> []; + {selected, []} -> []; _ -> error end; get_vcard(LUser, LServer, riak) -> @@ -336,39 +338,14 @@ set_vcard(User, LServer, VCARD) -> {<<"orgunit">>, OrgUnit}, {<<"lorgunit">>, LOrgUnit}]}]); odbc -> - Username = ejabberd_odbc:escape(User), - LUsername = ejabberd_odbc:escape(LUser), - SVCARD = - ejabberd_odbc:escape(fxml:element_to_binary(VCARD)), - SFN = ejabberd_odbc:escape(FN), - SLFN = ejabberd_odbc:escape(LFN), - SFamily = ejabberd_odbc:escape(Family), - SLFamily = ejabberd_odbc:escape(LFamily), - SGiven = ejabberd_odbc:escape(Given), - SLGiven = ejabberd_odbc:escape(LGiven), - SMiddle = ejabberd_odbc:escape(Middle), - SLMiddle = ejabberd_odbc:escape(LMiddle), - SNickname = ejabberd_odbc:escape(Nickname), - SLNickname = ejabberd_odbc:escape(LNickname), - SBDay = ejabberd_odbc:escape(BDay), - SLBDay = ejabberd_odbc:escape(LBDay), - SCTRY = ejabberd_odbc:escape(CTRY), - SLCTRY = ejabberd_odbc:escape(LCTRY), - SLocality = ejabberd_odbc:escape(Locality), - SLLocality = ejabberd_odbc:escape(LLocality), - SEMail = ejabberd_odbc:escape(EMail), - SLEMail = ejabberd_odbc:escape(LEMail), - SOrgName = ejabberd_odbc:escape(OrgName), - SLOrgName = ejabberd_odbc:escape(LOrgName), - SOrgUnit = ejabberd_odbc:escape(OrgUnit), - SLOrgUnit = ejabberd_odbc:escape(LOrgUnit), - odbc_queries:set_vcard(LServer, LUsername, SBDay, SCTRY, - SEMail, SFN, SFamily, SGiven, SLBDay, - SLCTRY, SLEMail, SLFN, SLFamily, - SLGiven, SLLocality, SLMiddle, - SLNickname, SLOrgName, SLOrgUnit, - SLocality, SMiddle, SNickname, SOrgName, - SOrgUnit, SVCARD, Username) + SVCARD = fxml:element_to_binary(VCARD), + odbc_queries:set_vcard(LServer, LUser, BDay, CTRY, + EMail, FN, Family, Given, LBDay, + LCTRY, LEMail, LFN, LFamily, + LGiven, LLocality, LMiddle, + LNickname, LOrgName, LOrgUnit, + Locality, Middle, Nickname, OrgName, + OrgUnit, SVCARD, User) end, ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD]) @@ -929,12 +906,14 @@ remove_user(LUser, LServer, mnesia) -> end, mnesia:transaction(F); remove_user(LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - ejabberd_odbc:sql_transaction(LServer, - [[<<"delete from vcard where username='">>, - Username, <<"';">>], - [<<"delete from vcard_search where lusername='">>, - Username, <<"';">>]]); + ejabberd_odbc:sql_transaction( + LServer, + fun() -> + ejabberd_odbc:sql_query_t( + ?SQL("delete from vcard where username=%(LUser)s")), + ejabberd_odbc:sql_query_t( + ?SQL("delete from vcard_search where lusername=%(LUser)s")) + end); remove_user(LUser, LServer, riak) -> {atomic, ejabberd_riak:delete(vcard, {LUser, LServer})}. diff --git a/src/odbc_queries.erl b/src/odbc_queries.erl index 44e2dbfb092..c12931c6e06 100644 --- a/src/odbc_queries.erl +++ b/src/odbc_queries.erl @@ -42,7 +42,7 @@ get_roster_groups/3, del_user_roster_t/2, get_roster_by_jid/3, get_rostergroup_by_jid/3, del_roster/3, del_roster_sql/2, update_roster/5, - update_roster_sql/4, roster_subscribe/4, + update_roster_sql/4, roster_subscribe/1, get_subscription/3, set_private_data/4, set_private_data_sql/3, get_private_data/3, get_private_data/2, del_user_private_storage/2, @@ -339,15 +339,13 @@ get_rostergroup_by_jid(LServer, LUser, SJID) -> ?SQL("select @(grp)s from rostergroups" " where username=%(LUser)s and jid=%(SJID)s")). -del_roster(_LServer, Username, SJID) -> - ejabberd_odbc:sql_query_t([<<"delete from rosterusers where " - "username='">>, - Username, <<"' and jid='">>, SJID, - <<"';">>]), - ejabberd_odbc:sql_query_t([<<"delete from rostergroups where " - "username='">>, - Username, <<"' and jid='">>, SJID, - <<"';">>]). +del_roster(_LServer, LUser, SJID) -> + ejabberd_odbc:sql_query_t( + ?SQL("delete from rosterusers" + " where username=%(LUser)s and jid=%(SJID)s")), + ejabberd_odbc:sql_query_t( + ?SQL("delete from rostergroups" + " where username=%(LUser)s and jid=%(SJID)s")). del_roster_sql(Username, SJID) -> [[<<"delete from rosterusers where " @@ -357,27 +355,19 @@ del_roster_sql(Username, SJID) -> "username='">>, Username, <<"' and jid='">>, SJID, <<"';">>]]. -update_roster(_LServer, Username, SJID, ItemVals, +update_roster(_LServer, LUser, SJID, ItemVals, ItemGroups) -> - update_t(<<"rosterusers">>, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - ItemVals, - [<<"username='">>, Username, <<"' and jid='">>, SJID, - <<"'">>]), - ejabberd_odbc:sql_query_t([<<"delete from rostergroups where " - "username='">>, - Username, <<"' and jid='">>, SJID, - <<"';">>]), - lists:foreach(fun (ItemGroup) -> - ejabberd_odbc:sql_query_t([<<"insert into rostergroups( " - " username, jid, grp) values ('">>, - join(ItemGroup, - <<"', '">>), - <<"');">>]) - end, - ItemGroups). + roster_subscribe(ItemVals), + ejabberd_odbc:sql_query_t( + ?SQL("delete from rostergroups" + " where username=%(LUser)s and jid=%(SJID)s")), + lists:foreach( + fun(ItemGroup) -> + ejabberd_odbc:sql_query_t( + ?SQL("insert into rostergroups(username, jid, grp) " + "values (%(LUser)s, %(SJID)s, %(ItemGroup)s)")) + end, + ItemGroups). update_roster_sql(Username, SJID, ItemVals, ItemGroups) -> @@ -399,14 +389,18 @@ update_roster_sql(Username, SJID, ItemVals, join(ItemGroup, <<"', '">>), <<"');">>] || ItemGroup <- ItemGroups]. -roster_subscribe(_LServer, Username, SJID, ItemVals) -> - update_t(<<"rosterusers">>, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - ItemVals, - [<<"username='">>, Username, <<"' and jid='">>, SJID, - <<"'">>]). +roster_subscribe({LUser, SJID, Name, SSubscription, SAsk, AskMessage}) -> + ?SQL_UPSERT_T( + "rosterusers", + ["!username=%(LUser)s", + "!jid=%(SJID)s", + "nick=%(Name)s", + "subscription=%(SSubscription)s", + "ask=%(SAsk)s", + "askmessage=%(AskMessage)s", + "server='N'", + "subscribe=''", + "type='item'"]). get_subscription(LServer, LUser, SJID) -> ejabberd_odbc:sql_query( @@ -447,53 +441,48 @@ del_user_private_storage(LServer, LUser) -> ?SQL("delete from private_storage" " where username=%(LUser)s")). -set_vcard(LServer, LUsername, SBDay, SCTRY, SEMail, SFN, - SFamily, SGiven, SLBDay, SLCTRY, SLEMail, SLFN, - SLFamily, SLGiven, SLLocality, SLMiddle, SLNickname, - SLOrgName, SLOrgUnit, SLocality, SMiddle, SNickname, - SOrgName, SOrgUnit, SVCARD, Username) -> - ejabberd_odbc:sql_transaction(LServer, - fun () -> - update_t(<<"vcard">>, - [<<"username">>, - <<"vcard">>], - [LUsername, SVCARD], - [<<"username='">>, LUsername, - <<"'">>]), - update_t(<<"vcard_search">>, - [<<"username">>, - <<"lusername">>, <<"fn">>, - <<"lfn">>, <<"family">>, - <<"lfamily">>, <<"given">>, - <<"lgiven">>, <<"middle">>, - <<"lmiddle">>, - <<"nickname">>, - <<"lnickname">>, <<"bday">>, - <<"lbday">>, <<"ctry">>, - <<"lctry">>, <<"locality">>, - <<"llocality">>, - <<"email">>, <<"lemail">>, - <<"orgname">>, - <<"lorgname">>, - <<"orgunit">>, - <<"lorgunit">>], - [Username, LUsername, SFN, - SLFN, SFamily, SLFamily, - SGiven, SLGiven, SMiddle, - SLMiddle, SNickname, - SLNickname, SBDay, SLBDay, - SCTRY, SLCTRY, SLocality, - SLLocality, SEMail, SLEMail, - SOrgName, SLOrgName, - SOrgUnit, SLOrgUnit], - [<<"lusername='">>, - LUsername, <<"'">>]) - end). - -get_vcard(LServer, Username) -> - ejabberd_odbc:sql_query(LServer, - [<<"select vcard from vcard where username='">>, - Username, <<"';">>]). +set_vcard(LServer, LUser, BDay, CTRY, EMail, FN, + Family, Given, LBDay, LCTRY, LEMail, LFN, + LFamily, LGiven, LLocality, LMiddle, LNickname, + LOrgName, LOrgUnit, Locality, Middle, Nickname, + OrgName, OrgUnit, SVCARD, User) -> + ejabberd_odbc:sql_transaction( + LServer, + fun() -> + ?SQL_UPSERT(LServer, "vcard", + ["!username=%(LUser)s", + "vcard=%(SVCARD)s"]), + ?SQL_UPSERT(LServer, "vcard_search", + ["username=%(User)s", + "!lusername=%(LUser)s", + "fn=%(FN)s", + "lfn=%(LFN)s", + "family=%(Family)s", + "lfamily=%(LFamily)s", + "given=%(Given)s", + "lgiven=%(LGiven)s", + "middle=%(Middle)s", + "lmiddle=%(LMiddle)s", + "nickname=%(Nickname)s", + "lnickname=%(LNickname)s", + "bday=%(BDay)s", + "lbday=%(LBDay)s", + "ctry=%(CTRY)s", + "lctry=%(LCTRY)s", + "locality=%(Locality)s", + "llocality=%(LLocality)s", + "email=%(EMail)s", + "lemail=%(LEMail)s", + "orgname=%(OrgName)s", + "lorgname=%(LOrgName)s", + "orgunit=%(OrgUnit)s", + "lorgunit=%(LOrgUnit)s"]) + end). + +get_vcard(LServer, LUser) -> + ejabberd_odbc:sql_query( + LServer, + ?SQL("select @(vcard)s from vcard where username=%(LUser)s")). get_default_privacy_list(LServer, LUser) -> ejabberd_odbc:sql_query( From 9a049442fff958ff01730575b8db011b16ee30d3 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Mon, 29 Feb 2016 16:56:25 +0300 Subject: [PATCH 620/695] Raise an error when there are no fields to set in ?SQL_UPSERT --- src/ejabberd_sql_pt.erl | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_sql_pt.erl b/src/ejabberd_sql_pt.erl index cb7a82e0f1e..660eac19767 100644 --- a/src/ejabberd_sql_pt.erl +++ b/src/ejabberd_sql_pt.erl @@ -60,9 +60,9 @@ transform(Form) -> case erl_syntax:type(Arg) of string -> S = erl_syntax:string_value(Arg), - ParseRes = - parse(S, erl_syntax:get_pos(Arg)), - make_sql_query(ParseRes); + Pos = erl_syntax:get_pos(Arg), + ParseRes = parse(S, Pos), + set_pos(make_sql_query(ParseRes), Pos); _ -> throw({error, erl_syntax:get_pos(Form), "?SQL argument must be " @@ -82,7 +82,10 @@ transform(Form) -> ParseRes = parse_upsert( erl_syntax:list_elements(FieldsArg)), - make_sql_upsert(Table, ParseRes); + Pos = erl_syntax:get_pos(Form), + set_pos( + make_sql_upsert(Table, ParseRes, Pos), + Pos); _ -> throw({error, erl_syntax:get_pos(Form), "?SQL_UPSERT arguments must be " @@ -322,7 +325,8 @@ parse_upsert_field1([C | S], Acc, ParamPos, Loc) -> parse_upsert_field1(S, [C | Acc], ParamPos, Loc). -make_sql_upsert(Table, ParseRes) -> +make_sql_upsert(Table, ParseRes, Pos) -> + check_upsert(ParseRes, Pos), erl_syntax:fun_expr( [erl_syntax:clause( [erl_syntax:atom(pgsql), erl_syntax:variable("__Version")], @@ -454,6 +458,22 @@ make_sql_upsert_pgsql901(Table, ParseRes) -> [Upsert]). +check_upsert(ParseRes, Pos) -> + Set = + lists:filter( + fun({_Field, Match, _ST}) -> + not Match + end, ParseRes), + case Set of + [] -> + throw({error, Pos, + "No ?SQL_UPSERT fields to set, use INSERT instead"}); + _ -> + ok + end, + ok. + + concat_states(States) -> lists:foldr( fun(ST11, ST2) -> @@ -507,9 +527,18 @@ resolve_vars(ST1, ST2) -> ST1#state{params = NewParams, 'query' = NewQuery}. - join_states([], _Sep) -> #state{}; join_states([H | T], Sep) -> J = [[H] | [[#state{'query' = [{str, Sep}]}, X] || X <- T]], concat_states(lists:append(J)). + + +set_pos(Tree, Pos) -> + erl_syntax_lib:map( + fun(Node) -> + case erl_syntax:get_pos(Node) of + 0 -> erl_syntax:set_pos(Node, Pos); + _ -> Node + end + end, Tree). From 79853ad44fafd9d8120ad38049200c58e36f20b9 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Wed, 2 Mar 2016 02:00:02 +0300 Subject: [PATCH 621/695] Missed a few calls in previous commits --- src/mod_roster.erl | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 79655af8ad3..997544b1e9e 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -645,14 +645,8 @@ get_subscription_lists(_, LUser, LServer, mnesia) -> _ -> [] end; get_subscription_lists(_, LUser, LServer, odbc) -> - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_roster(LServer, Username) of - {selected, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - Items} - when is_list(Items) -> + case catch odbc_queries:get_roster(LServer, LUser) of + {selected, Items} when is_list(Items) -> lists:map(fun(I) -> raw_to_record(LServer, I) end, Items); _ -> [] end; @@ -1149,14 +1143,8 @@ get_in_pending_subscriptions(Ls, User, Server, odbc) -> JID = jid:make(User, Server, <<"">>), LUser = JID#jid.luser, LServer = JID#jid.lserver, - Username = ejabberd_odbc:escape(LUser), - case catch odbc_queries:get_roster(LServer, Username) of - {selected, - [<<"username">>, <<"jid">>, <<"nick">>, - <<"subscription">>, <<"ask">>, <<"askmessage">>, - <<"server">>, <<"subscribe">>, <<"type">>], - Items} - when is_list(Items) -> + case catch odbc_queries:get_roster(LServer, LUser) of + {selected, Items} when is_list(Items) -> Ls ++ lists:map(fun (R) -> Message = R#roster.askmessage, From 96b09c587d871f18883e8c5d0700fbff8178800d Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 2 Mar 2016 13:35:35 +0100 Subject: [PATCH 622/695] Use upcoming version of ejabberd with Elixir 1.2 --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index f03dfdd5458..9419592c73b 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule Ejabberd.Mixfile do [app: :ejabberd, version: "16.02.0", description: description, - elixir: "~> 1.1", + elixir: "~> 1.2", elixirc_paths: ["lib"], compile_path: ".", compilers: [:asn1] ++ Mix.compilers, From fee587331090921bc204a8165de391abd312ad7c Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 3 Mar 2016 10:34:45 +0100 Subject: [PATCH 623/695] Minor format cleanup --- rebar.config | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/rebar.config b/rebar.config index d662f4190bf..d4c3342ba4a 100644 --- a/rebar.config +++ b/rebar.config @@ -14,38 +14,38 @@ {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.2"}}}, {fast_xml, ".*", {git, "https://github.com/processone/fast_xml", {tag, "1.1.3"}}}, {stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.1"}}}, - {esip, ".*", {git, "https://github.com/processone/esip", "1.0.2"}}, + {esip, ".*", {git, "https://github.com/processone/esip", {tag, "1.0.2"}}}, {fast_yaml, ".*", {git, "https://github.com/processone/fast_yaml", {tag, "1.0.2"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy", {tag, "0.14.7"}}}, - {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2.git", {tag, "0.6.1"}}}, + {p1_oauth2, ".*", {git, "https://github.com/processone/p1_oauth2", {tag, "0.6.1"}}}, {p1_xmlrpc, ".*", {git, "https://github.com/processone/p1_xmlrpc", {tag, "1.15.1"}}}, - {luerl, ".*", {git, "https://github.com/rvirding/luerl", - "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, + {luerl, ".*", {git, "https://github.com/rvirding/luerl", + "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", - {tag, "1.0.1"}}}}, + {tag, "1.0.1"}}}}, {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.0"}}}}, {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", - {tag, "1.1.5"}}}}, + {tag, "1.1.5"}}}}, {if_var_true, pam, {p1_pam, ".*", {git, "https://github.com/processone/epam", - {tag, "1.0.0"}}}}, + {tag, "1.0.0"}}}}, {if_var_true, zlib, {ezlib, ".*", {git, "https://github.com/processone/ezlib", - {tag, "1.0.1"}}}}, + {tag, "1.0.1"}}}}, {if_var_true, riak, {hamcrest, ".*", {git, "https://github.com/hyperthunk/hamcrest-erlang", - "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 + "908a24fda4a46776a5135db60ca071e3d783f9f6"}}}, % for riak_pb-2.1.0.7 {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", - "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, + "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", - {tag, "v1.1.0"}}}}, + {tag, "v1.1.0"}}}}, %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin {if_var_true, elixir, {rebar_elixir_plugin, ".*", - {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, + {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, {if_var_true, iconv, {iconv, ".*", {git, "https://github.com/processone/iconv", - {tag, "1.0.0"}}}}, + {tag, "1.0.0"}}}}, {if_var_true, tools, {meck, "0.8.2", {git, "https://github.com/eproxus/meck", - {tag, "0.8.2"}}}}, + {tag, "0.8.2"}}}}, {if_var_true, redis, {eredis, ".*", {git, "https://github.com/wooga/eredis", - {tag, "v1.0.8"}}}}]}. + {tag, "v1.0.8"}}}}]}. {if_var_true, latest_deps, {floating_deps, [cache_tab, @@ -53,7 +53,7 @@ stringprep, fast_xml, esip, - luerl, + luerl, stun, fast_yaml, p1_utils, From 3ecd7e850c3e56bb957fbb2369f7ac5453f6dfed Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 3 Mar 2016 10:36:13 +0100 Subject: [PATCH 624/695] Use Elixir v1.2.3 --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index d4c3342ba4a..131e3583d22 100644 --- a/rebar.config +++ b/rebar.config @@ -36,7 +36,7 @@ {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", - {tag, "v1.1.0"}}}}, + {tag, "v1.2.3"}}}}, %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, From e95cf420a2671c0f381724ee4af719a27ce5873d Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 3 Mar 2016 14:10:06 +0300 Subject: [PATCH 625/695] Enable flexible offline on disco#info as well --- src/mod_offline.erl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 0db1dd6817a..4e00d92353f 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -341,9 +341,15 @@ get_sm_items(_Acc, #jid{luser = U, lserver = S, lresource = R} = JID, get_sm_items(Acc, _From, _To, _Node, _Lang) -> Acc. -get_info(_Acc, #jid{luser = U, lserver = S}, #jid{luser = U, lserver = S}, - ?NS_FLEX_OFFLINE, _Lang) -> +get_info(_Acc, #jid{luser = U, lserver = S, lresource = R}, + #jid{luser = U, lserver = S}, ?NS_FLEX_OFFLINE, _Lang) -> N = jlib:integer_to_binary(count_offline_messages(U, S)), + case ejabberd_sm:get_session_pid(U, S, R) of + Pid when is_pid(Pid) -> + Pid ! dont_ask_offline; + none -> + ok + end, [#xmlel{name = <<"x">>, attrs = [{<<"xmlns">>, ?NS_XDATA}, {<<"type">>, <<"result">>}], From 10d6c330a5e98913703c4b3df2a9da4e60910d70 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 3 Mar 2016 14:43:56 +0100 Subject: [PATCH 626/695] Fix pubsub disco after host/serverhost cleanup --- src/mod_pubsub.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 7fb0fa6db26..f1f60f2cf86 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -504,7 +504,7 @@ disco_local_identity(Acc, _From, _To, _Node, _Lang) -> -> [binary(),...] ). disco_local_features(Acc, _From, To, <<>>, _Lang) -> - Host = To#jid.lserver, + Host = host(To#jid.lserver), Feats = case Acc of {result, I} -> I; _ -> [] From 44978ce978629a08fc4e86810a019a1ac5429c5a Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 3 Mar 2016 15:46:15 +0100 Subject: [PATCH 627/695] ext_mod: switch to fast_xml and remove old p1_logger reference --- src/ext_mod.erl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ext_mod.erl b/src/ext_mod.erl index 14ac21316e5..91526e71fd4 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -509,12 +509,11 @@ compile(_Module, _Spec, DestDir) -> filelib:ensure_dir(filename:join(Ebin, ".")), EjabBin = filename:dirname(code:which(ejabberd)), EjabInc = filename:join(filename:dirname(EjabBin), "include"), - XmlHrl = filename:join(EjabInc, "xml.hrl"), - Logger = [{d, 'P1LOGGER'} || code:is_loaded(lager)==false], + XmlHrl = filename:join(EjabInc, "fxml.hrl"), ExtLib = [{d, 'NO_EXT_LIB'} || filelib:is_file(XmlHrl)], Options = [{outdir, Ebin}, {i, "include"}, {i, EjabInc}, verbose, report_errors, report_warnings] - ++ Logger ++ ExtLib, + ++ ExtLib, [file:copy(App, Ebin) || App <- filelib:wildcard("src/*.app")], Result = [case compile:file(File, Options) of {ok, _} -> ok; From 9c3d57e63e3d606e92eac2a3c619bf71a730ce54 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 4 Mar 2016 11:09:14 +0100 Subject: [PATCH 628/695] Mark get_queue_length obsolete, and use count_offline_messages (#970) --- src/ejabberd_web_admin.erl | 3 +-- src/mod_admin_extra.erl | 2 +- src/mod_offline.erl | 7 ++++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ejabberd_web_admin.erl b/src/ejabberd_web_admin.erl index d69b2a6c15b..11d90ab80db 100644 --- a/src/ejabberd_web_admin.erl +++ b/src/ejabberd_web_admin.erl @@ -1520,8 +1520,7 @@ get_offlinemsg_length(ModOffline, User, Server) -> case ModOffline of none -> <<"disabled">>; _ -> - pretty_string_int(ModOffline:get_queue_length(User, - Server)) + pretty_string_int(ModOffline:count_offline_messages(User,Server)) end. get_offlinemsg_module(Server) -> diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index bd5a8489c9a..6180a16d109 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -531,7 +531,7 @@ get_commands_spec() -> tags = [offline], desc = "Get the number of unread offline messages", policy = user, - module = mod_offline, function = get_queue_length, + module = mod_offline, function = count_offline_messages, args = [], result = {res, integer}}, #ejabberd_commands{name = send_message, tags = [stanza], diff --git a/src/mod_offline.erl b/src/mod_offline.erl index 4e00d92353f..fa6a961fe0b 100644 --- a/src/mod_offline.erl +++ b/src/mod_offline.erl @@ -40,8 +40,6 @@ -behaviour(gen_mod). --export([count_offline_messages/2]). - -export([start/2, start_link/2, stop/1, @@ -61,6 +59,7 @@ import/3, export/1, get_queue_length/2, + count_offline_messages/2, get_offline_els/2, webadmin_page/3, webadmin_user/4, @@ -70,6 +69,8 @@ handle_info/2, terminate/2, code_change/3, mod_opt_type/1]). +-deprecated({get_queue_length,2}). + -include("ejabberd.hrl"). -include("logger.hrl"). @@ -1294,7 +1295,7 @@ get_messages_subset2(Max, Length, MsgsAll, odbc) -> MsgsFirstN ++ [IntermediateMsg] ++ MsgsLastN. webadmin_user(Acc, User, Server, Lang) -> - QueueLen = get_queue_length(jid:nodeprep(User), + QueueLen = count_offline_messages(jid:nodeprep(User), jid:nameprep(Server)), FQueueLen = [?AC(<<"queue/">>, (iolist_to_binary(integer_to_list(QueueLen))))], From 304afd75acd9b83e8604f25060115aeb5c4efb23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 4 Mar 2016 11:32:23 +0100 Subject: [PATCH 629/695] Compile ejabberd_config early to stop undefined behaviour warnings --- rebar.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rebar.config b/rebar.config index 131e3583d22..865517c9891 100644 --- a/rebar.config +++ b/rebar.config @@ -63,6 +63,8 @@ ezlib, iconv]}}. +{erl_first_files, ["src/ejabberd_config.erl"]}. + {erl_opts, [nowarn_deprecated_function, {if_var_false, debug, no_debug_info}, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, From 6e14a47316c1b94e9f2fb8356bffe87c8931efd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Fri, 4 Mar 2016 11:45:18 +0100 Subject: [PATCH 630/695] Define opt_type required be ejabberd_config behaviour. --- src/mod_metrics.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mod_metrics.erl b/src/mod_metrics.erl index 3e64da95272..c175fcb8e4d 100644 --- a/src/mod_metrics.erl +++ b/src/mod_metrics.erl @@ -39,7 +39,7 @@ s2s_send_packet, s2s_receive_packet, remove_user, register_user]). --export([start/2, stop/1, send_metrics/4]). +-export([start/2, stop/1, send_metrics/4, opt_type/1]). -export([offline_message_hook/3, sm_register_connection_hook/3, sm_remove_connection_hook/3, @@ -123,3 +123,6 @@ send_metrics(Host, Probe, Peer, Port) -> Error -> ?WARNING_MSG("can not open udp socket to grapherl: ~p", [Error]) end. + +opt_type(_) -> + []. From 4013629e5deecf3336b6ae97bf769852dc29c40e Mon Sep 17 00:00:00 2001 From: Anton Samets Date: Fri, 4 Mar 2016 15:52:38 +0300 Subject: [PATCH 631/695] EJAB-1480: fix issue with retreiving user roster --- src/mod_shared_roster_ldap.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_shared_roster_ldap.erl b/src/mod_shared_roster_ldap.erl index f57957d1a2b..dd6a7f6d424 100644 --- a/src/mod_shared_roster_ldap.erl +++ b/src/mod_shared_roster_ldap.erl @@ -145,7 +145,7 @@ get_user_roster(Items, {U, S} = US) -> %%case dict:find(US1, SRUsers1) of {value, _, SRUsers2} -> {Item#roster{subscription = both, ask = none}, SRUsers2}; %%{ok, _GroupNames} -> {Item#roster{subscription = both, ask = none}, dict:erase(US1, SRUsers1)}; - error -> {Item, SRUsers1} + false -> {Item, SRUsers1} end end, SRUsers, Items), From 8e6a3010266acfafc8d9e4e64f3335d5621dad36 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 7 Mar 2016 14:47:42 +0100 Subject: [PATCH 632/695] Fixed type specifications for 'rebar doc' - Fixed type @specs and -specs to remove 'rebar doc' errors - Removed a lot of wrong and deprecated documentation in ejabberd_piefxis.erl --- src/ejabberd_auth_external.erl | 4 +- src/ejabberd_config.erl | 2 +- src/ejabberd_logger.erl | 6 +++ src/ejabberd_piefxis.erl | 81 ---------------------------------- src/mod_pubsub.erl | 16 ++++++- 5 files changed, 23 insertions(+), 86 deletions(-) diff --git a/src/ejabberd_auth_external.erl b/src/ejabberd_auth_external.erl index 2a1cbf085fd..2944ac3f335 100644 --- a/src/ejabberd_auth_external.erl +++ b/src/ejabberd_auth_external.erl @@ -222,7 +222,7 @@ check_password_cache(User, Server, Password, get_password_internal(User, Server) -> ejabberd_auth_internal:get_password(User, Server). -%% @spec (User, Server, CacheTime) -> false | Password::string() +-spec get_password_cache(User::binary(), Server::binary(), CacheTime::integer()) -> Password::string() | false. get_password_cache(User, Server, CacheTime) -> case get_last_access(User, Server) of online -> get_password_internal(User, Server); @@ -273,10 +273,10 @@ is_fresh_enough(TimeStampLast, CacheTime) -> Now = p1_time_compat:system_time(seconds), TimeStampLast + CacheTime > Now. -%% @spec (User, Server) -> online | never | mod_last_required | TimeStamp::integer() %% Code copied from mod_configure.erl %% Code copied from web/ejabberd_web_admin.erl %% TODO: Update time format to XEP-0202: Entity Time +-spec(get_last_access(User::binary(), Server::binary()) -> (online | never | mod_last_required | integer())). get_last_access(User, Server) -> case ejabberd_sm:get_user_resources(User, Server) of [] -> diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 1f2eaa142c6..c500ee4ea36 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -112,7 +112,7 @@ get_env_config() -> %% @doc Read the ejabberd configuration file. %% It also includes additional configuration files and replaces macros. %% This function will crash if finds some error in the configuration file. -%% @spec (File::string()) -> #state{}. +%% @spec (File::string()) -> #state{} read_file(File) -> read_file(File, [{replace_macros, true}, {include_files, true}, diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 05499b45cae..605b1d6330c 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -50,6 +50,7 @@ %% "ejabberd.log" in current directory. %% Note: If the directory where to place the ejabberd log file to not exist, %% it is not created and no log file will be generated. +%% @spec () -> string() get_log_path() -> case ejabberd_config:env_binary_to_list(ejabberd, log_path) of {ok, Path} -> @@ -99,6 +100,7 @@ get_string_env(Name, Default) -> Default end. +%% @spec () -> ok start() -> application:load(sasl), application:set_env(sasl, sasl_error_logger, false), @@ -126,10 +128,12 @@ start() -> ejabberd:start_app(lager), ok. +%% @spec () -> ok reopen_log() -> %% Lager detects external log rotation automatically. ok. +%% @spec () -> ok rotate_log() -> lager_crash_log ! rotate, lists:foreach( @@ -139,6 +143,7 @@ rotate_log() -> ok end, gen_event:which_handlers(lager_event)). +%% @spec () -> {loglevel(), atom(), string()} get() -> case lager:get_loglevel(lager_console_backend) of none -> {0, no_log, "No log"}; @@ -152,6 +157,7 @@ get() -> debug -> {5, debug, "Debug"} end. +%% @spec (loglevel() | {loglevel(), list()}) -> {module, module()} set(LogLevel) when is_integer(LogLevel) -> LagerLogLevel = case LogLevel of 0 -> none; diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 028a8a8b3c0..123189dde10 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -80,7 +80,6 @@ import_file(FileName) -> import_file(FileName, #state{}). -spec import_file(binary(), state()) -> ok | {error, atom()}. - import_file(FileName, State) -> case file:open(FileName, [read, binary]) of {ok, Fd} -> @@ -97,72 +96,14 @@ import_file(FileName, State) -> {error, Reason} end. -%%%================================== -%%%% Process Elements -%%%================================== -%%%% Process Element -%%%================================== -%%%% Add user -%% @spec (El::xmlel(), Domain::string(), User::binary(), Password::binary() | none) -%% -> ok | {error, ErrorText::string()} -%% @doc Add a new user to the database. -%% If user already exists, it will be only updated. -spec export_server(binary()) -> any(). - -%% @spec (User::string(), Password::string(), Domain::string()) -%% -> ok | {atomic, exists} | {error, not_allowed} -%% @doc Create a new user export_server(Dir) -> export_hosts(?MYHOSTS, Dir). -%%%================================== -%%%% Populate user -%% @spec (User::string(), Domain::string(), El::xml()) -%% -> ok | {error, not_found} -%% -%% @doc Add a new user from a XML file with a roster list. -%% -%% Example of a file: -%% ``` -%% -%% -%% -%% -%% -%% -%% Friends -%% -%% -%% -%% -%% -%% ''' -spec export_host(binary(), binary()) -> any(). - export_host(Dir, Host) -> export_hosts([Host], Dir). -%% @spec User = String with the user name -%% Domain = String with a domain name -%% El = Sub XML element with vCard tags values -%% @ret ok | {error, not_found} -%% @doc Read vcards from the XML and send it to the server -%% -%% Example: -%% ``` -%% -%% -%% -%% -%% -%% Admin -%% -%% -%% -%% -%% ''' %%%=================================================================== %%% Internal functions %%%=================================================================== @@ -194,11 +135,6 @@ export_hosts(Hosts, Dir) -> {error, Reason} end. -%% @spec User = String with the user name -%% Domain = String with a domain name -%% El = Sub XML element with offline messages values -%% @ret ok | {error, not_found} -%% @doc Read off-line message from the XML and send it to the server export_host(Dir, FnH, Host) -> DFn = make_host_basefilename(Dir, FnH), case file:open(DFn, [raw, write]) of @@ -223,11 +159,6 @@ export_host(Dir, FnH, Host) -> {error, Reason} end. -%% @spec User = String with the user name -%% Domain = String with a domain name -%% El = Sub XML element with private storage values -%% @ret ok | {error, not_found} -%% @doc Private storage parsing export_users([{User, _S}|Users], Server, Fd) -> case export_user(User, Server, Fd) of ok -> @@ -238,8 +169,6 @@ export_users([{User, _S}|Users], Server, Fd) -> export_users([], _Server, _Fd) -> ok. -%%%================================== -%%%% Utilities export_user(User, Server, Fd) -> Password = ejabberd_auth:get_password_s(User, Server), LServer = jid:nameprep(Server), @@ -289,7 +218,6 @@ get_vcard(User, Server) -> [] end. -%%%================================== get_offline(User, Server) -> case mod_offline:get_offline_els(User, Server) of [] -> @@ -306,7 +234,6 @@ get_offline(User, Server) -> [#xmlel{name = <<"offline-messages">>, children = NewEls}] end. -%%%% Export hosts get_privacy(User, Server) -> case mod_privacy:get_user_lists(User, Server) of {ok, #privacy{default = Default, @@ -333,7 +260,6 @@ get_privacy(User, Server) -> [] end. -%% @spec (Dir::string(), Hosts::[string()]) -> ok get_roster(User, Server) -> JID = jid:make(User, Server, <<>>), case mod_roster:get_roster(User, Server) of @@ -576,8 +502,6 @@ process_roster(El, State = #state{user = U, server = S}) -> stop("Failed to write roster: ~p", [Err]) end. -%%%================================== -%%%% Export server process_privacy(El, State = #state{user = U, server = S}) -> JID = jid:make(U, S, <<"">>), case mod_privacy:process_iq_set( @@ -603,7 +527,6 @@ process_privacy(El, State = #state{user = U, server = S}) -> {ok, State} end. -%% @spec (Dir::string()) -> ok process_private(El, State = #state{user = U, server = S}) -> JID = jid:make(U, S, <<"">>), case mod_private:process_sm_iq( @@ -614,8 +537,6 @@ process_private(El, State = #state{user = U, server = S}) -> stop("Failed to write private: ~p", [Err]) end. -%%%================================== -%%%% Export host process_vcard(El, State = #state{user = U, server = S}) -> JID = jid:make(U, S, <<"">>), case mod_vcard:process_sm_iq( @@ -626,7 +547,6 @@ process_vcard(El, State = #state{user = U, server = S}) -> stop("Failed to write vcard: ~p", [Err]) end. -%% @spec (Dir::string(), Host::string()) -> ok process_offline_msg(El, State = #state{user = U, server = S}) -> FromS = fxml:get_attr_s(<<"from">>, El#xmlel.attrs), case jid:from_string(FromS) of @@ -643,7 +563,6 @@ process_offline_msg(El, State = #state{user = U, server = S}) -> stop("Invalid 'from' = ~s", [FromS]) end. -%% @spec (Dir::string(), Fn::string(), Host::string()) -> ok process_presence(El, #state{user = U, server = S} = State) -> FromS = fxml:get_attr_s(<<"from">>, El#xmlel.attrs), case jid:from_string(FromS) of diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index f1f60f2cf86..61546353f61 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -1775,6 +1775,20 @@ update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> %%
    • nodetree create_node checks if nodeid already exists
    • %%
    • node plugin create_node just sets default affiliation/subscription
    • %%
    +-spec(create_node/5 :: + ( + Host :: mod_pubsub:host(), + ServerHost :: binary(), + Node :: <<>> | mod_pubsub:nodeId(), + Owner :: jid(), + Type :: binary()) + -> {result, [xmlel(),...]} + %%% + | {error, xmlel()} + ). +create_node(Host, ServerHost, Node, Owner, Type) -> + create_node(Host, ServerHost, Node, Owner, Type, all, []). + -spec(create_node/7 :: ( Host :: mod_pubsub:host(), @@ -1788,8 +1802,6 @@ update_auth(Host, Node, Type, Nidx, Subscriber, Allow, Subs) -> %%% | {error, xmlel()} ). -create_node(Host, ServerHost, Node, Owner, Type) -> - create_node(Host, ServerHost, Node, Owner, Type, all, []). create_node(Host, ServerHost, <<>>, Owner, Type, Access, Configuration) -> case lists:member(<<"instant-nodes">>, plugin_features(Host, Type)) of true -> From 83accedded4dca7da531812559641db5ab416182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Galambosi?= Date: Mon, 7 Mar 2016 16:06:18 +0100 Subject: [PATCH 633/695] fix syntax highlighting by keeping "~s" together --- src/ejabberd_c2s.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 469350ba58f..97b759161fe 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -139,8 +139,8 @@ -define(STREAM_HEADER, <<"">>). + "herx.jabber.org/streams' id='~s' from='~s'~s" + "~s>">>). -define(STREAM_TRAILER, <<"">>). From 16c1b9a5c2a6c45ee0724830fa8c38a8a6e5e833 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 7 Mar 2016 17:34:08 +0100 Subject: [PATCH 634/695] Fix format_result also in xmlrpc, after aa5caa3 (#982) --- src/ejabberd_xmlrpc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_xmlrpc.erl b/src/ejabberd_xmlrpc.erl index 3078b64ea1c..c7e72d66d4b 100644 --- a/src/ejabberd_xmlrpc.erl +++ b/src/ejabberd_xmlrpc.erl @@ -491,7 +491,7 @@ format_result(Atom, {Name, atom}) -> [{Name, iolist_to_binary(atom_to_list(Atom))}]}; format_result(Int, {Name, integer}) -> {struct, [{Name, Int}]}; -format_result(String, {Name, string}) when is_list(String) -> +format_result([A|_]=String, {Name, string}) when is_list(String) and is_integer(A) -> {struct, [{Name, lists:flatten(String)}]}; format_result(Binary, {Name, string}) when is_binary(Binary) -> {struct, [{Name, binary_to_list(Binary)}]}; From c065a2c5b9aaa40859ef0625a4ea210a46b8af74 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 7 Mar 2016 22:26:46 +0100 Subject: [PATCH 635/695] Update gl.po --- priv/msgs/gl.po | 64 ++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index 7a8b27dcf1e..f446767846b 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -26,7 +26,7 @@ msgstr "foi expulsado" #: ejabberd_c2s.erl:2114 msgid "Your active privacy list has denied the routing of this stanza." -msgstr "" +msgstr "A súa lista de privacidade activa negou o encaminamiento desta estrofa." #: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" @@ -43,11 +43,11 @@ msgstr "" #: ejabberd_captcha.erl:192 msgid "If you don't see the CAPTCHA image here, visit the web page." -msgstr "" +msgstr "Si non ves a imaxe CAPTCHA aquí, visita a páxina web." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" -msgstr "" +msgstr "APTCHA páxina Web" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." @@ -71,7 +71,7 @@ msgstr "Contrasinal" #: ejabberd_oauth.erl:267 msgid "Accept" -msgstr "" +msgstr "Aceptar" #: ejabberd_web_admin.erl:202 ejabberd_web_admin.erl:214 #: ejabberd_web_admin.erl:234 ejabberd_web_admin.erl:246 @@ -1507,7 +1507,7 @@ msgstr "" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" -msgstr "" +msgstr "ejabberd servizo multidifusión" #: mod_offline.erl:647 msgid "" @@ -1626,7 +1626,7 @@ msgstr "Especificar o modelo do publicante" #: mod_pubsub.erl:3769 msgid "Purge all items when the relevant publisher goes offline" -msgstr "" +msgstr "Purgar todos os elementos cando o editor correspondente desconéctase" #: mod_pubsub.erl:3771 #, fuzzy @@ -1676,39 +1676,39 @@ msgstr "Os usuarios non están autorizados a rexistrar contas con tanta rapidez" #: mod_register_web.erl:105 msgid "Your Jabber account was successfully created." -msgstr "" +msgstr "A súa conta Jabber creouse correctamente." #: mod_register_web.erl:110 msgid "There was an error creating the account: " -msgstr "" +msgstr "Produciuse un erro ao crear a conta: " #: mod_register_web.erl:119 msgid "Your Jabber account was successfully deleted." -msgstr "" +msgstr "A súa conta Jabber eliminouse correctamente." #: mod_register_web.erl:124 msgid "There was an error deleting the account: " -msgstr "" +msgstr "Produciuse un erro ao eliminar a conta: " #: mod_register_web.erl:135 msgid "The password of your Jabber account was successfully changed." -msgstr "" +msgstr "O contrasinal da súa conta Jabber cambiouse correctamente." #: mod_register_web.erl:140 msgid "There was an error changing the password: " -msgstr "" +msgstr "Produciuse un erro ao cambiar o contrasinal: " #: mod_register_web.erl:175 mod_register_web.erl:183 msgid "Jabber Account Registration" -msgstr "" +msgstr "Rexistro de conta Jabber" #: mod_register_web.erl:186 mod_register_web.erl:204 mod_register_web.erl:212 msgid "Register a Jabber account" -msgstr "" +msgstr "Rexistrar unha conta Jabber" #: mod_register_web.erl:191 mod_register_web.erl:453 mod_register_web.erl:461 msgid "Unregister a Jabber account" -msgstr "" +msgstr "Eliminar o rexistro dunha conta Jabber" #: mod_register_web.erl:214 msgid "" @@ -1716,40 +1716,47 @@ msgid "" "(Jabber IDentifier) will be of the form: username@server. Please read " "carefully the instructions to fill correctly the fields." msgstr "" +"Esta páxina permite crear unha conta Jabber neste servidor Jabber. o seu JID " +"(Jabber IDentificador) será da forma: nomeusuario@servidor. Por favor le " +"coidadosamente as instrucións para encher correctamente os campos." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 #, fuzzy msgid "Username:" -msgstr "Nome de usuario en IRC" +msgstr "Nome de usuario:" #: mod_register_web.erl:230 msgid "This is case insensitive: macbeth is the same that MacBeth and Macbeth." -msgstr "" +msgstr "Esta é insensible: Macbeth é o mesmo que MacBeth e Macbeth." #: mod_register_web.erl:233 msgid "Characters not allowed:" -msgstr "" +msgstr "Caracteres non permitidos:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 #, fuzzy msgid "Server:" -msgstr "Servidor ~b" +msgstr "Servidor:" #: mod_register_web.erl:245 msgid "" "Don't tell your password to anybody, not even the administrators of the " -"Jabber server." +"Jabber Server." msgstr "" +"Non lle diga o seu contrasinal a ninguén, nin sequera os administradores do " +"Servidor Jabber." #: mod_register_web.erl:249 msgid "You can later change your password using a Jabber client." -msgstr "" +msgstr "Máis tarde, pode cambiar o seu contrasinal utilizando un cliente Jabber." #: mod_register_web.erl:252 msgid "" "Some Jabber clients can store your password in the computer, but you should " "do this only in your personal computer for safety reasons." msgstr "" +"Algúns clientes Jabber pode almacenar o contrasinal no computador, pero debe " +"facer isto só no seu computador persoal por razóns de seguridade." #: mod_register_web.erl:256 msgid "" @@ -1757,6 +1764,9 @@ msgid "" "Jabber there isn't an automated way to recover your password if you forget " "it." msgstr "" +"Memorice o seu contrasinal ou escribilo nun papel colocado nun lugar seguro. En " +"Jabber non hai unha forma automatizada para recuperar o seu contrasinal si " +"a esquece" #: mod_register_web.erl:262 mod_register_web.erl:374 #, fuzzy @@ -1766,25 +1776,25 @@ msgstr "Verificación da contrasinal" #: mod_register_web.erl:269 #, fuzzy msgid "Register" -msgstr "Lista de contactos" +msgstr "Rexistrar" #: mod_register_web.erl:366 #, fuzzy msgid "Old Password:" -msgstr "Contrasinal:" +msgstr "Contrasinal anterior:" #: mod_register_web.erl:370 #, fuzzy msgid "New Password:" -msgstr "Contrasinal:" +msgstr "Novo contrasinal:" #: mod_register_web.erl:463 msgid "This page allows to unregister a Jabber account in this Jabber server." -msgstr "" +msgstr "Esta páxina permite anular o rexistro dunha conta Jabber neste servidor Jabber." #: mod_register_web.erl:480 msgid "Unregister" -msgstr "" +msgstr "Eliminar rexistro" #: mod_roster.erl:1436 msgid "Subscription" @@ -1901,7 +1911,7 @@ msgstr "Necesitas un cliente con soporte de x:data para poder buscar" #: mod_vcard.erl:519 mod_vcard_ldap.erl:531 msgid "vCard User Search" -msgstr "Procura de usuario en vCard" +msgstr "vCard busqueda de usuario" #: mod_vcard.erl:580 mod_vcard_ldap.erl:586 msgid "ejabberd vCard module" From b6289d646fb134afd1336b6ca9bd4faeef80e233 Mon Sep 17 00:00:00 2001 From: Carlos Date: Tue, 8 Mar 2016 01:21:37 +0100 Subject: [PATCH 636/695] Update gl.po --- priv/msgs/gl.po | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index f446767846b..b697f381425 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -1,6 +1,6 @@ msgid "" msgstr "" -"Project-Id-Version: 2.1.0-alpha\n" +"Project-Id-Version: 16.02\n" "Last-Translator: Carlos E. Lopez - suso AT jabber-hispano.org\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -47,7 +47,7 @@ msgstr "Si non ves a imaxe CAPTCHA aquí, visita a páxina web." #: ejabberd_captcha.erl:227 msgid "CAPTCHA web page" -msgstr "APTCHA páxina Web" +msgstr "CAPTCHA páxina Web" #: ejabberd_captcha.erl:381 msgid "The CAPTCHA is valid." @@ -255,7 +255,7 @@ msgstr "Cambiar contrasinal" #: ejabberd_web_admin.erl:1673 #, fuzzy msgid "User ~s" -msgstr "Usuario " +msgstr "Usuario ~s" #: ejabberd_web_admin.erl:1684 msgid "Connected Resources:" @@ -289,7 +289,7 @@ msgstr "Nodos detidos" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 #, fuzzy msgid "Node ~p" -msgstr "Nodo " +msgstr "Nodo ~p" #: ejabberd_web_admin.erl:1842 mod_configure.erl:150 mod_configure.erl:611 msgid "Database" @@ -297,7 +297,7 @@ msgstr "Base de datos" #: ejabberd_web_admin.erl:1843 mod_configure.erl:159 mod_configure.erl:648 msgid "Backup" -msgstr "Gardar copia de seguridade" +msgstr "Copia de seguridade" #: ejabberd_web_admin.erl:1845 msgid "Listened Ports" @@ -328,7 +328,7 @@ msgstr "Erro na chamada RPC" #: ejabberd_web_admin.erl:1917 #, fuzzy msgid "Database Tables at ~p" -msgstr "Táboas da base de datos en " +msgstr "Táboas da base de datos en ~p" #: ejabberd_web_admin.erl:1927 mod_vcard.erl:490 mod_vcard.erl:616 msgid "Name" @@ -353,7 +353,7 @@ msgstr "Erro" #: ejabberd_web_admin.erl:1955 #, fuzzy msgid "Backup of ~p" -msgstr "Copia de seguridade de " +msgstr "Copia de seguridade de ~p" #: ejabberd_web_admin.erl:1959 msgid "" @@ -387,7 +387,7 @@ msgid "" "Restore binary backup after next ejabberd restart (requires less memory):" msgstr "" "Restaurar copia de seguridade binaria no seguinte reinicio de ejabberd " -"(require menos memoria que se instantánea):" +"(require menos memoria):" #: ejabberd_web_admin.erl:1999 msgid "Store plain text backup:" @@ -399,23 +399,23 @@ msgstr "Restaurar copias de seguridade de texto plano inmediatamente:" #: ejabberd_web_admin.erl:2019 msgid "Import users data from a PIEFXIS file (XEP-0227):" -msgstr "Importar usuarios desde un fichero PIEFXIS" +msgstr "Importar usuarios en un fichero PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -"Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " +"Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS (XEP-0227):" "(XEP-0227):" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -"Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " +"Exportar datos de los usuarios en un host de archivos PFX (XEP-0227):" "(XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" -msgstr "" +msgstr "Exportar todas lanas tablas de lanas consultas SQL a un archivo:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" From b5121a346d5775bdac20aa6a52a96434073fb1b6 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 8 Mar 2016 20:04:29 +0300 Subject: [PATCH 637/695] Experimental MIX (XEP-0369) support --- include/ns.hrl | 7 + src/ejabberd_local.erl | 2 +- src/ejabberd_sm.erl | 1 + src/mod_mix.erl | 329 +++++++++++++++++++++++++++++++++++++++++ src/mod_pubsub.erl | 2 +- src/node_mix.erl | 167 +++++++++++++++++++++ 6 files changed, 506 insertions(+), 2 deletions(-) create mode 100644 src/mod_mix.erl create mode 100644 src/node_mix.erl diff --git a/include/ns.hrl b/include/ns.hrl index 6934195d957..c7f55637248 100644 --- a/include/ns.hrl +++ b/include/ns.hrl @@ -157,3 +157,10 @@ -define(NS_HTTP_UPLOAD_OLD, <<"eu:siacs:conversations:http:upload">>). -define(NS_THUMBS_1, <<"urn:xmpp:thumbs:1">>). -define(NS_NICK, <<"http://jabber.org/protocol/nick">>). +-define(NS_MIX_0, <<"urn:xmpp:mix:0">>). +-define(NS_MIX_SERVICEINFO_0, <<"urn:xmpp:mix:0#serviceinfo">>). +-define(NS_MIX_NODES_MESSAGES, <<"urn:xmpp:mix:nodes:messages">>). +-define(NS_MIX_NODES_PRESENCE, <<"urn:xmpp:mix:nodes:presence">>). +-define(NS_MIX_NODES_PARTICIPANTS, <<"urn:xmpp:mix:nodes:participants">>). +-define(NS_MIX_NODES_SUBJECT, <<"urn:xmpp:mix:nodes:subject">>). +-define(NS_MIX_NODES_CONFIG, <<"urn:xmpp:mix:nodes:config">>). diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 1b7f93c77f1..292288a374b 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -32,7 +32,7 @@ %% API -export([start_link/0]). --export([route/3, route_iq/4, route_iq/5, +-export([route/3, route_iq/4, route_iq/5, process_iq/3, process_iq_reply/3, register_iq_handler/4, register_iq_handler/5, register_iq_response_handler/4, register_iq_response_handler/5, unregister_iq_handler/2, diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index b2e5a21f3e9..218e657f3cd 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -35,6 +35,7 @@ -export([start/0, start_link/0, route/3, + process_iq/3, open_session/5, open_session/6, close_session/4, diff --git a/src/mod_mix.erl b/src/mod_mix.erl new file mode 100644 index 00000000000..047ac8da1ad --- /dev/null +++ b/src/mod_mix.erl @@ -0,0 +1,329 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 2 Mar 2016 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-module(mod_mix). + +-behaviour(gen_server). +-behaviour(gen_mod). + +%% API +-export([start_link/2, start/2, stop/1, process_iq/3, + disco_items/5, disco_identity/5, disco_info/5, + disco_features/5]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-include("logger.hrl"). +-include("jlib.hrl"). +-include("pubsub.hrl"). + +-define(PROCNAME, ejabberd_mod_mix). +-define(NODES, [?NS_MIX_NODES_MESSAGES, + ?NS_MIX_NODES_PRESENCE, + ?NS_MIX_NODES_PARTICIPANTS, + ?NS_MIX_NODES_SUBJECT, + ?NS_MIX_NODES_CONFIG]). + +-record(state, {server_host :: binary(), + host :: binary()}). + +%%%=================================================================== +%%% API +%%%=================================================================== +start_link(Host, Opts) -> + Proc = gen_mod:get_module_proc(Host, ?PROCNAME), + gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). + +start(Host, Opts) -> + Proc = gen_mod:get_module_proc(Host, ?PROCNAME), + ChildSpec = {Proc, {?MODULE, start_link, [Host, Opts]}, + temporary, 5000, worker, [?MODULE]}, + supervisor:start_child(ejabberd_sup, ChildSpec). + +stop(Host) -> + Proc = gen_mod:get_module_proc(Host, ?PROCNAME), + supervisor:terminate_child(ejabberd_sup, Proc), + supervisor:delete_child(ejabberd_sup, Proc), + ok. + +disco_features(_Acc, _From, _To, _Node, _Lang) -> + {result, [?NS_MIX_0]}. + +disco_items(_Acc, _From, To, _Node, _Lang) when To#jid.luser /= <<"">> -> + To_s = jid:to_string(jid:remove_resource(To)), + {result, [#xmlel{name = <<"item">>, + attrs = [{<<"jid">>, To_s}, + {<<"node">>, Node}]} || Node <- ?NODES]}; +disco_items(_Acc, _From, _To, _Node, _Lang) -> + {result, []}. + +disco_identity(Acc, _From, To, _Node, _Lang) when To#jid.luser == <<"">> -> + Acc ++ [#xmlel{name = <<"identity">>, + attrs = + [{<<"category">>, <<"conference">>}, + {<<"name">>, <<"MIX service">>}, + {<<"type">>, <<"text">>}]}]; +disco_identity(Acc, _From, _To, _Node, _Lang) -> + Acc ++ [#xmlel{name = <<"identity">>, + attrs = + [{<<"category">>, <<"conference">>}, + {<<"type">>, <<"mix">>}]}]. + +disco_info(_Acc, _From, To, _Node, _Lang) when is_atom(To) -> + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"result">>}], + children = [#xmlel{name = <<"field">>, + attrs = [{<<"var">>, <<"FORM_TYPE">>}, + {<<"type">>, <<"hidden">>}], + children = [#xmlel{name = <<"value">>, + children = [{xmlcdata, + ?NS_MIX_SERVICEINFO_0}]}]}]}]; +disco_info(Acc, _From, _To, _Node, _Lang) -> + Acc. + +process_iq(From, To, + #iq{type = set, sub_el = #xmlel{name = <<"join">>} = SubEl} = IQ) -> + Nodes = lists:flatmap( + fun(#xmlel{name = <<"subscribe">>, attrs = Attrs}) -> + Node = fxml:get_attr_s(<<"node">>, Attrs), + case lists:member(Node, ?NODES) of + true -> [Node]; + false -> [] + end; + (_) -> + [] + end, SubEl#xmlel.children), + case subscribe_nodes(From, To, Nodes) of + {result, _} -> + case publish_participant(From, To) of + {result, _} -> + LFrom_s = jid:to_string(jid:tolower(jid:remove_resource(From))), + Subscribe = [#xmlel{name = <<"subscribe">>, + attrs = [{<<"node">>, Node}]} || Node <- Nodes], + IQ#iq{type = result, + sub_el = [#xmlel{name = <<"join">>, + attrs = [{<<"jid">>, LFrom_s}, + {<<"xmlns">>, ?NS_MIX_0}], + children = Subscribe}]}; + {error, Err} -> + IQ#iq{type = error, sub_el = [SubEl, Err]} + end; + {error, Err} -> + IQ#iq{type = error, sub_el = [SubEl, Err]} + end; +process_iq(From, To, + #iq{type = set, sub_el = #xmlel{name = <<"leave">>} = SubEl} = IQ) -> + case delete_participant(From, To) of + {result, _} -> + case unsubscribe_nodes(From, To, ?NODES) of + {result, _} -> + IQ#iq{type = result, sub_el = []}; + {error, Err} -> + IQ#iq{type = error, sub_el = [SubEl, Err]} + end; + {error, Err} -> + IQ#iq{type = error, sub_el = [SubEl, Err]} + end; +process_iq(_From, _To, #iq{sub_el = SubEl} = IQ) -> + IQ#iq{type = error, sub_el = [SubEl, ?ERR_BAD_REQUEST]}. + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== +init([ServerHost, Opts]) -> + Host = gen_mod:get_opt_host(ServerHost, Opts, <<"mix.@HOST@">>), + IQDisc = gen_mod:get_opt(iqdisc, Opts, fun gen_iq_handler:check_type/1, + one_queue), + ConfigTab = gen_mod:get_module_proc(Host, config), + ets:new(ConfigTab, [named_table]), + ets:insert(ConfigTab, {plugins, [<<"mix">>]}), + ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_items, 100), + ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 100), + ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, disco_identity, 100), + ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, disco_items, 100), + ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, disco_features, 100), + ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, disco_identity, 100), + ejabberd_hooks:add(disco_info, Host, ?MODULE, disco_info, 100), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_DISCO_ITEMS, mod_disco, + process_local_iq_items, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_local, Host, + ?NS_DISCO_INFO, mod_disco, + process_local_iq_info, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_DISCO_ITEMS, mod_disco, + process_local_iq_items, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_DISCO_INFO, mod_disco, + process_local_iq_info, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_PUBSUB, mod_pubsub, iq_sm, IQDisc), + gen_iq_handler:add_iq_handler(ejabberd_sm, Host, + ?NS_MIX_0, ?MODULE, process_iq, IQDisc), + ejabberd_router:register_route(Host), + {ok, #state{server_host = ServerHost, host = Host}}. + +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info({route, From, To, Packet}, State) -> + case catch do_route(State, From, To, Packet) of + {'EXIT', _} = Err -> + try + ?ERROR_MSG("failed to route packet ~p from '~s' to '~s': ~p", + [Packet, jid:to_string(From), jid:to_string(To), Err]), + ErrPkt = jlib:make_error_reply(Packet, ?ERR_INTERNAL_SERVER_ERROR), + ejabberd_router:route_error(To, From, ErrPkt, Packet) + catch _:_ -> + ok + end; + _ -> + ok + end, + {noreply, State}; +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +do_route(_State, From, To, #xmlel{name = <<"iq">>} = Packet) -> + if To#jid.luser == <<"">> -> + ejabberd_local:process_iq(From, To, Packet); + true -> + ejabberd_sm:process_iq(From, To, Packet) + end; +do_route(_State, From, To, #xmlel{name = <<"presence">>} = Packet) + when To#jid.luser /= <<"">> -> + case fxml:get_tag_attr_s(<<"type">>, Packet) of + <<"unavailable">> -> + delete_presence(From, To); + _ -> + ok + end; +do_route(_State, _From, _To, _Packet) -> + ok. + +subscribe_nodes(From, To, Nodes) -> + LTo = jid:tolower(jid:remove_resource(To)), + LFrom = jid:tolower(jid:remove_resource(From)), + From_s = jid:to_string(LFrom), + lists:foldl( + fun(_Node, {error, _} = Err) -> + Err; + (Node, {result, _}) -> + case mod_pubsub:subscribe_node(LTo, Node, From, From_s, []) of + {error, _} = Err -> + case is_item_not_found(Err) of + true -> + case mod_pubsub:create_node( + LTo, To#jid.lserver, Node, LFrom, <<"mix">>) of + {result, _} -> + mod_pubsub:subscribe_node(LTo, Node, From, From_s, []); + Error -> + Error + end; + false -> + Err + end; + {result, _} = Result -> + Result + end + end, {result, []}, Nodes). + +unsubscribe_nodes(From, To, Nodes) -> + LTo = jid:tolower(jid:remove_resource(To)), + LFrom = jid:tolower(jid:remove_resource(From)), + From_s = jid:to_string(LFrom), + lists:foldl( + fun(_Node, {error, _} = Err) -> + Err; + (Node, {result, _} = Result) -> + case mod_pubsub:unsubscribe_node(LTo, Node, From, From_s, <<"">>) of + {error, _} = Err -> + case is_not_subscribed(Err) of + true -> Result; + _ -> Err + end; + {result, _} = Res -> + Res + end + end, {result, []}, Nodes). + +publish_participant(From, To) -> + LFrom = jid:tolower(jid:remove_resource(From)), + LTo = jid:tolower(jid:remove_resource(To)), + Participant = #xmlel{name = <<"participant">>, + attrs = [{<<"xmlns">>, ?NS_MIX_0}, + {<<"jid">>, jid:to_string(LFrom)}]}, + ItemID = p1_sha:sha(jid:to_string(LFrom)), + mod_pubsub:publish_item( + LTo, To#jid.lserver, ?NS_MIX_NODES_PARTICIPANTS, + From, ItemID, [Participant]). + +delete_presence(From, To) -> + LFrom = jid:tolower(From), + LTo = jid:tolower(jid:remove_resource(To)), + case mod_pubsub:get_items(LTo, ?NS_MIX_NODES_PRESENCE) of + Items when is_list(Items) -> + lists:foreach( + fun(#pubsub_item{modification = {_, LJID}, + itemid = {ItemID, _}}) when LJID == LFrom -> + delete_item(From, To, ?NS_MIX_NODES_PRESENCE, ItemID); + (_) -> + ok + end, Items); + _ -> + ok + end. + +delete_participant(From, To) -> + LFrom = jid:tolower(jid:remove_resource(From)), + ItemID = p1_sha:sha(jid:to_string(LFrom)), + delete_presence(From, To), + delete_item(From, To, ?NS_MIX_NODES_PARTICIPANTS, ItemID). + +delete_item(From, To, Node, ItemID) -> + LTo = jid:tolower(jid:remove_resource(To)), + case mod_pubsub:delete_item( + LTo, Node, From, ItemID, true) of + {result, _} = Res -> + Res; + {error, _} = Err -> + case is_item_not_found(Err) of + true -> {result, []}; + false -> Err + end + end. + +is_item_not_found({error, ErrEl}) -> + case fxml:get_subtag_with_xmlns( + ErrEl, <<"item-not-found">>, ?NS_STANZAS) of + #xmlel{} -> true; + _ -> false + end. + +is_not_subscribed({error, ErrEl}) -> + case fxml:get_subtag_with_xmlns( + ErrEl, <<"not-subscribed">>, ?NS_PUBSUB_ERRORS) of + #xmlel{} -> true; + _ -> false + end. diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 61546353f61..ed3debbf15d 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -63,7 +63,7 @@ %% exports for console debug manual use -export([create_node/5, create_node/7, delete_node/3, subscribe_node/5, unsubscribe_node/5, publish_item/6, - delete_item/4, send_items/7, get_items/2, get_item/3, + delete_item/4, delete_item/5, send_items/7, get_items/2, get_item/3, get_cached_item/2, get_configure/5, set_configure/5, tree_action/3, node_action/4, node_call/4]). diff --git a/src/node_mix.erl b/src/node_mix.erl new file mode 100644 index 00000000000..b0410a8c339 --- /dev/null +++ b/src/node_mix.erl @@ -0,0 +1,167 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 8 Mar 2016 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-module(node_mix). + +-behaviour(gen_pubsub_node). + +%% API +-export([init/3, terminate/2, options/0, features/0, + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1]). + +-include("pubsub.hrl"). + +%%%=================================================================== +%%% API +%%%=================================================================== +init(Host, ServerHost, Opts) -> + node_flat:init(Host, ServerHost, Opts). + +terminate(Host, ServerHost) -> + node_flat:terminate(Host, ServerHost). + +options() -> + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, open}, + {roster_groups_allowed, []}, + {publish_model, open}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, true}, + {broadcast_all_resources, true}, + {presence_based_delivery, false}]. + +features() -> + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"instant-nodes">>, + <<"item-ids">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_flat:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_flat:create_node(Nidx, Owner). + +delete_node(Removed) -> + node_flat:delete_node(Removed). + +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_flat:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). + +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_flat:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_flat:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_flat:remove_extra_items(Nidx, MaxItems, ItemIds). + +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_flat:delete_item(Nidx, Publisher, PublishModel, ItemId). + +purge_node(Nidx, Owner) -> + node_flat:purge_node(Nidx, Owner). + +get_entity_affiliations(Host, Owner) -> + node_flat:get_entity_affiliations(Host, Owner). + +get_node_affiliations(Nidx) -> + node_flat:get_node_affiliations(Nidx). + +get_affiliation(Nidx, Owner) -> + node_flat:get_affiliation(Nidx, Owner). + +set_affiliation(Nidx, Owner, Affiliation) -> + node_flat:set_affiliation(Nidx, Owner, Affiliation). + +get_entity_subscriptions(Host, Owner) -> + node_flat:get_entity_subscriptions(Host, Owner). + +get_node_subscriptions(Nidx) -> + node_flat:get_node_subscriptions(Nidx). + +get_subscriptions(Nidx, Owner) -> + node_flat:get_subscriptions(Nidx, Owner). + +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_flat:set_subscriptions(Nidx, Owner, Subscription, SubId). + +get_pending_nodes(Host, Owner) -> + node_flat:get_pending_nodes(Host, Owner). + +get_states(Nidx) -> + node_flat:get_states(Nidx). + +get_state(Nidx, JID) -> + node_flat:get_state(Nidx, JID). + +set_state(State) -> + node_flat:set_state(State). + +get_items(Nidx, From, RSM) -> + node_flat:get_items(Nidx, From, RSM). + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_flat:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). + +get_item(Nidx, ItemId) -> + node_flat:get_item(Nidx, ItemId). + +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). + +set_item(Item) -> + node_flat:set_item(Item). + +get_item_name(Host, Node, Id) -> + node_flat:get_item_name(Host, Node, Id). + +node_to_path(Node) -> + node_flat:node_to_path(Node). + +path_to_node(Path) -> + node_flat:path_to_node(Path). + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== From ae4fa2218086621c26095c291ae66daaa2f4eb3a Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Wed, 9 Mar 2016 00:27:06 +0100 Subject: [PATCH 638/695] mod_http_upload: Add XEP-0363 v0.2 support Include the maximum file size in the service discovery information, as specified by XEP-0363, version 0.2. --- src/mod_http_upload.erl | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index d360ac195c0..5635102b27a 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -535,7 +535,8 @@ process_iq(_From, IQ#iq{type = result, sub_el = [#xmlel{name = <<"query">>, attrs = [{<<"xmlns">>, ?NS_DISCO_INFO}], - children = iq_disco_info(Lang, Name) ++ AddInfo}]}; + children = iq_disco_info(ServerHost, Lang, Name) + ++ AddInfo}]}; process_iq(From, #iq{type = get, xmlns = XMLNS, lang = Lang, sub_el = SubEl} = IQ, #state{server_host = ServerHost, access = Access} = State) @@ -751,9 +752,36 @@ map_int_to_char(N) when N =< 61 -> N + 61. % Lower-case character. yield_content_type(<<"">>) -> ?DEFAULT_CONTENT_TYPE; yield_content_type(Type) -> Type. --spec iq_disco_info(binary(), binary()) -> [xmlel()]. - -iq_disco_info(Lang, Name) -> +-spec iq_disco_info(binary(), binary(), binary()) -> [xmlel()]. + +iq_disco_info(Host, Lang, Name) -> + Form = case gen_mod:get_module_opt(Host, ?MODULE, max_size, + fun(I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end, + 104857600) of + infinity -> + []; + MaxSize -> + MaxSizeStr = jlib:integer_to_binary(MaxSize), + Fields = [#xmlel{name = <<"field">>, + attrs = [{<<"type">>, <<"hidden">>}, + {<<"var">>, <<"FORM_TYPE">>}], + children = [#xmlel{name = <<"value">>, + children = + [{xmlcdata, + ?NS_HTTP_UPLOAD}]}]}, + #xmlel{name = <<"field">>, + attrs = [{<<"var">>, <<"max-file-size">>}], + children = [#xmlel{name = <<"value">>, + children = + [{xmlcdata, + MaxSizeStr}]}]}], + [#xmlel{name = <<"x">>, + attrs = [{<<"xmlns">>, ?NS_XDATA}, + {<<"type">>, <<"result">>}], + children = Fields}] + end, [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"store">>}, {<<"type">>, <<"file">>}, @@ -761,7 +789,7 @@ iq_disco_info(Lang, Name) -> #xmlel{name = <<"feature">>, attrs = [{<<"var">>, ?NS_HTTP_UPLOAD}]}, #xmlel{name = <<"feature">>, - attrs = [{<<"var">>, ?NS_HTTP_UPLOAD_OLD}]}]. + attrs = [{<<"var">>, ?NS_HTTP_UPLOAD_OLD}]} | Form]. %% HTTP request handling. From 1860801e36bf96164ea2d8ad727d72ed594daf3a Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 9 Mar 2016 11:14:45 +0300 Subject: [PATCH 639/695] Unregister hooks and iq handlers on terminate --- src/mod_mix.erl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/mod_mix.erl b/src/mod_mix.erl index 047ac8da1ad..48dd7724d28 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -196,7 +196,21 @@ handle_info({route, From, To, Packet}, State) -> handle_info(_Info, State) -> {noreply, State}. -terminate(_Reason, _State) -> +terminate(_Reason, #state{host = Host}) -> + ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_items, 100), + ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 100), + ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, disco_identity, 100), + ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, disco_items, 100), + ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, disco_features, 100), + ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, disco_identity, 100), + ejabberd_hooks:delete(disco_info, Host, ?MODULE, disco_info, 100), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS), + gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_INFO), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PUBSUB), + gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MIX_0), + ejabberd_router:unregister_route(Host), ok. code_change(_OldVsn, State, _Extra) -> From e31799a3b195e7f1a1f28b562b16a680396b9c90 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 9 Mar 2016 11:19:15 +0300 Subject: [PATCH 640/695] Define mod_opt_type/1 callback --- src/mod_mix.erl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mod_mix.erl b/src/mod_mix.erl index 48dd7724d28..8224ec78a6e 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -14,7 +14,7 @@ %% API -export([start_link/2, start/2, stop/1, process_iq/3, disco_items/5, disco_identity/5, disco_info/5, - disco_features/5]). + disco_features/5, mod_opt_type/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -341,3 +341,7 @@ is_not_subscribed({error, ErrEl}) -> #xmlel{} -> true; _ -> false end. + +mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1; +mod_opt_type(host) -> fun iolist_to_binary/1; +mod_opt_type(_) -> [host, iqdisc]. From 842d52352a52e504e9be858302443252b7cf07d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 9 Mar 2016 14:25:57 +0100 Subject: [PATCH 641/695] Fix escaping of argument in iexlive and iexdebug --- ejabberdctl.template | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 07395aafdd1..aa9c2eb817c 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -159,6 +159,15 @@ export CONTRIB_MODULES_PATH export CONTRIB_MODULES_CONF_DIR export ERL_LIBS +shell_escape_str() +{ + if test $# -eq 0; then + printf '"" ' + else + shell_escape "$@" + fi +} + shell_escape() { local RES=() @@ -208,10 +217,10 @@ iexdebug() # Elixir shell is hidden as default CMD="`shell_escape \"$IEX\" \"$IEXNAME\" \"debug-${TTY}-${ERLANG_NODE}\"` \ -remsh $ERLANG_NODE \ - --erl \"`shell_escape \"$KERNEL_OPTS\"\" \ - --erl \"`shell_escape \"$ERLANG_OPTS\"\" \ - --erl \"`shell_escape \"${ARGS[@]}\"\" \ - --erl \"`shell_escape \"$@\"\"" + --erl `shell_escape \"$KERNEL_OPTS\"` \ + --erl `shell_escape \"$ERLANG_OPTS\"` \ + --erl `shell_escape \"${ARGS[@]}\"` \ + --erl `shell_escape_str \"$@\"`" $EXEC_CMD "$CMD" } @@ -233,14 +242,15 @@ live() iexlive() { livewarning + echo $@ CMD="`shell_escape \"$IEX\" \"$IEXNAME\" \"${ERLANG_NODE}\"` \ --erl \"-mnesia dir \\\"$SPOOL_DIR\\\"\" \ --erl \"`shell_escape \"$KERNEL_OPTS\"`\" \ --erl \"`shell_escape \"$EJABBERD_OPTS\"`\" \ --app ejabberd \ - --erl \"`shell_escape \"$ERLANG_OPTS\"`\" \ - --erl \"`shell_escape \"${ARGS[@]}\"`\" \ - --erl \"`shell_escape \"$@\"`\"" + --erl `shell_escape \"$ERLANG_OPTS\"` \ + --erl `shell_escape \"${ARGS[@]}\"` \ + --erl `shell_escape_str \"$@\"`" $EXEC_CMD "$CMD" } From f4ee8a25051a51b4fdd1318cb6918e05404a466b Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 9 Mar 2016 19:12:56 +0100 Subject: [PATCH 642/695] Add Elixir Logger Backend to bridge logs from lager We will need to support loglevel bridging. It should help with #966 --- src/ejabberd_logger.erl | 44 ++++++++++++- src/elixir_logger_backend.erl | 115 ++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 src/elixir_logger_backend.erl diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 605b1d6330c..a13ac814a73 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -102,6 +102,29 @@ get_string_env(Name, Default) -> %% @spec () -> ok start() -> + StartedApps = application:which_applications(5000), + case lists:keyfind(logger, 1, StartedApps) of + {logger, _, _} -> + error_logger:info_msg("Ignoring logger options, using Elixir Logger.", []), + %% Do not start lager, we rely on Elixir Logger + do_start_for_logger(); + _ -> + do_start() + end. + +do_start_for_logger() -> + application:load(sasl), + application:set_env(sasl, sasl_error_logger, false), + application:load(lager), + application:set_env(lager, error_logger_redirect, false), + application:set_env(lager, error_logger_whitelist, ['Elixir.Logger.ErrorHandler']), + application:set_env(lager, crash_log, false), + application:set_env(lager, handlers, [{elixir_logger_backend, [{level, debug}]}]), + ejabberd:start_app(lager), + ok. + +%% Start lager +do_start() -> application:load(sasl), application:set_env(sasl, sasl_error_logger, false), application:load(lager), @@ -145,7 +168,7 @@ rotate_log() -> %% @spec () -> {loglevel(), atom(), string()} get() -> - case lager:get_loglevel(lager_console_backend) of + case get_lager_loglevel() of none -> {0, no_log, "No log"}; emergency -> {1, critical, "Critical"}; alert -> {1, critical, "Critical"}; @@ -168,7 +191,7 @@ set(LogLevel) when is_integer(LogLevel) -> 5 -> debug; E -> throw({wrong_loglevel, E}) end, - case lager:get_loglevel(lager_console_backend) of + case get_lager_loglevel() of LagerLogLevel -> ok; _ -> @@ -186,3 +209,20 @@ set(LogLevel) when is_integer(LogLevel) -> set({_LogLevel, _}) -> error_logger:error_msg("custom loglevels are not supported for 'lager'"), {module, lager}. + +get_lager_loglevel() -> + R = case get_lager_handlers() of + [] -> none; + [elixir_logger_backend] -> debug; + [FirstHandler|_] -> + lager:get_loglevel(FirstHandler) + end, + R. + +get_lager_handlers() -> + case catch gen_event:which_handlers(lager_event) of + {'EXIT',noproc} -> + []; + Result -> + Result + end. diff --git a/src/elixir_logger_backend.erl b/src/elixir_logger_backend.erl new file mode 100644 index 00000000000..6bd5b638e09 --- /dev/null +++ b/src/elixir_logger_backend.erl @@ -0,0 +1,115 @@ +%%%------------------------------------------------------------------- +%%% @author Mickael Remond +%%% @doc +%%% This module bridges lager logs to Elixir Logger. +%%% @end +%%% Created : 9 March 2016 by Mickael Remond +%%% +%%% ejabberd, Copyright (C) 2002-2016 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%------------------------------------------------------------------- + +-module(elixir_logger_backend). + +-behaviour(gen_event). + +-export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, + code_change/3]). + +init(_Opts) -> + State = [], + {ok, State}. + +%% @private +handle_event({log, LagerMsg}, State) -> + #{mode := Mode, truncate := Truncate, level := MinLevel, utc_log := UTCLog} = 'Elixir.Logger.Config':'__data__'(), + MsgLevel = severity_to_level(lager_msg:severity(LagerMsg)), + case {lager_util:is_loggable(LagerMsg, debug, ?MODULE), 'Elixir.Logger':compare_levels(MsgLevel, MinLevel)} of + {_, lt}-> + {ok, State}; + {true, _} -> + Metadata = normalize_pid(lager_msg:metadata(LagerMsg)), + Message = 'Elixir.Logger.Utils':truncate(lager_msg:message(LagerMsg), Truncate), + Timestamp = timestamp(lager_msg:timestamp(LagerMsg), UTCLog), + GroupLeader = case proplists:get_value(pid, Metadata, self()) of + Pid when is_pid(Pid) -> + erlang:process_info(self(), group_leader); + _ -> {group_leader, self()} + end, + notify(Mode, {MsgLevel, GroupLeader, {'Elixir.Logger', Message, Timestamp, Metadata}}), + {ok, State}; + _ -> + {ok, State} + end; +handle_event(_, State) -> + {ok, State}. + +%% @private +%% TODO Handle loglevels +handle_call(_Msg, State) -> + {ok, ok, State}. + +%% @private +handle_info(_Msg, State) -> + {ok, State}. + +%% @private +terminate(_Reason, _State) -> + ok. + +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +notify(sync, Msg) -> + gen_event:sync_notify('Elixir.Logger', Msg); +notify(async, Msg) -> gen_event:notify('Elixir.Logger', Msg). + +normalize_pid(Metadata) -> + case proplists:get_value(pid, Metadata) of + Pid when is_pid(Pid) -> Metadata; + Pid when is_list(Pid) -> + M1 = proplists:delete(pid, Metadata), + case catch erlang:list_to_pid(Pid) of + {'EXIT', _} -> + M1; + PidAsPid -> + [{pid, PidAsPid}|M1] + end; + _ -> + proplists:delete(pid, Metadata) + end. + +%% Return timestamp with milliseconds +timestamp(Time, UTCLog) -> + {_, _, Micro} = erlang:timestamp(), + {Date, {Hours, Minutes, Seconds}} = + case UTCLog of + true -> calendar:now_to_universal_time(Time); + false -> calendar:now_to_local_time(Time) + end, + {Date, {Hours, Minutes, Seconds, Micro div 1000}}. + + +severity_to_level(debug) -> debug; +severity_to_level(info) -> info; +severity_to_level(notice) -> info; +severity_to_level(warning) -> warn; +severity_to_level(error) -> error; +severity_to_level(critical) -> error; +severity_to_level(alert) -> error; +severity_to_level(emergency) -> error. From 9e6efaf9bca37b3431db2278c6e650582e47716a Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 9 Mar 2016 20:57:01 +0100 Subject: [PATCH 643/695] Use p1_time_compat util for generating timestamp --- src/elixir_logger_backend.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elixir_logger_backend.erl b/src/elixir_logger_backend.erl index 6bd5b638e09..8c634934c8e 100644 --- a/src/elixir_logger_backend.erl +++ b/src/elixir_logger_backend.erl @@ -96,7 +96,7 @@ normalize_pid(Metadata) -> %% Return timestamp with milliseconds timestamp(Time, UTCLog) -> - {_, _, Micro} = erlang:timestamp(), + {_, _, Micro} = p1_time_compat:timestamp(), {Date, {Hours, Minutes, Seconds}} = case UTCLog of true -> calendar:now_to_universal_time(Time); From 035c63fd2a0d3e51d1baf73d0d9f8c710c4e663a Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 9 Mar 2016 21:03:06 +0100 Subject: [PATCH 644/695] Fix call to lager_util:is_loggable/3 --- src/elixir_logger_backend.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elixir_logger_backend.erl b/src/elixir_logger_backend.erl index 8c634934c8e..583d46a5cce 100644 --- a/src/elixir_logger_backend.erl +++ b/src/elixir_logger_backend.erl @@ -38,7 +38,7 @@ init(_Opts) -> handle_event({log, LagerMsg}, State) -> #{mode := Mode, truncate := Truncate, level := MinLevel, utc_log := UTCLog} = 'Elixir.Logger.Config':'__data__'(), MsgLevel = severity_to_level(lager_msg:severity(LagerMsg)), - case {lager_util:is_loggable(LagerMsg, debug, ?MODULE), 'Elixir.Logger':compare_levels(MsgLevel, MinLevel)} of + case {lager_util:is_loggable(LagerMsg, lager_util:level_to_num(debug), ?MODULE), 'Elixir.Logger':compare_levels(MsgLevel, MinLevel)} of {_, lt}-> {ok, State}; {true, _} -> From 92a01819322cdb7452f3d6a724aec65c4696dfe4 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 9 Mar 2016 22:30:46 +0100 Subject: [PATCH 645/695] Lager to Elixir Logger bridge is now compliant with ejabberd loglevel set / get This should fix #966 --- src/ejabberd_logger.erl | 24 +++++++++++++++--------- src/elixir_logger_backend.erl | 21 ++++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index a13ac814a73..795d4f390e4 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -104,8 +104,10 @@ get_string_env(Name, Default) -> start() -> StartedApps = application:which_applications(5000), case lists:keyfind(logger, 1, StartedApps) of + %% Elixir logger is started. We assume everything is in place + %% to use lager to Elixir logger bridge. {logger, _, _} -> - error_logger:info_msg("Ignoring logger options, using Elixir Logger.", []), + error_logger:info_msg("Ignoring ejabberd logger options, using Elixir Logger.", []), %% Do not start lager, we rely on Elixir Logger do_start_for_logger(); _ -> @@ -119,7 +121,7 @@ do_start_for_logger() -> application:set_env(lager, error_logger_redirect, false), application:set_env(lager, error_logger_whitelist, ['Elixir.Logger.ErrorHandler']), application:set_env(lager, crash_log, false), - application:set_env(lager, handlers, [{elixir_logger_backend, [{level, debug}]}]), + application:set_env(lager, handlers, [{elixir_logger_backend, [{level, info}]}]), ejabberd:start_app(lager), ok. @@ -201,6 +203,8 @@ set(LogLevel) when is_integer(LogLevel) -> lager:set_loglevel(H, LagerLogLevel); (lager_console_backend = H) -> lager:set_loglevel(H, LagerLogLevel); + (elixir_logger_backend = H) -> + lager:set_loglevel(H, LagerLogLevel); (_) -> ok end, gen_event:which_handlers(lager_event)) @@ -211,13 +215,15 @@ set({_LogLevel, _}) -> {module, lager}. get_lager_loglevel() -> - R = case get_lager_handlers() of - [] -> none; - [elixir_logger_backend] -> debug; - [FirstHandler|_] -> - lager:get_loglevel(FirstHandler) - end, - R. + Handlers = get_lager_handlers(), + lists:foldl(fun(lager_console_backend, _Acc) -> + lager:get_loglevel(lager_console_backend); + (elixir_logger_backend, _Acc) -> + lager:get_loglevel(elixir_logger_backend); + (_, Acc) -> + Acc + end, + none, Handlers). get_lager_handlers() -> case catch gen_event:which_handlers(lager_event) of diff --git a/src/elixir_logger_backend.erl b/src/elixir_logger_backend.erl index 583d46a5cce..c055853f798 100644 --- a/src/elixir_logger_backend.erl +++ b/src/elixir_logger_backend.erl @@ -30,15 +30,19 @@ -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). -init(_Opts) -> - State = [], +-record(state, {level = debug}). + +init(Opts) -> + Level = proplists:get_value(level, Opts, debug), + State = #state{level = Level}, {ok, State}. %% @private handle_event({log, LagerMsg}, State) -> #{mode := Mode, truncate := Truncate, level := MinLevel, utc_log := UTCLog} = 'Elixir.Logger.Config':'__data__'(), MsgLevel = severity_to_level(lager_msg:severity(LagerMsg)), - case {lager_util:is_loggable(LagerMsg, lager_util:level_to_num(debug), ?MODULE), 'Elixir.Logger':compare_levels(MsgLevel, MinLevel)} of + case {lager_util:is_loggable(LagerMsg, lager_util:level_to_num(State#state.level), ?MODULE), + 'Elixir.Logger':compare_levels(MsgLevel, MinLevel)} of {_, lt}-> {ok, State}; {true, _} -> @@ -55,13 +59,15 @@ handle_event({log, LagerMsg}, State) -> _ -> {ok, State} end; -handle_event(_, State) -> +handle_event(_Msg, State) -> {ok, State}. %% @private %% TODO Handle loglevels -handle_call(_Msg, State) -> - {ok, ok, State}. +handle_call(get_loglevel, State) -> + {ok, lager_util:config_to_mask(State#state.level), State}; +handle_call({set_loglevel, Config}, State) -> + {ok, ok, State#state{level = Config}}. %% @private handle_info(_Msg, State) -> @@ -77,7 +83,8 @@ code_change(_OldVsn, State, _Extra) -> notify(sync, Msg) -> gen_event:sync_notify('Elixir.Logger', Msg); -notify(async, Msg) -> gen_event:notify('Elixir.Logger', Msg). +notify(async, Msg) -> + gen_event:notify('Elixir.Logger', Msg). normalize_pid(Metadata) -> case proplists:get_value(pid, Metadata) of From 15ee72138ac04e09a54ce05ae43fb837288ab178 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 10 Mar 2016 17:42:37 +0300 Subject: [PATCH 646/695] Add tests for MIX --- test/ejabberd_SUITE.erl | 90 ++++++++++- test/ejabberd_SUITE_data/ejabberd.yml | 2 + test/suite.erl | 8 + tools/xmpp_codec.erl | 222 +++++++++++++++++++++++++- tools/xmpp_codec.hrl | 11 +- tools/xmpp_codec.spec | 37 ++++- 6 files changed, 359 insertions(+), 11 deletions(-) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index 1b8d5f4775a..f17bfeb4c8b 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -12,8 +12,8 @@ -import(suite, [init_config/1, connect/1, disconnect/1, recv/0, send/2, send_recv/2, my_jid/1, server_jid/1, - pubsub_jid/1, proxy_jid/1, muc_jid/1, - muc_room_jid/1, get_features/2, re_register/1, + pubsub_jid/1, proxy_jid/1, muc_jid/1, muc_room_jid/1, + mix_jid/1, mix_room_jid/1, get_features/2, re_register/1, is_feature_advertised/2, subscribe_to_events/1, is_feature_advertised/3, set_opt/3, auth_SASL/2, wait_for_master/1, wait_for_slave/1, @@ -249,6 +249,8 @@ db_tests(DB) when DB == mnesia; DB == redis -> test_unregister]}, {test_muc_register, [sequence], [muc_register_master, muc_register_slave]}, + {test_mix, [parallel], + [mix_master, mix_slave]}, {test_roster_subscribe, [parallel], [roster_subscribe_master, roster_subscribe_slave]}, @@ -882,6 +884,90 @@ pubsub(Config) -> jid = my_jid(Config)}}]}), disconnect(Config). +mix_master(Config) -> + MIX = mix_jid(Config), + Room = mix_room_jid(Config), + MyJID = my_jid(Config), + MyBareJID = jid:remove_resource(MyJID), + true = is_feature_advertised(Config, ?NS_MIX_0, MIX), + #iq{type = result, + sub_els = + [#disco_info{ + identities = [#identity{category = <<"conference">>, + type = <<"text">>}], + xdata = [#xdata{type = result, fields = XFields}]}]} = + send_recv(Config, #iq{type = get, to = MIX, sub_els = [#disco_info{}]}), + true = lists:any( + fun(#xdata_field{var = <<"FORM_TYPE">>, + values = [?NS_MIX_SERVICEINFO_0]}) -> true; + (_) -> false + end, XFields), + %% Joining + Nodes = [?NS_MIX_NODES_MESSAGES, ?NS_MIX_NODES_PRESENCE, + ?NS_MIX_NODES_PARTICIPANTS, ?NS_MIX_NODES_SUBJECT, + ?NS_MIX_NODES_CONFIG], + I0 = send(Config, #iq{type = set, to = Room, + sub_els = [#mix_join{subscribe = Nodes}]}), + {_, #message{sub_els = + [#pubsub_event{ + items = [#pubsub_event_items{ + node = ?NS_MIX_NODES_PARTICIPANTS, + items = [#pubsub_event_item{ + id = ParticipantID, + xml_els = [PXML]}]}]}]}} = + ?recv2(#iq{type = result, id = I0, + sub_els = [#mix_join{subscribe = Nodes, jid = MyBareJID}]}, + #message{from = Room}), + #mix_participant{jid = MyBareJID} = xmpp_codec:decode(PXML), + %% Coming online + PresenceID = randoms:get_string(), + Presence = xmpp_codec:encode(#presence{}), + I1 = send( + Config, + #iq{type = set, to = Room, + sub_els = + [#pubsub{ + publish = #pubsub_publish{ + node = ?NS_MIX_NODES_PRESENCE, + items = [#pubsub_item{ + id = PresenceID, + xml_els = [Presence]}]}}]}), + ?recv2(#iq{type = result, id = I1, + sub_els = + [#pubsub{ + publish = #pubsub_publish{ + node = ?NS_MIX_NODES_PRESENCE, + items = [#pubsub_item{id = PresenceID}]}}]}, + #message{from = Room, + sub_els = + [#pubsub_event{ + items = [#pubsub_event_items{ + node = ?NS_MIX_NODES_PRESENCE, + items = [#pubsub_event_item{ + id = PresenceID, + xml_els = [Presence]}]}]}]}), + %% Coming offline + send(Config, #presence{type = unavailable, to = Room}), + %% Receiving presence retract event + #message{from = Room, + sub_els = [#pubsub_event{ + items = [#pubsub_event_items{ + node = ?NS_MIX_NODES_PRESENCE, + retract = [PresenceID]}]}]} = recv(), + %% Leaving + I2 = send(Config, #iq{type = set, to = Room, sub_els = [#mix_leave{}]}), + ?recv2(#iq{type = result, id = I2, sub_els = []}, + #message{from = Room, + sub_els = + [#pubsub_event{ + items = [#pubsub_event_items{ + node = ?NS_MIX_NODES_PARTICIPANTS, + retract = [ParticipantID]}]}]}), + disconnect(Config). + +mix_slave(Config) -> + disconnect(Config). + roster_subscribe_master(Config) -> send(Config, #presence{}), ?recv1(#presence{}), diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 5507900b871..96453f77b6f 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -197,6 +197,7 @@ Welcome to this XMPP server." - "flat" - "hometree" - "pep" + mod_mix: [] mod_roster: versioning: true store_current_id: true @@ -252,6 +253,7 @@ Welcome to this XMPP server." - "flat" - "hometree" - "pep" + mod_mix: [] mod_roster: versioning: true store_current_id: true diff --git a/test/suite.erl b/test/suite.erl index a0e0a48237d..bc094fa311c 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -354,6 +354,14 @@ muc_room_jid(Config) -> Server = ?config(server, Config), jid:make(<<"test">>, <<"conference.", Server/binary>>, <<>>). +mix_jid(Config) -> + Server = ?config(server, Config), + jid:make(<<>>, <<"mix.", Server/binary>>, <<>>). + +mix_room_jid(Config) -> + Server = ?config(server, Config), + jid:make(<<"test">>, <<"mix.", Server/binary>>, <<>>). + id() -> id(undefined). diff --git a/tools/xmpp_codec.erl b/tools/xmpp_codec.erl index 917418f5548..01e0676ae8a 100644 --- a/tools/xmpp_codec.erl +++ b/tools/xmpp_codec.erl @@ -15,6 +15,16 @@ decode(_el) -> decode(_el, []). decode({xmlel, _name, _attrs, _} = _el, Opts) -> IgnoreEls = proplists:get_bool(ignore_els, Opts), case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"participant">>, <<"urn:xmpp:mix:0">>} -> + decode_mix_participant(<<"urn:xmpp:mix:0">>, IgnoreEls, + _el); + {<<"leave">>, <<"urn:xmpp:mix:0">>} -> + decode_mix_leave(<<"urn:xmpp:mix:0">>, IgnoreEls, _el); + {<<"join">>, <<"urn:xmpp:mix:0">>} -> + decode_mix_join(<<"urn:xmpp:mix:0">>, IgnoreEls, _el); + {<<"subscribe">>, <<"urn:xmpp:mix:0">>} -> + decode_mix_subscribe(<<"urn:xmpp:mix:0">>, IgnoreEls, + _el); {<<"offline">>, <<"http://jabber.org/protocol/offline">>} -> decode_offline(<<"http://jabber.org/protocol/offline">>, @@ -1088,6 +1098,10 @@ decode({xmlel, _name, _attrs, _} = _el, Opts) -> is_known_tag({xmlel, _name, _attrs, _} = _el) -> case {_name, get_attr(<<"xmlns">>, _attrs)} of + {<<"participant">>, <<"urn:xmpp:mix:0">>} -> true; + {<<"leave">>, <<"urn:xmpp:mix:0">>} -> true; + {<<"join">>, <<"urn:xmpp:mix:0">>} -> true; + {<<"subscribe">>, <<"urn:xmpp:mix:0">>} -> true; {<<"offline">>, <<"http://jabber.org/protocol/offline">>} -> true; @@ -1987,7 +2001,7 @@ encode({pubsub_items, _, _, _, _} = Items) -> encode_pubsub_items(Items, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub">>}]); -encode({pubsub_event_item, _, _, _} = Item) -> +encode({pubsub_event_item, _, _, _, _} = Item) -> encode_pubsub_event_item(Item, [{<<"xmlns">>, <<"http://jabber.org/protocol/pubsub#event">>}]); @@ -2160,7 +2174,16 @@ encode({offline_item, _, _} = Item) -> encode({offline, _, _, _} = Offline) -> encode_offline(Offline, [{<<"xmlns">>, - <<"http://jabber.org/protocol/offline">>}]). + <<"http://jabber.org/protocol/offline">>}]); +encode({mix_join, _, _} = Join) -> + encode_mix_join(Join, + [{<<"xmlns">>, <<"urn:xmpp:mix:0">>}]); +encode({mix_leave} = Leave) -> + encode_mix_leave(Leave, + [{<<"xmlns">>, <<"urn:xmpp:mix:0">>}]); +encode({mix_participant, _, _} = Participant) -> + encode_mix_participant(Participant, + [{<<"xmlns">>, <<"urn:xmpp:mix:0">>}]). get_ns({last, _, _}) -> <<"jabber:iq:last">>; get_ns({version, _, _, _}) -> <<"jabber:iq:version">>; @@ -2286,7 +2309,7 @@ get_ns({pubsub_item, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; get_ns({pubsub_items, _, _, _, _}) -> <<"http://jabber.org/protocol/pubsub">>; -get_ns({pubsub_event_item, _, _, _}) -> +get_ns({pubsub_event_item, _, _, _, _}) -> <<"http://jabber.org/protocol/pubsub#event">>; get_ns({pubsub_event_items, _, _, _}) -> <<"http://jabber.org/protocol/pubsub#event">>; @@ -2359,6 +2382,9 @@ get_ns({offline_item, _, _}) -> <<"http://jabber.org/protocol/offline">>; get_ns({offline, _, _, _}) -> <<"http://jabber.org/protocol/offline">>; +get_ns({mix_join, _, _}) -> <<"urn:xmpp:mix:0">>; +get_ns({mix_leave}) -> <<"urn:xmpp:mix:0">>; +get_ns({mix_participant, _, _}) -> <<"urn:xmpp:mix:0">>; get_ns(_) -> <<>>. dec_int(Val) -> dec_int(Val, infinity, infinity). @@ -2505,7 +2531,8 @@ pp(pubsub_subscription, 4) -> [jid, node, subid, type]; pp(pubsub_affiliation, 2) -> [node, type]; pp(pubsub_item, 2) -> [id, xml_els]; pp(pubsub_items, 4) -> [node, max_items, subid, items]; -pp(pubsub_event_item, 3) -> [id, node, publisher]; +pp(pubsub_event_item, 4) -> + [id, node, publisher, xml_els]; pp(pubsub_event_items, 3) -> [node, retract, items]; pp(pubsub_event, 1) -> [items]; pp(pubsub_subscribe, 2) -> [node, jid]; @@ -2564,6 +2591,9 @@ pp(sm_a, 2) -> [h, xmlns]; pp(sm_failed, 2) -> [reason, xmlns]; pp(offline_item, 2) -> [node, action]; pp(offline, 3) -> [items, purge, fetch]; +pp(mix_join, 2) -> [jid, subscribe]; +pp(mix_leave, 0) -> []; +pp(mix_participant, 2) -> [jid, nick]; pp(_, _) -> no. enc_bool(false) -> <<"false">>; @@ -2606,6 +2636,170 @@ dec_tzo(Val) -> M = jlib:binary_to_integer(M1), if H >= -12, H =< 12, M >= 0, M < 60 -> {H, M} end. +decode_mix_participant(__TopXMLNS, __IgnoreEls, + {xmlel, <<"participant">>, _attrs, _els}) -> + {Jid, Nick} = decode_mix_participant_attrs(__TopXMLNS, + _attrs, undefined, undefined), + {mix_participant, Jid, Nick}. + +decode_mix_participant_attrs(__TopXMLNS, + [{<<"jid">>, _val} | _attrs], _Jid, Nick) -> + decode_mix_participant_attrs(__TopXMLNS, _attrs, _val, + Nick); +decode_mix_participant_attrs(__TopXMLNS, + [{<<"nick">>, _val} | _attrs], Jid, _Nick) -> + decode_mix_participant_attrs(__TopXMLNS, _attrs, Jid, + _val); +decode_mix_participant_attrs(__TopXMLNS, [_ | _attrs], + Jid, Nick) -> + decode_mix_participant_attrs(__TopXMLNS, _attrs, Jid, + Nick); +decode_mix_participant_attrs(__TopXMLNS, [], Jid, + Nick) -> + {decode_mix_participant_attr_jid(__TopXMLNS, Jid), + decode_mix_participant_attr_nick(__TopXMLNS, Nick)}. + +encode_mix_participant({mix_participant, Jid, Nick}, + _xmlns_attrs) -> + _els = [], + _attrs = encode_mix_participant_attr_nick(Nick, + encode_mix_participant_attr_jid(Jid, + _xmlns_attrs)), + {xmlel, <<"participant">>, _attrs, _els}. + +decode_mix_participant_attr_jid(__TopXMLNS, + undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"jid">>, <<"participant">>, + __TopXMLNS}}); +decode_mix_participant_attr_jid(__TopXMLNS, _val) -> + case catch dec_jid(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"jid">>, <<"participant">>, + __TopXMLNS}}); + _res -> _res + end. + +encode_mix_participant_attr_jid(_val, _acc) -> + [{<<"jid">>, enc_jid(_val)} | _acc]. + +decode_mix_participant_attr_nick(__TopXMLNS, + undefined) -> + undefined; +decode_mix_participant_attr_nick(__TopXMLNS, _val) -> + _val. + +encode_mix_participant_attr_nick(undefined, _acc) -> + _acc; +encode_mix_participant_attr_nick(_val, _acc) -> + [{<<"nick">>, _val} | _acc]. + +decode_mix_leave(__TopXMLNS, __IgnoreEls, + {xmlel, <<"leave">>, _attrs, _els}) -> + {mix_leave}. + +encode_mix_leave({mix_leave}, _xmlns_attrs) -> + _els = [], + _attrs = _xmlns_attrs, + {xmlel, <<"leave">>, _attrs, _els}. + +decode_mix_join(__TopXMLNS, __IgnoreEls, + {xmlel, <<"join">>, _attrs, _els}) -> + Subscribe = decode_mix_join_els(__TopXMLNS, __IgnoreEls, + _els, []), + Jid = decode_mix_join_attrs(__TopXMLNS, _attrs, + undefined), + {mix_join, Jid, Subscribe}. + +decode_mix_join_els(__TopXMLNS, __IgnoreEls, [], + Subscribe) -> + lists:reverse(Subscribe); +decode_mix_join_els(__TopXMLNS, __IgnoreEls, + [{xmlel, <<"subscribe">>, _attrs, _} = _el | _els], + Subscribe) -> + _xmlns = get_attr(<<"xmlns">>, _attrs), + if _xmlns == <<>>; _xmlns == __TopXMLNS -> + decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els, + [decode_mix_subscribe(__TopXMLNS, __IgnoreEls, + _el) + | Subscribe]); + true -> + decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els, + Subscribe) + end; +decode_mix_join_els(__TopXMLNS, __IgnoreEls, [_ | _els], + Subscribe) -> + decode_mix_join_els(__TopXMLNS, __IgnoreEls, _els, + Subscribe). + +decode_mix_join_attrs(__TopXMLNS, + [{<<"jid">>, _val} | _attrs], _Jid) -> + decode_mix_join_attrs(__TopXMLNS, _attrs, _val); +decode_mix_join_attrs(__TopXMLNS, [_ | _attrs], Jid) -> + decode_mix_join_attrs(__TopXMLNS, _attrs, Jid); +decode_mix_join_attrs(__TopXMLNS, [], Jid) -> + decode_mix_join_attr_jid(__TopXMLNS, Jid). + +encode_mix_join({mix_join, Jid, Subscribe}, + _xmlns_attrs) -> + _els = + lists:reverse('encode_mix_join_$subscribe'(Subscribe, + [])), + _attrs = encode_mix_join_attr_jid(Jid, _xmlns_attrs), + {xmlel, <<"join">>, _attrs, _els}. + +'encode_mix_join_$subscribe'([], _acc) -> _acc; +'encode_mix_join_$subscribe'([Subscribe | _els], + _acc) -> + 'encode_mix_join_$subscribe'(_els, + [encode_mix_subscribe(Subscribe, []) | _acc]). + +decode_mix_join_attr_jid(__TopXMLNS, undefined) -> + undefined; +decode_mix_join_attr_jid(__TopXMLNS, _val) -> + case catch dec_jid(_val) of + {'EXIT', _} -> + erlang:error({xmpp_codec, + {bad_attr_value, <<"jid">>, <<"join">>, __TopXMLNS}}); + _res -> _res + end. + +encode_mix_join_attr_jid(undefined, _acc) -> _acc; +encode_mix_join_attr_jid(_val, _acc) -> + [{<<"jid">>, enc_jid(_val)} | _acc]. + +decode_mix_subscribe(__TopXMLNS, __IgnoreEls, + {xmlel, <<"subscribe">>, _attrs, _els}) -> + Node = decode_mix_subscribe_attrs(__TopXMLNS, _attrs, + undefined), + Node. + +decode_mix_subscribe_attrs(__TopXMLNS, + [{<<"node">>, _val} | _attrs], _Node) -> + decode_mix_subscribe_attrs(__TopXMLNS, _attrs, _val); +decode_mix_subscribe_attrs(__TopXMLNS, [_ | _attrs], + Node) -> + decode_mix_subscribe_attrs(__TopXMLNS, _attrs, Node); +decode_mix_subscribe_attrs(__TopXMLNS, [], Node) -> + decode_mix_subscribe_attr_node(__TopXMLNS, Node). + +encode_mix_subscribe(Node, _xmlns_attrs) -> + _els = [], + _attrs = encode_mix_subscribe_attr_node(Node, + _xmlns_attrs), + {xmlel, <<"subscribe">>, _attrs, _els}. + +decode_mix_subscribe_attr_node(__TopXMLNS, undefined) -> + erlang:error({xmpp_codec, + {missing_attr, <<"node">>, <<"subscribe">>, + __TopXMLNS}}); +decode_mix_subscribe_attr_node(__TopXMLNS, _val) -> + _val. + +encode_mix_subscribe_attr_node(_val, _acc) -> + [{<<"node">>, _val} | _acc]. + decode_offline(__TopXMLNS, __IgnoreEls, {xmlel, <<"offline">>, _attrs, _els}) -> {Items, Purge, Fetch} = decode_offline_els(__TopXMLNS, @@ -7883,10 +8077,24 @@ encode_pubsub_event_items_attr_node(_val, _acc) -> decode_pubsub_event_item(__TopXMLNS, __IgnoreEls, {xmlel, <<"item">>, _attrs, _els}) -> + __Xmls = decode_pubsub_event_item_els(__TopXMLNS, + __IgnoreEls, _els, []), {Id, Node, Publisher} = decode_pubsub_event_item_attrs(__TopXMLNS, _attrs, undefined, undefined, undefined), - {pubsub_event_item, Id, Node, Publisher}. + {pubsub_event_item, Id, Node, Publisher, __Xmls}. + +decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, + [], __Xmls) -> + lists:reverse(__Xmls); +decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, + [{xmlel, _, _, _} = _el | _els], __Xmls) -> + decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, + _els, [_el | __Xmls]); +decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, + [_ | _els], __Xmls) -> + decode_pubsub_event_item_els(__TopXMLNS, __IgnoreEls, + _els, __Xmls). decode_pubsub_event_item_attrs(__TopXMLNS, [{<<"id">>, _val} | _attrs], _Id, Node, @@ -7915,9 +8123,9 @@ decode_pubsub_event_item_attrs(__TopXMLNS, [], Id, Node, Publisher)}. encode_pubsub_event_item({pubsub_event_item, Id, Node, - Publisher}, + Publisher, __Xmls}, _xmlns_attrs) -> - _els = [], + _els = __Xmls, _attrs = encode_pubsub_event_item_attr_publisher(Publisher, encode_pubsub_event_item_attr_node(Node, diff --git a/tools/xmpp_codec.hrl b/tools/xmpp_codec.hrl index 1426287bfc5..b2773a6c1bc 100644 --- a/tools/xmpp_codec.hrl +++ b/tools/xmpp_codec.hrl @@ -36,6 +36,8 @@ jid :: any(), subid :: binary()}). +-record(mix_leave, {}). + -record(ping, {}). -record(delay, {stamp :: any(), @@ -98,7 +100,8 @@ -record(pubsub_event_item, {id :: binary(), node :: binary(), - publisher :: binary()}). + publisher :: binary(), + xml_els = [] :: [any()]}). -record(sm_r, {xmlns :: binary()}). @@ -229,6 +232,9 @@ notify = false :: any(), items = [] :: [#pubsub_item{}]}). +-record(mix_participant, {jid :: any(), + nick :: binary()}). + -record(vcard_geo, {lat :: binary(), lon :: binary()}). @@ -471,6 +477,9 @@ error :: #error{}, sub_els = [] :: [any()]}). +-record(mix_join, {jid :: any(), + subscribe = [] :: [binary()]}). + -record(privacy_item, {order :: non_neg_integer(), action :: 'allow' | 'deny', type :: 'group' | 'jid' | 'subscription', diff --git a/tools/xmpp_codec.spec b/tools/xmpp_codec.spec index 129a4efba9a..e61b951c513 100644 --- a/tools/xmpp_codec.spec +++ b/tools/xmpp_codec.spec @@ -1645,7 +1645,7 @@ -xml(pubsub_event_item, #elem{name = <<"item">>, xmlns = <<"http://jabber.org/protocol/pubsub#event">>, - result = {pubsub_event_item, '$id', '$node', '$publisher'}, + result = {pubsub_event_item, '$id', '$node', '$publisher', '$_xmls'}, attrs = [#attr{name = <<"id">>}, #attr{name = <<"node">>}, #attr{name = <<"publisher">>}]}). @@ -2427,6 +2427,41 @@ label = '$fetch', default = false}, #ref{name = offline_item, min = 0, label = '$items'}]}). +-xml(mix_subscribe, + #elem{name = <<"subscribe">>, + xmlns = <<"urn:xmpp:mix:0">>, + result = '$node', + attrs = [#attr{name = <<"node">>, + required = true, + label = '$node'}]}). + +-xml(mix_join, + #elem{name = <<"join">>, + xmlns = <<"urn:xmpp:mix:0">>, + result = {mix_join, '$jid', '$subscribe'}, + attrs = [#attr{name = <<"jid">>, + label = '$jid', + dec = {dec_jid, []}, + enc = {enc_jid, []}}], + refs = [#ref{name = mix_subscribe, min = 0, label = '$subscribe'}]}). + +-xml(mix_leave, + #elem{name = <<"leave">>, + xmlns = <<"urn:xmpp:mix:0">>, + result = {mix_leave}}). + +-xml(mix_participant, + #elem{name = <<"participant">>, + xmlns = <<"urn:xmpp:mix:0">>, + result = {mix_participant, '$jid', '$nick'}, + attrs = [#attr{name = <<"jid">>, + required = true, + label = '$jid', + dec = {dec_jid, []}, + enc = {enc_jid, []}}, + #attr{name = <<"nick">>, + label = '$nick'}]}). + dec_tzo(Val) -> [H1, M1] = str:tokens(Val, <<":">>), H = jlib:binary_to_integer(H1), From 8b03c0a3856fc067ae1d16e9e2a93dfd39981d62 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Thu, 10 Mar 2016 17:46:15 +0100 Subject: [PATCH 647/695] Minimal auth_method ordering fix --- src/ejabberd_config.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index c500ee4ea36..eb06b98f616 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -408,7 +408,7 @@ maps_to_lists(IMap) -> end, [], IMap). merge_configs(Terms, ResMap) -> - lists:foldl(fun({Name, Val}, Map) when is_list(Val) -> + lists:foldl(fun({Name, Val}, Map) when is_list(Val), Name =/= auth_method -> Old = maps:get(Name, Map, #{}), New = lists:foldl(fun(SVal, OMap) -> NVal = if Name == host_config orelse Name == append_host_config -> From 0d1edc477190242a7e64eb1a2640eabef970860c Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Fri, 11 Mar 2016 12:31:16 +0100 Subject: [PATCH 648/695] Don't enable in-band registration by default --- ejabberd.yml.example | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index e20dc0dfb4e..74a9538cdc1 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -616,45 +616,39 @@ modules: - "flat" - "hometree" - "pep" # pep requires mod_caps - mod_register: + ## mod_register: ## ## Protect In-Band account registrations with CAPTCHA. ## - ## captcha_protected: true - + ## captcha_protected: true ## ## Set the minimum informational entropy for passwords. ## - ## password_strength: 32 - + ## password_strength: 32 ## ## After successful registration, the user receives ## a message with this subject and body. ## - welcome_message: - subject: "Welcome!" - body: |- - Hi. - Welcome to this XMPP server. - + ## welcome_message: + ## subject: "Welcome!" + ## body: |- + ## Hi. + ## Welcome to this XMPP server. ## ## When a user registers, send a notification to ## these XMPP accounts. ## - ## registration_watchers: - ## - "admin1@example.org" - + ## registration_watchers: + ## - "admin1@example.org" ## ## Only clients in the server machine can register accounts ## - ip_access: trusted_network - + ## ip_access: trusted_network ## ## Local c2s or remote s2s users cannot register accounts ## - ## access_from: deny - - access: register + ## access_from: deny + ## access: register mod_roster: {} mod_shared_roster: {} mod_stats: {} From 9297782868178a47725f20df9f7a51ad59a3e5e3 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 11 Mar 2016 17:25:46 +0100 Subject: [PATCH 649/695] Fix config fetch after host/serverhost cleanup --- src/mod_pubsub.erl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index ed3debbf15d..8017e3e5d52 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -3953,20 +3953,14 @@ set_xoption(Host, [{<<"pubsub#itemreply">>, [Val]} | Opts], NewOpts) -> set_xoption(Host, [_ | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts). -get_max_items_node({_, ServerHost, _}) -> - get_max_items_node(ServerHost); get_max_items_node(Host) -> config(serverhost(Host), max_items_node, undefined). -get_max_subscriptions_node({_, ServerHost, _}) -> - get_max_subscriptions_node(ServerHost); get_max_subscriptions_node(Host) -> config(serverhost(Host), max_subscriptions_node, undefined). %%%% last item cache handling -is_last_item_cache_enabled({_, ServerHost, _}) -> - is_last_item_cache_enabled(ServerHost); is_last_item_cache_enabled(Host) -> config(serverhost(Host), last_item_cache, false). From 9ceeaf213ba3ca46a71f7fdb48dfd7608c8fbc40 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sat, 12 Mar 2016 17:54:23 +0100 Subject: [PATCH 650/695] Provide guidance for issue reporting and pull requests on Github --- .github/ISSUE_TEMPLATE | 16 ++++++++++++++++ .github/PULL_REQUEST_TEMPLATE | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE create mode 100644 .github/PULL_REQUEST_TEMPLATE diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 00000000000..8d1a5f259b7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,16 @@ +Please answer these questions before submitting your issue. It may help ! + +Thanks! + +1. What version of ejabberd are you using ? + + +2. What operating system are you using ? + + +3. How did you install ejabberd (source, package, distribution) ? + + +4. What did not work as expected ? What that error in the log ? + What that unexpected behaviour ? What was the expected result ? + diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 00000000000..554cad4b62e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE @@ -0,0 +1,23 @@ +We are open to contribution for ejabberd, as Github pull requests (PR). +Here is a few points to consider before submitting your pull request. +(You can remove the whole text after reading). + +1. Does this PR address an issue ? + Please reference it in PR description. + +2. Have you properly described the proposed changed ? + +3. Please, make sure the change is atomic and does only touch the + needed modules. + If you have other changes / fixes to provide, please make them as + separate PR. + +4. If you change or new feature involves backends, + did you make sure you change is compliant with all backends or + provide the feature for all backends ? + +5. Do you provides tests ? + How can we check the behaviour of the code ? + +6. Did you consider documentation changes on project + processone/docs.ejabberd.im ? From 357e48fb6b60b72f050a438164a1d5590caca8f0 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Mar 2016 11:38:40 +0300 Subject: [PATCH 651/695] Make it possible to get virtual host of a registered route --- src/ejabberd_local.erl | 1 + src/ejabberd_router.erl | 109 ++++++++++++++++++++++-------------- src/ejabberd_service.erl | 2 +- src/mod_echo.erl | 2 +- src/mod_http_upload.erl | 2 +- src/mod_irc.erl | 2 +- src/mod_mix.erl | 2 +- src/mod_muc.erl | 2 +- src/mod_multicast.erl | 2 +- src/mod_proxy65_service.erl | 2 +- src/mod_pubsub.erl | 2 +- src/mod_vcard.erl | 2 +- src/mod_vcard_ldap.erl | 2 +- 13 files changed, 79 insertions(+), 53 deletions(-) diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 292288a374b..7c30f3b6c42 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -178,6 +178,7 @@ bounce_resource_packet(From, To, Packet) -> init([]) -> lists:foreach(fun (Host) -> ejabberd_router:register_route(Host, + Host, {apply, ?MODULE, route}), ejabberd_hooks:add(local_send_to_resource_hook, Host, diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index da1bd3e0fc0..e29d6acfb1e 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -36,7 +36,9 @@ route_error/4, register_route/1, register_route/2, + register_route/3, register_routes/1, + host_of_route/1, unregister_route/1, unregister_routes/1, dirty_get_all_routes/0, @@ -55,7 +57,7 @@ -type local_hint() :: undefined | integer() | {apply, atom(), atom()}. --record(route, {domain, pid, local_hint}). +-record(route, {domain, server_host, pid, local_hint}). -record(state, {}). @@ -94,19 +96,29 @@ route_error(From, To, ErrPacket, OrigPacket) -> -spec register_route(binary()) -> term(). register_route(Domain) -> - register_route(Domain, undefined). + ?WARNING_MSG("~s:register_route/1 is deprected, " + "use ~s:register_route/2 instead", + [?MODULE, ?MODULE]), + register_route(Domain, ?MYNAME). --spec register_route(binary(), local_hint()) -> term(). +-spec register_route(binary(), binary()) -> term(). -register_route(Domain, LocalHint) -> - case jid:nameprep(Domain) of - error -> erlang:error({invalid_domain, Domain}); - LDomain -> +register_route(Domain, ServerHost) -> + register_route(Domain, ServerHost, undefined). + +-spec register_route(binary(), binary(), local_hint()) -> term(). + +register_route(Domain, ServerHost, LocalHint) -> + case {jid:nameprep(Domain), jid:nameprep(ServerHost)} of + {error, _} -> erlang:error({invalid_domain, Domain}); + {_, error} -> erlang:error({invalid_domain, ServerHost}); + {LDomain, LServerHost} -> Pid = self(), case get_component_number(LDomain) of undefined -> F = fun () -> mnesia:write(#route{domain = LDomain, pid = Pid, + server_host = LServerHost, local_hint = LocalHint}) end, mnesia:transaction(F); @@ -115,46 +127,42 @@ register_route(Domain, LocalHint) -> case mnesia:wread({route, LDomain}) of [] -> mnesia:write(#route{domain = LDomain, + server_host = LServerHost, pid = Pid, local_hint = 1}), - lists:foreach(fun (I) -> - mnesia:write(#route{domain - = - LDomain, - pid - = - undefined, - local_hint - = - I}) - end, - lists:seq(2, N)); + lists:foreach( + fun (I) -> + mnesia:write( + #route{domain = LDomain, + pid = undefined, + server_host = LServerHost, + local_hint = I}) + end, + lists:seq(2, N)); Rs -> - lists:any(fun (#route{pid = undefined, - local_hint = I} = - R) -> - mnesia:write(#route{domain = - LDomain, - pid = - Pid, - local_hint - = - I}), - mnesia:delete_object(R), - true; - (_) -> false - end, - Rs) + lists:any( + fun (#route{pid = undefined, + local_hint = I} = R) -> + mnesia:write( + #route{domain = LDomain, + pid = Pid, + server_host = LServerHost, + local_hint = I}), + mnesia:delete_object(R), + true; + (_) -> false + end, + Rs) end end, mnesia:transaction(F) end end. --spec register_routes([binary()]) -> ok. +-spec register_routes([{binary(), binary()}]) -> ok. register_routes(Domains) -> - lists:foreach(fun (Domain) -> register_route(Domain) + lists:foreach(fun ({Domain, ServerHost}) -> register_route(Domain, ServerHost) end, Domains). @@ -183,7 +191,9 @@ unregister_route(Domain) -> of [R] -> I = R#route.local_hint, + ServerHost = R#route.server_host, mnesia:write(#route{domain = LDomain, + server_host = ServerHost, pid = undefined, local_hint = I}), mnesia:delete_object(R); @@ -211,6 +221,20 @@ dirty_get_all_routes() -> dirty_get_all_domains() -> lists:usort(mnesia:dirty_all_keys(route)). +-spec host_of_route(binary()) -> binary(). + +host_of_route(Domain) -> + case jid:nameprep(Domain) of + error -> + erlang:error({invalid_domain, Domain}); + LDomain -> + case mnesia:dirty_read(route, LDomain) of + [#route{server_host = ServerHost}|_] -> + ServerHost; + [] -> + erlang:error({unregistered_route, Domain}) + end + end. %%==================================================================== %% gen_server callbacks @@ -283,8 +307,11 @@ handle_info({'DOWN', _Ref, _Type, Pid, _Info}, State) -> if is_integer(E#route.local_hint) -> LDomain = E#route.domain, I = E#route.local_hint, + ServerHost = E#route.server_host, mnesia:write(#route{domain = LDomain, + server_host = + ServerHost, pid = undefined, local_hint = @@ -394,12 +421,10 @@ get_component_number(LDomain) -> undefined). update_tables() -> - case catch mnesia:table_info(route, attributes) of - [domain, node, pid] -> mnesia:delete_table(route); - [domain, pid] -> mnesia:delete_table(route); - [domain, pid, local_hint] -> ok; - [domain, pid, local_hint|_] -> mnesia:delete_table(route); - {'EXIT', _} -> ok + try + mnesia:transform_table(route, ignore, record_info(fields, route)) + catch exit:{aborted, {no_exists, _}} -> + ok end, case lists:member(local_route, mnesia:system_info(tables)) diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index e5508a19080..5caae610281 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -222,7 +222,7 @@ wait_for_handshake({xmlstreamelement, El}, StateData) -> send_text(StateData, <<"">>), lists:foreach( fun (H) -> - ejabberd_router:register_route(H), + ejabberd_router:register_route(H, ?MYNAME), ?INFO_MSG("Route registered for service ~p~n", [H]) end, dict:fetch_keys(StateData#state.host_opts)), diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 8e7394cb489..7184ee4e7a8 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -86,7 +86,7 @@ stop(Host) -> init([Host, Opts]) -> MyHost = gen_mod:get_opt_host(Host, Opts, <<"echo.@HOST@">>), - ejabberd_router:register_route(MyHost), + ejabberd_router:register_route(MyHost, Host), {ok, #state{host = MyHost}}. %%-------------------------------------------------------------------- diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 5635102b27a..6c029c437be 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -306,7 +306,7 @@ init({ServerHost, Opts}) -> false -> ok end, - ejabberd_router:register_route(Host), + ejabberd_router:register_route(Host, ServerHost), {ok, #state{server_host = ServerHost, host = Host, name = Name, access = Access, max_size = MaxSize, secret_length = SecretLength, jid_in_url = JIDinURL, diff --git a/src/mod_irc.erl b/src/mod_irc.erl index b7300e28b36..d5cd01353e8 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -133,7 +133,7 @@ init([Host, Opts]) -> catch ets:new(irc_connection, [named_table, public, {keypos, #irc_connection.jid_server_host}]), - ejabberd_router:register_route(MyHost), + ejabberd_router:register_route(MyHost, Host), {ok, #state{host = MyHost, server_host = Host, access = Access}}. diff --git a/src/mod_mix.erl b/src/mod_mix.erl index 8224ec78a6e..d8cf94ac350 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -168,7 +168,7 @@ init([ServerHost, Opts]) -> ?NS_PUBSUB, mod_pubsub, iq_sm, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MIX_0, ?MODULE, process_iq, IQDisc), - ejabberd_router:register_route(Host), + ejabberd_router:register_route(Host, ServerHost), {ok, #state{server_host = ServerHost, host = Host}}. handle_call(_Request, _From, State) -> diff --git a/src/mod_muc.erl b/src/mod_muc.erl index de795fc0e35..0d37a236e24 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -373,7 +373,7 @@ init([Host, Opts]) -> RoomShaper = gen_mod:get_opt(room_shaper, Opts, fun(A) when is_atom(A) -> A end, none), - ejabberd_router:register_route(MyHost), + ejabberd_router:register_route(MyHost, Host), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, HistorySize, RoomShaper), diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 5c662a868d7..0c6130482b2 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -151,7 +151,7 @@ init([LServerS, Opts]) -> try_start_loop(), create_pool(), ejabberd_router_multicast:register_route(LServerS), - ejabberd_router:register_route(LServiceS), + ejabberd_router:register_route(LServiceS, LServerS), {ok, #state{lservice = LServiceS, lserver = LServerS, access = Access, service_limits = SLimits}}. diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 3fb86360a11..8b4644ba8b1 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -63,7 +63,7 @@ start_link(Host, Opts) -> init([Host, Opts]) -> State = parse_options(Host, Opts), - ejabberd_router:register_route(State#state.myhost), + ejabberd_router:register_route(State#state.myhost, Host), {ok, State}. terminate(_Reason, #state{myhost = MyHost}) -> diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 8017e3e5d52..5fa8a989b28 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -241,6 +241,7 @@ stop(Host) -> init([ServerHost, Opts]) -> ?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]), Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>), + ejabberd_router:register_route(Host, ServerHost), Access = gen_mod:get_opt(access_createnode, Opts, fun(A) when is_atom(A) -> A end, all), PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, @@ -309,7 +310,6 @@ init([ServerHost, Opts]) -> false -> ok end, - ejabberd_router:register_route(Host), pubsub_migrate:update_node_database(Host, ServerHost), pubsub_migrate:update_state_database(Host, ServerHost), pubsub_migrate:update_lastitem_database(Host, ServerHost), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 3652fb2af07..256dc5de744 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -105,7 +105,7 @@ init(Host, ServerHost, Search) -> case Search of false -> loop(Host, ServerHost); _ -> - ejabberd_router:register_route(Host), + ejabberd_router:register_route(Host, ServerHost), loop(Host, ServerHost) end. diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 25239133c1b..98aaf9362a1 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -173,7 +173,7 @@ init([Host, Opts]) -> State#state.password, State#state.tls_options), case State#state.search of true -> - ejabberd_router:register_route(State#state.myhost); + ejabberd_router:register_route(State#state.myhost, Host); _ -> ok end, {ok, State}. From 5045fb584de1266de04383e549ef601581bf836f Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Mar 2016 13:16:43 +0300 Subject: [PATCH 652/695] Define pubsub node configuration per route/host explicitly --- src/mod_pubsub.erl | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 5fa8a989b28..38d4b7405a3 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -257,22 +257,26 @@ init([ServerHost, Opts]) -> DefaultNodeCfg = gen_mod:get_opt(default_node_config, Opts, fun(A) when is_list(A) -> filter_node_options(A) end, []), pubsub_index:init(Host, ServerHost, Opts), - ets:new(gen_mod:get_module_proc(ServerHost, config), [set, named_table]), {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts), mnesia:create_table(pubsub_last_item, [{ram_copies, [node()]}, {attributes, record_info(fields, pubsub_last_item)}]), mod_disco:register_feature(ServerHost, ?NS_PUBSUB), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {nodetree, NodeTree}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {plugins, Plugins}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {last_item_cache, LastItemCache}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_items_node, MaxItemsNode}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {max_subscriptions_node, MaxSubsNode}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {default_node_config, DefaultNodeCfg}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {pep_mapping, PepMapping}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {ignore_pep_from_offline, PepOffline}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {host, Host}), - ets:insert(gen_mod:get_module_proc(ServerHost, config), {access, Access}), + lists:foreach( + fun(H) -> + T = gen_mod:get_module_proc(H, config), + ets:new(T, [set, named_table]), + ets:insert(T, {nodetree, NodeTree}), + ets:insert(T, {plugins, Plugins}), + ets:insert(T, {last_item_cache, LastItemCache}), + ets:insert(T, {max_items_node, MaxItemsNode}), + ets:insert(T, {max_subscriptions_node, MaxSubsNode}), + ets:insert(T, {default_node_config, DefaultNodeCfg}), + ets:insert(T, {pep_mapping, PepMapping}), + ets:insert(T, {ignore_pep_from_offline, PepOffline}), + ets:insert(T, {host, Host}), + ets:insert(T, {access, Access}) + end, [Host, ServerHost]), ejabberd_hooks:add(sm_remove_connection_hook, ServerHost, ?MODULE, on_user_offline, 75), ejabberd_hooks:add(disco_local_identity, ServerHost, @@ -3641,7 +3645,7 @@ get_option(Options, Var, Def) -> end. node_options(Host, Type) -> - case config(serverhost(Host), default_node_config) of + case config(Host, default_node_config) of undefined -> node_plugin_options(Host, Type); [] -> node_plugin_options(Host, Type); Config -> Config @@ -3954,15 +3958,15 @@ set_xoption(Host, [_ | Opts], NewOpts) -> set_xoption(Host, Opts, NewOpts). get_max_items_node(Host) -> - config(serverhost(Host), max_items_node, undefined). + config(Host, max_items_node, undefined). get_max_subscriptions_node(Host) -> - config(serverhost(Host), max_subscriptions_node, undefined). + config(Host, max_subscriptions_node, undefined). %%%% last item cache handling is_last_item_cache_enabled(Host) -> - config(serverhost(Host), last_item_cache, false). + config(Host, last_item_cache, false). set_cached_item({_, ServerHost, _}, Nidx, ItemId, Publisher, Payload) -> set_cached_item(ServerHost, Nidx, ItemId, Publisher, Payload); @@ -4013,13 +4017,12 @@ host(ServerHost) -> config(ServerHost, host, <<"pubsub.", ServerHost/binary>>). serverhost({_U, ServerHost, _R})-> - ServerHost; + serverhost(ServerHost); serverhost(Host) -> - [_, ServerHost] = binary:split(Host, <<".">>), - ServerHost. + ejabberd_router:host_of_route(Host). tree(Host) -> - case config(serverhost(Host), nodetree) of + case config(Host, nodetree) of undefined -> tree(Host, ?STDTREE); Tree -> Tree end. @@ -4041,7 +4044,7 @@ plugin(Host, Name) -> end. plugins(Host) -> - case config(serverhost(Host), plugins) of + case config(Host, plugins) of undefined -> [?STDNODE]; [] -> [?STDNODE]; Plugins -> Plugins @@ -4056,6 +4059,9 @@ subscription_plugin(Host) -> config(ServerHost, Key) -> config(ServerHost, Key, undefined). + +config({_User, Host, _Resource}, Key, Default) -> + config(Host, Key, Default); config(ServerHost, Key, Default) -> case catch ets:lookup(gen_mod:get_module_proc(ServerHost, config), Key) of [{Key, Value}] -> Value; From 50e5cdc2fa41be8b9f8a04b7474421ebac88fb53 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Mar 2016 13:16:55 +0300 Subject: [PATCH 653/695] Add ODBC tests for MIX --- test/ejabberd_SUITE.erl | 2 ++ test/ejabberd_SUITE_data/ejabberd.yml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index f17bfeb4c8b..b239ddf0b0b 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -293,6 +293,8 @@ db_tests(_) -> test_unregister]}, {test_muc_register, [sequence], [muc_register_master, muc_register_slave]}, + {test_mix, [parallel], + [mix_master, mix_slave]}, {test_roster_subscribe, [parallel], [roster_subscribe_master, roster_subscribe_slave]}, diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml index 96453f77b6f..923d690248b 100644 --- a/test/ejabberd_SUITE_data/ejabberd.yml +++ b/test/ejabberd_SUITE_data/ejabberd.yml @@ -35,6 +35,7 @@ host_config: - "flat" - "hometree" - "pep" + mod_mix: [] mod_roster: versioning: true store_current_id: true @@ -88,6 +89,7 @@ Welcome to this XMPP server." - "flat" - "hometree" - "pep" + mod_mix: [] mod_roster: versioning: true store_current_id: true @@ -147,6 +149,7 @@ Welcome to this XMPP server." - "flat" - "hometree" - "pep" + mod_mix: [] mod_roster: versioning: true store_current_id: true From 5a4b7817df6c3251d947f0a341fdbf833ab60926 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Mar 2016 15:38:50 +0300 Subject: [PATCH 654/695] Add ODBC backend for MIX --- src/node_mix_odbc.erl | 170 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 src/node_mix_odbc.erl diff --git a/src/node_mix_odbc.erl b/src/node_mix_odbc.erl new file mode 100644 index 00000000000..e7cc6883ad1 --- /dev/null +++ b/src/node_mix_odbc.erl @@ -0,0 +1,170 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeny Khramtsov +%%% @copyright (C) 2016, Evgeny Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 8 Mar 2016 by Evgeny Khramtsov +%%%------------------------------------------------------------------- +-module(node_mix_odbc). + +-behaviour(gen_pubsub_node). + +%% API +-export([init/3, terminate/2, options/0, features/0, + create_node_permission/6, create_node/2, delete_node/1, + purge_node/2, subscribe_node/8, unsubscribe_node/4, + publish_item/6, delete_item/4, remove_extra_items/3, + get_entity_affiliations/2, get_node_affiliations/1, + get_affiliation/2, set_affiliation/3, + get_entity_subscriptions/2, get_node_subscriptions/1, + get_subscriptions/2, set_subscriptions/4, + get_pending_nodes/2, get_states/1, get_state/2, + set_state/1, get_items/7, get_items/3, get_item/7, + get_item/2, set_item/1, get_item_name/3, node_to_path/1, + path_to_node/1, get_entity_subscriptions_for_send_last/2]). + +-include("pubsub.hrl"). + +%%%=================================================================== +%%% API +%%%=================================================================== +init(Host, ServerHost, Opts) -> + node_flat_odbc:init(Host, ServerHost, Opts). + +terminate(Host, ServerHost) -> + node_flat_odbc:terminate(Host, ServerHost). + +options() -> + [{deliver_payloads, true}, + {notify_config, false}, + {notify_delete, false}, + {notify_retract, true}, + {purge_offline, false}, + {persist_items, true}, + {max_items, ?MAXITEMS}, + {subscribe, true}, + {access_model, open}, + {roster_groups_allowed, []}, + {publish_model, open}, + {notification_type, headline}, + {max_payload_size, ?MAX_PAYLOAD_SIZE}, + {send_last_published_item, never}, + {deliver_notifications, true}, + {broadcast_all_resources, true}, + {presence_based_delivery, false}]. + +features() -> + [<<"create-nodes">>, + <<"delete-nodes">>, + <<"delete-items">>, + <<"instant-nodes">>, + <<"item-ids">>, + <<"outcast-affiliation">>, + <<"persistent-items">>, + <<"publish">>, + <<"purge-nodes">>, + <<"retract-items">>, + <<"retrieve-affiliations">>, + <<"retrieve-items">>, + <<"retrieve-subscriptions">>, + <<"subscribe">>, + <<"subscription-notifications">>]. + +create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access) -> + node_flat_odbc:create_node_permission(Host, ServerHost, Node, ParentNode, Owner, Access). + +create_node(Nidx, Owner) -> + node_flat_odbc:create_node(Nidx, Owner). + +delete_node(Removed) -> + node_flat_odbc:delete_node(Removed). + +subscribe_node(Nidx, Sender, Subscriber, AccessModel, + SendLast, PresenceSubscription, RosterGroup, Options) -> + node_flat_odbc:subscribe_node(Nidx, Sender, Subscriber, AccessModel, SendLast, + PresenceSubscription, RosterGroup, Options). + +unsubscribe_node(Nidx, Sender, Subscriber, SubId) -> + node_flat_odbc:unsubscribe_node(Nidx, Sender, Subscriber, SubId). + +publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload) -> + node_flat_odbc:publish_item(Nidx, Publisher, Model, MaxItems, ItemId, Payload). + +remove_extra_items(Nidx, MaxItems, ItemIds) -> + node_flat_odbc:remove_extra_items(Nidx, MaxItems, ItemIds). + +delete_item(Nidx, Publisher, PublishModel, ItemId) -> + node_flat_odbc:delete_item(Nidx, Publisher, PublishModel, ItemId). + +purge_node(Nidx, Owner) -> + node_flat_odbc:purge_node(Nidx, Owner). + +get_entity_affiliations(Host, Owner) -> + node_flat_odbc:get_entity_affiliations(Host, Owner). + +get_node_affiliations(Nidx) -> + node_flat_odbc:get_node_affiliations(Nidx). + +get_affiliation(Nidx, Owner) -> + node_flat_odbc:get_affiliation(Nidx, Owner). + +set_affiliation(Nidx, Owner, Affiliation) -> + node_flat_odbc:set_affiliation(Nidx, Owner, Affiliation). + +get_entity_subscriptions(Host, Owner) -> + node_flat_odbc:get_entity_subscriptions(Host, Owner). + +get_node_subscriptions(Nidx) -> + node_flat_odbc:get_node_subscriptions(Nidx). + +get_subscriptions(Nidx, Owner) -> + node_flat_odbc:get_subscriptions(Nidx, Owner). + +set_subscriptions(Nidx, Owner, Subscription, SubId) -> + node_flat_odbc:set_subscriptions(Nidx, Owner, Subscription, SubId). + +get_pending_nodes(Host, Owner) -> + node_flat_odbc:get_pending_nodes(Host, Owner). + +get_states(Nidx) -> + node_flat_odbc:get_states(Nidx). + +get_state(Nidx, JID) -> + node_flat_odbc:get_state(Nidx, JID). + +set_state(State) -> + node_flat_odbc:set_state(State). + +get_items(Nidx, From, RSM) -> + node_flat_odbc:get_items(Nidx, From, RSM). + +get_items(Nidx, JID, AccessModel, PresenceSubscription, RosterGroup, SubId, RSM) -> + node_flat_odbc:get_items(Nidx, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId, RSM). + +get_item(Nidx, ItemId) -> + node_flat_odbc:get_item(Nidx, ItemId). + +get_item(Nidx, ItemId, JID, AccessModel, PresenceSubscription, RosterGroup, SubId) -> + node_flat_odbc:get_item(Nidx, ItemId, JID, AccessModel, + PresenceSubscription, RosterGroup, SubId). + +set_item(Item) -> + node_flat_odbc:set_item(Item). + +get_item_name(Host, Node, Id) -> + node_flat_odbc:get_item_name(Host, Node, Id). + +node_to_path(Node) -> + node_flat_odbc:node_to_path(Node). + +path_to_node(Path) -> + node_flat_odbc:path_to_node(Path). + +get_entity_subscriptions_for_send_last(Host, Owner) -> + node_flat_odbc:get_entity_subscriptions_for_send_last(Host, Owner). + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== From 55c567ff0017923cc953d1579560dd98b6bd48eb Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Sun, 13 Mar 2016 17:37:39 +0300 Subject: [PATCH 655/695] Unregister route at the very end --- src/mod_pubsub.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 38d4b7405a3..6531ed8764c 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -877,7 +877,6 @@ handle_info(_Info, State) -> %% @private terminate(_Reason, #state{host = Host, server_host = ServerHost, nodetree = TreePlugin, plugins = Plugins}) -> - ejabberd_router:unregister_route(Host), case lists:member(?PEPNODE, Plugins) of true -> ejabberd_hooks:delete(caps_add, ServerHost, @@ -922,7 +921,8 @@ terminate(_Reason, Pid -> Pid ! stop end, - terminate_plugins(Host, ServerHost, Plugins, TreePlugin). + terminate_plugins(Host, ServerHost, Plugins, TreePlugin), + ejabberd_router:unregister_route(Host). %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} From 91573a8e822b6704bd846ea93c267a71e5d0221f Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 14 Mar 2016 00:05:50 +0100 Subject: [PATCH 656/695] Don't store watchdog notifications in MAM archives --- src/ejabberd_system_monitor.erl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index 3ea6360339a..3f6c0566771 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -186,18 +186,24 @@ process_large_heap(Pid, Info) -> "much memory:~n~p~n~s", [node(), Pid, Info, DetailedInfo])), From = jid:make(<<"">>, Host, <<"watchdog">>), + Hint = [#xmlel{name = <<"no-permanent-store">>, + attrs = [{<<"xmlns">>, ?NS_HINTS}]}], lists:foreach(fun (JID) -> - send_message(From, jid:make(JID), Body) + send_message(From, jid:make(JID), Body, Hint) end, JIDs). send_message(From, To, Body) -> + send_message(From, To, Body, []). + +send_message(From, To, Body, ExtraEls) -> ejabberd_router:route(From, To, #xmlel{name = <<"message">>, attrs = [{<<"type">>, <<"chat">>}], children = [#xmlel{name = <<"body">>, attrs = [], children = - [{xmlcdata, Body}]}]}). + [{xmlcdata, Body}]} + | ExtraEls]}). get_admin_jids() -> ejabberd_config:get_option( From b871fbba1b8f90d982cf6627b1b89ac58c282293 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 14 Mar 2016 00:51:12 +0100 Subject: [PATCH 657/695] Fix result type of "connected_users_info" command Closes #1002. --- src/mod_admin_extra.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 6180a16d109..ad3f10abb4d 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -861,7 +861,8 @@ connected_users_info() -> PI when is_integer(PI) -> PI; _ -> nil end, - {[U, $@, S, $/, R], atom_to_list(Conn), IPS, Port, PriorityI, NodeS, Uptime} + {binary_to_list(<>), + atom_to_list(Conn), IPS, Port, PriorityI, NodeS, Uptime} end, USRIs). From 9440049208232572750e56550b49f587c6cf4609 Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 14 Mar 2016 12:47:52 +0100 Subject: [PATCH 658/695] Update gl.po --- priv/msgs/gl.po | 158 ++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 93 deletions(-) diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index b697f381425..8834767c980 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -9,7 +9,7 @@ msgstr "" #: ejabberd_c2s.erl:505 ejabberd_c2s.erl:853 msgid "Use of STARTTLS required" -msgstr "É obrigatorio usar STARTTLS" +msgstr "Requírese o uso de STARTTLS" #: ejabberd_c2s.erl:604 msgid "No resource provided" @@ -30,7 +30,7 @@ msgstr "A súa lista de privacidade activa negou o encaminamiento desta estrofa. #: ejabberd_c2s.erl:2429 msgid "Too many unacked stanzas" -msgstr "" +msgstr "Demasiadas mensaxes sen recoñecer recibilos" #: ejabberd_captcha.erl:122 ejabberd_captcha.erl:245 ejabberd_captcha.erl:284 msgid "Enter the text you see" @@ -59,9 +59,8 @@ msgid "User" msgstr "Usuario" #: ejabberd_oauth.erl:256 -#, fuzzy msgid "Server" -msgstr "Servidor ~b" +msgstr "Servidor" #: ejabberd_oauth.erl:259 ejabberd_web_admin.erl:1408 mod_configure.erl:1398 #: mod_configure.erl:1485 mod_configure.erl:1889 mod_configure.erl:2123 @@ -253,7 +252,6 @@ msgid "Change Password" msgstr "Cambiar contrasinal" #: ejabberd_web_admin.erl:1673 -#, fuzzy msgid "User ~s" msgstr "Usuario ~s" @@ -287,7 +285,6 @@ msgid "Stopped Nodes" msgstr "Nodos detidos" #: ejabberd_web_admin.erl:1833 ejabberd_web_admin.erl:1858 -#, fuzzy msgid "Node ~p" msgstr "Nodo ~p" @@ -326,7 +323,6 @@ msgid "RPC Call Error" msgstr "Erro na chamada RPC" #: ejabberd_web_admin.erl:1917 -#, fuzzy msgid "Database Tables at ~p" msgstr "Táboas da base de datos en ~p" @@ -336,7 +332,7 @@ msgstr "Nome" #: ejabberd_web_admin.erl:1928 msgid "Storage Type" -msgstr "Tipo de almacenamiento" +msgstr "Tipo de almacenamento" #: ejabberd_web_admin.erl:1929 msgid "Elements" @@ -351,7 +347,6 @@ msgid "Error" msgstr "Erro" #: ejabberd_web_admin.erl:1955 -#, fuzzy msgid "Backup of ~p" msgstr "Copia de seguridade de ~p" @@ -404,22 +399,22 @@ msgstr "Importar usuarios en un fichero PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2032 msgid "Export data of all users in the server to PIEFXIS files (XEP-0227):" msgstr "" -"Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS (XEP-0227):" +"Exportar datos de todos os usuarios do servidor a ficheros PIEFXIS " "(XEP-0227):" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" msgstr "" -"Exportar datos de los usuarios en un host de archivos PFX (XEP-0227):" +"Exportar datos de los usuarios en un host de archivos PFX " "(XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" -msgstr "Exportar todas lanas tablas de lanas consultas SQL a un archivo:" +msgstr "Exportar todas as táboas a un ficheiro SQL:" #: ejabberd_web_admin.erl:2076 msgid "Import user data from jabberd14 spool file:" -msgstr "Importar usuario de fichero spool de jabberd14:" +msgstr "Importar usuario de ficheiro spool de jabberd14:" #: ejabberd_web_admin.erl:2087 msgid "Import users data from jabberd14 spool directory:" @@ -432,7 +427,7 @@ msgstr "Portos de escoita en " #: ejabberd_web_admin.erl:2144 #, fuzzy msgid "Modules at ~p" -msgstr "Módulos en " +msgstr "Módulos en ~p" #: ejabberd_web_admin.erl:2175 msgid "Statistics of ~p" @@ -463,9 +458,8 @@ msgid "Transactions Logged:" msgstr "Transaccións rexistradas:" #: ejabberd_web_admin.erl:2243 -#, fuzzy msgid "Update ~p" -msgstr "Actualizar" +msgstr "Actualizar ~p" #: ejabberd_web_admin.erl:2254 msgid "Update plan" @@ -525,7 +519,7 @@ msgstr "Pong" #: mod_announce.erl:523 msgid "Really delete message of the day?" -msgstr "Está seguro de quere borrar a mensaxe do dia?" +msgstr "¿Está seguro que quere borrar a mensaxe do dia?" #: mod_announce.erl:536 mod_configure.erl:1238 mod_configure.erl:1298 msgid "Subject" @@ -553,7 +547,7 @@ msgstr "Enviar anuncio a todos os usuarios en todos os dominios" #: mod_announce.erl:668 msgid "Send announcement to all online users" -msgstr "Enviar anuncio a todos los usuarios conectados" +msgstr "Enviar anuncio a todos os usuarios conectados" #: mod_announce.erl:670 mod_configure.erl:1231 mod_configure.erl:1291 msgid "Send announcement to all online users on all hosts" @@ -844,18 +838,20 @@ msgid "" "Too many (~p) failed authentications from this IP address (~s). The address " "will be unblocked at ~s UTC" msgstr "" +"Demasiados (~p) fallou autenticaciones desde esta dirección IP (~s). A dirección " +"será desbloqueada as ~s UTC" #: mod_http_upload.erl:586 msgid "Please specify file size." -msgstr "" +msgstr "Por favor, especifica o tamaño do arquivo" #: mod_http_upload.erl:590 msgid "Please specify file name." -msgstr "" +msgstr "Por favor, indique o nome do arquivo." #: mod_ip_blacklist.erl:121 msgid "This IP address is blacklisted in ~s" -msgstr "" +msgstr "Esta dirección IP está na lista negra en ~s" #: mod_irc.erl:220 mod_muc.erl:467 msgid "Access denied by service policy" @@ -884,8 +880,8 @@ msgid "" "Enter username, encodings, ports and passwords you wish to use for " "connecting to IRC servers" msgstr "" -"Introduza o nome de usuario, codificaciones de carácter, portos e " -"contrasinal que pretende utilizar a conectar a servidores de IRC" +"Introduce o nome de usuario, codificaciones de carácteres, portos e " +"contrasinai que queiras usar ao conectar nos servidores de IRC" #: mod_irc.erl:667 msgid "IRC Username" @@ -970,9 +966,8 @@ msgid "Server ~b" msgstr "Servidor ~b" #: mod_mam.erl:541 -#, fuzzy msgid "Only members may query archives of this room" -msgstr "Só os moderadores están autorizados a cambiar o tema nesta sala" +msgstr "Só membros poden consultar o arquivo de mensaxes da sala" #: mod_muc.erl:585 msgid "Only service administrators are allowed to send service messages" @@ -994,10 +989,9 @@ msgstr "Salas de charla" #: mod_muc.erl:781 msgid "Empty Rooms" -msgstr "" +msgstr "Salas baleiras" #: mod_muc.erl:933 -#, fuzzy msgid "You need a client that supports x:data to register the nickname" msgstr "" "Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" @@ -1030,34 +1024,31 @@ msgstr "Módulo de MUC para ejabberd" #: mod_muc_admin.erl:231 mod_muc_admin.erl:234 mod_muc_admin.erl:246 #: mod_muc_admin.erl:320 msgid "Multi-User Chat" -msgstr "" +msgstr "Salas de Charla" #: mod_muc_admin.erl:249 -#, fuzzy msgid "Total rooms" -msgstr "Salas de charla" +msgstr "Salas totais" #: mod_muc_admin.erl:250 -#, fuzzy msgid "Permanent rooms" -msgstr "sae da sala" +msgstr "Salas permanentes" #: mod_muc_admin.erl:251 -#, fuzzy msgid "Registered nicknames" -msgstr "Usuarios rexistrados" +msgstr "Alcumes rexistrados" #: mod_muc_admin.erl:254 msgid "List of rooms" -msgstr "" +msgstr "Lista de salas" #: mod_muc_log.erl:398 mod_muc_log.erl:407 msgid "Chatroom configuration modified" -msgstr "Configuración de la sala modificada" +msgstr "Configuración da sala modificada" #: mod_muc_log.erl:410 msgid "joins the room" -msgstr "entra en la sala" +msgstr "entra na sala" #: mod_muc_log.erl:413 mod_muc_log.erl:416 msgid "leaves the room" @@ -1088,24 +1079,20 @@ msgid " has set the subject to: " msgstr " puxo o asunto: " #: mod_muc_log.erl:493 -#, fuzzy msgid "Chatroom is created" -msgstr "Salas de charla" +msgstr "Creouse a sala" #: mod_muc_log.erl:495 -#, fuzzy msgid "Chatroom is destroyed" -msgstr "Salas de charla" +msgstr "Destruíuse a sala" #: mod_muc_log.erl:497 -#, fuzzy msgid "Chatroom is started" -msgstr "Salas de charla" +msgstr "Iniciouse a sala" #: mod_muc_log.erl:499 -#, fuzzy msgid "Chatroom is stopped" -msgstr "Salas de charla" +msgstr "Detívose a sala" #: mod_muc_log.erl:503 msgid "Monday" @@ -1200,6 +1187,8 @@ msgid "" "It is not allowed to send error messages to the room. The participant (~s) " "has sent an error message (~s) and got kicked from the room" msgstr "" +"Non está permitido enviar mensaxes de erro á sala. Este participante (~s) " +"enviou unha mensaxe de erro (~s) e foi expulsado da sala" #: mod_muc_room.erl:241 msgid "It is not allowed to send private messages to the conference" @@ -1207,20 +1196,19 @@ msgstr "Impedir o envio de mensaxes privadas á sala" #: mod_muc_room.erl:316 msgid "Please, wait for a while before sending new voice request" -msgstr "" +msgstr "Por favor, espera un pouco antes de enviar outra petición de voz" #: mod_muc_room.erl:329 msgid "Voice requests are disabled in this conference" -msgstr "" +msgstr "As peticións de voz están desactivadas nesta sala" #: mod_muc_room.erl:347 msgid "Failed to extract JID from your voice request approval" -msgstr "" +msgstr "Fallo ao extraer o Jabber ID da túa aprobación de petición de voz" #: mod_muc_room.erl:377 -#, fuzzy msgid "Only moderators can approve voice requests" -msgstr "Permitir aos usuarios enviar invitacións" +msgstr "Só os moderadores poden aprobar peticións de voz" #: mod_muc_room.erl:389 msgid "Improper message type" @@ -1269,11 +1257,11 @@ msgstr "Os visitantes non poden enviar mensaxes a todos os ocupantes" #: mod_muc_room.erl:1080 msgid "Visitors are not allowed to change their nicknames in this room" msgstr "" -"Os visitantes non están autorizados a cambiar os seus That alcumes nesta sala" +"Os visitantes non teñen permitido cambiar os seus alcumes nesta sala" #: mod_muc_room.erl:1093 mod_muc_room.erl:1835 msgid "That nickname is already in use by another occupant" -msgstr "Ese alcume que xa está en uso por outro ocupante" +msgstr "Ese alcume xa está a ser usado por outro ocupante" #: mod_muc_room.erl:1822 msgid "You have been banned from this room" @@ -1289,12 +1277,11 @@ msgstr "Necesítase contrasinal para entrar nesta sala" #: mod_muc_room.erl:1898 mod_register.erl:295 msgid "Too many CAPTCHA requests" -msgstr "" +msgstr "Demasiadas peticións de CAPTCHA" #: mod_muc_room.erl:1908 mod_register.erl:301 -#, fuzzy msgid "Unable to generate a CAPTCHA" -msgstr "Non se pode xerar un CAPTCHA" +msgstr "No se pudo generar un CAPTCHA" #: mod_muc_room.erl:1919 msgid "Incorrect password" @@ -1378,20 +1365,19 @@ msgstr "calquera" #: mod_muc_room.erl:3471 msgid "Roles for which Presence is Broadcasted" -msgstr "" +msgstr "Roles para os que si se difunde a súa Presenza" #: mod_muc_room.erl:3486 -#, fuzzy msgid "Moderator" -msgstr "só moderadores" +msgstr "Moderator" #: mod_muc_room.erl:3496 msgid "Participant" -msgstr "" +msgstr "Participante" #: mod_muc_room.erl:3506 msgid "Visitor" -msgstr "" +msgstr "Visitante" #: mod_muc_room.erl:3513 msgid "Make room members-only" @@ -1414,13 +1400,12 @@ msgid "Allow users to send private messages" msgstr "Permitir aos usuarios enviar mensaxes privadas" #: mod_muc_room.erl:3533 -#, fuzzy msgid "Allow visitors to send private messages to" -msgstr "Permitir aos usuarios enviar mensaxes privadas" +msgstr "Permitir aos visitantes enviar mensaxes privadas a" #: mod_muc_room.erl:3551 msgid "nobody" -msgstr "" +msgstr "ninguén" #: mod_muc_room.erl:3576 msgid "Allow users to query other users" @@ -1440,13 +1425,12 @@ msgid "Allow visitors to change nickname" msgstr "Permitir aos visitantes cambiarse o alcume" #: mod_muc_room.erl:3589 -#, fuzzy msgid "Allow visitors to send voice requests" -msgstr "Permitir aos usuarios enviar invitacións" +msgstr "Permitir aos visitantes enviar peticións de voz" #: mod_muc_room.erl:3592 msgid "Minimum interval between voice requests (in seconds)" -msgstr "" +msgstr "Intervalo mínimo entre peticións de voz (en segundos)" #: mod_muc_room.erl:3599 msgid "Make room CAPTCHA protected" @@ -1454,11 +1438,11 @@ msgstr "Protexer a sala con CAPTCHA" #: mod_muc_room.erl:3606 msgid "Enable message archiving" -msgstr "" +msgstr "Activar o almacenamento de mensaxes" #: mod_muc_room.erl:3612 msgid "Exclude Jabber IDs from CAPTCHA challenge" -msgstr "" +msgstr "Excluír Jabber IDs das probas de CAPTCHA" #: mod_muc_room.erl:3621 msgid "Enable logging" @@ -1478,20 +1462,19 @@ msgstr "privado" #: mod_muc_room.erl:4326 msgid "Voice request" -msgstr "" +msgstr "Petición de voz" #: mod_muc_room.erl:4331 msgid "Either approve or decline the voice request." -msgstr "" +msgstr "Aproba ou rexeita a petición de voz." #: mod_muc_room.erl:4351 -#, fuzzy msgid "User JID" -msgstr "Usuario " +msgstr "Jabber IDE do usuario" #: mod_muc_room.erl:4355 msgid "Grant voice to this person?" -msgstr "" +msgstr "¿Conceder voz a esta persoa?" #: mod_muc_room.erl:4498 msgid "~s invites you to the room ~s" @@ -1503,11 +1486,11 @@ msgstr "a contrasinal é" #: mod_multicast.erl:291 msgid "Multicast" -msgstr "" +msgstr "Multicast" #: mod_multicast.erl:306 msgid "ejabberd Multicast service" -msgstr "ejabberd servizo multidifusión" +msgstr "Servizo Multicast de ejabberd" #: mod_offline.erl:647 msgid "" @@ -1546,7 +1529,7 @@ msgstr "Borrar Todas as Mensaxes Sen conexión" #: mod_proxy65_service.erl:248 msgid "ejabberd SOCKS5 Bytestreams module" -msgstr "ejabberd SOCKS5 Bytestreams module" +msgstr "Módulo SOCKS5 Bytestreams para ejabberd" #: mod_pubsub.erl:1102 msgid "Publish-Subscribe" @@ -1566,7 +1549,7 @@ msgstr "Decidir se aprobar a subscripción desta entidade." #: mod_pubsub.erl:1559 msgid "Node ID" -msgstr "Nodo IDE" +msgstr "Nodo ID" #: mod_pubsub.erl:1571 msgid "Subscriber Address" @@ -1602,7 +1585,7 @@ msgstr "Persistir elementos ao almacenar" #: mod_pubsub.erl:3757 msgid "A friendly name for the node" -msgstr "Un nome para o nodo" +msgstr "Un nome sinxelo para o nodo" #: mod_pubsub.erl:3759 msgid "Max # of items to persist" @@ -1629,9 +1612,8 @@ msgid "Purge all items when the relevant publisher goes offline" msgstr "Purgar todos os elementos cando o editor correspondente desconéctase" #: mod_pubsub.erl:3771 -#, fuzzy msgid "Specify the event message type" -msgstr "Especifica o modelo de acceso" +msgstr "Especifica o tipo da mensaxe de evento" #: mod_pubsub.erl:3773 msgid "Max payload size in bytes" @@ -1650,15 +1632,13 @@ msgid "The collections with which a node is affiliated" msgstr "As coleccións coas que un nodo está afiliado" #: mod_register.erl:209 -#, fuzzy msgid "The CAPTCHA verification has failed" -msgstr "O CAPTCHA é válido." +msgstr "A verificación de CAPTCHA fallou" #: mod_register.erl:253 -#, fuzzy msgid "You need a client that supports x:data and CAPTCHA to register" msgstr "" -"Necesitas un cliente con soporte de x:data para poder rexistrar o alcume" +"Necesitas un cliente con soporte de x:data e CAPTCHA para rexistrarche" #: mod_register.erl:259 mod_register.erl:320 msgid "Choose a username and password to register with this server" @@ -1666,9 +1646,8 @@ msgstr "" "Escolle un nome de usuario e contrasinal para rexistrarche neste servidor" #: mod_register.erl:373 mod_register.erl:421 -#, fuzzy msgid "The password is too weak" -msgstr "a contrasinal é" +msgstr "O contrasinal é demasiado débil" #: mod_register.erl:426 msgid "Users are not allowed to register accounts so quickly" @@ -1721,7 +1700,6 @@ msgstr "" "coidadosamente as instrucións para encher correctamente os campos." #: mod_register_web.erl:224 mod_register_web.erl:360 mod_register_web.erl:469 -#, fuzzy msgid "Username:" msgstr "Nome de usuario:" @@ -1734,7 +1712,6 @@ msgid "Characters not allowed:" msgstr "Caracteres non permitidos:" #: mod_register_web.erl:236 mod_register_web.erl:364 mod_register_web.erl:473 -#, fuzzy msgid "Server:" msgstr "Servidor:" @@ -1769,22 +1746,18 @@ msgstr "" "a esquece" #: mod_register_web.erl:262 mod_register_web.erl:374 -#, fuzzy msgid "Password Verification:" msgstr "Verificación da contrasinal" #: mod_register_web.erl:269 -#, fuzzy msgid "Register" msgstr "Rexistrar" #: mod_register_web.erl:366 -#, fuzzy msgid "Old Password:" msgstr "Contrasinal anterior:" #: mod_register_web.erl:370 -#, fuzzy msgid "New Password:" msgstr "Novo contrasinal:" @@ -1952,7 +1925,6 @@ msgstr "Rechea campos para buscar usuarios Jabber que concuerden" #~ "Este participante é expulsado da sala, porque el enviou un erro de " #~ "presenza" -#, fuzzy #~ msgid "CAPTCHA test failed" #~ msgstr "O CAPTCHA é válido." From 5351e8236d34b72b0498c98da53587bdd6245c09 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 14 Mar 2016 12:53:14 +0100 Subject: [PATCH 659/695] Fix Addresses element which lacked others local destinations When sending single packet, in addresses include all other group destinations, not only oneself --- src/mod_multicast.erl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 0c6130482b2..83520c0bebd 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -395,7 +395,7 @@ act_groups(FromJID, Packet_stripped, AAttrs, LServiceS, perform(From, Packet, AAttrs, _, {route_single, Group}) -> [route_packet(From, ToUser, Packet, AAttrs, - Group#group.addresses) + Group#group.others, Group#group.addresses) || ToUser <- Group#group.dests]; perform(From, Packet, AAttrs, _, {{route_multicast, JID, RLimits}, Group}) -> @@ -634,13 +634,13 @@ decide_action_group(Group) -> %%% Route packet %%%------------------------- -route_packet(From, ToDest, Packet, AAttrs, Addresses) -> +route_packet(From, ToDest, Packet, AAttrs, Others, Addresses) -> Dests = case ToDest#dest.type of <<"bcc">> -> []; _ -> [ToDest] end, route_packet2(From, ToDest#dest.jid_string, Dests, - Packet, AAttrs, Addresses). + Packet, AAttrs, {Others, Addresses}). route_packet_multicast(From, ToS, Packet, AAttrs, Dests, Addresses, Limits) -> @@ -666,6 +666,8 @@ route_packet2(From, ToS, Dests, Packet, AAttrs, ToJID = stj(ToS), ejabberd_router:route(From, ToJID, Packet2). +append_dests(_Dests, {Others, Addresses}) -> + Addresses++Others; append_dests([], Addresses) -> Addresses; append_dests([Dest | Dests], Addresses) -> append_dests(Dests, [Dest#dest.full_xml | Addresses]). @@ -912,8 +914,9 @@ received_awaiter(JID, Waiter, LServiceS) -> From = Waiter#waiter.sender, Packet = Waiter#waiter.packet, AAttrs = Waiter#waiter.aattrs, + Others = Group#group.others, Addresses = Waiter#waiter.addresses, - [route_packet(From, ToUser, Packet, AAttrs, Addresses) + [route_packet(From, ToUser, Packet, AAttrs, Others, Addresses) || ToUser <- Group#group.dests]; true -> send_query_info(RServer, LServiceS), From 7f25c3b3e8da5a6d27457011e578de80b0195bfa Mon Sep 17 00:00:00 2001 From: Carlos Date: Mon, 14 Mar 2016 16:52:16 +0100 Subject: [PATCH 660/695] Update gl.po --- priv/msgs/gl.po | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/priv/msgs/gl.po b/priv/msgs/gl.po index 8834767c980..4d75d21dae2 100644 --- a/priv/msgs/gl.po +++ b/priv/msgs/gl.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: 16.02\n" -"Last-Translator: Carlos E. Lopez - suso AT jabber-hispano.org\n" +"Last-Translator: Carlos E. Lopez - carlos AT suchat.org\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -237,7 +237,6 @@ msgid "Outgoing s2s Connections:" msgstr "Conexións S2S saíntes:" #: ejabberd_web_admin.erl:1559 -#, fuzzy msgid "Incoming s2s Connections:" msgstr "Conexións S2S saíntes:" @@ -404,9 +403,7 @@ msgstr "" #: ejabberd_web_admin.erl:2044 msgid "Export data of users in a host to PIEFXIS files (XEP-0227):" -msgstr "" -"Exportar datos de los usuarios en un host de archivos PFX " -"(XEP-0227):" +msgstr "Exportar datos dos usuarios dun dominio a ficheiros PIEFXIS (XEP-0227):" #: ejabberd_web_admin.erl:2060 msgid "Export all tables as SQL queries to a file:" @@ -425,7 +422,6 @@ msgid "Listened Ports at " msgstr "Portos de escoita en " #: ejabberd_web_admin.erl:2144 -#, fuzzy msgid "Modules at ~p" msgstr "Módulos en ~p" @@ -589,7 +585,7 @@ msgstr "Iniciar módulos" #: mod_configure.erl:156 mod_configure.erl:638 msgid "Stop Modules" -msgstr "Detener módulos" +msgstr "Deter módulos" #: mod_configure.erl:162 mod_configure.erl:650 msgid "Restore" @@ -1068,7 +1064,7 @@ msgstr "foi expulsado, porque a sala cambiouse a só-membros" #: mod_muc_log.erl:445 msgid "has been kicked because of a system shutdown" -msgstr "foi expulsado por mor dun sistema de peche" +msgstr "foi expulsado porque o sistema vaise a deter" #: mod_muc_log.erl:450 msgid "is now known as" @@ -1470,7 +1466,7 @@ msgstr "Aproba ou rexeita a petición de voz." #: mod_muc_room.erl:4351 msgid "User JID" -msgstr "Jabber IDE do usuario" +msgstr "Jabber ID do usuario" #: mod_muc_room.erl:4355 msgid "Grant voice to this person?" @@ -1855,8 +1851,8 @@ msgid "" "Fill in the form to search for any matching Jabber User (Add * to the end of " "field to match substring)" msgstr "" -"Enche o formulario para buscar usuarios Jabber. Engade * ao final dun campo " -"para buscar subcadenas." +"Enche o formulario para buscar usuarios Jabber (Engade * ao final dun campo " +"para buscar subcadenas)" #: mod_vcard.erl:490 mod_vcard.erl:615 msgid "Full Name" From 68675effac34de2f01555efaae9dab4f5c9f7b40 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Tue, 15 Mar 2016 00:12:01 +0100 Subject: [PATCH 661/695] Apply cosmetic changes to GitHub templates --- .github/ISSUE_TEMPLATE | 13 ++++++------- .github/PULL_REQUEST_TEMPLATE | 33 +++++++++++++++------------------ 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE index 8d1a5f259b7..d31eb5bb301 100644 --- a/.github/ISSUE_TEMPLATE +++ b/.github/ISSUE_TEMPLATE @@ -1,16 +1,15 @@ -Please answer these questions before submitting your issue. It may help ! +> What version of ejabberd are you using? -Thanks! -1. What version of ejabberd are you using ? +> What operating system (version) are you using? -2. What operating system are you using ? -3. How did you install ejabberd (source, package, distribution) ? +> How did you install ejabberd (source, package, distribution)? -4. What did not work as expected ? What that error in the log ? - What that unexpected behaviour ? What was the expected result ? + +> What did not work as expected? Are there error messages in the log? What +> was the unexpected behavior? What was the expected result? diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 554cad4b62e..643d025d01c 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,23 +1,20 @@ -We are open to contribution for ejabberd, as Github pull requests (PR). -Here is a few points to consider before submitting your pull request. -(You can remove the whole text after reading). +We are open to contributions for ejabberd, as GitHub pull requests (PR). +Here are a few points to consider before submitting your PR. (You can +remove the whole text after reading.) -1. Does this PR address an issue ? - Please reference it in PR description. +1. Does this PR address an issue? Please reference it in the PR + description. -2. Have you properly described the proposed changed ? +2. Have you properly described the proposed change? -3. Please, make sure the change is atomic and does only touch the - needed modules. - If you have other changes / fixes to provide, please make them as - separate PR. +3. Please make sure the change is atomic and does only touch the needed + modules. If you have other changes/fixes to provide, please submit + them as separate PRs. -4. If you change or new feature involves backends, - did you make sure you change is compliant with all backends or - provide the feature for all backends ? - -5. Do you provides tests ? - How can we check the behaviour of the code ? +4. If your change or new feature involves storage backends, did you make + sure your change works with all backends? -6. Did you consider documentation changes on project - processone/docs.ejabberd.im ? +5. Do you provide tests? How can we check the behavior of the code? + +6. Did you consider documentation changes in the + processone/docs.ejabberd.im repository? From 058b3d96bf4c6829b20d967df8b05b04ef91807b Mon Sep 17 00:00:00 2001 From: root Date: Tue, 15 Mar 2016 10:57:56 +0500 Subject: [PATCH 662/695] Bare JID in 'from' of Roster Push (RFC 6121 section 2.1.6) in mod_admin_extra --- src/mod_admin_extra.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index ad3f10abb4d..b8ee49f77f2 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -1194,7 +1194,7 @@ push_roster_item(LU, LS, R, U, S, Action) -> ejabberd_sm:route(LJID, LJID, BroadcastEl), Item = build_roster_item(U, S, Action), ResIQ = build_iq_roster_push(Item), - ejabberd_router:route(LJID, LJID, ResIQ). + ejabberd_router:route(jlib:jid_remove_resource(LJID), LJID, ResIQ). build_roster_item(U, S, {add, Nick, Subs, Group}) -> {xmlel, <<"item">>, From 5b5548b8cae9fc64eb2792da668103af64673544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Tue, 15 Mar 2016 18:14:27 +0100 Subject: [PATCH 663/695] Produce less verbose logs for tests on travis --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 15363180940..c5e0547e03a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,9 @@ script: - make - make install - make xref - - make test + - sed -i -e 's/ct:pal/ct:log/' test/suite.erl + - ln -sf ../sql priv/ + - escript ./rebar skip_deps=true ct -v - grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log after_script: From 367adc2113115b408cb71316f98cf009b68795f3 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Tue, 15 Mar 2016 22:42:07 +0100 Subject: [PATCH 664/695] Better error reporting when running Elixir test suite --- test/elixir_SUITE.erl | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/test/elixir_SUITE.erl b/test/elixir_SUITE.erl index 6243456bdeb..b9a0b1a2311 100644 --- a/test/elixir_SUITE.erl +++ b/test/elixir_SUITE.erl @@ -8,7 +8,7 @@ %%% Example: Is run with: %%% ./rebar skip_deps=true ct suites=elixir %%% or from ejabber overall test suite: -%%% make test +%%% make quicktest %%% @end %%% Created : 19 Feb 2015 by Mickael Remond %%%------------------------------------------------------------------- @@ -17,6 +17,10 @@ -compile(export_all). +init_per_suite(Config) -> + check_meck(), + Config. + init_per_testcase(_TestCase, Config) -> process_flag(error_handler, ?MODULE), Config. @@ -32,9 +36,19 @@ all() -> [] end. +check_meck() -> + case catch meck:module_info(module) of + meck -> + ok; + {'EXIT',{undef, _}} -> + ct:print("meck is not available. Please make sure you configured ejabberd with --enable-elixir --enable-tools"), + ok + end. + is_elixir_available() -> case catch elixir:module_info() of {'EXIT',{undef,_}} -> + ct:print("ejabberd has not been build with Elixir support, skipping Elixir tests."), false; ModInfo when is_list(ModInfo) -> true @@ -55,7 +69,14 @@ run_elixir_test(Func) -> 'Elixir.Code':load_file(list_to_binary(filename:join(test_dir(), atom_to_list(Func)))), %% I did not use map syntax, so that this file can still be build under R16 ResultMap = 'Elixir.ExUnit':run(), - {ok, 0} = maps:find(failures, ResultMap). + case maps:find(failures, ResultMap) of + {ok, 0} -> + %% Zero failures + ok; + {ok, Failures} -> + ct:print("Elixir tests failed: ~.10B~nSee logs for details", [Failures]), + ct:fail(elixir_test_failure) + end. test_dir() -> {ok, CWD} = file:get_cwd(), From b40154f8f4132a5b0e15d1893db9fc42e98b1653 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 16 Mar 2016 08:55:25 +0100 Subject: [PATCH 665/695] Update OTP release to use and drop release 17.1 Attempt to build with Elixir --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c5e0547e03a..829b53fa455 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ language: erlang otp_release: - - 17.1 - 17.5 - - 18.0 + - 18.2.1 services: - riak @@ -22,6 +21,8 @@ before_install: - sudo add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.6' - sudo apt-get -qq update - sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6 + # /END MYSQL 5.6 + install: - sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev @@ -40,7 +41,7 @@ before_script: script: - ./autogen.sh - - ./configure --prefix=/tmp/ejabberd --enable-all --disable-odbc --disable-elixir + - ./configure --prefix=/tmp/ejabberd --enable-all --disable-odbc - make - make install - make xref From 74053b114e6145c8dce4110a15a801a4ba9a0257 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 16 Mar 2016 09:01:40 +0100 Subject: [PATCH 666/695] When building Elixir inside ejabberd, rely on version 1.1 for Erlang R17 compliance --- rebar.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rebar.config b/rebar.config index 865517c9891..1f064dd5ea8 100644 --- a/rebar.config +++ b/rebar.config @@ -36,7 +36,7 @@ {if_var_true, riak, {riakc, ".*", {git, "https://github.com/basho/riak-erlang-client", "527722d12d0433b837cdb92a60900c2cb5df8942"}}}, {if_var_true, elixir, {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", - {tag, "v1.2.3"}}}}, + {tag, "v1.1.1"}}}}, %% TODO: When modules are fully migrated to new structure and mix, we will not need anymore rebar_elixir_plugin {if_var_true, elixir, {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}, From c985a2bd3da2252fc604eea7b4d5b31ae1c5fcff Mon Sep 17 00:00:00 2001 From: Badlop Date: Wed, 16 Mar 2016 11:11:43 +0100 Subject: [PATCH 667/695] Start ezlib only if required, as it's optional (#1006) --- src/ejabberd_app.erl | 1 - src/ejabberd_receiver.erl | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index 66de3ceb714..e493eac0174 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -256,7 +256,6 @@ start_apps() -> ejabberd:start_app(fast_tls), ejabberd:start_app(fast_xml), ejabberd:start_app(stringprep), - ejabberd:start_app(ezlib), ejabberd:start_app(cache_tab). opt_type(net_ticktime) -> diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl index 9fdc86f8abc..0a33e30ec26 100644 --- a/src/ejabberd_receiver.erl +++ b/src/ejabberd_receiver.erl @@ -141,6 +141,7 @@ handle_call({starttls, TLSSocket}, _From, State) -> handle_call({compress, Data}, _From, #state{socket = Socket, sock_mod = SockMod} = State) -> + ejabberd:start_app(ezlib), {ok, ZlibSocket} = ezlib:enable_zlib(SockMod, Socket), if Data /= undefined -> do_send(State, Data); From efbaba5d04ef4423fe035d0fc19515be85072d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 16 Mar 2016 11:30:35 +0100 Subject: [PATCH 668/695] Make auto generated resources shorter --- src/ejabberd_c2s.erl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 97b759161fe..a5802a5b3eb 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -999,7 +999,7 @@ resource_conflict_action(U, S, R) -> acceptnew -> {accept_resource, R}; closenew -> closenew; setresource -> - Rnew = iolist_to_binary([randoms:get_string(),randoms:get_string(),randoms:get_string()]), + Rnew = new_uniq_id(), {accept_resource, Rnew} end. @@ -1026,8 +1026,7 @@ wait_for_bind({xmlstreamelement, El}, StateData) -> [{elem, <<"resource">>}, cdata]), R = case jid:resourceprep(R1) of error -> error; - <<"">> -> - iolist_to_binary([randoms:get_string(),randoms:get_string(),randoms:get_string()]); + <<"">> -> new_uniq_id(); Resource -> Resource end, case R of @@ -1913,6 +1912,10 @@ send_trailer(StateData) -> new_id() -> randoms:get_string(). +new_uniq_id() -> + iolist_to_binary([randoms:get_string(), + jlib:integer_to_binary(p1_time_compat:unique_integer(positive))]). + is_auth_packet(El) -> case jlib:iq_query_info(El) of #iq{id = ID, type = Type, xmlns = ?NS_AUTH, sub_el = SubEl} -> From 7b72247b2c37ad1b87fdacbb4049b630c8ff1150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Wed, 16 Mar 2016 13:32:19 +0100 Subject: [PATCH 669/695] Don't use jlib:jid_remove_resource --- src/mod_admin_extra.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index b8ee49f77f2..343a1a3a2ac 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -1194,7 +1194,7 @@ push_roster_item(LU, LS, R, U, S, Action) -> ejabberd_sm:route(LJID, LJID, BroadcastEl), Item = build_roster_item(U, S, Action), ResIQ = build_iq_roster_push(Item), - ejabberd_router:route(jlib:jid_remove_resource(LJID), LJID, ResIQ). + ejabberd_router:route(jid:remove_resource(LJID), LJID, ResIQ). build_roster_item(U, S, {add, Nick, Subs, Group}) -> {xmlel, <<"item">>, From ef02053a9ddf057a1c76da3409f2218c1d778b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Thu, 17 Mar 2016 18:41:24 +0100 Subject: [PATCH 670/695] Fix issue #1015 --- src/ejabberd_c2s.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index a5802a5b3eb..d58c1e1d234 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -1914,7 +1914,7 @@ new_id() -> randoms:get_string(). new_uniq_id() -> iolist_to_binary([randoms:get_string(), - jlib:integer_to_binary(p1_time_compat:unique_integer(positive))]). + jlib:integer_to_binary(p1_time_compat:unique_integer([positive]))]). is_auth_packet(El) -> case jlib:iq_query_info(El) of From f19a54e9a12d49e295cdc86ad79b32bc95b31285 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 18 Mar 2016 10:22:11 +0100 Subject: [PATCH 671/695] Escape quoting node name for ejabberdctl ping --- ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index aa9c2eb817c..3f74da69597 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -332,7 +332,7 @@ ping() $NAME ping-${TTY}-${ERLANG_NODE} \ -hidden \ $KERNEL_OPTS $ERLANG_OPTS \ - -eval 'io:format(\"~p~n\",[net_adm:ping($1)])' \ + -eval 'io:format(\"~p~n\",[net_adm:ping('\"'\"'$1'\"'\"')])' \ -s erlang halt -output text -noinput" } From 939bb244e1be08832e21a43afd13b0c96f0790d2 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Fri, 18 Mar 2016 11:08:30 +0100 Subject: [PATCH 672/695] Extend scope of ejabberdctl ping --- ejabberdctl.template | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index 3f74da69597..dca23fe81fd 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -328,8 +328,15 @@ etop() ping() { TTY=`tty | sed -e 's/.*\///g'` + if [ "$1" = "${1%.*}" ] ; then + PING_NAME="-sname" + PING_NODE=$(hostname -s) + else + PING_NAME="-name" + PING_NODE=$(hostname) + fi $EXEC_CMD "$ERL \ - $NAME ping-${TTY}-${ERLANG_NODE} \ + $PING_NAME ping-${TTY}@${PING_NODE} \ -hidden \ $KERNEL_OPTS $ERLANG_OPTS \ -eval 'io:format(\"~p~n\",[net_adm:ping('\"'\"'$1'\"'\"')])' \ From 2d103b4ae1db89a22b0a90d647632417e1b298dd Mon Sep 17 00:00:00 2001 From: HAMANO Tsukasa Date: Sat, 19 Mar 2016 01:41:14 +0900 Subject: [PATCH 673/695] support riak authentication --- src/ejabberd_riak.erl | 12 +++++------ src/ejabberd_riak_sup.erl | 42 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/ejabberd_riak.erl b/src/ejabberd_riak.erl index 22da9d2e9de..90bdb4c060f 100644 --- a/src/ejabberd_riak.erl +++ b/src/ejabberd_riak.erl @@ -28,7 +28,7 @@ -behaviour(gen_server). %% API --export([start_link/4, get_proc/1, make_bucket/1, put/2, put/3, +-export([start_link/5, get_proc/1, make_bucket/1, put/2, put/3, get/2, get/3, get_by_index/4, delete/1, delete/2, count_by_index/3, get_by_index_range/5, get_keys/1, get_keys_by_index/3, is_connected/0, @@ -68,8 +68,8 @@ %%% API %%%=================================================================== %% @private -start_link(Num, Server, Port, _StartInterval) -> - gen_server:start_link({local, get_proc(Num)}, ?MODULE, [Server, Port], []). +start_link(Num, Server, Port, _StartInterval, Options) -> + gen_server:start_link({local, get_proc(Num)}, ?MODULE, [Server, Port, Options], []). %% @private is_connected() -> @@ -429,10 +429,8 @@ map_key(Obj, _, _) -> %%% gen_server API %%%=================================================================== %% @private -init([Server, Port]) -> - case riakc_pb_socket:start( - Server, Port, - [auto_reconnect]) of +init([Server, Port, Options]) -> + case riakc_pb_socket:start(Server, Port, Options) of {ok, Pid} -> erlang:monitor(process, Pid), {ok, #state{pid = Pid}}; diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index 319d1707df1..7294e0055f7 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -103,12 +103,26 @@ init([]) -> StartInterval = get_start_interval(), Server = get_riak_server(), Port = get_riak_port(), + CACertFile = get_riak_cacertfile(), + Username = get_riak_username(), + Password = get_riak_password(), + Options = lists:filter( + fun(X) -> X /= nil end, + [auto_reconnect, + if CACertFile /= nil -> {cacertfile ,CACertFile}; + true -> nil + end, + if (Username /= nil) and (Password /= nil) -> + {credentials, Username, Password}; + true -> nil + end + ]), {ok, {{one_for_one, PoolSize*10, 1}, lists:map( fun(I) -> {ejabberd_riak:get_proc(I), {ejabberd_riak, start_link, - [I, Server, Port, StartInterval*1000]}, + [I, Server, Port, StartInterval*1000, Options]}, transient, 2000, worker, [?MODULE]} end, lists:seq(1, PoolSize))}}. @@ -131,6 +145,27 @@ get_riak_server() -> binary_to_list(iolist_to_binary(S)) end, ?DEFAULT_RIAK_HOST). +get_riak_cacertfile() -> + ejabberd_config:get_option( + riak_cacertfile, + fun(S) -> + binary_to_list(iolist_to_binary(S)) + end, nil). + +get_riak_username() -> + ejabberd_config:get_option( + riak_username, + fun(S) -> + binary_to_list(iolist_to_binary(S)) + end, nil). + +get_riak_password() -> + ejabberd_config:get_option( + riak_password, + fun(S) -> + binary_to_list(iolist_to_binary(S)) + end, nil). + get_riak_port() -> ejabberd_config:get_option( riak_port, @@ -162,6 +197,9 @@ opt_type(riak_port) -> fun (_) -> true end; opt_type(riak_server) -> fun (_) -> true end; opt_type(riak_start_interval) -> fun (N) when is_integer(N), N >= 1 -> N end; +opt_type(riak_cacertfile) -> fun iolist_to_binary/1; +opt_type(riak_username) -> fun iolist_to_binary/1; +opt_type(riak_password) -> fun iolist_to_binary/1; opt_type(_) -> [modules, riak_pool_size, riak_port, riak_server, - riak_start_interval]. + riak_start_interval, riak_cacertfile, riak_username, riak_password]. From dc7b2c45c22dca33a25002e7e85168621e4346ea Mon Sep 17 00:00:00 2001 From: Badlop Date: Sat, 19 Mar 2016 17:42:12 +0100 Subject: [PATCH 674/695] Fix indentation of mod_register in default configuration file --- ejabberd.yml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberd.yml.example b/ejabberd.yml.example index 74a9538cdc1..11b27e65014 100644 --- a/ejabberd.yml.example +++ b/ejabberd.yml.example @@ -616,7 +616,7 @@ modules: - "flat" - "hometree" - "pep" # pep requires mod_caps - ## mod_register: + ## mod_register: ## ## Protect In-Band account registrations with CAPTCHA. ## From 0e3026539ea072c54fb2ade9b08d0e65247c3ac3 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 09:42:59 +0100 Subject: [PATCH 675/695] Comment on error failures in logs + indenting --- test/ejabberd_hooks_test.exs | 51 ++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/test/ejabberd_hooks_test.exs b/test/ejabberd_hooks_test.exs index ff753a7bbca..6493642deee 100644 --- a/test/ejabberd_hooks_test.exs +++ b/test/ejabberd_hooks_test.exs @@ -18,30 +18,41 @@ # # ---------------------------------------------------------------------- +# Notes on the tests: +# +# This test suite will print out errors in logs for tests: +# +# test "Error in run_fold is ignored" +# test "Throw in run_fold is ignored" +# test "Exit in run_fold is ignored" +# +# Those tests are not failing and we can safely ignore those errors in +# log as we are exercising hook handler recovery from that situation. + defmodule EjabberdHooksTest do use ExUnit.Case, async: true - + @author "mremond@process-one.net" @host <<"domain.net">> @self __MODULE__ - + setup_all do {:ok, _Pid} = :ejabberd_hooks.start_link :ok end - + setup do :meck.unload :true = :ejabberd_hooks.delete_all_hooks :ok - end - + end + test "An anonymous function can be added as a hook" do hookname = :test_fun_hook :ok = :ejabberd_hooks.add(hookname, @host, fn _ -> :ok end, 50) [{50, :undefined, _}] = :ejabberd_hooks.get_handlers(hookname, @host) end - + test "A module function can be added as a hook" do hookname = :test_mod_hook callback = :hook_callback @@ -51,7 +62,7 @@ defmodule EjabberdHooksTest do test "An anonymous function can be removed from hook handlers" do hookname = :test_fun_hook - anon_fun = fn _ -> :ok end + anon_fun = fn _ -> :ok end :ok = :ejabberd_hooks.add(hookname, @host, anon_fun, 50) :ok = :ejabberd_hooks.delete(hookname, @host, anon_fun, 50) [] = :ejabberd_hooks.get_handlers(hookname, @host) @@ -77,20 +88,20 @@ defmodule EjabberdHooksTest do end # TODO test "Several handlers are run in order by hook" - + test "Hook run chain is stopped when handler return 'stop'" do # setup test hookname = :test_mod_hook modulename = :hook_module mock(modulename, :hook_callback1, fn _ -> :stop end) mock(modulename, :hook_callback2, fn _ -> :end_result end) - + :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 50) :ok = :ejabberd_hooks.run(hookname, @host, [:hook_params]) # callback2 is never run: - [{_pid, {^modulename, _callback, [:hook_params]}, :stop}] = :meck.history(modulename) + [{_pid, {^modulename, _callback, [:hook_params]}, :stop}] = :meck.history(modulename) end test "Run fold hooks accumulate state in correct order through handlers" do @@ -99,10 +110,10 @@ defmodule EjabberdHooksTest do modulename = :hook_module mock(modulename, :hook_callback1, fn(list, user) -> [user|list] end) mock(modulename, :hook_callback2, fn(list, _user) -> ["jid2"|list] end) - + :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) - + ["jid2", "jid1"] = :ejabberd_hooks.run_fold(hookname, @host, [], ["jid1"]) end @@ -115,12 +126,12 @@ defmodule EjabberdHooksTest do :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback2, 50) :ok = :ejabberd_hooks.add(hookname, @host, modulename, :hook_callback1, 40) - + :second = :ejabberd_hooks.run_fold(hookname, @host, :started, []) # Both module have been called: 2 = length(:meck.history(modulename)) end - + # TODO: Test with ability to stop and return a value test "Hook run_fold chain is stopped when handler return 'stop'" do # setup test @@ -148,19 +159,19 @@ defmodule EjabberdHooksTest do test "Exit in run_fold is ignored" do run_fold_crash(fn(_acc) -> exit :crashed end) end - + # test for run hook with various number of params - def run_hook(params, fun, result) do + def run_hook(params, fun, result) do # setup test hookname = :test_mod_hook modulename = :hook_module callback = :hook_callback mock(modulename, callback, fun) - + # Then check :ok = :ejabberd_hooks.add(hookname, @host, modulename, callback, 40) :ok = :ejabberd_hooks.run(hookname, @host, params) - [{_pid, {^modulename, ^callback, ^params}, ^result}] = :meck.history(modulename) + [{_pid, {^modulename, ^callback, ^params}, ^result}] = :meck.history(modulename) end def run_fold_crash(crash_fun) do @@ -175,7 +186,7 @@ defmodule EjabberdHooksTest do :final = :ejabberd_hooks.run_fold(hookname, @host, :started, []) # Both handlers were called - 2 = length(:meck.history(modulename)) + 2 = length(:meck.history(modulename)) end # TODO refactor: Move to ejabberd_test_mock @@ -188,5 +199,5 @@ defmodule EjabberdHooksTest do :meck.expect(module, function, fun) end - + end From 31c194a682d41663a66f7d9b42fcc950511de83a Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 09:44:23 +0100 Subject: [PATCH 676/695] Add simple Elixir unit test on jid:from_string --- src/jid.erl | 10 +++++++--- test/jid_test.exs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 test/jid_test.exs diff --git a/src/jid.erl b/src/jid.erl index cc387ecbe4d..7bdd652ae5e 100644 --- a/src/jid.erl +++ b/src/jid.erl @@ -87,9 +87,13 @@ split(#jid{user = U, server = S, resource = R}) -> split(_) -> error. --spec from_string(binary()) -> jid() | error. - -from_string(S) -> +-spec from_string([binary()|string()]) -> jid() | error. +from_string(S) when is_list(S) -> + %% We do not accept list because we want to enforce good practice of + %% using binaries for string. However, we do not let it crash to avoid + %% losing associated ets table. + {error, need_jid_as_binary}; +from_string(S) when is_binary(S) -> SplitPattern = ets:lookup_element(jlib, string_to_jid_pattern, 2), Size = size(S), End = Size-1, diff --git a/test/jid_test.exs b/test/jid_test.exs new file mode 100644 index 00000000000..b75a3603a08 --- /dev/null +++ b/test/jid_test.exs @@ -0,0 +1,44 @@ +# ---------------------------------------------------------------------- +# +# ejabberd, Copyright (C) 2002-2016 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# ---------------------------------------------------------------------- + +defmodule JidTest do + @author "mremond@process-one.net" + + use ExUnit.Case, async: true + + require Record + Record.defrecord :jid, Record.extract(:jid, from_lib: "ejabberd/include/jlib.hrl") + + setup_all do + :stringprep.start + :jid.start + end + + test "create a jid from a binary" do + jid = :jid.from_string("test@localhost/resource") + assert jid(jid, :user) == "test" + assert jid(jid, :server) == "localhost" + assert jid(jid, :resource) == "resource" + end + + test "Check that sending a list to from_string/1 does not crash the jid process" do + {:error, :need_jid_as_binary} = :jid.from_string('test@localhost/resource') + end +end From c924cd42ff88a8efbd996516ad8743eb2b7e1cd5 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 09:45:40 +0100 Subject: [PATCH 677/695] Run basic Elixir unit tests --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 829b53fa455..6114d083643 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,7 @@ script: - make - make install - make xref + - make quicktest - sed -i -e 's/ct:pal/ct:log/' test/suite.erl - ln -sf ../sql priv/ - escript ./rebar skip_deps=true ct -v From c98df3c0da7013c2baadd88a433089100a64a2fc Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 10:06:07 +0100 Subject: [PATCH 678/695] Attempting to use other keyserver, as we see failure from Travis fetching --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6114d083643..a87bb648d26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ before_install: # See: https://github.com/travis-ci/travis-ci/issues/1986 # - sudo sed -i -e s/table_cache/table_open_cache/ -e /log_slow_queries/d /etc/mysql/my.cnf - - sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 5072E1F5 + - sudo apt-key adv --keyserver subkeys.pgp.net --recv-keys 5072E1F5 - sudo add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.6' - sudo apt-get -qq update - sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6 From 3441157a38e571ae1b29787e8f623000e630cb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chmielowski?= Date: Mon, 21 Mar 2016 11:02:32 +0100 Subject: [PATCH 679/695] Use static key for mysql repo --- .travis.yml | 2 +- .travis/mysql_repo_key.asc | 96 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 .travis/mysql_repo_key.asc diff --git a/.travis.yml b/.travis.yml index a87bb648d26..92154cf5f5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ before_install: # See: https://github.com/travis-ci/travis-ci/issues/1986 # - sudo sed -i -e s/table_cache/table_open_cache/ -e /log_slow_queries/d /etc/mysql/my.cnf - - sudo apt-key adv --keyserver subkeys.pgp.net --recv-keys 5072E1F5 + - sudo apt-key adv --import .travis/mysql_repo_key.asc - sudo add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.6' - sudo apt-get -qq update - sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6 diff --git a/.travis/mysql_repo_key.asc b/.travis/mysql_repo_key.asc new file mode 100644 index 00000000000..063f5148a8e --- /dev/null +++ b/.travis/mysql_repo_key.asc @@ -0,0 +1,96 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.9 (SunOS) + +mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3 +RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ +fw2vOUgCmYv2hW0hyDHuvYlQA/BThQoADgj8AW6/0Lo7V1W9/8VuHP0gQwCgvzV3 +BqOxRznNCRCRxAuAuVztHRcEAJooQK1+iSiunZMYD1WufeXfshc57S/+yeJkegNW +hxwR9pRWVArNYJdDRT+rf2RUe3vpquKNQU/hnEIUHJRQqYHo8gTxvxXNQc7fJYLV +K2HtkrPbP72vwsEKMYhhr0eKCbtLGfls9krjJ6sBgACyP/Vb7hiPwxh6rDZ7ITnE +kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI +QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep +rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q2TXlTUUwgUmVs +ZWFzZSBFbmdpbmVlcmluZyA8bXlzcWwtYnVpbGRAb3NzLm9yYWNsZS5jb20+iGkE +ExECACkCGyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAIZAQUCUwHUZgUJGmbLywAK +CRCMcY07UHLh9V+DAKCjS1gGwgVI/eut+5L+l2v3ybl+ZgCcD7ZoA341HtoroV3U +6xRD09fUgeq0O015U1FMIFBhY2thZ2Ugc2lnbmluZyBrZXkgKHd3dy5teXNxbC5j +b20pIDxidWlsZEBteXNxbC5jb20+iG8EMBECAC8FAk53Pa0oHSBidWlsZEBteXNx +bC5jb20gd2lsbCBzdG9wIHdvcmtpbmcgc29vbgAKCRCMcY07UHLh9bU9AJ9xDK0o +xJFL9vTl9OSZC4lX0K9AzwCcCrS9cnJyz79eaRjL0s2r/CcljdyIZQQTEQIAHQUC +R6yUtAUJDTBYqAULBwoDBAMVAwIDFgIBAheAABIJEIxxjTtQcuH1B2VHUEcAAQGu +kgCffz4GUEjzXkOi71VcwgCxASTgbe0An34LPr1j9fCbrXWXO14msIADfb5piEwE +ExECAAwFAj4+o9EFgwlmALsACgkQSVDhKrJykfIk4QCfWbEeKN+3TRspe+5xKj+k +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 +AcOphrnJ +=443I +-----END PGP PUBLIC KEY BLOCK----- From ef04dd75aa91793cd5fb8c87265c0b5214e0b575 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 12:01:20 +0100 Subject: [PATCH 680/695] Add Coveralls support --- .travis.yml | 6 +++++- cover.spec | 5 +++++ rebar.config | 4 ++++ rebar.config.script | 27 ++++++++++++++++++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 cover.spec diff --git a/.travis.yml b/.travis.yml index 92154cf5f5e..a0c1d0bb79e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_install: - sudo apt-get -qq update - sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6 # /END MYSQL 5.6 - + - pip install --user cpp-coveralls coveralls-merge install: - sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev @@ -57,5 +57,9 @@ after_script: after_failure: - find logs -name ejabberd.log -exec cat '{}' ';' +after_success: + - coveralls --exclude lib --exclude tests --gcov-options '\-lp' --dump c.json + - coveralls-merge c.json erlang.json + notifications: email: false diff --git a/cover.spec b/cover.spec new file mode 100644 index 00000000000..7d504d5581e --- /dev/null +++ b/cover.spec @@ -0,0 +1,5 @@ +{level, details}. +{incl_dirs, ["src", "ebin"]}. +{excl_mods, [eldap, 'ELDAPv3']}. +{export, "logs/all.coverdata"}. + diff --git a/rebar.config b/rebar.config index 1f064dd5ea8..d4dac434917 100644 --- a/rebar.config +++ b/rebar.config @@ -67,6 +67,7 @@ {erl_opts, [nowarn_deprecated_function, {if_var_false, debug, no_debug_info}, + {if_var_true, debug, debug_info}, {if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATWAY_WORKAROUND'}}, {if_var_match, db_type, mssql, {d, 'mssql'}}, {if_var_true, erlang_deprecated_types, {d, 'ERL_DEPRECATED_TYPES'}}, @@ -111,6 +112,9 @@ {eunit_compile_opts, [{i, "tools"}]}. +{cover_enabled, true}. +{cover_export_enabled, true}. + {post_hook_configure, [{"fast_tls", []}, {"stringprep", []}, {"fast_yaml", []}, diff --git a/rebar.config.script b/rebar.config.script index a7120b12a43..90928420428 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -7,6 +7,20 @@ %%% Created : 1 May 2013 by Evgeniy Khramtsov %%%------------------------------------------------------------------- +ModCfg0 = fun(F, Cfg, [Key|Tail], Op, Default) -> + {OldVal,PartCfg} = case lists:keytake(Key, 1, Cfg) of + {value, {_, V1}, V2} -> {V1, V2}; + false -> {if Tail == [] -> Default; true -> [] end, Cfg} + end, + case Tail of + [] -> + [{Key, Op(OldVal)} | PartCfg]; + _ -> + [{Key, F(F, OldVal, Tail, Op, Default)} | PartCfg] + end + end, +ModCfg = fun(Cfg, Keys, Op, Default) -> ModCfg0(ModCfg0, Cfg, Keys, Op, Default) end. + Cfg = case file:consult(filename:join(filename:dirname(SCRIPT), "vars.config")) of {ok, Terms} -> Terms; @@ -107,9 +121,20 @@ Conf5 = case lists:keytake(floating_deps, 1, Conf3) of Conf3 end, +%% When running Travis test, upload test coverage result to coveralls: +Conf6 = case os:getenv("TRAVIS") of + "true" -> + JobId = os:getenv("TRAVIS_JOB_ID"), + CfgTemp = ModCfg(Conf5, [deps], fun(V) -> [{coveralls, ".*", {git, "https://github.com/markusn/coveralls-erl.git", "master"}}|V] end, []), + ModCfg(CfgTemp, [post_hooks], fun(V) -> V ++ [{ct, "echo '\n%%! -pa ebin/ deps/coveralls/ebin\nmain(_)->{ok,F}=file:open(\"erlang.json\",[write]),io:fwrite(F,\"~s\",[coveralls:convert_file(\"logs/all.coverdata\", \""++JobId++"\", \"travis-ci\")]).' > getcover.erl"}, + {ct, "escript ./getcover.erl"}] end, []); + _ -> + Conf5 + end, + %io:format("ejabberd configuration:~n ~p~n", [Conf5]), -Conf5. +Conf6. %% Local Variables: %% mode: erlang From 95475966fdad213cf51992128e0210d29aa31d75 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 12:15:07 +0100 Subject: [PATCH 681/695] We do not have C code to cover, they are in dependencies. --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index a0c1d0bb79e..c122ed60fd5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ before_install: - sudo apt-get -qq update - sudo apt-get -qq -o Dpkg::Options::=--force-confold install mysql-server-5.6 # /END MYSQL 5.6 - - pip install --user cpp-coveralls coveralls-merge + - pip install --user coveralls-merge install: - sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev @@ -58,8 +58,7 @@ after_failure: - find logs -name ejabberd.log -exec cat '{}' ';' after_success: - - coveralls --exclude lib --exclude tests --gcov-options '\-lp' --dump c.json - - coveralls-merge c.json erlang.json + - coveralls-merge erlang.json notifications: email: false From 0112135096e620a7d0177f56f6d8b1d80e9141f3 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 14:12:00 +0100 Subject: [PATCH 682/695] Elixir test suite is already run with global CT run command --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c122ed60fd5..4abacd21317 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,6 @@ script: - make - make install - make xref - - make quicktest - sed -i -e 's/ct:pal/ct:log/' test/suite.erl - ln -sf ../sql priv/ - escript ./rebar skip_deps=true ct -v From 107569a17d425cce44012daa7cf5addb3dfa9a4b Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Mar 2016 16:19:06 +0100 Subject: [PATCH 683/695] New command delete_mnesia deletes all tables that can be exported --- src/ejabberd_admin.erl | 4 ++++ src/ejd2odbc.erl | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index c9e5b1780d1..b22a70385f8 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -196,6 +196,10 @@ get_commands_spec() -> desc = "Export all tables as SQL queries to a file", module = ejd2odbc, function = export, args = [{host, string}, {file, string}], result = {res, rescode}}, + #ejabberd_commands{name = delete_mnesia, tags = [mnesia, odbc], + desc = "Export all tables as SQL queries to a file", + module = ejd2odbc, function = delete, + args = [{host, string}], result = {res, rescode}}, #ejabberd_commands{name = convert_to_scram, tags = [odbc], desc = "Convert the passwords in 'users' ODBC table to SCRAM", module = ejabberd_auth_odbc, function = convert_to_scram, diff --git a/src/ejd2odbc.erl b/src/ejd2odbc.erl index 4cb937ef94f..1df88470cbe 100644 --- a/src/ejd2odbc.erl +++ b/src/ejd2odbc.erl @@ -30,7 +30,7 @@ -include("logger.hrl"). -export([export/2, export/3, import_file/2, import/2, - import/3]). + import/3, delete/1]). -define(MAX_RECORDS_PER_TRANSACTION, 100). @@ -80,6 +80,20 @@ export(Server, Output, Module) -> end, Module:export(Server)), close_output(Output, IO). +delete(Server) -> + Modules = modules(), + lists:foreach( + fun(Module) -> + delete(Server, Module) + end, Modules). + +delete(Server, Module) -> + LServer = jid:nameprep(iolist_to_binary(Server)), + lists:foreach( + fun({Table, ConvertFun}) -> + delete(LServer, Table, ConvertFun) + end, Module:export(Server)). + import_file(Server, FileName) when is_binary(FileName) -> import(Server, binary_to_list(FileName)); import_file(Server, FileName) -> @@ -160,6 +174,25 @@ output(_LServer, Table, Fd, SQLs) -> file:write(Fd, ["-- \n-- Mnesia table: ", atom_to_list(Table), "\n--\n", SQLs]). +delete(LServer, Table, ConvertFun) -> + F = fun () -> + mnesia:write_lock_table(Table), + {_N, SQLs} = + mnesia:foldl( + fun(R, {N, SQLs} = Acc) -> + case ConvertFun(LServer, R) of + [] -> + Acc; + _SQL -> + mnesia:delete_object(R), + Acc + end + end, + {0, []}, Table), + delete(LServer, Table, SQLs) + end, + mnesia:transaction(F). + import(LServer, SelectQuery, IO, ConvertFun, Opts) -> F = case proplists:get_bool(fast, Opts) of true -> From e7ef65a22dd1e957ef0162e0f05ef1e5b93d8bd4 Mon Sep 17 00:00:00 2001 From: Badlop Date: Mon, 21 Mar 2016 18:30:05 +0100 Subject: [PATCH 684/695] Improve ban_account command to work with other DBs than Mnesia (#977) --- src/mod_admin_extra.erl | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl index 343a1a3a2ac..f0e5671996b 100644 --- a/src/mod_admin_extra.erl +++ b/src/mod_admin_extra.erl @@ -748,21 +748,7 @@ kick_sessions(User, Server, Reason) -> fun(Resource) -> kick_this_session(User, Server, Resource, Reason) end, - get_resources(User, Server)). - -get_resources(User, Server) -> - lists:map( - fun(Session) -> - element(3, Session#session.usr) - end, - get_sessions(User, Server)). - -get_sessions(User, Server) -> - LUser = jid:nodeprep(User), - LServer = jid:nameprep(Server), - Sessions = mnesia:dirty_index_read(session, {LUser, LServer}, #session.us), - true = is_list(Sessions), - Sessions. + ejabberd_sm:get_user_resources(User, Server)). set_random_password(User, Server, Reason) -> NewPass = build_random_password(Reason), From f8cf1aef9126e77ea34c86cf33c2d29772eb6a22 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Mon, 21 Mar 2016 19:43:59 +0100 Subject: [PATCH 685/695] Disable Riak test on Travis as they are too unpredictable on Travis For now, we are running them on local Jenkins --- .travis.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4abacd21317..e7046767f01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,13 +31,19 @@ before_script: - mkdir "$PWD/ebin" - echo "[{riak_kv, [{add_paths, [\"$PWD/ebin/\"]}]}]." > advanced.config - sudo mv advanced.config /etc/riak/advanced.config - - sudo service riak restart + # MR: Temporarily stopping Riak to disable tests as Riak is too unreliable on Travis-ci + #- sudo service riak restart + - sudo service riak stop - mysql -u root -e "CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test';" - mysql -u root -e "CREATE DATABASE ejabberd_test;" - mysql -u root -e "GRANT ALL ON ejabberd_test.* TO 'ejabberd_test'@'localhost';" - psql -U postgres -c "CREATE USER ejabberd_test WITH PASSWORD 'ejabberd_test';" - psql -U postgres -c "CREATE DATABASE ejabberd_test;" - psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE ejabberd_test TO ejabberd_test;" + # MR: Temporarily stopping Riak to disable tests as Riak is too unreliable on Travis-ci + #- sudo /usr/sbin/riak-admin wait-for-service riak_kv 'riak@127.0.0.1' + #- sudo /usr/sbin/riak-admin test + # - tail -n 100000 /etc/riak/* script: - ./autogen.sh @@ -54,6 +60,8 @@ after_script: - find logs -name suite.log -exec cat '{}' ';' after_failure: + # Try checking Riak database logs + - tail -n 100000 /var/log/riak/*.log - find logs -name ejabberd.log -exec cat '{}' ';' after_success: From 57f7b34b90e8d0970b72dd25928263168ef142fc Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Mar 2016 13:25:34 +0300 Subject: [PATCH 686/695] Do not auto append IP suffix to usernames (#1008) --- src/ejabberd_odbc.erl | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/ejabberd_odbc.erl b/src/ejabberd_odbc.erl index f756fdeb1ec..e98665862b9 100644 --- a/src/ejabberd_odbc.erl +++ b/src/ejabberd_odbc.erl @@ -898,8 +898,7 @@ db_opts(Host) -> <<"">>), case Type of mssql -> - Username = get_mssql_user(Server, User), - [odbc, <<"DSN=", Host/binary, ";UID=", Username/binary, + [odbc, <<"DSN=", Host/binary, ";UID=", User/binary, ";PWD=", Pass/binary>>]; _ -> [Type, Server, Port, DB, User, Pass] @@ -959,21 +958,6 @@ init_mssql(Host) -> Err end. -get_mssql_user(Server, User) -> - HostName = case inet_parse:address(binary_to_list(Server)) of - {ok, _} -> - Server; - {error, _} -> - hd(str:tokens(Server, <<".">>)) - end, - UserName = case str:chr(User, $@) of - 0 -> - <>; - _ -> - User - end, - UserName. - tmp_dir() -> filename:join(["/tmp", "ejabberd"]). From bdce5556bdc5001925111c1b7d6402ac1282ef72 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Mar 2016 19:03:06 +0300 Subject: [PATCH 687/695] Tell Travis not to fail if some tests are skipped --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e7046767f01..db7e3b3473e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,7 +54,8 @@ script: - sed -i -e 's/ct:pal/ct:log/' test/suite.erl - ln -sf ../sql priv/ - escript ./rebar skip_deps=true ct -v - - grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log + #- grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log + grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, 0 failed' logs/raw.log after_script: - find logs -name suite.log -exec cat '{}' ';' From b90c3764c0c058ecc2fb483bdda77d58b78c240c Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Mar 2016 19:05:38 +0300 Subject: [PATCH 688/695] Fix a typo in travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index db7e3b3473e..a2a95d95394 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ script: - ln -sf ../sql priv/ - escript ./rebar skip_deps=true ct -v #- grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, .* of \1 ' logs/raw.log - grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, 0 failed' logs/raw.log + - grep -q 'TEST COMPLETE, \([[:digit:]]*\) ok, 0 failed' logs/raw.log after_script: - find logs -name suite.log -exec cat '{}' ';' From 61e914a83f8f2c69e8cc233ec59fce2fdaf83133 Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Mar 2016 19:32:30 +0300 Subject: [PATCH 689/695] Keep alive Riak connections by default --- src/ejabberd_riak.erl | 8 +++++++- src/ejabberd_riak_sup.erl | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ejabberd_riak.erl b/src/ejabberd_riak.erl index 90bdb4c060f..82ffe5e3d6e 100644 --- a/src/ejabberd_riak.erl +++ b/src/ejabberd_riak.erl @@ -73,7 +73,13 @@ start_link(Num, Server, Port, _StartInterval, Options) -> %% @private is_connected() -> - catch riakc_pb_socket:is_connected(get_random_pid()). + lists:all( + fun({_Id, Pid, _Type, _Modules}) when is_pid(Pid) -> + case catch riakc_pb_socket:is_connected(get_random_pid()) of + true -> true; + _ -> false + end + end, supervisor:which_children(ejabberd_riak_sup)). %% @private get_proc(I) -> diff --git a/src/ejabberd_riak_sup.erl b/src/ejabberd_riak_sup.erl index 7294e0055f7..af811441bb1 100644 --- a/src/ejabberd_riak_sup.erl +++ b/src/ejabberd_riak_sup.erl @@ -109,6 +109,7 @@ init([]) -> Options = lists:filter( fun(X) -> X /= nil end, [auto_reconnect, + {keepalive, true}, if CACertFile /= nil -> {cacertfile ,CACertFile}; true -> nil end, From cb27a3540e62e19c2ac0aeadd804f666597cf0bd Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Tue, 22 Mar 2016 19:58:59 +0300 Subject: [PATCH 690/695] Fix is_connected/0 function --- src/ejabberd_riak.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ejabberd_riak.erl b/src/ejabberd_riak.erl index 82ffe5e3d6e..575810acc75 100644 --- a/src/ejabberd_riak.erl +++ b/src/ejabberd_riak.erl @@ -75,10 +75,12 @@ start_link(Num, Server, Port, _StartInterval, Options) -> is_connected() -> lists:all( fun({_Id, Pid, _Type, _Modules}) when is_pid(Pid) -> - case catch riakc_pb_socket:is_connected(get_random_pid()) of + case catch riakc_pb_socket:is_connected(get_riak_pid(Pid)) of true -> true; _ -> false - end + end; + (_) -> + false end, supervisor:which_children(ejabberd_riak_sup)). %% @private @@ -521,6 +523,9 @@ make_invalid_object(Val) -> get_random_pid() -> PoolPid = ejabberd_riak_sup:get_random_pid(), + get_riak_pid(PoolPid). + +get_riak_pid(PoolPid) -> case catch gen_server:call(PoolPid, get_pid) of {ok, Pid} -> Pid; From 7066338948a17bf7e538887fc0398a28eab5d15b Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Wed, 23 Mar 2016 16:16:50 +0100 Subject: [PATCH 691/695] Enable Riak test suite on Travis-CI --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a2a95d95394..51fd036df33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,21 +28,21 @@ install: - sudo apt-get -qq install libexpat1-dev libyaml-dev libpam0g-dev libsqlite3-dev before_script: + # Ulimit: See Travis-CI issue report: https://github.com/travis-ci/travis-ci/issues/3328 + - sudo sh -c 'ulimit -n 4096' + - sudo sh -c 'echo "ulimit -n 4096" > /etc/default/riak' - mkdir "$PWD/ebin" - echo "[{riak_kv, [{add_paths, [\"$PWD/ebin/\"]}]}]." > advanced.config - sudo mv advanced.config /etc/riak/advanced.config - # MR: Temporarily stopping Riak to disable tests as Riak is too unreliable on Travis-ci - #- sudo service riak restart - - sudo service riak stop + - sudo service riak restart - mysql -u root -e "CREATE USER 'ejabberd_test'@'localhost' IDENTIFIED BY 'ejabberd_test';" - mysql -u root -e "CREATE DATABASE ejabberd_test;" - mysql -u root -e "GRANT ALL ON ejabberd_test.* TO 'ejabberd_test'@'localhost';" - psql -U postgres -c "CREATE USER ejabberd_test WITH PASSWORD 'ejabberd_test';" - psql -U postgres -c "CREATE DATABASE ejabberd_test;" - psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE ejabberd_test TO ejabberd_test;" - # MR: Temporarily stopping Riak to disable tests as Riak is too unreliable on Travis-ci - #- sudo /usr/sbin/riak-admin wait-for-service riak_kv 'riak@127.0.0.1' - #- sudo /usr/sbin/riak-admin test + - sudo /usr/sbin/riak-admin wait-for-service riak_kv 'riak@127.0.0.1' + - sudo /usr/sbin/riak-admin test # - tail -n 100000 /etc/riak/* script: From a3a33bd5fcca1d21eecbf5b4332716dd6e191056 Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Thu, 24 Mar 2016 10:02:13 +0100 Subject: [PATCH 692/695] Allow running test groups independently We need to be able to run only a few test groups, even if we do not have all database backends installed and configured locally. ejabberd test suite configures a specific host per backend. I changed ejabberd to allow ignoring some hosts from config file on start, by providing the exact list of hosts we want to start. This is done by setting an ejabberd app Erlang environment variable 'hosts' and passing the list of hosts we want to actually define. When doing so, the backend specific hosts defined in ejabberd test configuration file are simply ignored. As a result, we do not try to connect to unavailable backends. I linked that part to CT run test by defining the hosts list based on environment variable CT_BACKENDS. This variable is expected to be a comma separated list of available backends. When Erlang Common Tests are run with that environment variable set, only the host matching the name of the backend will be set, plus the default "localhost", common to many tests. This can be combined with rebar ct groups list. Example commands to run tests: CT_BACKENDS=riak,mnesia rebar ct suites=ejabberd CT_BACKENDS=mnesia rebar ct suites=ejabberd groups=mnesia --- src/ejabberd_config.erl | 71 +++++++++++++++++++++++++++++------------ test/ejabberd_SUITE.erl | 63 ++++++++++++++++++++++++++++-------- test/suite.erl | 14 +++++++- 3 files changed, 113 insertions(+), 35 deletions(-) diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index eb06b98f616..6f7368b7c83 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -38,6 +38,8 @@ convert_to_yaml/1, convert_to_yaml/2, env_binary_to_list/2, opt_type/1, may_hide_data/1]). +-export([start/2]). + -include("ejabberd.hrl"). -include("logger.hrl"). -include("ejabberd_config.hrl"). @@ -52,22 +54,12 @@ %% @type macro_value() = term(). - start() -> - case catch mnesia:table_info(local_config, storage_type) of - disc_copies -> - mnesia:delete_table(local_config); - _ -> - ok - end, - mnesia:create_table(local_config, - [{ram_copies, [node()]}, - {local_content, true}, - {attributes, record_info(fields, local_config)}]), - mnesia:add_table_copy(local_config, node(), ram_copies), + mnesia_init(), Config = get_ejabberd_config_path(), State0 = read_file(Config), - State = validate_opts(State0), + State1 = hosts_to_start(State0), + State2 = validate_opts(State1), %% This start time is used by mod_last: UnixTime = p1_time_compat:system_time(seconds), SharedKey = case erlang:get_cookie() of @@ -76,9 +68,45 @@ start() -> Cookie -> p1_sha:sha(jlib:atom_to_binary(Cookie)) end, - State1 = set_option({node_start, global}, UnixTime, State), - State2 = set_option({shared_key, global}, SharedKey, State1), - set_opts(State2). + State3 = set_option({node_start, global}, UnixTime, State2), + State4 = set_option({shared_key, global}, SharedKey, State3), + set_opts(State4). + +%% When starting ejabberd for testing, we sometimes want to start a +%% subset of hosts from the one define in the config file. +%% This function override the host list read from config file by the +%% one we provide. +%% Hosts to start are defined in an ejabberd application environment +%% variable 'hosts' to make it easy to ignore some host in config +%% file. +hosts_to_start(State) -> + case application:get_env(ejabberd, hosts) of + undefined -> + %% Start all hosts as defined in config file + State; + {ok, Hosts} -> + set_hosts_in_options(Hosts, State) + end. + +%% @private +%% At the moment, these functions are mainly used to setup unit tests. +-spec(start/2 :: (Hosts :: [binary()], Opts :: [acl:acl() | local_config()]) -> ok). +start(Hosts, Opts) -> + mnesia_init(), + set_opts(#state{hosts = Hosts, opts = Opts}). + +mnesia_init() -> + case catch mnesia:table_info(local_config, storage_type) of + disc_copies -> + mnesia:delete_table(local_config); + _ -> + ok + end, + mnesia:create_table(local_config, + [{ram_copies, [node()]}, + {local_content, true}, + {attributes, record_info(fields, local_config)}]), + mnesia:add_table_copy(local_config, node(), ram_copies). %% @doc Get the filename of the ejabberd configuration file. %% The filename can be specified with: erl -config "/path/to/ejabberd.yml". @@ -277,7 +305,7 @@ search_hosts(Term, State) -> {host, Host} -> if State#state.hosts == [] -> - add_hosts_to_option([Host], State); + set_hosts_in_options([Host], State); true -> ?ERROR_MSG("Can't load config file: " "too many hosts definitions", []), @@ -286,7 +314,7 @@ search_hosts(Term, State) -> {hosts, Hosts} -> if State#state.hosts == [] -> - add_hosts_to_option(Hosts, State); + set_hosts_in_options(Hosts, State); true -> ?ERROR_MSG("Can't load config file: " "too many hosts definitions", []), @@ -296,9 +324,12 @@ search_hosts(Term, State) -> State end. -add_hosts_to_option(Hosts, State) -> +set_hosts_in_options(Hosts, State) -> PrepHosts = normalize_hosts(Hosts), - set_option({hosts, global}, PrepHosts, State#state{hosts = PrepHosts}). + NewOpts = lists:filter(fun({local_config,{hosts,global},_}) -> false; + (_) -> true + end, State#state.opts), + set_option({hosts, global}, PrepHosts, State#state{hosts = PrepHosts, opts = NewOpts}). normalize_hosts(Hosts) -> normalize_hosts(Hosts,[]). diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl index b239ddf0b0b..b9ba9956a5b 100644 --- a/test/ejabberd_SUITE.erl +++ b/test/ejabberd_SUITE.erl @@ -35,22 +35,57 @@ init_per_suite(Config) -> LDIFFile = filename:join([DataDir, "ejabberd.ldif"]), {ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])), {ok, _} = ldap_srv:start(LDIFFile), - ok = application:start(ejabberd), + start_ejabberd(NewConfig), NewConfig. +start_ejabberd(Config) -> + case proplists:get_value(backends, Config) of + all -> + ok = application:start(ejabberd, transient); + Backends when is_list(Backends) -> + Hosts = lists:map(fun(Backend) -> Backend ++ ".localhost" end, Backends), + application:load(ejabberd), + AllHosts = Hosts ++ ["localhost"], %% We always need localhost for the generic no_db tests + application:set_env(ejabberd, hosts, AllHosts), + ok = application:start(ejabberd, transient) + end. + end_per_suite(_Config) -> - ok. + application:stop(ejabberd). -init_per_group(no_db, Config) -> +-define(BACKENDS, [mnesia,redis,mysql,pgsql,sqlite,ldap,extauth,riak]). + +init_per_group(Group, Config) -> + case lists:member(Group, ?BACKENDS) of + false -> + %% Not a backend related group, do default init: + do_init_per_group(Group, Config); + true -> + case proplists:get_value(backends, Config) of + all -> + %% All backends enabled + do_init_per_group(Group, Config); + Backends -> + %% Skipped backends that were not explicitely enabled + case lists:member(atom_to_list(Group), Backends) of + true -> + do_init_per_group(Group, Config); + false -> + {skip, {disabled_backend, Group}} + end + end + end. + +do_init_per_group(no_db, Config) -> re_register(Config), Config; -init_per_group(mnesia, Config) -> +do_init_per_group(mnesia, Config) -> mod_muc:shutdown_rooms(?MNESIA_VHOST), set_opt(server, ?MNESIA_VHOST, Config); -init_per_group(redis, Config) -> +do_init_per_group(redis, Config) -> mod_muc:shutdown_rooms(?REDIS_VHOST), set_opt(server, ?REDIS_VHOST, Config); -init_per_group(mysql, Config) -> +do_init_per_group(mysql, Config) -> case catch ejabberd_odbc:sql_query(?MYSQL_VHOST, [<<"select 1;">>]) of {selected, _, _} -> mod_muc:shutdown_rooms(?MYSQL_VHOST), @@ -59,7 +94,7 @@ init_per_group(mysql, Config) -> Err -> {skip, {mysql_not_available, Err}} end; -init_per_group(pgsql, Config) -> +do_init_per_group(pgsql, Config) -> case catch ejabberd_odbc:sql_query(?PGSQL_VHOST, [<<"select 1;">>]) of {selected, _, _} -> mod_muc:shutdown_rooms(?PGSQL_VHOST), @@ -68,7 +103,7 @@ init_per_group(pgsql, Config) -> Err -> {skip, {pgsql_not_available, Err}} end; -init_per_group(sqlite, Config) -> +do_init_per_group(sqlite, Config) -> case catch ejabberd_odbc:sql_query(?SQLITE_VHOST, [<<"select 1;">>]) of {selected, _, _} -> mod_muc:shutdown_rooms(?SQLITE_VHOST), @@ -76,11 +111,11 @@ init_per_group(sqlite, Config) -> Err -> {skip, {sqlite_not_available, Err}} end; -init_per_group(ldap, Config) -> +do_init_per_group(ldap, Config) -> set_opt(server, ?LDAP_VHOST, Config); -init_per_group(extauth, Config) -> +do_init_per_group(extauth, Config) -> set_opt(server, ?EXTAUTH_VHOST, Config); -init_per_group(riak, Config) -> +do_init_per_group(riak, Config) -> case ejabberd_riak:is_connected() of true -> mod_muc:shutdown_rooms(?RIAK_VHOST), @@ -89,7 +124,7 @@ init_per_group(riak, Config) -> Err -> {skip, {riak_not_available, Err}} end; -init_per_group(_GroupName, Config) -> +do_init_per_group(_GroupName, Config) -> Pid = start_event_relay(), set_opt(event_relay, Pid, Config). @@ -967,9 +1002,9 @@ mix_master(Config) -> retract = [ParticipantID]}]}]}), disconnect(Config). -mix_slave(Config) -> +mix_slave(Config) -> disconnect(Config). - + roster_subscribe_master(Config) -> send(Config, #presence{}), ?recv1(#presence{}), diff --git a/test/suite.erl b/test/suite.erl index bc094fa311c..8000e1d2975 100644 --- a/test/suite.erl +++ b/test/suite.erl @@ -65,9 +65,21 @@ init_config(Config) -> {resource, <<"resource">>}, {master_resource, <<"master_resource">>}, {slave_resource, <<"slave_resource">>}, - {password, <<"password">>} + {password, <<"password">>}, + {backends, get_config_backends()} |Config]. +%% Read environment variable CT_DB=riak,mysql to limit the backends to test. +%% You can thus limit the backend you want to test with: +%% CT_BACKENDS=riak,mysql rebar ct suites=ejabberd +get_config_backends() -> + case os:getenv("CT_BACKENDS") of + false -> all; + String -> + Backends0 = string:tokens(String, ","), + lists:map(fun(Backend) -> string:strip(Backend, both, $ ) end, Backends0) + end. + process_config_tpl(Content, []) -> Content; process_config_tpl(Content, [{Name, DefaultValue} | Rest]) -> From df4c551f06d3fba29f1074e1e6b54fa44755d8fd Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 24 Mar 2016 10:21:51 +0100 Subject: [PATCH 693/695] Specify lacking nodename (thanks to hamano)(#1020) --- ejabberdctl.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberdctl.template b/ejabberdctl.template index dca23fe81fd..6b06226ac52 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -394,7 +394,7 @@ ctl() # concurrent invocations using a bound # number of atoms for N in `seq 1 $MAXCONNID`; do - CTL_CONN="ejabberdctl-$N" + CTL_CONN="ctl-$N-${ERLANG_NODE}" CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN" ( exec 8>"$CTL_LOCKFILE" From 914578a85ec0e6b11dc547e6906dd69bb22cfa86 Mon Sep 17 00:00:00 2001 From: Christophe Romain Date: Thu, 24 Mar 2016 11:06:42 +0100 Subject: [PATCH 694/695] Fix start via systemd (#978) --- ejabberd.service.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ejabberd.service.template b/ejabberd.service.template index 79c2a644101..80b15adbdd6 100644 --- a/ejabberd.service.template +++ b/ejabberd.service.template @@ -7,7 +7,7 @@ User=ejabberd Group=ejabberd LimitNOFILE=16000 RestartSec=5 -ExecStart=/bin/sh @ctlscriptpath@/ejabberdctl start +ExecStart=@ctlscriptpath@/ejabberdctl start ExecStop=@ctlscriptpath@/ejabberdctl stop ExecReload=@ctlscriptpath@/ejabberdctl reload_config Type=oneshot From 8e053e14074e477d9dde20dfe5870fda83feec67 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Thu, 9 Apr 2015 00:09:12 -0300 Subject: [PATCH 695/695] MojoAuth module Permits use of MojoAuth (http://mojoauth.mojolingo.com/) in ejabberd. MojoAuth is a set of standard approaches to cross-app authentication based on HMAC which is specified in RFC2104. --- rebar.config | 1 + src/ejabberd_auth.erl | 2 +- src/ejabberd_auth_mojoauth.erl | 99 ++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/ejabberd_auth_mojoauth.erl diff --git a/rebar.config b/rebar.config index d4dac434917..107aec84a93 100644 --- a/rebar.config +++ b/rebar.config @@ -21,6 +21,7 @@ {p1_xmlrpc, ".*", {git, "https://github.com/processone/p1_xmlrpc", {tag, "1.15.1"}}}, {luerl, ".*", {git, "https://github.com/rvirding/luerl", "9524d0309a88b7c62ae93da0b632b185de3ba9db"}}, + {mojoauth, ".*", {git, "https://github.com/adhearsion/mojoauth.erl.git", "ec1b805c119cecd93291846c862db40fa5d35ca4"}}, {if_var_true, mysql, {p1_mysql, ".*", {git, "https://github.com/processone/p1_mysql", {tag, "1.0.1"}}}}, {if_var_true, pgsql, {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 343ad943694..ea0c212d213 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -136,7 +136,7 @@ check_password(User, AuthzId, Server, Password, Digest, %% {true, AuthModule} | false %% where %% AuthModule = ejabberd_auth_anonymous | ejabberd_auth_external -%% | ejabberd_auth_internal | ejabberd_auth_ldap +%% | ejabberd_auth_internal | ejabberd_auth_ldap | ejabberd_auth_mojoauth %% | ejabberd_auth_odbc | ejabberd_auth_pam | ejabberd_auth_riak -spec check_password_with_authmodule(binary(), binary(), binary(), binary()) -> false | {true, atom()}. diff --git a/src/ejabberd_auth_mojoauth.erl b/src/ejabberd_auth_mojoauth.erl new file mode 100644 index 00000000000..126adce97d4 --- /dev/null +++ b/src/ejabberd_auth_mojoauth.erl @@ -0,0 +1,99 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_auth_mojoauth.erl +%%% Author : Ben Langfeld +%%% Purpose : Authentication via MojoAuth (http://mojoauth.mojolingo.com/) +%%% Created : 18 February 2015 by Ben Langfeld +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2015 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., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%---------------------------------------------------------------------- + +-module(ejabberd_auth_mojoauth). + +-author('ben@langfeld.me'). + +-behaviour(ejabberd_auth). + +%% External exports +-export([start/1, set_password/3, check_password/4, + check_password/6, try_register/3, + dirty_get_registered_users/0, get_vh_registered_users/1, + get_vh_registered_users/2, + get_vh_registered_users_number/1, + get_vh_registered_users_number/2, get_password/2, + get_password_s/2, is_user_exists/2, remove_user/2, + remove_user/3, store_type/0, + plain_password_required/0]). + +-include("ejabberd.hrl"). +-include("logger.hrl"). + +%%%---------------------------------------------------------------------- +%%% API +%%%---------------------------------------------------------------------- +start(Host) -> + ejabberd_auth_internal:start(Host). + +plain_password_required() -> true. + +store_type() -> external. + +secret(Server) -> + LServer = jlib:nameprep(Server), + ejabberd_config:get_option( + {mojoauth_secret, LServer}, + fun(V) -> iolist_to_binary(V) end, + "mojoauth"). + +check_password(User, AuthzId, Server, Password) -> + case mojoauth:test_credentials([{username, User}, {password, Password}], secret(Server)) of + {ok, AuthzId} -> true; + _ -> false + end. + +check_password(User, AuthzId, Server, Password, _Digest, _DigestGen) -> + check_password(User, AuthzId, Server, Password). + +set_password(_User, _Server, _Password) -> {error, not_allowed}. + +try_register(_User, _Server, _Password) -> {error, not_allowed}. + +dirty_get_registered_users() -> + ejabberd_auth_internal:dirty_get_registered_users(). + +get_vh_registered_users(Server) -> + ejabberd_auth_internal:get_vh_registered_users(Server). + +get_vh_registered_users(Server, Data) -> + ejabberd_auth_internal:get_vh_registered_users(Server, Data). + +get_vh_registered_users_number(Server) -> + ejabberd_auth_internal:get_vh_registered_users_number(Server). + +get_vh_registered_users_number(Server, Data) -> + ejabberd_auth_internal:get_vh_registered_users_number(Server, Data). + +get_password(_User, _Server) -> false. + +get_password_s(_User, _Server) -> <<"">>. + +is_user_exists(_User, _Server) -> true. + +remove_user(_User, _Server) -> false. + +remove_user(_User, _Server, _Password) -> false.

    4i48n6hNxkl5z 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